1 # This file is part of lyx2lyx
2 # -*- coding: utf-8 -*-
3 # Copyright (C) 2007-2008 The LyX Team <lyx-devel@lists.lyx.org>
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 """ Convert files to the file format generated by lyx 1.6"""
25 from parser_tools import find_token, find_end_of, find_tokens, get_value, get_value_string
27 ####################################################################
28 # Private helper functions
30 def find_end_of_inset(lines, i):
31 " Find end of inset, where lines[i] is included."
32 return find_end_of(lines, i, "\\begin_inset", "\\end_inset")
36 # document.body[i] = wrap_insert_ert(...)
37 # wrap_into_ert may returns a multiline string, which should NOT appear
38 # in document.body. Insetad, do something like this:
39 # subst = wrap_inset_ert(...)
40 # subst = subst.split('\n')
41 # document.body[i:i+1] = subst
43 # where the last statement resets the counter to accord with the added
45 def wrap_into_ert(string, src, dst):
46 '''Within string, replace occurrences of src with dst, wrapped into ERT
47 E.g.: wrap_into_ert('sch\"on', "\\", "\\backslash") is:
48 sch<ERT>\\backslash</ERT>"on'''
49 return string.replace(src, '\n\\begin_inset ERT\nstatus collapsed\n\\begin_layout Standard\n'
50 + dst + '\n\\end_layout\n\\end_inset\n')
52 def put_cmd_in_ert(string):
53 string = string.replace('\\', "\\backslash\n")
54 string = "\\begin_inset ERT\nstatus collapsed\n\\begin_layout Standard\n" \
55 + string + "\n\\end_layout\n\\end_inset"
58 def add_to_preamble(document, text):
59 """ Add text to the preamble if it is not already there.
60 Only the first line is checked!"""
62 if find_token(document.preamble, text[0], 0) != -1:
65 document.preamble.extend(text)
67 def insert_to_preamble(index, document, text):
68 """ Insert text to the preamble at a given line"""
70 document.preamble.insert(index, text)
72 # Convert a LyX length into a LaTeX length
74 units = {"text%":"\\backslash\ntextwidth", "col%":"\\backslash\ncolumnwidth",
75 "page%":"\\backslash\npagewidth", "line%":"\\backslash\nlinewidth",
76 "theight%":"\\backslash\ntextheight", "pheight%":"\\backslash\npageheight"}
78 # Convert LyX units to LaTeX units
79 for unit in units.keys():
80 if len.find(unit) != -1:
81 len = '%f' % (len2value(len) / 100)
82 len = len.strip('0') + units[unit]
87 # Return the value of len without the unit in numerical form.
89 result = re.search('([+-]?[0-9.]+)', len)
91 return float(result.group(1))
95 # Unfortunately, this doesn't really work, since Standard isn't always default.
96 # But it's as good as we can do right now.
97 def find_default_layout(document, start, end):
98 l = find_token(document.body, "\\begin_layout Standard", start, end)
100 l = find_token(document.body, "\\begin_layout PlainLayout", start, end)
102 l = find_token(document.body, "\\begin_layout Plain Layout", start, end)
105 def get_option(document, m, option, default):
106 l = document.body[m].find(option)
109 val = document.body[m][l:].split('"')[1]
112 def remove_option(document, m, option):
113 l = document.body[m].find(option)
115 val = document.body[m][l:].split('"')[1]
116 document.body[m] = document.body[m][:l-1] + document.body[m][l+len(option + '="' + val + '"'):]
119 def set_option(document, m, option, value):
120 l = document.body[m].find(option)
122 oldval = document.body[m][l:].split('"')[1]
123 l = l + len(option + '="')
124 document.body[m] = document.body[m][:l] + value + document.body[m][l+len(oldval):]
126 document.body[m] = document.body[m][:-1] + ' ' + option + '="' + value + '">'
130 def read_unicodesymbols():
131 " Read the unicodesymbols list of unicode characters and corresponding commands."
132 pathname = os.path.abspath(os.path.dirname(sys.argv[0]))
133 fp = open(os.path.join(pathname.strip('lyx2lyx'), 'unicodesymbols'))
135 # Two backslashes, followed by some non-word character, and then a character
136 # in brackets. The idea is to check for constructs like: \"{u}, which is how
137 # they are written in the unicodesymbols file; but they can also be written
139 r = re.compile(r'\\\\(\W)\{(\w)\}')
140 for line in fp.readlines():
141 if line[0] != '#' and line.strip() != "":
142 line=line.replace(' "',' ') # remove all quotation marks with spaces before
143 line=line.replace('" ',' ') # remove all quotation marks with spaces after
144 line=line.replace(r'\"','"') # replace \" by " (for characters with diaeresis)
146 [ucs4,command,dead] = line.split(None,2)
147 if command[0:1] != "\\":
149 spec_chars.append([command, unichr(eval(ucs4))])
155 # If the character is a double-quote, then we need to escape it, too,
156 # since it is done that way in the LyX file.
157 if m.group(1) == "\"":
159 command += m.group(1) + m.group(2)
160 spec_chars.append([command, unichr(eval(ucs4))])
165 def extract_argument(line):
166 'Extracts a LaTeX argument from the start of line. Returns (arg, rest).'
171 bracere = re.compile("(\s*)(.*)")
172 n = bracere.match(line)
173 whitespace = n.group(1)
176 if brace != "[" and brace != "{":
200 # We never found the matching brace
201 # So, to be on the safe side, let's just return everything
202 # which will then get wrapped as ERT
204 return (line[:pos + 1], line[pos + 1:])
208 '''Converts LaTeX commands into ERT. line may well be a multi-line
209 string when it is returned.'''
214 ## FIXME Escaped \ ??
215 # This regex looks for a LaTeX command---i.e., something of the form
216 # "\alPhaStuFF", or "\X", where X is any character---where the command
217 # may also be preceded by an additional backslash, which is how it would
218 # appear (e.g.) in an InsetIndex.
219 labelre = re.compile(r'(.*?)\\?(\\(?:[a-zA-Z]+|.))(.*)')
221 m = labelre.match(line)
228 (arg, rest) = extract_argument(end)
233 # If we wanted to put labels into an InsetLabel, for example, then we
234 # would just need to test here for cmd == "label" and then take some
235 # appropriate action, i.e., to use arg to get the content and then
236 # wrap it appropriately.
237 cmd = put_cmd_in_ert(cmd)
238 retval += "\n" + cmd + "\n"
240 m = labelre.match(line)
246 #Might should do latex2ert first, then deal with stuff that DOESN'T
247 #end up inside ERT. That routine could be modified so that it returned
248 #a list of lines, and we could then skip ERT bits and only deal with
251 '''Takes a string, possibly multi-line, and returns the result of
252 converting LaTeX constructs into LyX constructs. Returns a list of
253 lines, suitable for insertion into document.body.'''
257 # Convert LaTeX to Unicode
258 reps = read_unicodesymbols()
259 # Commands of this sort need to be checked to make sure they are
260 # followed by a non-alpha character, lest we replace too much.
261 hardone = re.compile(r'^\\\\[a-zA-Z]+$')
264 if hardone.match(rep[0]):
267 pos = data.find(rep[0], pos)
270 nextpos = pos + len(rep[0])
271 if nextpos < len(data) and data[nextpos].isalpha():
272 # not the end of that command
275 data = data[:pos] + rep[1] + data[nextpos:]
278 data = data.replace(rep[0], rep[1])
281 data = wrap_into_ert(data, r'\"', '"')
284 mathre = re.compile('^(.*?)(\$.*?\$)(.*)')
285 lines = data.split('\n')
287 #document.warning("LINE: " + line)
288 #document.warning(str(i) + ":" + document.body[i])
289 #document.warning("LAST: " + document.body[-1])
294 f = m.group(2).replace('\\\\', '\\')
299 subst = s.split('\n')
301 retval.append("\\begin_inset Formula " + f)
302 retval.append("\\end_inset")
304 # Handle whatever is left, which is just text
306 subst = g.split('\n')
311 def lyx2latex(lines):
312 'Convert some LyX stuff into corresponding LaTeX stuff, as best we can.'
313 # clean up multiline stuff
316 reps = read_unicodesymbols()
318 for curline in range(len(lines)):
319 line = lines[curline]
320 if line.startswith("\\begin_inset ERT"):
321 # We don't want to replace things inside ERT, so figure out
322 # where the end of the inset is.
323 ert_end = find_end_of_inset(lines, curline + 1)
325 elif line.startswith("\\begin_inset Formula"):
327 elif line.startswith("\\begin_inset Quotes"):
328 # For now, we do a very basic reversion. Someone who understands
329 # quotes is welcome to fix it up.
330 qtype = line[20:].strip()
344 elif line.isspace() or \
345 line.startswith("\\begin_layout") or \
346 line.startswith("\\end_layout") or \
347 line.startswith("\\begin_inset") or \
348 line.startswith("\\end_inset") or \
349 line.startswith("\\lang") or \
350 line.strip() == "status collapsed" or \
351 line.strip() == "status open":
355 # a lossless reversion is not possible
356 # try at least to handle some common insets and settings
357 # do not replace inside ERTs
358 if ert_end >= curline:
359 line = line.replace(r'\backslash', r'\\')
361 # Do the LyX text --> LaTeX conversion
363 line = line.replace(rep[1], rep[0] + "{}")
364 line = line.replace(r'\backslash', r'\textbackslash{}')
365 line = line.replace(r'\series bold', r'\bfseries{}').replace(r'\series default', r'\mdseries{}')
366 line = line.replace(r'\shape italic', r'\itshape{}').replace(r'\shape smallcaps', r'\scshape{}')
367 line = line.replace(r'\shape slanted', r'\slshape{}').replace(r'\shape default', r'\upshape{}')
368 line = line.replace(r'\emph on', r'\em{}').replace(r'\emph default', r'\em{}')
369 line = line.replace(r'\noun on', r'\scshape{}').replace(r'\noun default', r'\upshape{}')
370 line = line.replace(r'\bar under', r'\underbar{').replace(r'\bar default', r'}')
371 line = line.replace(r'\family sans', r'\sffamily{}').replace(r'\family default', r'\normalfont{}')
372 line = line.replace(r'\family typewriter', r'\ttfamily{}').replace(r'\family roman', r'\rmfamily{}')
373 line = line.replace(r'\InsetSpace ', r'').replace(r'\SpecialChar ', r'')
378 ####################################################################
380 def convert_ltcaption(document):
383 i = find_token(document.body, "\\begin_inset Tabular", i)
386 j = find_end_of_inset(document.body, i + 1)
388 document.warning("Malformed LyX document: Could not find end of tabular.")
391 nrows = int(document.body[i+1].split('"')[3])
392 ncols = int(document.body[i+1].split('"')[5])
395 for k in range(nrows):
396 m = find_token(document.body, "<row", m)
399 for k in range(ncols):
400 m = find_token(document.body, "<cell", m)
402 mend = find_token(document.body, "</cell>", m + 1)
403 # first look for caption insets
404 mcap = find_token(document.body, "\\begin_inset Caption", m + 1, mend)
405 # then look for ERT captions
407 mcap = find_token(document.body, "caption", m + 1, mend)
409 mcap = find_token(document.body, "\\backslash", mcap - 1, mcap)
412 if caption == 'true':
414 set_option(document, r, 'caption', 'true')
415 set_option(document, m, 'multicolumn', '1')
416 set_option(document, m, 'bottomline', 'false')
417 set_option(document, m, 'topline', 'false')
418 set_option(document, m, 'rightline', 'false')
419 set_option(document, m, 'leftline', 'false')
420 #j = find_end_of_inset(document.body, j + 1)
422 set_option(document, m, 'multicolumn', '2')
429 #FIXME Use of wrap_into_ert can confuse lyx2lyx
430 def revert_ltcaption(document):
433 i = find_token(document.body, "\\begin_inset Tabular", i)
436 j = find_end_of_inset(document.body, i + 1)
438 document.warning("Malformed LyX document: Could not find end of tabular.")
442 nrows = int(document.body[i+1].split('"')[3])
443 ncols = int(document.body[i+1].split('"')[5])
445 for k in range(nrows):
446 m = find_token(document.body, "<row", m)
447 caption = get_option(document, m, 'caption', 'false')
448 if caption == 'true':
449 remove_option(document, m, 'caption')
450 for k in range(ncols):
451 m = find_token(document.body, "<cell", m)
452 remove_option(document, m, 'multicolumn')
454 m = find_token(document.body, "\\begin_inset Caption", m)
457 m = find_end_of_inset(document.body, m + 1)
458 document.body[m] += wrap_into_ert("","","\\backslash\n\\backslash\n%")
464 def convert_tablines(document):
467 i = find_token(document.body, "\\begin_inset Tabular", i)
469 # LyX 1.3 inserted an extra space between \begin_inset
470 # and Tabular so let us try if this is the case and fix it.
471 i = find_token(document.body, "\\begin_inset Tabular", i)
475 document.body[i] = "\\begin_inset Tabular"
476 j = find_end_of_inset(document.body, i + 1)
478 document.warning("Malformed LyX document: Could not find end of tabular.")
482 nrows = int(document.body[i+1].split('"')[3])
483 ncols = int(document.body[i+1].split('"')[5])
486 for k in range(ncols):
487 m = find_token(document.body, "<column", m)
488 left = get_option(document, m, 'leftline', 'false')
489 right = get_option(document, m, 'rightline', 'false')
490 col_info.append([left, right])
491 remove_option(document, m, 'leftline')
492 remove_option(document, m, 'rightline')
496 for k in range(nrows):
497 m = find_token(document.body, "<row", m)
498 top = get_option(document, m, 'topline', 'false')
499 bottom = get_option(document, m, 'bottomline', 'false')
500 row_info.append([top, bottom])
501 remove_option(document, m, 'topline')
502 remove_option(document, m, 'bottomline')
507 for k in range(nrows*ncols):
508 m = find_token(document.body, "<cell", m)
509 mc_info.append(get_option(document, m, 'multicolumn', '0'))
512 for l in range(nrows):
513 for k in range(ncols):
514 m = find_token(document.body, '<cell', m)
515 if mc_info[l*ncols + k] == '0':
516 r = set_option(document, m, 'topline', row_info[l][0])
517 r = set_option(document, m, 'bottomline', row_info[l][1])
518 r = set_option(document, m, 'leftline', col_info[k][0])
519 r = set_option(document, m, 'rightline', col_info[k][1])
520 elif mc_info[l*ncols + k] == '1':
522 while s < ncols and mc_info[l*ncols + s] == '2':
524 if s < ncols and mc_info[l*ncols + s] != '1':
525 r = set_option(document, m, 'rightline', col_info[k][1])
526 if k > 0 and mc_info[l*ncols + k - 1] == '0':
527 r = set_option(document, m, 'leftline', col_info[k][0])
532 def revert_tablines(document):
535 i = find_token(document.body, "\\begin_inset Tabular", i)
538 j = find_end_of_inset(document.body, i + 1)
540 document.warning("Malformed LyX document: Could not find end of tabular.")
544 nrows = int(document.body[i+1].split('"')[3])
545 ncols = int(document.body[i+1].split('"')[5])
548 for k in range(nrows*ncols):
549 m = find_token(document.body, "<cell", m)
550 top = get_option(document, m, 'topline', 'false')
551 bottom = get_option(document, m, 'bottomline', 'false')
552 left = get_option(document, m, 'leftline', 'false')
553 right = get_option(document, m, 'rightline', 'false')
554 lines.append([top, bottom, left, right])
557 # we will want to ignore longtable captions
560 for k in range(nrows):
561 m = find_token(document.body, "<row", m)
562 caption = get_option(document, m, 'caption', 'false')
563 caption_info.append([caption])
568 for k in range(ncols):
569 m = find_token(document.body, "<column", m)
571 for l in range(nrows):
572 left = lines[l*ncols + k][2]
573 if left == 'false' and caption_info[l] == 'false':
575 set_option(document, m, 'leftline', left)
577 for l in range(nrows):
578 right = lines[l*ncols + k][3]
579 if right == 'false' and caption_info[l] == 'false':
581 set_option(document, m, 'rightline', right)
585 for k in range(nrows):
586 m = find_token(document.body, "<row", m)
588 for l in range(ncols):
589 top = lines[k*ncols + l][0]
592 if caption_info[k] == 'false':
594 set_option(document, m, 'topline', top)
596 for l in range(ncols):
597 bottom = lines[k*ncols + l][1]
598 if bottom == 'false':
600 if caption_info[k] == 'false':
602 set_option(document, m, 'bottomline', bottom)
608 def fix_wrong_tables(document):
611 i = find_token(document.body, "\\begin_inset Tabular", i)
614 j = find_end_of_inset(document.body, i + 1)
616 document.warning("Malformed LyX document: Could not find end of tabular.")
620 nrows = int(document.body[i+1].split('"')[3])
621 ncols = int(document.body[i+1].split('"')[5])
623 for l in range(nrows):
625 for k in range(ncols):
626 m = find_token(document.body, '<cell', m)
628 if document.body[m].find('multicolumn') != -1:
629 multicol_cont = int(document.body[m].split('"')[1])
631 if multicol_cont == 2 and (k == 0 or prev_multicolumn == 0):
632 document.body[m] = document.body[m][:5] + document.body[m][21:]
635 prev_multicolumn = multicol_cont
642 def close_begin_deeper(document):
646 i = find_tokens(document.body, ["\\begin_deeper", "\\end_deeper"], i)
651 if document.body[i][:13] == "\\begin_deeper":
658 document.body[-2:-2] = ['\\end_deeper' for i in range(depth)]
661 def long_charstyle_names(document):
664 i = find_token(document.body, "\\begin_inset CharStyle", i)
667 document.body[i] = document.body[i].replace("CharStyle ", "CharStyle CharStyle:")
670 def revert_long_charstyle_names(document):
673 i = find_token(document.body, "\\begin_inset CharStyle", i)
676 document.body[i] = document.body[i].replace("CharStyle CharStyle:", "CharStyle ")
680 def axe_show_label(document):
683 i = find_token(document.body, "\\begin_inset CharStyle", i)
686 if document.body[i + 1].find("show_label") != -1:
687 if document.body[i + 1].find("true") != -1:
688 document.body[i + 1] = "status open"
689 del document.body[ i + 2]
691 if document.body[i + 1].find("false") != -1:
692 document.body[i + 1] = "status collapsed"
693 del document.body[ i + 2]
695 document.warning("Malformed LyX document: show_label neither false nor true.")
697 document.warning("Malformed LyX document: show_label missing in CharStyle.")
702 def revert_show_label(document):
705 i = find_token(document.body, "\\begin_inset CharStyle", i)
708 if document.body[i + 1].find("status open") != -1:
709 document.body.insert(i + 1, "show_label true")
711 if document.body[i + 1].find("status collapsed") != -1:
712 document.body.insert(i + 1, "show_label false")
714 document.warning("Malformed LyX document: no legal status line in CharStyle.")
717 def revert_begin_modules(document):
720 i = find_token(document.header, "\\begin_modules", i)
723 j = find_end_of(document.header, i, "\\begin_modules", "\\end_modules")
725 # this should not happen
727 document.header[i : j + 1] = []
729 def convert_flex(document):
730 "Convert CharStyle to Flex"
733 i = find_token(document.body, "\\begin_inset CharStyle", i)
736 document.body[i] = document.body[i].replace('\\begin_inset CharStyle', '\\begin_inset Flex')
738 def revert_flex(document):
739 "Convert Flex to CharStyle"
742 i = find_token(document.body, "\\begin_inset Flex", i)
745 document.body[i] = document.body[i].replace('\\begin_inset Flex', '\\begin_inset CharStyle')
748 # Discard PDF options for hyperref
749 def revert_pdf_options(document):
750 "Revert PDF options for hyperref."
751 # store the PDF options and delete the entries from the Lyx file
759 bookmarksnumbered = ""
761 bookmarksopenlevel = ""
769 i = find_token(document.header, "\\use_hyperref", i)
771 hyperref = get_value(document.header, "\\use_hyperref", i) == 'true'
772 del document.header[i]
773 i = find_token(document.header, "\\pdf_store_options", i)
775 del document.header[i]
776 i = find_token(document.header, "\\pdf_title", 0)
778 title = get_value_string(document.header, '\\pdf_title', 0, 0, True)
779 title = ' pdftitle={' + title + '}'
780 del document.header[i]
781 i = find_token(document.header, "\\pdf_author", 0)
783 author = get_value_string(document.header, '\\pdf_author', 0, 0, True)
785 author = ' pdfauthor={' + author + '}'
787 author = ',\n pdfauthor={' + author + '}'
788 del document.header[i]
789 i = find_token(document.header, "\\pdf_subject", 0)
791 subject = get_value_string(document.header, '\\pdf_subject', 0, 0, True)
792 if title == "" and author == "":
793 subject = ' pdfsubject={' + subject + '}'
795 subject = ',\n pdfsubject={' + subject + '}'
796 del document.header[i]
797 i = find_token(document.header, "\\pdf_keywords", 0)
799 keywords = get_value_string(document.header, '\\pdf_keywords', 0, 0, True)
800 if title == "" and author == "" and subject == "":
801 keywords = ' pdfkeywords={' + keywords + '}'
803 keywords = ',\n pdfkeywords={' + keywords + '}'
804 del document.header[i]
805 i = find_token(document.header, "\\pdf_bookmarks", 0)
807 bookmarks = get_value_string(document.header, '\\pdf_bookmarks', 0)
808 bookmarks = ',\n bookmarks=' + bookmarks
809 del document.header[i]
810 i = find_token(document.header, "\\pdf_bookmarksnumbered", i)
812 bookmarksnumbered = get_value_string(document.header, '\\pdf_bookmarksnumbered', 0)
813 bookmarksnumbered = ',\n bookmarksnumbered=' + bookmarksnumbered
814 del document.header[i]
815 i = find_token(document.header, "\\pdf_bookmarksopen", i)
817 bookmarksopen = get_value_string(document.header, '\\pdf_bookmarksopen', 0)
818 bookmarksopen = ',\n bookmarksopen=' + bookmarksopen
819 del document.header[i]
820 i = find_token(document.header, "\\pdf_bookmarksopenlevel", i)
822 bookmarksopenlevel = get_value_string(document.header, '\\pdf_bookmarksopenlevel', 0, 0, True)
823 bookmarksopenlevel = ',\n bookmarksopenlevel=' + bookmarksopenlevel
824 del document.header[i]
825 i = find_token(document.header, "\\pdf_breaklinks", i)
827 breaklinks = get_value_string(document.header, '\\pdf_breaklinks', 0)
828 breaklinks = ',\n breaklinks=' + breaklinks
829 del document.header[i]
830 i = find_token(document.header, "\\pdf_pdfborder", i)
832 pdfborder = get_value_string(document.header, '\\pdf_pdfborder', 0)
833 if pdfborder == 'true':
834 pdfborder = ',\n pdfborder={0 0 0}'
836 pdfborder = ',\n pdfborder={0 0 1}'
837 del document.header[i]
838 i = find_token(document.header, "\\pdf_colorlinks", i)
840 colorlinks = get_value_string(document.header, '\\pdf_colorlinks', 0)
841 colorlinks = ',\n colorlinks=' + colorlinks
842 del document.header[i]
843 i = find_token(document.header, "\\pdf_backref", i)
845 backref = get_value_string(document.header, '\\pdf_backref', 0)
846 backref = ',\n backref=' + backref
847 del document.header[i]
848 i = find_token(document.header, "\\pdf_pagebackref", i)
850 pagebackref = get_value_string(document.header, '\\pdf_pagebackref', 0)
851 pagebackref = ',\n pagebackref=' + pagebackref
852 del document.header[i]
853 i = find_token(document.header, "\\pdf_pagemode", 0)
855 pagemode = get_value_string(document.header, '\\pdf_pagemode', 0)
856 pagemode = ',\n pdfpagemode=' + pagemode
857 del document.header[i]
858 i = find_token(document.header, "\\pdf_quoted_options", 0)
860 otheroptions = get_value_string(document.header, '\\pdf_quoted_options', 0, 0, True)
861 if title == "" and author == "" and subject == "" and keywords == "":
862 otheroptions = ' ' + otheroptions
864 otheroptions = ',\n ' + otheroptions
865 del document.header[i]
867 # write to the preamble when hyperref was used
869 # preamble write preparations
870 # bookmark numbers are only output when they are turned on
871 if bookmarksopen == ',\n bookmarksopen=true':
872 bookmarksopen = bookmarksopen + bookmarksopenlevel
873 if bookmarks == ',\n bookmarks=true':
874 bookmarks = bookmarks + bookmarksnumbered + bookmarksopen
876 bookmarks = bookmarks
877 # hypersetup is only output when there are things to be set up
878 setupstart = '\\hypersetup{%\n'
880 if otheroptions == "" and title == "" and author == ""\
881 and subject == "" and keywords == "":
885 # babel must be loaded before hyperref and hyperref the first part
886 # of the preamble, like in LyX 1.6
887 insert_to_preamble(0, document,
888 '% Commands inserted by lyx2lyx for PDF properties\n'
889 + '\\usepackage{babel}\n'
890 + '\\usepackage[unicode=true'
909 def remove_inzip_options(document):
910 "Remove inzipName and embed options from the Graphics inset"
913 i = find_token(document.body, "\\begin_inset Graphics", i)
916 j = find_end_of_inset(document.body, i + 1)
919 document.warning("Malformed LyX document: Could not find end of graphics inset.")
920 # If there's a inzip param, just remove that
921 k = find_token(document.body, "\tinzipName", i + 1, j)
924 # embed option must follow the inzipName option
925 del document.body[k+1]
929 def convert_inset_command(document):
932 \begin_inset LatexCommand cmd
934 \begin_inset CommandInset InsetType
939 i = find_token(document.body, "\\begin_inset LatexCommand", i)
942 line = document.body[i]
943 r = re.compile(r'\\begin_inset LatexCommand (.*)$')
947 #this is adapted from factory.cpp
948 if cmdName[0:4].lower() == "cite":
949 insetName = "citation"
950 elif cmdName == "url" or cmdName == "htmlurl":
952 elif cmdName[-3:] == "ref":
954 elif cmdName == "tableofcontents":
956 elif cmdName == "printnomenclature":
957 insetName = "nomencl_print"
958 elif cmdName == "printindex":
959 insetName = "index_print"
962 insertion = ["\\begin_inset CommandInset " + insetName, "LatexCommand " + cmdName]
963 document.body[i : i+1] = insertion
966 def revert_inset_command(document):
969 \begin_inset CommandInset InsetType
972 \begin_inset LatexCommand cmd
973 Some insets may end up being converted to insets earlier versions of LyX
974 will not be able to recognize. Not sure what to do about that.
978 i = find_token(document.body, "\\begin_inset CommandInset", i)
981 nextline = document.body[i+1]
982 r = re.compile(r'LatexCommand\s+(.*)$')
983 m = r.match(nextline)
985 document.warning("Malformed LyX document: Missing LatexCommand in " + document.body[i] + ".")
988 insertion = ["\\begin_inset LatexCommand " + cmdName]
989 document.body[i : i+2] = insertion
992 def convert_wrapfig_options(document):
993 "Convert optional options for wrap floats (wrapfig)."
994 # adds the tokens "lines", "placement", and "overhang"
997 i = find_token(document.body, "\\begin_inset Wrap figure", i)
1000 document.body.insert(i + 1, "lines 0")
1001 j = find_token(document.body, "placement", i)
1002 # placement can be already set or not; if not, set it
1004 document.body.insert(i + 3, "overhang 0col%")
1006 document.body.insert(i + 2, "placement o")
1007 document.body.insert(i + 3, "overhang 0col%")
1011 def revert_wrapfig_options(document):
1012 "Revert optional options for wrap floats (wrapfig)."
1015 i = find_token(document.body, "\\begin_inset Wrap figure", i)
1018 j = find_end_of_inset(document.body, i)
1020 document.warning("Can't find end of Wrap inset at line " + str(i))
1023 k = find_default_layout(document, i, j)
1025 document.warning("Can't find default layout for Wrap figure!")
1028 # Options should be between i and k now
1029 l = find_token(document.body, "lines", i, k)
1031 document.warning("Can't find lines option for Wrap figure!")
1034 m = find_token(document.body, "overhang", i + 1, k)
1036 document.warning("Malformed LyX document: Couldn't find overhang parameter of wrap float!")
1039 # Do these in reverse order
1040 del document.body[m]
1041 del document.body[l]
1045 def convert_latexcommand_index(document):
1046 "Convert from LatexCommand form to collapsable form."
1048 r1 = re.compile('name "(.*)"')
1050 i = find_token(document.body, "\\begin_inset CommandInset index", i)
1053 if document.body[i + 1] != "LatexCommand index": # Might also be index_print
1055 j = find_end_of_inset(document.body, i + 2)
1057 document.warning("Unable to find end of index inset at line " + i + "!")
1060 m = r1.match(document.body[i + 2])
1062 document.warning("Unable to match: " + document.body[i+2])
1065 fullcontent = m.group(1)
1066 linelist = latex2lyx(fullcontent)
1067 #document.warning(fullcontent)
1069 linelist = ["\\begin_inset Index", "status collapsed", "\\begin_layout Standard", ""] + \
1070 linelist + ["\\end_layout"]
1071 document.body[i : j] = linelist
1072 i += len(linelist) - (j - i)
1075 def revert_latexcommand_index(document):
1076 "Revert from collapsable form to LatexCommand form."
1079 i = find_token(document.body, "\\begin_inset Index", i)
1082 j = find_end_of_inset(document.body, i + 1)
1086 content = lyx2latex(document.body[i:j])
1088 content = content.replace('"', r'\"')
1089 document.body[i:j] = ["\\begin_inset CommandInset index", "LatexCommand index",
1090 "name " + '"' + content + '"', ""]
1094 def revert_wraptable(document):
1095 "Revert wrap table to wrap figure."
1098 i = find_token(document.body, "\\begin_inset Wrap table", i)
1101 document.body[i] = document.body[i].replace('\\begin_inset Wrap table', '\\begin_inset Wrap figure')
1105 def revert_vietnamese(document):
1106 "Set language Vietnamese to English"
1107 # Set document language from Vietnamese to English
1109 if document.language == "vietnamese":
1110 document.language = "english"
1111 i = find_token(document.header, "\\language", 0)
1113 document.header[i] = "\\language english"
1116 j = find_token(document.body, "\\lang vietnamese", j)
1119 document.body[j] = document.body[j].replace("\\lang vietnamese", "\\lang english")
1123 def convert_japanese_cjk(document):
1124 "Set language japanese to japanese-cjk"
1125 # Set document language from japanese-plain to japanese
1127 if document.language == "japanese":
1128 document.language = "japanese-cjk"
1129 i = find_token(document.header, "\\language", 0)
1131 document.header[i] = "\\language japanese-cjk"
1134 j = find_token(document.body, "\\lang japanese", j)
1137 document.body[j] = document.body[j].replace("\\lang japanese", "\\lang japanese-cjk")
1141 def revert_japanese(document):
1142 "Set language japanese-plain to japanese"
1143 # Set document language from japanese-plain to japanese
1145 if document.language == "japanese-plain":
1146 document.language = "japanese"
1147 i = find_token(document.header, "\\language", 0)
1149 document.header[i] = "\\language japanese"
1152 j = find_token(document.body, "\\lang japanese-plain", j)
1155 document.body[j] = document.body[j].replace("\\lang japanese-plain", "\\lang japanese")
1159 def revert_japanese_cjk(document):
1160 "Set language japanese-cjk to japanese"
1161 # Set document language from japanese-plain to japanese
1163 if document.language == "japanese-cjk":
1164 document.language = "japanese"
1165 i = find_token(document.header, "\\language", 0)
1167 document.header[i] = "\\language japanese"
1170 j = find_token(document.body, "\\lang japanese-cjk", j)
1173 document.body[j] = document.body[j].replace("\\lang japanese-cjk", "\\lang japanese")
1177 def revert_japanese_encoding(document):
1178 "Set input encoding form EUC-JP-plain to EUC-JP etc."
1179 # Set input encoding form EUC-JP-plain to EUC-JP etc.
1181 i = find_token(document.header, "\\inputencoding EUC-JP-plain", 0)
1183 document.header[i] = "\\inputencoding EUC-JP"
1185 j = find_token(document.header, "\\inputencoding JIS-plain", 0)
1187 document.header[j] = "\\inputencoding JIS"
1189 k = find_token(document.header, "\\inputencoding SJIS-plain", 0)
1190 if k != -1: # convert to UTF8 since there is currently no SJIS encoding
1191 document.header[k] = "\\inputencoding UTF8"
1194 def revert_inset_info(document):
1195 'Replace info inset with its content'
1198 i = find_token(document.body, '\\begin_inset Info', i)
1201 j = find_end_of_inset(document.body, i + 1)
1204 document.warning("Malformed LyX document: Could not find end of Info inset.")
1207 for k in range(i, j+1):
1208 if document.body[k].startswith("arg"):
1209 arg = document.body[k][3:].strip().strip('"')
1210 if document.body[k].startswith("type"):
1211 type = document.body[k][4:].strip().strip('"')
1212 # I think there is a newline after \\end_inset, which should be removed.
1213 if document.body[j + 1].strip() == "":
1214 document.body[i : (j + 2)] = [type + ':' + arg]
1216 document.body[i : (j + 1)] = [type + ':' + arg]
1219 def convert_pdf_options(document):
1220 # Set the pdfusetitle tag, delete the pdf_store_options,
1221 # set quotes for bookmarksopenlevel"
1222 has_hr = get_value(document.header, "\\use_hyperref", 0, default = "0")
1224 k = find_token(document.header, "\\use_hyperref", 0)
1225 document.header.insert(k + 1, "\\pdf_pdfusetitle true")
1226 k = find_token(document.header, "\\pdf_store_options", 0)
1228 del document.header[k]
1229 i = find_token(document.header, "\\pdf_bookmarksopenlevel", k)
1231 document.header[i] = document.header[i].replace('"', '')
1234 def revert_pdf_options_2(document):
1235 # reset the pdfusetitle tag, set quotes for bookmarksopenlevel"
1236 k = find_token(document.header, "\\use_hyperref", 0)
1237 i = find_token(document.header, "\\pdf_pdfusetitle", k)
1239 del document.header[i]
1240 i = find_token(document.header, "\\pdf_bookmarksopenlevel", k)
1242 values = document.header[i].split()
1243 values[1] = ' "' + values[1] + '"'
1244 document.header[i] = ''.join(values)
1247 def convert_htmlurl(document):
1248 'Convert "htmlurl" to "href" insets for docbook'
1249 if document.backend != "docbook":
1253 i = find_token(document.body, "\\begin_inset CommandInset url", i)
1256 document.body[i] = "\\begin_inset CommandInset href"
1257 document.body[i + 1] = "LatexCommand href"
1261 def convert_url(document):
1262 'Convert url insets to url charstyles'
1263 if document.backend == "docbook":
1267 i = find_token(document.body, "\\begin_inset CommandInset url", i)
1270 n = find_token(document.body, "name", i)
1272 # place the URL name in typewriter before the new URL insert
1273 # grab the name 'bla' from the e.g. the line 'name "bla"',
1274 # therefore start with the 6th character
1275 name = document.body[n][6:-1]
1276 newname = [name + " "]
1277 document.body[i:i] = newname
1279 j = find_token(document.body, "target", i)
1281 document.warning("Malformed LyX document: Can't find target for url inset")
1284 target = document.body[j][8:-1]
1285 k = find_token(document.body, "\\end_inset", j)
1287 document.warning("Malformed LyX document: Can't find end of url inset")
1290 newstuff = ["\\begin_inset Flex URL",
1291 "status collapsed", "",
1292 "\\begin_layout Standard",
1297 document.body[i:k] = newstuff
1300 def convert_ams_classes(document):
1301 tc = document.textclass
1302 if (tc != "amsart" and tc != "amsart-plain" and
1303 tc != "amsart-seq" and tc != "amsbook"):
1305 if tc == "amsart-plain":
1306 document.textclass = "amsart"
1307 document.set_textclass()
1308 document.add_module("Theorems (Starred)")
1310 if tc == "amsart-seq":
1311 document.textclass = "amsart"
1312 document.set_textclass()
1313 document.add_module("Theorems (AMS)")
1315 #Now we want to see if any of the environments in the extended theorems
1316 #module were used in this document. If so, we'll add that module, too.
1317 layouts = ["Criterion", "Algorithm", "Axiom", "Condition", "Note", \
1318 "Notation", "Summary", "Acknowledgement", "Conclusion", "Fact", \
1321 r = re.compile(r'^\\begin_layout (.*?)\*?\s*$')
1324 i = find_token(document.body, "\\begin_layout", i)
1327 m = r.match(document.body[i])
1329 # This is an empty layout
1330 # document.warning("Weirdly formed \\begin_layout at line %d of body!" % i)
1334 if layouts.count(m) != 0:
1335 document.add_module("Theorems (AMS-Extended)")
1339 def revert_href(document):
1340 'Reverts hyperlink insets (href) to url insets (url)'
1343 i = find_token(document.body, "\\begin_inset CommandInset href", i)
1346 document.body[i : i + 2] = \
1347 ["\\begin_inset CommandInset url", "LatexCommand url"]
1350 def revert_url(document):
1351 'Reverts Flex URL insets to old-style URL insets'
1354 i = find_token(document.body, "\\begin_inset Flex URL", i)
1357 j = find_end_of_inset(document.body, i)
1359 document.warning("Can't find end of inset in revert_url!")
1361 k = find_default_layout(document, i, j)
1363 document.warning("Can't find default layout in revert_url!")
1366 l = find_end_of(document.body, k, "\\begin_layout", "\\end_layout")
1367 if l == -1 or l >= j:
1368 document.warning("Can't find end of default layout in revert_url!")
1371 # OK, so the inset's data is between lines k and l.
1372 data = " ".join(document.body[k+1:l])
1374 newinset = ["\\begin_inset LatexCommand url", "target \"" + data + "\"",\
1376 document.body[i:j+1] = newinset
1377 i = i + len(newinset)
1380 def convert_include(document):
1381 'Converts include insets to new format.'
1383 r = re.compile(r'\\begin_inset Include\s+\\([^{]+){([^}]*)}(?:\[(.*)\])?')
1385 i = find_token(document.body, "\\begin_inset Include", i)
1388 line = document.body[i]
1389 previewline = document.body[i + 1]
1392 document.warning("Unable to match line " + str(i) + " of body!")
1398 insertion = ["\\begin_inset CommandInset include",
1399 "LatexCommand " + cmd, previewline,
1400 "filename \"" + fn + "\""]
1403 insertion.append("lstparams " + '"' + opt + '"')
1405 document.body[i : i + 2] = insertion
1409 def revert_include(document):
1410 'Reverts include insets to old format.'
1412 r0 = re.compile('preview.*')
1413 r1 = re.compile('LatexCommand (.+)')
1414 r2 = re.compile('filename "(.+)"')
1415 r3 = re.compile('lstparams "(.*)"')
1417 i = find_token(document.body, "\\begin_inset CommandInset include", i)
1421 if r0.match(document.body[nextline]):
1422 previewline = document.body[nextline]
1426 m = r1.match(document.body[nextline])
1428 document.warning("Malformed LyX document: No LatexCommand line for `" +
1429 document.body[i] + "' on line " + str(i) + ".")
1434 m = r2.match(document.body[nextline])
1436 document.warning("Malformed LyX document: No filename line for `" + \
1437 document.body[i] + "' on line " + str(i) + ".")
1443 if (cmd == "lstinputlisting"):
1444 m = r3.match(document.body[nextline])
1446 options = m.group(1)
1449 newline = "\\begin_inset Include \\" + cmd + "{" + fn + "}"
1451 newline += ("[" + options + "]")
1452 insertion = [newline]
1453 if previewline != "":
1454 insertion.append(previewline)
1455 document.body[i : nextline] = insertion
1459 def revert_albanian(document):
1460 "Set language Albanian to English"
1462 if document.language == "albanian":
1463 document.language = "english"
1464 i = find_token(document.header, "\\language", 0)
1466 document.header[i] = "\\language english"
1469 j = find_token(document.body, "\\lang albanian", j)
1472 document.body[j] = document.body[j].replace("\\lang albanian", "\\lang english")
1476 def revert_lowersorbian(document):
1477 "Set language lower Sorbian to English"
1479 if document.language == "lowersorbian":
1480 document.language = "english"
1481 i = find_token(document.header, "\\language", 0)
1483 document.header[i] = "\\language english"
1486 j = find_token(document.body, "\\lang lowersorbian", j)
1489 document.body[j] = document.body[j].replace("\\lang lowersorbian", "\\lang english")
1493 def revert_uppersorbian(document):
1494 "Set language uppersorbian to usorbian as this was used in LyX 1.5"
1496 if document.language == "uppersorbian":
1497 document.language = "usorbian"
1498 i = find_token(document.header, "\\language", 0)
1500 document.header[i] = "\\language usorbian"
1503 j = find_token(document.body, "\\lang uppersorbian", j)
1506 document.body[j] = document.body[j].replace("\\lang uppersorbian", "\\lang usorbian")
1510 def convert_usorbian(document):
1511 "Set language usorbian to uppersorbian"
1513 if document.language == "usorbian":
1514 document.language = "uppersorbian"
1515 i = find_token(document.header, "\\language", 0)
1517 document.header[i] = "\\language uppersorbian"
1520 j = find_token(document.body, "\\lang usorbian", j)
1523 document.body[j] = document.body[j].replace("\\lang usorbian", "\\lang uppersorbian")
1527 def revert_macro_optional_params(document):
1528 "Convert macro definitions with optional parameters into ERTs"
1529 # Stub to convert macro definitions with one or more optional parameters
1530 # into uninterpreted ERT insets
1533 def revert_hyperlinktype(document):
1534 'Reverts hyperlink type'
1538 i = find_token(document.body, "target", i)
1541 j = find_token(document.body, "type", i)
1545 del document.body[j]
1549 def revert_pagebreak(document):
1550 'Reverts pagebreak to ERT'
1553 i = find_token(document.body, "\\pagebreak", i)
1556 document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1557 '\\begin_layout Standard\n\n\n\\backslash\n' \
1558 'pagebreak{}\n\\end_layout\n\n\\end_inset\n\n'
1562 def revert_linebreak(document):
1563 'Reverts linebreak to ERT'
1566 i = find_token(document.body, "\\linebreak", i)
1569 document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1570 '\\begin_layout Standard\n\n\n\\backslash\n' \
1571 'linebreak{}\n\\end_layout\n\n\\end_inset\n\n'
1575 def revert_latin(document):
1576 "Set language Latin to English"
1578 if document.language == "latin":
1579 document.language = "english"
1580 i = find_token(document.header, "\\language", 0)
1582 document.header[i] = "\\language english"
1585 j = find_token(document.body, "\\lang latin", j)
1588 document.body[j] = document.body[j].replace("\\lang latin", "\\lang english")
1592 def revert_samin(document):
1593 "Set language North Sami to English"
1595 if document.language == "samin":
1596 document.language = "english"
1597 i = find_token(document.header, "\\language", 0)
1599 document.header[i] = "\\language english"
1602 j = find_token(document.body, "\\lang samin", j)
1605 document.body[j] = document.body[j].replace("\\lang samin", "\\lang english")
1609 def convert_serbocroatian(document):
1610 "Set language Serbocroatian to Croatian as this was really Croatian in LyX 1.5"
1612 if document.language == "serbocroatian":
1613 document.language = "croatian"
1614 i = find_token(document.header, "\\language", 0)
1616 document.header[i] = "\\language croatian"
1619 j = find_token(document.body, "\\lang serbocroatian", j)
1622 document.body[j] = document.body[j].replace("\\lang serbocroatian", "\\lang croatian")
1626 def convert_framed_notes(document):
1627 "Convert framed notes to boxes. "
1630 i = find_tokens(document.body, ["\\begin_inset Note Framed", "\\begin_inset Note Shaded"], i)
1633 subst = [document.body[i].replace("\\begin_inset Note", "\\begin_inset Box"),
1642 'height_special "totalheight"']
1643 document.body[i:i+1] = subst
1647 def convert_module_names(document):
1648 modulemap = { 'Braille' : 'braille', 'Endnote' : 'endnotes', 'Foot to End' : 'foottoend',\
1649 'Hanging' : 'hanging', 'Linguistics' : 'linguistics', 'Logical Markup' : 'logicalmkup', \
1650 'Theorems (AMS-Extended)' : 'theorems-ams-extended', 'Theorems (AMS)' : 'theorems-ams', \
1651 'Theorems (Order By Chapter)' : 'theorems-chap', 'Theorems (Order By Section)' : 'theorems-sec', \
1652 'Theorems (Starred)' : 'theorems-starred', 'Theorems' : 'theorems-std' }
1653 modlist = document.get_module_list()
1654 if len(modlist) == 0:
1658 if modulemap.has_key(mod):
1659 newmodlist.append(modulemap[mod])
1661 document.warning("Can't find module %s in the module map!" % mod)
1662 newmodlist.append(mod)
1663 document.set_module_list(newmodlist)
1666 def revert_module_names(document):
1667 modulemap = { 'braille' : 'Braille', 'endnotes' : 'Endnote', 'foottoend' : 'Foot to End',\
1668 'hanging' : 'Hanging', 'linguistics' : 'Linguistics', 'logicalmkup' : 'Logical Markup', \
1669 'theorems-ams-extended' : 'Theorems (AMS-Extended)', 'theorems-ams' : 'Theorems (AMS)', \
1670 'theorems-chap' : 'Theorems (Order By Chapter)', 'theorems-sec' : 'Theorems (Order By Section)', \
1671 'theorems-starred' : 'Theorems (Starred)', 'theorems-std' : 'Theorems'}
1672 modlist = document.get_module_list()
1673 if len(modlist) == 0:
1677 if modulemap.has_key(mod):
1678 newmodlist.append(modulemap[mod])
1680 document.warning("Can't find module %s in the module map!" % mod)
1681 newmodlist.append(mod)
1682 document.set_module_list(newmodlist)
1685 def revert_colsep(document):
1686 i = find_token(document.header, "\\columnsep", 0)
1689 colsepline = document.header[i]
1690 r = re.compile(r'\\columnsep (.*)')
1691 m = r.match(colsepline)
1693 document.warning("Malformed column separation line!")
1696 del document.header[i]
1697 #it seems to be safe to add the package even if it is already used
1698 pretext = ["\\usepackage{geometry}", "\\geometry{columnsep=" + colsep + "}"]
1700 add_to_preamble(document, pretext)
1703 def revert_framed_notes(document):
1704 "Revert framed boxes to notes. "
1707 i = find_tokens(document.body, ["\\begin_inset Box Framed", "\\begin_inset Box Shaded"], i)
1711 j = find_end_of_inset(document.body, i + 1)
1714 document.warning("Malformed LyX document: Could not find end of Box inset.")
1715 k = find_token(document.body, "status", i + 1, j)
1717 document.warning("Malformed LyX document: Missing `status' tag in Box inset.")
1719 status = document.body[k]
1720 l = find_default_layout(document, i + 1, j)
1722 document.warning("Malformed LyX document: Missing `\\begin_layout' in Box inset.")
1724 m = find_token(document.body, "\\end_layout", i + 1, j)
1726 document.warning("Malformed LyX document: Missing `\\end_layout' in Box inset.")
1728 ibox = find_token(document.body, "has_inner_box 1", i + 1, k)
1729 pbox = find_token(document.body, "use_parbox 1", i + 1, k)
1730 if ibox == -1 and pbox == -1:
1731 document.body[i] = document.body[i].replace("\\begin_inset Box", "\\begin_inset Note")
1732 del document.body[i+1:k]
1734 document.body[i] = document.body[i].replace("\\begin_inset Box Shaded", "\\begin_inset Box Frameless")
1735 subst1 = [document.body[l],
1736 "\\begin_inset Note Shaded",
1738 '\\begin_layout Standard']
1739 document.body[l:l + 1] = subst1
1740 subst2 = [document.body[m], "\\end_layout", "\\end_inset"]
1741 document.body[m:m + 1] = subst2
1745 def revert_slash(document):
1746 'Revert \\SpecialChar \\slash{} to ERT'
1747 r = re.compile(r'\\SpecialChar \\slash{}')
1749 while i < len(document.body):
1750 m = r.match(document.body[i])
1752 subst = ['\\begin_inset ERT',
1753 'status collapsed', '',
1754 '\\begin_layout Standard',
1755 '', '', '\\backslash',
1759 document.body[i: i+1] = subst
1765 def revert_nobreakdash(document):
1766 'Revert \\SpecialChar \\nobreakdash- to ERT'
1768 while i < len(document.body):
1769 line = document.body[i]
1770 r = re.compile(r'\\SpecialChar \\nobreakdash-')
1773 subst = ['\\begin_inset ERT',
1774 'status collapsed', '',
1775 '\\begin_layout Standard', '', '',
1780 document.body[i:i+1] = subst
1782 j = find_token(document.header, "\\use_amsmath", 0)
1784 document.warning("Malformed LyX document: Missing '\\use_amsmath'.")
1786 document.header[j] = "\\use_amsmath 2"
1791 #Returns number of lines added/removed
1792 def revert_nocite_key(body, start, end):
1793 'key "..." -> \nocite{...}'
1794 r = re.compile(r'^key "(.*)"')
1798 m = r.match(body[i])
1800 body[i:i+1] = ["\\backslash", "nocite{" + m.group(1) + "}"]
1801 j += 1 # because we added a line
1802 i += 2 # skip that line
1805 j -= 1 # because we deleted a line
1806 # no need to change i, since it now points to the next line
1810 def revert_nocite(document):
1811 "Revert LatexCommand nocite to ERT"
1814 i = find_token(document.body, "\\begin_inset CommandInset citation", i)
1817 if (document.body[i+1] != "LatexCommand nocite"):
1818 # note that we already incremented i
1821 insetEnd = find_end_of_inset(document.body, i)
1823 #this should not happen
1824 document.warning("End of CommandInset citation not found in revert_nocite!")
1827 paramLocation = i + 2 #start of the inset's parameters
1829 document.body[i:i+2] = \
1830 ["\\begin_inset ERT", "status collapsed", "", "\\begin_layout Standard"]
1831 # that added two lines
1834 #print insetEnd, document.body[i: insetEnd + 1]
1835 insetEnd += revert_nocite_key(document.body, paramLocation, insetEnd)
1836 #print insetEnd, document.body[i: insetEnd + 1]
1837 document.body.insert(insetEnd, "\\end_layout")
1838 document.body.insert(insetEnd + 1, "")
1842 def revert_btprintall(document):
1843 "Revert (non-bibtopic) btPrintAll option to ERT \nocite{*}"
1844 i = find_token(document.header, '\\use_bibtopic', 0)
1846 document.warning("Malformed lyx document: Missing '\\use_bibtopic'.")
1848 if get_value(document.header, '\\use_bibtopic', 0) == "false":
1850 while i < len(document.body):
1851 i = find_token(document.body, "\\begin_inset CommandInset bibtex", i)
1854 j = find_end_of_inset(document.body, i + 1)
1856 #this should not happen
1857 document.warning("End of CommandInset bibtex not found in revert_btprintall!")
1858 j = len(document.body)
1859 # this range isn't really right, but it should be OK, since we shouldn't
1860 # see more than one matching line in each inset
1862 for k in range(i, j):
1863 if (document.body[k] == 'btprint "btPrintAll"'):
1864 del document.body[k]
1865 subst = ["\\begin_inset ERT",
1866 "status collapsed", "",
1867 "\\begin_layout Standard", "",
1872 document.body[i:i] = subst
1873 addlines = addedlines + len(subst) - 1
1877 def revert_bahasam(document):
1878 "Set language Bahasa Malaysia to Bahasa Indonesia"
1880 if document.language == "bahasam":
1881 document.language = "bahasa"
1882 i = find_token(document.header, "\\language", 0)
1884 document.header[i] = "\\language bahasa"
1887 j = find_token(document.body, "\\lang bahasam", j)
1890 document.body[j] = document.body[j].replace("\\lang bahasam", "\\lang bahasa")
1894 def revert_interlingua(document):
1895 "Set language Interlingua to English"
1897 if document.language == "interlingua":
1898 document.language = "english"
1899 i = find_token(document.header, "\\language", 0)
1901 document.header[i] = "\\language english"
1904 j = find_token(document.body, "\\lang interlingua", j)
1907 document.body[j] = document.body[j].replace("\\lang interlingua", "\\lang english")
1911 def revert_serbianlatin(document):
1912 "Set language Serbian-Latin to Croatian"
1914 if document.language == "serbian-latin":
1915 document.language = "croatian"
1916 i = find_token(document.header, "\\language", 0)
1918 document.header[i] = "\\language croatian"
1921 j = find_token(document.body, "\\lang serbian-latin", j)
1924 document.body[j] = document.body[j].replace("\\lang serbian-latin", "\\lang croatian")
1928 def revert_rotfloat(document):
1929 " Revert sideways custom floats. "
1932 # whitespace intended (exclude \\begin_inset FloatList)
1933 i = find_token(document.body, "\\begin_inset Float ", i)
1936 line = document.body[i]
1937 r = re.compile(r'\\begin_inset Float (.*)$')
1940 document.warning("Unable to match line " + str(i) + " of body!")
1943 floattype = m.group(1)
1944 if floattype == "figure" or floattype == "table":
1947 j = find_end_of_inset(document.body, i)
1949 document.warning("Malformed lyx document: Missing '\\end_inset' in revert_rotfloat.")
1953 if get_value(document.body, 'sideways', i, j) == "false":
1956 l = find_default_layout(document, i + 1, j)
1958 document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
1960 subst = ['\\begin_layout Standard',
1961 '\\begin_inset ERT',
1962 'status collapsed', '',
1963 '\\begin_layout Standard', '', '',
1965 'end{sideways' + floattype + '}',
1966 '\\end_layout', '', '\\end_inset']
1967 document.body[j : j+1] = subst
1968 addedLines = len(subst) - 1
1969 del document.body[i+1 : l]
1970 addedLines -= (l-1) - (i+1)
1971 subst = ['\\begin_inset ERT', 'status collapsed', '',
1972 '\\begin_layout Standard', '', '', '\\backslash',
1973 'begin{sideways' + floattype + '}',
1974 '\\end_layout', '', '\\end_inset', '',
1976 document.body[i : i+1] = subst
1977 addedLines += len(subst) - 1
1978 if floattype == "algorithm":
1979 add_to_preamble(document,
1980 ['% Commands inserted by lyx2lyx for sideways algorithm float',
1981 '\\usepackage{rotfloat}',
1982 '\\floatstyle{ruled}',
1983 '\\newfloat{algorithm}{tbp}{loa}',
1984 '\\floatname{algorithm}{Algorithm}'])
1986 document.warning("Cannot create preamble definition for custom float" + floattype + ".")
1990 def revert_widesideways(document):
1991 " Revert wide sideways floats. "
1994 # whitespace intended (exclude \\begin_inset FloatList)
1995 i = find_token(document.body, '\\begin_inset Float ', i)
1998 line = document.body[i]
1999 r = re.compile(r'\\begin_inset Float (.*)$')
2002 document.warning("Unable to match line " + str(i) + " of body!")
2005 floattype = m.group(1)
2006 if floattype != "figure" and floattype != "table":
2009 j = find_end_of_inset(document.body, i)
2011 document.warning("Malformed lyx document: Missing '\\end_inset' in revert_widesideways.")
2014 if get_value(document.body, 'sideways', i, j) == "false" or \
2015 get_value(document.body, 'wide', i, j) == "false":
2018 l = find_default_layout(document, i + 1, j)
2020 document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
2022 subst = ['\\begin_layout Standard', '\\begin_inset ERT',
2023 'status collapsed', '',
2024 '\\begin_layout Standard', '', '', '\\backslash',
2025 'end{sideways' + floattype + '*}',
2026 '\\end_layout', '', '\\end_inset']
2027 document.body[j : j+1] = subst
2028 addedLines = len(subst) - 1
2029 del document.body[i+1:l-1]
2030 addedLines -= (l-1) - (i+1)
2031 subst = ['\\begin_inset ERT', 'status collapsed', '',
2032 '\\begin_layout Standard', '', '', '\\backslash',
2033 'begin{sideways' + floattype + '*}', '\\end_layout', '',
2034 '\\end_inset', '', '\\end_layout', '']
2035 document.body[i : i+1] = subst
2036 addedLines += len(subst) - 1
2037 add_to_preamble(document, ['\\usepackage{rotfloat}\n'])
2041 def revert_inset_embedding(document, type):
2042 ' Remove embed tag from certain type of insets'
2045 i = find_token(document.body, "\\begin_inset %s" % type, i)
2048 j = find_end_of_inset(document.body, i)
2050 document.warning("Malformed lyx document: Missing '\\end_inset' in revert_inset_embedding.")
2053 k = find_token(document.body, "\tembed", i, j)
2055 k = find_token(document.body, "embed", i, j)
2057 del document.body[k]
2061 def revert_external_embedding(document):
2062 ' Remove embed tag from external inset '
2063 revert_inset_embedding(document, 'External')
2066 def convert_subfig(document):
2067 " Convert subfigures to subfloats. "
2070 i = find_token(document.body, '\\begin_inset Graphics', i)
2073 endInset = find_end_of_inset(document.body, i)
2075 document.warning("Malformed lyx document: Missing '\\end_inset' in convert_subfig.")
2078 k = find_token(document.body, '\tsubcaption', i, endInset)
2082 l = find_token(document.body, '\tsubcaptionText', i, endInset)
2084 document.warning("Malformed lyx document: Can't find subcaptionText!")
2087 caption = document.body[l][16:].strip('"')
2088 del document.body[l]
2089 del document.body[k]
2091 subst = ['\\begin_inset Float figure', 'wide false', 'sideways false',
2092 'status open', '', '\\begin_layout Plain Layout', '\\begin_inset Caption',
2093 '', '\\begin_layout Plain Layout'] + latex2lyx(caption) + \
2094 [ '\\end_layout', '', '\\end_inset', '',
2095 '\\end_layout', '', '\\begin_layout Plain Layout']
2096 document.body[i : i] = subst
2097 addedLines += len(subst)
2098 endInset += addedLines
2099 subst = ['', '\\end_inset', '', '\\end_layout']
2100 document.body[endInset : endInset] = subst
2101 addedLines += len(subst)
2105 def revert_subfig(document):
2106 " Revert subfloats. "
2109 # whitespace intended (exclude \\begin_inset FloatList)
2110 i = find_tokens(document.body, ['\\begin_inset Float ', '\\begin_inset Wrap'], i)
2116 j = find_end_of_inset(document.body, i)
2118 document.warning("Malformed lyx document: Missing '\\end_inset' (float) at line " + str(i + len(document.header)) + ".\n\t" + document.body[i])
2119 # document.warning(document.body[i-1] + "\n" + document.body[i+1])
2121 continue # this will get us back to the outer loop, since j == -1
2122 # look for embedded float (= subfloat)
2123 # whitespace intended (exclude \\begin_inset FloatList)
2124 k = find_token(document.body, '\\begin_inset Float ', i + 1, j)
2127 l = find_end_of_inset(document.body, k)
2129 document.warning("Malformed lyx document: Missing '\\end_inset' (embedded float).")
2132 continue # escape to the outer loop
2133 m = find_default_layout(document, k + 1, l)
2135 cap = find_token(document.body, '\\begin_inset Caption', k + 1, l)
2140 capend = find_end_of_inset(document.body, cap)
2142 document.warning("Malformed lyx document: Missing '\\end_inset' (caption).")
2146 lbl = find_token(document.body, '\\begin_inset CommandInset label', cap, capend)
2148 lblend = find_end_of_inset(document.body, lbl + 1)
2150 document.warning("Malformed lyx document: Missing '\\end_inset' (label).")
2152 for line in document.body[lbl:lblend + 1]:
2153 if line.startswith('name '):
2154 label = line.split()[1].strip('"')
2161 opt = find_token(document.body, '\\begin_inset OptArg', cap, capend)
2163 optend = find_end_of_inset(document.body, opt)
2165 document.warning("Malformed lyx document: Missing '\\end_inset' (OptArg).")
2167 optc = find_default_layout(document, opt, optend)
2169 document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
2171 optcend = find_end_of(document.body, optc, "\\begin_layout", "\\end_layout")
2172 for line in document.body[optc:optcend]:
2173 if not line.startswith('\\'):
2174 shortcap += line.strip()
2178 for line in document.body[cap:capend]:
2179 if line in document.body[lbl:lblend]:
2181 elif line in document.body[opt:optend]:
2183 elif not line.startswith('\\'):
2184 caption += line.strip()
2186 caption += "\\backslash\nlabel{" + label + "}"
2187 subst = '\\begin_layout Plain Layout\n\\begin_inset ERT\nstatus collapsed\n\n' \
2188 '\\begin_layout Plain Layout\n\n}\n\\end_layout\n\n\\end_inset\n\n' \
2189 '\\end_layout\n\n\\begin_layout Plain Layout\n'
2190 subst = subst.split('\n')
2191 document.body[l : l+1] = subst
2192 addedLines = len(subst) - 1
2193 # this is before l and so is unchanged by the multiline insertion
2195 del document.body[cap:capend+1]
2196 addedLines -= (capend + 1 - cap)
2197 del document.body[k+1:m-1]
2198 addedLines -= (m - 1 - (k + 1))
2199 insertion = '\\begin_inset ERT\nstatus collapsed\n\n' \
2200 '\\begin_layout Plain Layout\n\n\\backslash\n' \
2202 if len(shortcap) > 0:
2203 insertion = insertion + "[" + shortcap + "]"
2204 if len(caption) > 0:
2205 insertion = insertion + "[" + caption + "]"
2206 insertion = insertion + '{%\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n'
2207 insertion = insertion.split('\n')
2208 document.body[k : k + 1] = insertion
2209 addedLines += len(insertion) - 1
2210 add_to_preamble(document, ['\\usepackage{subfig}\n'])
2214 def revert_wrapplacement(document):
2215 " Revert placement options wrap floats (wrapfig). "
2218 i = find_token(document.body, "\\begin_inset Wrap figure", i)
2221 e = find_end_of_inset(document.body, i)
2222 j = find_token(document.body, "placement", i + 1, e)
2224 document.warning("Malformed LyX document: Couldn't find placement parameter of wrap float.")
2227 r = re.compile("placement (o|i|l|r)")
2228 m = r.match(document.body[j])
2230 document.warning("Malformed LyX document: Placement option isn't O|I|R|L!")
2231 document.body[j] = "placement " + m.group(1).lower()
2235 def remove_extra_embedded_files(document):
2236 " Remove \extra_embedded_files from buffer params "
2237 i = find_token(document.header, '\\extra_embedded_files', 0)
2240 document.header.pop(i)
2243 def convert_spaceinset(document):
2244 " Convert '\\InsetSpace foo' to '\\begin_inset Space foo\n\\end_inset' "
2246 while i < len(document.body):
2247 m = re.match(r'(.*)\\InsetSpace (.*)', document.body[i])
2251 subst = [before, "\\begin_inset Space " + after, "\\end_inset"]
2252 document.body[i: i+1] = subst
2258 def revert_spaceinset(document):
2259 " Revert '\\begin_inset Space foo\n\\end_inset' to '\\InsetSpace foo' "
2262 i = find_token(document.body, "\\begin_inset Space", i)
2265 j = find_end_of_inset(document.body, i)
2267 document.warning("Malformed LyX document: Could not find end of space inset.")
2269 document.body[i] = document.body[i].replace('\\begin_inset Space', '\\InsetSpace')
2270 del document.body[j]
2273 def convert_hfill(document):
2274 " Convert hfill to space inset "
2277 i = find_token(document.body, "\\hfill", i)
2280 subst = document.body[i].replace('\\hfill', \
2281 '\n\\begin_inset Space \\hfill{}\n\\end_inset')
2282 subst = subst.split('\n')
2283 document.body[i : i+1] = subst
2287 def revert_hfills(document):
2288 ' Revert \\hfill commands '
2289 hfill = re.compile(r'\\hfill')
2290 dotfill = re.compile(r'\\dotfill')
2291 hrulefill = re.compile(r'\\hrulefill')
2294 i = find_token(document.body, "\\InsetSpace", i)
2297 if hfill.search(document.body[i]):
2298 document.body[i] = \
2299 document.body[i].replace('\\InsetSpace \\hfill{}', '\\hfill')
2302 if dotfill.search(document.body[i]):
2303 subst = document.body[i].replace('\\InsetSpace \\dotfill{}', \
2304 '\\begin_inset ERT\nstatus collapsed\n\n' \
2305 '\\begin_layout Standard\n\n\n\\backslash\n' \
2306 'dotfill{}\n\\end_layout\n\n\\end_inset\n\n')
2307 subst = subst.split('\n')
2308 document.body[i : i+1] = subst
2311 if hrulefill.search(document.body[i]):
2312 subst = document.body[i].replace('\\InsetSpace \\hrulefill{}', \
2313 '\\begin_inset ERT\nstatus collapsed\n\n' \
2314 '\\begin_layout Standard\n\n\n\\backslash\n' \
2315 'hrulefill{}\n\\end_layout\n\n\\end_inset\n\n')
2316 subst = subst.split('\n')
2317 document.body[i : i+1] = subst
2322 def revert_hspace(document):
2323 ' Revert \\InsetSpace \\hspace{} to ERT '
2325 hspace = re.compile(r'\\hspace{}')
2326 hstar = re.compile(r'\\hspace\*{}')
2328 i = find_token(document.body, "\\InsetSpace \\hspace", i)
2331 length = get_value(document.body, '\\length', i+1)
2333 document.warning("Malformed lyx document: Missing '\\length' in Space inset.")
2335 del document.body[i+1]
2337 if hstar.search(document.body[i]):
2338 subst = document.body[i].replace('\\InsetSpace \\hspace*{}', \
2339 '\\begin_inset ERT\nstatus collapsed\n\n' \
2340 '\\begin_layout Standard\n\n\n\\backslash\n' \
2341 'hspace*{' + length + '}\n\\end_layout\n\n\\end_inset\n\n')
2342 subst = subst.split('\n')
2343 document.body[i : i+1] = subst
2344 addedLines += len(subst) - 1
2347 if hspace.search(document.body[i]):
2348 subst = document.body[i].replace('\\InsetSpace \\hspace{}', \
2349 '\\begin_inset ERT\nstatus collapsed\n\n' \
2350 '\\begin_layout Standard\n\n\n\\backslash\n' \
2351 'hspace{' + length + '}\n\\end_layout\n\n\\end_inset\n\n')
2352 subst = subst.split('\n')
2353 document.body[i : i+1] = subst
2354 addedLines += len(subst) - 1
2360 def revert_protected_hfill(document):
2361 ' Revert \\begin_inset Space \\hspace*{\\fill} to ERT '
2364 i = find_token(document.body, '\\begin_inset Space \\hspace*{\\fill}', i)
2367 j = find_end_of_inset(document.body, i)
2369 document.warning("Malformed LyX document: Could not find end of space inset.")
2371 del document.body[j]
2372 subst = document.body[i].replace('\\begin_inset Space \\hspace*{\\fill}', \
2373 '\\begin_inset ERT\nstatus collapsed\n\n' \
2374 '\\begin_layout Standard\n\n\n\\backslash\n' \
2375 'hspace*{\n\\backslash\nfill}\n\\end_layout\n\n\\end_inset\n\n')
2376 subst = subst.split('\n')
2377 document.body[i : i+1] = subst
2381 def revert_leftarrowfill(document):
2382 ' Revert \\begin_inset Space \\leftarrowfill{} to ERT '
2385 i = find_token(document.body, '\\begin_inset Space \\leftarrowfill{}', i)
2388 j = find_end_of_inset(document.body, i)
2390 document.warning("Malformed LyX document: Could not find end of space inset.")
2392 del document.body[j]
2393 subst = document.body[i].replace('\\begin_inset Space \\leftarrowfill{}', \
2394 '\\begin_inset ERT\nstatus collapsed\n\n' \
2395 '\\begin_layout Standard\n\n\n\\backslash\n' \
2396 'leftarrowfill{}\n\\end_layout\n\n\\end_inset\n\n')
2397 subst = subst.split('\n')
2398 document.body[i : i+1] = subst
2402 def revert_rightarrowfill(document):
2403 ' Revert \\begin_inset Space \\rightarrowfill{} to ERT '
2406 i = find_token(document.body, '\\begin_inset Space \\rightarrowfill{}', i)
2409 j = find_end_of_inset(document.body, i)
2411 document.warning("Malformed LyX document: Could not find end of space inset.")
2413 del document.body[j]
2414 subst = document.body[i].replace('\\begin_inset Space \\rightarrowfill{}', \
2415 '\\begin_inset ERT\nstatus collapsed\n\n' \
2416 '\\begin_layout Standard\n\n\n\\backslash\n' \
2417 'rightarrowfill{}\n\\end_layout\n\n\\end_inset\n\n')
2418 subst = subst.split('\n')
2419 document.body[i : i+1] = subst
2423 def revert_upbracefill(document):
2424 ' Revert \\begin_inset Space \\upbracefill{} to ERT '
2427 i = find_token(document.body, '\\begin_inset Space \\upbracefill{}', i)
2430 j = find_end_of_inset(document.body, i)
2432 document.warning("Malformed LyX document: Could not find end of space inset.")
2434 del document.body[j]
2435 subst = document.body[i].replace('\\begin_inset Space \\upbracefill{}', \
2436 '\\begin_inset ERT\nstatus collapsed\n\n' \
2437 '\\begin_layout Standard\n\n\n\\backslash\n' \
2438 'upbracefill{}\n\\end_layout\n\n\\end_inset\n\n')
2439 subst = subst.split('\n')
2440 document.body[i : i+1] = subst
2444 def revert_downbracefill(document):
2445 ' Revert \\begin_inset Space \\downbracefill{} to ERT '
2448 i = find_token(document.body, '\\begin_inset Space \\downbracefill{}', i)
2451 j = find_end_of_inset(document.body, i)
2453 document.warning("Malformed LyX document: Could not find end of space inset.")
2455 del document.body[j]
2456 subst = document.body[i].replace('\\begin_inset Space \\downbracefill{}', \
2457 '\\begin_inset ERT\nstatus collapsed\n\n' \
2458 '\\begin_layout Standard\n\n\n\\backslash\n' \
2459 'downbracefill{}\n\\end_layout\n\n\\end_inset\n\n')
2460 subst = subst.split('\n')
2461 document.body[i : i+1] = subst
2465 def revert_local_layout(document):
2466 ' Revert local layout headers.'
2469 i = find_token(document.header, "\\begin_local_layout", i)
2472 j = find_end_of(document.header, i, "\\begin_local_layout", "\\end_local_layout")
2474 # this should not happen
2476 document.header[i : j + 1] = []
2479 def convert_pagebreaks(document):
2480 ' Convert inline Newpage insets to new format '
2483 i = find_token(document.body, '\\newpage', i)
2486 document.body[i:i+1] = ['\\begin_inset Newpage newpage',
2490 i = find_token(document.body, '\\pagebreak', i)
2493 document.body[i:i+1] = ['\\begin_inset Newpage pagebreak',
2497 i = find_token(document.body, '\\clearpage', i)
2500 document.body[i:i+1] = ['\\begin_inset Newpage clearpage',
2504 i = find_token(document.body, '\\cleardoublepage', i)
2507 document.body[i:i+1] = ['\\begin_inset Newpage cleardoublepage',
2511 def revert_pagebreaks(document):
2512 ' Revert \\begin_inset Newpage to previous inline format '
2515 i = find_token(document.body, '\\begin_inset Newpage', i)
2518 j = find_end_of_inset(document.body, i)
2520 document.warning("Malformed LyX document: Could not find end of Newpage inset.")
2522 del document.body[j]
2523 document.body[i] = document.body[i].replace('\\begin_inset Newpage newpage', '\\newpage')
2524 document.body[i] = document.body[i].replace('\\begin_inset Newpage pagebreak', '\\pagebreak')
2525 document.body[i] = document.body[i].replace('\\begin_inset Newpage clearpage', '\\clearpage')
2526 document.body[i] = document.body[i].replace('\\begin_inset Newpage cleardoublepage', '\\cleardoublepage')
2529 def convert_linebreaks(document):
2530 ' Convert inline Newline insets to new format '
2533 i = find_token(document.body, '\\newline', i)
2536 document.body[i:i+1] = ['\\begin_inset Newline newline',
2540 i = find_token(document.body, '\\linebreak', i)
2543 document.body[i:i+1] = ['\\begin_inset Newline linebreak',
2547 def revert_linebreaks(document):
2548 ' Revert \\begin_inset Newline to previous inline format '
2551 i = find_token(document.body, '\\begin_inset Newline', i)
2554 j = find_end_of_inset(document.body, i)
2556 document.warning("Malformed LyX document: Could not find end of Newline inset.")
2558 del document.body[j]
2559 document.body[i] = document.body[i].replace('\\begin_inset Newline newline', '\\newline')
2560 document.body[i] = document.body[i].replace('\\begin_inset Newline linebreak', '\\linebreak')
2563 def convert_japanese_plain(document):
2564 ' Set language japanese-plain to japanese '
2566 if document.language == "japanese-plain":
2567 document.language = "japanese"
2568 i = find_token(document.header, "\\language", 0)
2570 document.header[i] = "\\language japanese"
2573 j = find_token(document.body, "\\lang japanese-plain", j)
2576 document.body[j] = document.body[j].replace("\\lang japanese-plain", "\\lang japanese")
2580 def revert_pdfpages(document):
2581 ' Revert pdfpages external inset to ERT '
2584 i = find_token(document.body, "\\begin_inset External", i)
2587 j = find_end_of_inset(document.body, i)
2589 document.warning("Malformed lyx document: Missing '\\end_inset' in revert_pdfpages.")
2592 if get_value(document.body, 'template', i, j) == "PDFPages":
2593 filename = get_value(document.body, 'filename', i, j)
2595 r = re.compile(r'\textra PDFLaTeX \"(.*)\"$')
2596 for k in range(i, j):
2597 m = r.match(document.body[k])
2600 angle = get_value(document.body, 'rotateAngle', i, j)
2601 width = get_value(document.body, 'width', i, j)
2602 height = get_value(document.body, 'height', i, j)
2603 scale = get_value(document.body, 'scale', i, j)
2604 keepAspectRatio = find_token(document.body, "\tkeepAspectRatio", i, j)
2608 options += ",angle=" + angle
2610 options += "angle=" + angle
2613 options += ",width=" + convert_len(width)
2615 options += "width=" + convert_len(width)
2618 options += ",height=" + convert_len(height)
2620 options += "height=" + convert_len(height)
2623 options += ",scale=" + scale
2625 options += "scale=" + scale
2626 if keepAspectRatio != '':
2628 options += ",keepaspectratio"
2630 options += "keepaspectratio"
2632 options = '[' + options + ']'
2633 del document.body[i+1:j+1]
2634 document.body[i:i+1] = ['\\begin_inset ERT',
2637 '\\begin_layout Standard',
2640 'includepdf' + options + '{' + filename + '}',
2644 add_to_preamble(document, ['\\usepackage{pdfpages}\n'])
2650 def revert_mexican(document):
2651 ' Set language Spanish(Mexico) to Spanish '
2653 if document.language == "spanish-mexico":
2654 document.language = "spanish"
2655 i = find_token(document.header, "\\language", 0)
2657 document.header[i] = "\\language spanish"
2660 j = find_token(document.body, "\\lang spanish-mexico", j)
2663 document.body[j] = document.body[j].replace("\\lang spanish-mexico", "\\lang spanish")
2667 def remove_embedding(document):
2668 ' Remove embed tag from all insets '
2669 revert_inset_embedding(document, 'Graphics')
2670 revert_inset_embedding(document, 'External')
2671 revert_inset_embedding(document, 'CommandInset include')
2672 revert_inset_embedding(document, 'CommandInset bibtex')
2675 def revert_master(document):
2676 ' Remove master param '
2677 i = find_token(document.header, "\\master", 0)
2679 del document.header[i]
2682 def revert_graphics_group(document):
2683 ' Revert group information from graphics insets '
2686 i = find_token(document.body, "\\begin_inset Graphics", i)
2689 j = find_end_of_inset(document.body, i)
2691 document.warning("Malformed lyx document: Missing '\\end_inset' in revert_graphics_group.")
2694 k = find_token(document.body, " groupId", i, j)
2698 del document.body[k]
2702 def update_apa_styles(document):
2703 ' Replace obsolete styles '
2705 if document.textclass != "apa":
2708 obsoletedby = { "Acknowledgments": "Acknowledgements",
2709 "Section*": "Section",
2710 "Subsection*": "Subsection",
2711 "Subsubsection*": "Subsubsection",
2712 "Paragraph*": "Paragraph",
2713 "Subparagraph*": "Subparagraph"}
2716 i = find_token(document.body, "\\begin_layout", i)
2720 layout = document.body[i][14:]
2721 if layout in obsoletedby:
2722 document.body[i] = "\\begin_layout " + obsoletedby[layout]
2727 def convert_paper_sizes(document):
2728 ' exchange size options legalpaper and executivepaper to correct order '
2729 # routine is needed to fix http://bugzilla.lyx.org/show_bug.cgi?id=4868
2732 i = find_token(document.header, "\\papersize executivepaper", 0)
2734 document.header[i] = "\\papersize legalpaper"
2736 j = find_token(document.header, "\\papersize legalpaper", 0)
2738 document.header[j] = "\\papersize executivepaper"
2741 def revert_paper_sizes(document):
2742 ' exchange size options legalpaper and executivepaper to correct order '
2745 i = find_token(document.header, "\\papersize executivepaper", 0)
2747 document.header[i] = "\\papersize legalpaper"
2749 j = find_token(document.header, "\\papersize legalpaper", 0)
2751 document.header[j] = "\\papersize executivepaper"
2754 def convert_InsetSpace(document):
2755 " Convert '\\begin_inset Space foo' to '\\begin_inset space foo'"
2758 i = find_token(document.body, "\\begin_inset Space", i)
2761 document.body[i] = document.body[i].replace('\\begin_inset Space', '\\begin_inset space')
2764 def revert_InsetSpace(document):
2765 " Revert '\\begin_inset space foo' to '\\begin_inset Space foo'"
2768 i = find_token(document.body, "\\begin_inset space", i)
2771 document.body[i] = document.body[i].replace('\\begin_inset space', '\\begin_inset Space')
2774 def convert_display_enum(document):
2775 " Convert 'display foo' to 'display false/true'"
2778 i = find_token(document.body, "\tdisplay", i)
2781 val = get_value(document.body, 'display', i)
2783 document.body[i] = document.body[i].replace('none', 'false')
2784 if val == "default":
2785 document.body[i] = document.body[i].replace('default', 'true')
2786 if val == "monochrome":
2787 document.body[i] = document.body[i].replace('monochrome', 'true')
2788 if val == "grayscale":
2789 document.body[i] = document.body[i].replace('grayscale', 'true')
2791 document.body[i] = document.body[i].replace('color', 'true')
2792 if val == "preview":
2793 document.body[i] = document.body[i].replace('preview', 'true')
2797 def revert_display_enum(document):
2798 " Revert 'display false/true' to 'display none/color'"
2801 i = find_token(document.body, "\tdisplay", i)
2804 val = get_value(document.body, 'display', i)
2806 document.body[i] = document.body[i].replace('false', 'none')
2808 document.body[i] = document.body[i].replace('true', 'default')
2812 def remove_fontsCJK(document):
2813 ' Remove font_cjk param '
2814 i = find_token(document.header, "\\font_cjk", 0)
2816 del document.header[i]
2819 def convert_plain_layout(document):
2820 " Convert 'PlainLayout' to 'Plain Layout'"
2823 i = find_token(document.body, '\\begin_layout PlainLayout', i)
2826 document.body[i] = document.body[i].replace('\\begin_layout PlainLayout', \
2827 '\\begin_layout Plain Layout')
2831 def revert_plain_layout(document):
2832 " Convert 'PlainLayout' to 'Plain Layout'"
2835 i = find_token(document.body, '\\begin_layout Plain Layout', i)
2838 document.body[i] = document.body[i].replace('\\begin_layout Plain Layout', \
2839 '\\begin_layout PlainLayout')
2843 def revert_plainlayout(document):
2844 " Convert 'PlainLayout' to 'Plain Layout'"
2847 i = find_token(document.body, '\\begin_layout PlainLayout', i)
2850 # This will be incorrect for some document classes, since Standard is not always
2851 # the default. But (a) it is probably the best we can do and (b) it will actually
2852 # work, in fact, since an unknown layout will be converted to default.
2853 document.body[i] = document.body[i].replace('\\begin_layout PlainLayout', \
2854 '\\begin_layout Standard')
2858 def revert_polytonicgreek(document):
2859 "Set language polytonic Greek to Greek"
2861 if document.language == "polutonikogreek":
2862 document.language = "greek"
2863 i = find_token(document.header, "\\language", 0)
2865 document.header[i] = "\\language greek"
2868 j = find_token(document.body, "\\lang polutonikogreek", j)
2871 document.body[j] = document.body[j].replace("\\lang polutonikogreek", "\\lang greek")
2875 def revert_removed_modules(document):
2878 i = find_token(document.header, "\\begin_remove_modules", i)
2881 j = find_end_of(document.header, i, "\\begin_remove_modules", "\\end_remove_modules")
2883 # this should not happen
2885 document.header[i : j + 1] = []
2888 def add_plain_layout(document):
2891 i = find_token(document.body, "\\begin_layout", i)
2894 if len(document.body[i].split()) == 1:
2895 document.body[i] = "\\begin_layout Plain Layout"
2902 supported_versions = ["1.6.0","1.6"]
2903 convert = [[277, [fix_wrong_tables]],
2904 [278, [close_begin_deeper]],
2905 [279, [long_charstyle_names]],
2906 [280, [axe_show_label]],
2909 [283, [convert_flex]],
2913 [287, [convert_wrapfig_options]],
2914 [288, [convert_inset_command]],
2915 [289, [convert_latexcommand_index]],
2918 [292, [convert_japanese_cjk]],
2920 [294, [convert_pdf_options]],
2921 [295, [convert_htmlurl, convert_url]],
2922 [296, [convert_include]],
2923 [297, [convert_usorbian]],
2929 [303, [convert_serbocroatian]],
2930 [304, [convert_framed_notes]],
2937 [311, [convert_ams_classes]],
2939 [313, [convert_module_names]],
2942 [316, [convert_subfig]],
2945 [319, [convert_spaceinset, convert_hfill]],
2947 [321, [convert_tablines]],
2948 [322, [convert_plain_layout]],
2949 [323, [convert_pagebreaks]],
2950 [324, [convert_linebreaks]],
2951 [325, [convert_japanese_plain]],
2954 [328, [remove_embedding, remove_extra_embedded_files, remove_inzip_options]],
2957 [331, [convert_ltcaption]],
2959 [333, [update_apa_styles]],
2960 [334, [convert_paper_sizes]],
2961 [335, [convert_InsetSpace]],
2963 [337, [convert_display_enum]],
2966 [340, [add_plain_layout]]
2969 revert = [[339, []],
2970 [338, [revert_removed_modules]],
2971 [337, [revert_polytonicgreek]],
2972 [336, [revert_display_enum]],
2973 [335, [remove_fontsCJK]],
2974 [334, [revert_InsetSpace]],
2975 [333, [revert_paper_sizes]],
2977 [331, [revert_graphics_group]],
2978 [330, [revert_ltcaption]],
2979 [329, [revert_leftarrowfill, revert_rightarrowfill, revert_upbracefill, revert_downbracefill]],
2980 [328, [revert_master]],
2982 [326, [revert_mexican]],
2983 [325, [revert_pdfpages]],
2985 [323, [revert_linebreaks]],
2986 [322, [revert_pagebreaks]],
2987 [321, [revert_local_layout, revert_plain_layout]],
2988 [320, [revert_tablines]],
2989 [319, [revert_protected_hfill]],
2990 [318, [revert_spaceinset, revert_hfills, revert_hspace]],
2991 [317, [remove_extra_embedded_files]],
2992 [316, [revert_wrapplacement]],
2993 [315, [revert_subfig]],
2994 [314, [revert_colsep, revert_plainlayout]],
2996 [312, [revert_module_names]],
2997 [311, [revert_rotfloat, revert_widesideways]],
2998 [310, [revert_external_embedding]],
2999 [309, [revert_btprintall]],
3000 [308, [revert_nocite]],
3001 [307, [revert_serbianlatin]],
3002 [306, [revert_slash, revert_nobreakdash]],
3003 [305, [revert_interlingua]],
3004 [304, [revert_bahasam]],
3005 [303, [revert_framed_notes]],
3007 [301, [revert_latin, revert_samin]],
3008 [300, [revert_linebreak]],
3009 [299, [revert_pagebreak]],
3010 [298, [revert_hyperlinktype]],
3011 [297, [revert_macro_optional_params]],
3012 [296, [revert_albanian, revert_lowersorbian, revert_uppersorbian]],
3013 [295, [revert_include]],
3014 [294, [revert_href, revert_url]],
3015 [293, [revert_pdf_options_2]],
3016 [292, [revert_inset_info]],
3017 [291, [revert_japanese, revert_japanese_encoding, revert_japanese_cjk]],
3018 [290, [revert_vietnamese]],
3019 [289, [revert_wraptable]],
3020 [288, [revert_latexcommand_index]],
3021 [287, [revert_inset_command]],
3022 [286, [revert_wrapfig_options]],
3023 [285, [revert_pdf_options]],
3024 [284, [remove_inzip_options]],
3026 [282, [revert_flex]],
3028 [280, [revert_begin_modules]],
3029 [279, [revert_show_label]],
3030 [278, [revert_long_charstyle_names]],
3036 if __name__ == "__main__":