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 '''Takes a string, possibly multi-line, and returns the result of
247 converting LaTeX constructs into LyX constructs. Returns a list of
248 lines, suitable for insertion into document.body.'''
252 # Convert LaTeX to Unicode
253 reps = read_unicodesymbols()
254 # Commands of this sort need to be checked to make sure they are
255 # followed by a non-alpha character, lest we replace too much.
256 hardone = re.compile(r'^\\\\[a-zA-Z]+$')
259 if hardone.match(rep[0]):
262 pos = data.find(rep[0], pos)
265 nextpos = pos + len(rep[0])
266 if nextpos < len(data) and data[nextpos].isalpha():
267 # not the end of that command
270 data = data[:pos] + rep[1] + data[nextpos:]
273 data = data.replace(rep[0], rep[1])
276 data = wrap_into_ert(data, r'\"', '"')
279 mathre = re.compile('^(.*?)(\$.*?\$)(.*)')
280 lines = data.split('\n')
282 #document.warning("LINE: " + line)
283 #document.warning(str(i) + ":" + document.body[i])
284 #document.warning("LAST: " + document.body[-1])
289 f = m.group(2).replace('\\\\', '\\')
294 subst = s.split('\n')
296 retval.append("\\begin_inset Formula " + f)
297 retval.append("\\end_inset")
299 # Handle whatever is left, which is just text
301 subst = g.split('\n')
306 def lyx2latex(lines):
307 'Convert some LyX stuff into corresponding LaTeX stuff, as best we can.'
308 # clean up multiline stuff
311 reps = read_unicodesymbols()
313 for curline in range(len(lines)):
314 line = lines[curline]
315 if line.startswith("\\begin_inset ERT"):
316 # We don't want to replace things inside ERT, so figure out
317 # where the end of the inset is.
318 ert_end = find_end_of_inset(lines, curline + 1)
320 elif line.startswith("\\begin_inset Formula"):
322 elif line.startswith("\\begin_inset Quotes"):
323 # For now, we do a very basic reversion. Someone who understands
324 # quotes is welcome to fix it up.
325 qtype = line[20:].strip()
339 elif line.isspace() or \
340 line.startswith("\\begin_layout") or \
341 line.startswith("\\end_layout") or \
342 line.startswith("\\begin_inset") or \
343 line.startswith("\\end_inset") or \
344 line.startswith("\\lang") or \
345 line.strip() == "status collapsed" or \
346 line.strip() == "status open":
350 # a lossless reversion is not possible
351 # try at least to handle some common insets and settings
352 # do not replace inside ERTs
353 if ert_end >= curline:
354 line = line.replace(r'\backslash', r'\\')
356 # Do the LyX text --> LaTeX conversion
358 line = line.replace(rep[1], rep[0])
359 line = line.replace(r'\backslash', r'\textbackslash{}')
360 line = line.replace(r'\series bold', r'\bfseries{}').replace(r'\series default', r'\mdseries{}')
361 line = line.replace(r'\shape italic', r'\itshape{}').replace(r'\shape smallcaps', r'\scshape{}')
362 line = line.replace(r'\shape slanted', r'\slshape{}').replace(r'\shape default', r'\upshape{}')
363 line = line.replace(r'\emph on', r'\em{}').replace(r'\emph default', r'\em{}')
364 line = line.replace(r'\noun on', r'\scshape{}').replace(r'\noun default', r'\upshape{}')
365 line = line.replace(r'\bar under', r'\underbar{').replace(r'\bar default', r'}')
366 line = line.replace(r'\family sans', r'\sffamily{}').replace(r'\family default', r'\normalfont{}')
367 line = line.replace(r'\family typewriter', r'\ttfamily{}').replace(r'\family roman', r'\rmfamily{}')
368 line = line.replace(r'\InsetSpace ', r'').replace(r'\SpecialChar ', r'')
373 ####################################################################
375 def convert_ltcaption(document):
378 i = find_token(document.body, "\\begin_inset Tabular", i)
381 j = find_end_of_inset(document.body, i + 1)
383 document.warning("Malformed LyX document: Could not find end of tabular.")
386 nrows = int(document.body[i+1].split('"')[3])
387 ncols = int(document.body[i+1].split('"')[5])
390 for k in range(nrows):
391 m = find_token(document.body, "<row", m)
394 for k in range(ncols):
395 m = find_token(document.body, "<cell", m)
397 mend = find_token(document.body, "</cell>", m + 1)
398 # first look for caption insets
399 mcap = find_token(document.body, "\\begin_inset Caption", m + 1, mend)
400 # then look for ERT captions
402 mcap = find_token(document.body, "caption", m + 1, mend)
404 mcap = find_token(document.body, "\\backslash", mcap - 1, mcap)
407 if caption == 'true':
409 set_option(document, r, 'caption', 'true')
410 set_option(document, m, 'multicolumn', '1')
411 set_option(document, m, 'bottomline', 'false')
412 set_option(document, m, 'topline', 'false')
413 set_option(document, m, 'rightline', 'false')
414 set_option(document, m, 'leftline', 'false')
415 #j = find_end_of_inset(document.body, j + 1)
417 set_option(document, m, 'multicolumn', '2')
424 #FIXME Use of wrap_into_ert can confuse lyx2lyx
425 def revert_ltcaption(document):
428 i = find_token(document.body, "\\begin_inset Tabular", i)
431 j = find_end_of_inset(document.body, i + 1)
433 document.warning("Malformed LyX document: Could not find end of tabular.")
437 nrows = int(document.body[i+1].split('"')[3])
438 ncols = int(document.body[i+1].split('"')[5])
440 for k in range(nrows):
441 m = find_token(document.body, "<row", m)
442 caption = get_option(document, m, 'caption', 'false')
443 if caption == 'true':
444 remove_option(document, m, 'caption')
445 for k in range(ncols):
446 m = find_token(document.body, "<cell", m)
447 remove_option(document, m, 'multicolumn')
449 m = find_token(document.body, "\\begin_inset Caption", m)
452 m = find_end_of_inset(document.body, m + 1)
453 document.body[m] += wrap_into_ert("","","\\backslash\n\\backslash\n%")
459 def convert_tablines(document):
462 i = find_token(document.body, "\\begin_inset Tabular", i)
464 # LyX 1.3 inserted an extra space between \begin_inset
465 # and Tabular so let us try if this is the case and fix it.
466 i = find_token(document.body, "\\begin_inset Tabular", i)
470 document.body[i] = "\\begin_inset Tabular"
471 j = find_end_of_inset(document.body, i + 1)
473 document.warning("Malformed LyX document: Could not find end of tabular.")
477 nrows = int(document.body[i+1].split('"')[3])
478 ncols = int(document.body[i+1].split('"')[5])
481 for k in range(ncols):
482 m = find_token(document.body, "<column", m)
483 left = get_option(document, m, 'leftline', 'false')
484 right = get_option(document, m, 'rightline', 'false')
485 col_info.append([left, right])
486 remove_option(document, m, 'leftline')
487 remove_option(document, m, 'rightline')
491 for k in range(nrows):
492 m = find_token(document.body, "<row", m)
493 top = get_option(document, m, 'topline', 'false')
494 bottom = get_option(document, m, 'bottomline', 'false')
495 row_info.append([top, bottom])
496 remove_option(document, m, 'topline')
497 remove_option(document, m, 'bottomline')
502 for k in range(nrows*ncols):
503 m = find_token(document.body, "<cell", m)
504 mc_info.append(get_option(document, m, 'multicolumn', '0'))
507 for l in range(nrows):
508 for k in range(ncols):
509 m = find_token(document.body, '<cell', m)
510 if mc_info[l*ncols + k] == '0':
511 r = set_option(document, m, 'topline', row_info[l][0])
512 r = set_option(document, m, 'bottomline', row_info[l][1])
513 r = set_option(document, m, 'leftline', col_info[k][0])
514 r = set_option(document, m, 'rightline', col_info[k][1])
515 elif mc_info[l*ncols + k] == '1':
517 while s < ncols and mc_info[l*ncols + s] == '2':
519 if s < ncols and mc_info[l*ncols + s] != '1':
520 r = set_option(document, m, 'rightline', col_info[k][1])
521 if k > 0 and mc_info[l*ncols + k - 1] == '0':
522 r = set_option(document, m, 'leftline', col_info[k][0])
527 def revert_tablines(document):
530 i = find_token(document.body, "\\begin_inset Tabular", i)
533 j = find_end_of_inset(document.body, i + 1)
535 document.warning("Malformed LyX document: Could not find end of tabular.")
539 nrows = int(document.body[i+1].split('"')[3])
540 ncols = int(document.body[i+1].split('"')[5])
543 for k in range(nrows*ncols):
544 m = find_token(document.body, "<cell", m)
545 top = get_option(document, m, 'topline', 'false')
546 bottom = get_option(document, m, 'bottomline', 'false')
547 left = get_option(document, m, 'leftline', 'false')
548 right = get_option(document, m, 'rightline', 'false')
549 lines.append([top, bottom, left, right])
552 # we will want to ignore longtable captions
555 for k in range(nrows):
556 m = find_token(document.body, "<row", m)
557 caption = get_option(document, m, 'caption', 'false')
558 caption_info.append([caption])
563 for k in range(ncols):
564 m = find_token(document.body, "<column", m)
566 for l in range(nrows):
567 left = lines[l*ncols + k][2]
568 if left == 'false' and caption_info[l] == 'false':
570 set_option(document, m, 'leftline', left)
572 for l in range(nrows):
573 right = lines[l*ncols + k][3]
574 if right == 'false' and caption_info[l] == 'false':
576 set_option(document, m, 'rightline', right)
580 for k in range(nrows):
581 m = find_token(document.body, "<row", m)
583 for l in range(ncols):
584 top = lines[k*ncols + l][0]
587 if caption_info[k] == 'false':
589 set_option(document, m, 'topline', top)
591 for l in range(ncols):
592 bottom = lines[k*ncols + l][1]
593 if bottom == 'false':
595 if caption_info[k] == 'false':
597 set_option(document, m, 'bottomline', bottom)
603 def fix_wrong_tables(document):
606 i = find_token(document.body, "\\begin_inset Tabular", i)
609 j = find_end_of_inset(document.body, i + 1)
611 document.warning("Malformed LyX document: Could not find end of tabular.")
615 nrows = int(document.body[i+1].split('"')[3])
616 ncols = int(document.body[i+1].split('"')[5])
618 for l in range(nrows):
620 for k in range(ncols):
621 m = find_token(document.body, '<cell', m)
623 if document.body[m].find('multicolumn') != -1:
624 multicol_cont = int(document.body[m].split('"')[1])
626 if multicol_cont == 2 and (k == 0 or prev_multicolumn == 0):
627 document.body[m] = document.body[m][:5] + document.body[m][21:]
630 prev_multicolumn = multicol_cont
637 def close_begin_deeper(document):
641 i = find_tokens(document.body, ["\\begin_deeper", "\\end_deeper"], i)
646 if document.body[i][:13] == "\\begin_deeper":
653 document.body[-2:-2] = ['\\end_deeper' for i in range(depth)]
656 def long_charstyle_names(document):
659 i = find_token(document.body, "\\begin_inset CharStyle", i)
662 document.body[i] = document.body[i].replace("CharStyle ", "CharStyle CharStyle:")
665 def revert_long_charstyle_names(document):
668 i = find_token(document.body, "\\begin_inset CharStyle", i)
671 document.body[i] = document.body[i].replace("CharStyle CharStyle:", "CharStyle ")
675 def axe_show_label(document):
678 i = find_token(document.body, "\\begin_inset CharStyle", i)
681 if document.body[i + 1].find("show_label") != -1:
682 if document.body[i + 1].find("true") != -1:
683 document.body[i + 1] = "status open"
684 del document.body[ i + 2]
686 if document.body[i + 1].find("false") != -1:
687 document.body[i + 1] = "status collapsed"
688 del document.body[ i + 2]
690 document.warning("Malformed LyX document: show_label neither false nor true.")
692 document.warning("Malformed LyX document: show_label missing in CharStyle.")
697 def revert_show_label(document):
700 i = find_token(document.body, "\\begin_inset CharStyle", i)
703 if document.body[i + 1].find("status open") != -1:
704 document.body.insert(i + 1, "show_label true")
706 if document.body[i + 1].find("status collapsed") != -1:
707 document.body.insert(i + 1, "show_label false")
709 document.warning("Malformed LyX document: no legal status line in CharStyle.")
712 def revert_begin_modules(document):
715 i = find_token(document.header, "\\begin_modules", i)
718 j = find_end_of(document.header, i, "\\begin_modules", "\\end_modules")
720 # this should not happen
722 document.header[i : j + 1] = []
724 def convert_flex(document):
725 "Convert CharStyle to Flex"
728 i = find_token(document.body, "\\begin_inset CharStyle", i)
731 document.body[i] = document.body[i].replace('\\begin_inset CharStyle', '\\begin_inset Flex')
733 def revert_flex(document):
734 "Convert Flex to CharStyle"
737 i = find_token(document.body, "\\begin_inset Flex", i)
740 document.body[i] = document.body[i].replace('\\begin_inset Flex', '\\begin_inset CharStyle')
743 # Discard PDF options for hyperref
744 def revert_pdf_options(document):
745 "Revert PDF options for hyperref."
746 # store the PDF options and delete the entries from the Lyx file
754 bookmarksnumbered = ""
756 bookmarksopenlevel = ""
764 i = find_token(document.header, "\\use_hyperref", i)
766 hyperref = get_value(document.header, "\\use_hyperref", i) == 'true'
767 del document.header[i]
768 i = find_token(document.header, "\\pdf_store_options", i)
770 del document.header[i]
771 i = find_token(document.header, "\\pdf_title", 0)
773 title = get_value_string(document.header, '\\pdf_title', 0, 0, True)
774 title = ' pdftitle={' + title + '}'
775 del document.header[i]
776 i = find_token(document.header, "\\pdf_author", 0)
778 author = get_value_string(document.header, '\\pdf_author', 0, 0, True)
780 author = ' pdfauthor={' + author + '}'
782 author = ',\n pdfauthor={' + author + '}'
783 del document.header[i]
784 i = find_token(document.header, "\\pdf_subject", 0)
786 subject = get_value_string(document.header, '\\pdf_subject', 0, 0, True)
787 if title == "" and author == "":
788 subject = ' pdfsubject={' + subject + '}'
790 subject = ',\n pdfsubject={' + subject + '}'
791 del document.header[i]
792 i = find_token(document.header, "\\pdf_keywords", 0)
794 keywords = get_value_string(document.header, '\\pdf_keywords', 0, 0, True)
795 if title == "" and author == "" and subject == "":
796 keywords = ' pdfkeywords={' + keywords + '}'
798 keywords = ',\n pdfkeywords={' + keywords + '}'
799 del document.header[i]
800 i = find_token(document.header, "\\pdf_bookmarks", 0)
802 bookmarks = get_value_string(document.header, '\\pdf_bookmarks', 0)
803 bookmarks = ',\n bookmarks=' + bookmarks
804 del document.header[i]
805 i = find_token(document.header, "\\pdf_bookmarksnumbered", i)
807 bookmarksnumbered = get_value_string(document.header, '\\pdf_bookmarksnumbered', 0)
808 bookmarksnumbered = ',\n bookmarksnumbered=' + bookmarksnumbered
809 del document.header[i]
810 i = find_token(document.header, "\\pdf_bookmarksopen", i)
812 bookmarksopen = get_value_string(document.header, '\\pdf_bookmarksopen', 0)
813 bookmarksopen = ',\n bookmarksopen=' + bookmarksopen
814 del document.header[i]
815 i = find_token(document.header, "\\pdf_bookmarksopenlevel", i)
817 bookmarksopenlevel = get_value_string(document.header, '\\pdf_bookmarksopenlevel', 0, 0, True)
818 bookmarksopenlevel = ',\n bookmarksopenlevel=' + bookmarksopenlevel
819 del document.header[i]
820 i = find_token(document.header, "\\pdf_breaklinks", i)
822 breaklinks = get_value_string(document.header, '\\pdf_breaklinks', 0)
823 breaklinks = ',\n breaklinks=' + breaklinks
824 del document.header[i]
825 i = find_token(document.header, "\\pdf_pdfborder", i)
827 pdfborder = get_value_string(document.header, '\\pdf_pdfborder', 0)
828 if pdfborder == 'true':
829 pdfborder = ',\n pdfborder={0 0 0}'
831 pdfborder = ',\n pdfborder={0 0 1}'
832 del document.header[i]
833 i = find_token(document.header, "\\pdf_colorlinks", i)
835 colorlinks = get_value_string(document.header, '\\pdf_colorlinks', 0)
836 colorlinks = ',\n colorlinks=' + colorlinks
837 del document.header[i]
838 i = find_token(document.header, "\\pdf_backref", i)
840 backref = get_value_string(document.header, '\\pdf_backref', 0)
841 backref = ',\n backref=' + backref
842 del document.header[i]
843 i = find_token(document.header, "\\pdf_pagebackref", i)
845 pagebackref = get_value_string(document.header, '\\pdf_pagebackref', 0)
846 pagebackref = ',\n pagebackref=' + pagebackref
847 del document.header[i]
848 i = find_token(document.header, "\\pdf_pagemode", 0)
850 pagemode = get_value_string(document.header, '\\pdf_pagemode', 0)
851 pagemode = ',\n pdfpagemode=' + pagemode
852 del document.header[i]
853 i = find_token(document.header, "\\pdf_quoted_options", 0)
855 otheroptions = get_value_string(document.header, '\\pdf_quoted_options', 0, 0, True)
856 if title == "" and author == "" and subject == "" and keywords == "":
857 otheroptions = ' ' + otheroptions
859 otheroptions = ',\n ' + otheroptions
860 del document.header[i]
862 # write to the preamble when hyperref was used
864 # preamble write preparations
865 # bookmark numbers are only output when they are turned on
866 if bookmarksopen == ',\n bookmarksopen=true':
867 bookmarksopen = bookmarksopen + bookmarksopenlevel
868 if bookmarks == ',\n bookmarks=true':
869 bookmarks = bookmarks + bookmarksnumbered + bookmarksopen
871 bookmarks = bookmarks
872 # hypersetup is only output when there are things to be set up
873 setupstart = '\\hypersetup{%\n'
875 if otheroptions == "" and title == "" and author == ""\
876 and subject == "" and keywords == "":
880 # babel must be loaded before hyperref and hyperref the first part
881 # of the preamble, like in LyX 1.6
882 insert_to_preamble(0, document,
883 '% Commands inserted by lyx2lyx for PDF properties\n'
884 + '\\usepackage{babel}\n'
885 + '\\usepackage[unicode=true'
904 def remove_inzip_options(document):
905 "Remove inzipName and embed options from the Graphics inset"
908 i = find_token(document.body, "\\begin_inset Graphics", i)
911 j = find_end_of_inset(document.body, i + 1)
914 document.warning("Malformed LyX document: Could not find end of graphics inset.")
915 # If there's a inzip param, just remove that
916 k = find_token(document.body, "\tinzipName", i + 1, j)
919 # embed option must follow the inzipName option
920 del document.body[k+1]
924 def convert_inset_command(document):
927 \begin_inset LatexCommand cmd
929 \begin_inset CommandInset InsetType
934 i = find_token(document.body, "\\begin_inset LatexCommand", i)
937 line = document.body[i]
938 r = re.compile(r'\\begin_inset LatexCommand (.*)$')
942 #this is adapted from factory.cpp
943 if cmdName[0:4].lower() == "cite":
944 insetName = "citation"
945 elif cmdName == "url" or cmdName == "htmlurl":
947 elif cmdName[-3:] == "ref":
949 elif cmdName == "tableofcontents":
951 elif cmdName == "printnomenclature":
952 insetName = "nomencl_print"
953 elif cmdName == "printindex":
954 insetName = "index_print"
957 insertion = ["\\begin_inset CommandInset " + insetName, "LatexCommand " + cmdName]
958 document.body[i : i+1] = insertion
961 def revert_inset_command(document):
964 \begin_inset CommandInset InsetType
967 \begin_inset LatexCommand cmd
968 Some insets may end up being converted to insets earlier versions of LyX
969 will not be able to recognize. Not sure what to do about that.
973 i = find_token(document.body, "\\begin_inset CommandInset", i)
976 nextline = document.body[i+1]
977 r = re.compile(r'LatexCommand\s+(.*)$')
978 m = r.match(nextline)
980 document.warning("Malformed LyX document: Missing LatexCommand in " + document.body[i] + ".")
983 insertion = ["\\begin_inset LatexCommand " + cmdName]
984 document.body[i : i+2] = insertion
987 def convert_wrapfig_options(document):
988 "Convert optional options for wrap floats (wrapfig)."
989 # adds the tokens "lines", "placement", and "overhang"
992 i = find_token(document.body, "\\begin_inset Wrap figure", i)
995 document.body.insert(i + 1, "lines 0")
996 j = find_token(document.body, "placement", i)
997 # placement can be already set or not; if not, set it
999 document.body.insert(i + 3, "overhang 0col%")
1001 document.body.insert(i + 2, "placement o")
1002 document.body.insert(i + 3, "overhang 0col%")
1006 def revert_wrapfig_options(document):
1007 "Revert optional options for wrap floats (wrapfig)."
1010 i = find_token(document.body, "\\begin_inset Wrap figure", i)
1013 j = find_end_of_inset(document.body, i)
1015 document.warning("Can't find end of Wrap inset at line " + str(i))
1018 k = find_default_layout(document, i, j)
1020 document.warning("Can't find default layout for Wrap figure!")
1023 # Options should be between i and k now
1024 l = find_token(document.body, "lines", i, k)
1026 document.warning("Can't find lines option for Wrap figure!")
1029 m = find_token(document.body, "overhang", i + 1, k)
1031 document.warning("Malformed LyX document: Couldn't find overhang parameter of wrap float!")
1034 # Do these in reverse order
1035 del document.body[m]
1036 del document.body[l]
1040 def convert_latexcommand_index(document):
1041 "Convert from LatexCommand form to collapsable form."
1043 r1 = re.compile('name "(.*)"')
1045 i = find_token(document.body, "\\begin_inset CommandInset index", i)
1048 if document.body[i + 1] != "LatexCommand index": # Might also be index_print
1050 j = find_end_of_inset(document.body, i + 2)
1052 document.warning("Unable to find end of index inset at line " + i + "!")
1055 m = r1.match(document.body[i + 2])
1057 document.warning("Unable to match: " + document.body[i+2])
1060 fullcontent = m.group(1)
1061 linelist = latex2lyx(fullcontent)
1062 #document.warning(fullcontent)
1064 linelist = ["\\begin_inset Index", "status collapsed", "\\begin_layout Standard", ""] + \
1065 linelist + ["\\end_layout"]
1066 document.body[i : j] = linelist
1067 i += len(linelist) - (j - i)
1070 def revert_latexcommand_index(document):
1071 "Revert from collapsable form to LatexCommand form."
1074 i = find_token(document.body, "\\begin_inset Index", i)
1077 j = find_end_of_inset(document.body, i + 1)
1081 content = lyx2latex(document.body[i:j])
1083 content = content.replace('"', r'\"')
1084 document.body[i:j] = ["\\begin_inset CommandInset index", "LatexCommand index",
1085 "name " + '"' + content + '"', ""]
1089 def revert_wraptable(document):
1090 "Revert wrap table to wrap figure."
1093 i = find_token(document.body, "\\begin_inset Wrap table", i)
1096 document.body[i] = document.body[i].replace('\\begin_inset Wrap table', '\\begin_inset Wrap figure')
1100 def revert_vietnamese(document):
1101 "Set language Vietnamese to English"
1102 # Set document language from Vietnamese to English
1104 if document.language == "vietnamese":
1105 document.language = "english"
1106 i = find_token(document.header, "\\language", 0)
1108 document.header[i] = "\\language english"
1111 j = find_token(document.body, "\\lang vietnamese", j)
1114 document.body[j] = document.body[j].replace("\\lang vietnamese", "\\lang english")
1118 def convert_japanese_cjk(document):
1119 "Set language japanese to japanese-cjk"
1120 # Set document language from japanese-plain to japanese
1122 if document.language == "japanese":
1123 document.language = "japanese-cjk"
1124 i = find_token(document.header, "\\language", 0)
1126 document.header[i] = "\\language japanese-cjk"
1129 j = find_token(document.body, "\\lang japanese", j)
1132 document.body[j] = document.body[j].replace("\\lang japanese", "\\lang japanese-cjk")
1136 def revert_japanese(document):
1137 "Set language japanese-plain to japanese"
1138 # Set document language from japanese-plain to japanese
1140 if document.language == "japanese-plain":
1141 document.language = "japanese"
1142 i = find_token(document.header, "\\language", 0)
1144 document.header[i] = "\\language japanese"
1147 j = find_token(document.body, "\\lang japanese-plain", j)
1150 document.body[j] = document.body[j].replace("\\lang japanese-plain", "\\lang japanese")
1154 def revert_japanese_cjk(document):
1155 "Set language japanese-cjk to japanese"
1156 # Set document language from japanese-plain to japanese
1158 if document.language == "japanese-cjk":
1159 document.language = "japanese"
1160 i = find_token(document.header, "\\language", 0)
1162 document.header[i] = "\\language japanese"
1165 j = find_token(document.body, "\\lang japanese-cjk", j)
1168 document.body[j] = document.body[j].replace("\\lang japanese-cjk", "\\lang japanese")
1172 def revert_japanese_encoding(document):
1173 "Set input encoding form EUC-JP-plain to EUC-JP etc."
1174 # Set input encoding form EUC-JP-plain to EUC-JP etc.
1176 i = find_token(document.header, "\\inputencoding EUC-JP-plain", 0)
1178 document.header[i] = "\\inputencoding EUC-JP"
1180 j = find_token(document.header, "\\inputencoding JIS-plain", 0)
1182 document.header[j] = "\\inputencoding JIS"
1184 k = find_token(document.header, "\\inputencoding SJIS-plain", 0)
1185 if k != -1: # convert to UTF8 since there is currently no SJIS encoding
1186 document.header[k] = "\\inputencoding UTF8"
1189 def revert_inset_info(document):
1190 'Replace info inset with its content'
1193 i = find_token(document.body, '\\begin_inset Info', i)
1196 j = find_end_of_inset(document.body, i + 1)
1199 document.warning("Malformed LyX document: Could not find end of Info inset.")
1202 for k in range(i, j+1):
1203 if document.body[k].startswith("arg"):
1204 arg = document.body[k][3:].strip().strip('"')
1205 if document.body[k].startswith("type"):
1206 type = document.body[k][4:].strip().strip('"')
1207 # I think there is a newline after \\end_inset, which should be removed.
1208 if document.body[j + 1].strip() == "":
1209 document.body[i : (j + 2)] = [type + ':' + arg]
1211 document.body[i : (j + 1)] = [type + ':' + arg]
1214 def convert_pdf_options(document):
1215 # Set the pdfusetitle tag, delete the pdf_store_options,
1216 # set quotes for bookmarksopenlevel"
1217 has_hr = get_value(document.header, "\\use_hyperref", 0, default = "0")
1219 k = find_token(document.header, "\\use_hyperref", 0)
1220 document.header.insert(k + 1, "\\pdf_pdfusetitle true")
1221 k = find_token(document.header, "\\pdf_store_options", 0)
1223 del document.header[k]
1224 i = find_token(document.header, "\\pdf_bookmarksopenlevel", k)
1226 document.header[i] = document.header[i].replace('"', '')
1229 def revert_pdf_options_2(document):
1230 # reset the pdfusetitle tag, set quotes for bookmarksopenlevel"
1231 k = find_token(document.header, "\\use_hyperref", 0)
1232 i = find_token(document.header, "\\pdf_pdfusetitle", k)
1234 del document.header[i]
1235 i = find_token(document.header, "\\pdf_bookmarksopenlevel", k)
1237 values = document.header[i].split()
1238 values[1] = ' "' + values[1] + '"'
1239 document.header[i] = ''.join(values)
1242 def convert_htmlurl(document):
1243 'Convert "htmlurl" to "href" insets for docbook'
1244 if document.backend != "docbook":
1248 i = find_token(document.body, "\\begin_inset CommandInset url", i)
1251 document.body[i] = "\\begin_inset CommandInset href"
1252 document.body[i + 1] = "LatexCommand href"
1256 def convert_url(document):
1257 'Convert url insets to url charstyles'
1258 if document.backend == "docbook":
1262 i = find_token(document.body, "\\begin_inset CommandInset url", i)
1265 n = find_token(document.body, "name", i)
1267 # place the URL name in typewriter before the new URL insert
1268 # grab the name 'bla' from the e.g. the line 'name "bla"',
1269 # therefore start with the 6th character
1270 name = document.body[n][6:-1]
1271 newname = [name + " "]
1272 document.body[i:i] = newname
1274 j = find_token(document.body, "target", i)
1276 document.warning("Malformed LyX document: Can't find target for url inset")
1279 target = document.body[j][8:-1]
1280 k = find_token(document.body, "\\end_inset", j)
1282 document.warning("Malformed LyX document: Can't find end of url inset")
1285 newstuff = ["\\begin_inset Flex URL",
1286 "status collapsed", "",
1287 "\\begin_layout Standard",
1292 document.body[i:k] = newstuff
1295 def convert_ams_classes(document):
1296 tc = document.textclass
1297 if (tc != "amsart" and tc != "amsart-plain" and
1298 tc != "amsart-seq" and tc != "amsbook"):
1300 if tc == "amsart-plain":
1301 document.textclass = "amsart"
1302 document.set_textclass()
1303 document.add_module("Theorems (Starred)")
1305 if tc == "amsart-seq":
1306 document.textclass = "amsart"
1307 document.set_textclass()
1308 document.add_module("Theorems (AMS)")
1310 #Now we want to see if any of the environments in the extended theorems
1311 #module were used in this document. If so, we'll add that module, too.
1312 layouts = ["Criterion", "Algorithm", "Axiom", "Condition", "Note", \
1313 "Notation", "Summary", "Acknowledgement", "Conclusion", "Fact", \
1316 r = re.compile(r'^\\begin_layout (.*?)\*?\s*$')
1319 i = find_token(document.body, "\\begin_layout", i)
1322 m = r.match(document.body[i])
1324 # This is an empty layout
1325 # document.warning("Weirdly formed \\begin_layout at line %d of body!" % i)
1329 if layouts.count(m) != 0:
1330 document.add_module("Theorems (AMS-Extended)")
1334 def revert_href(document):
1335 'Reverts hyperlink insets (href) to url insets (url)'
1338 i = find_token(document.body, "\\begin_inset CommandInset href", i)
1341 document.body[i : i + 2] = \
1342 ["\\begin_inset CommandInset url", "LatexCommand url"]
1345 def revert_url(document):
1346 'Reverts Flex URL insets to old-style URL insets'
1349 i = find_token(document.body, "\\begin_inset Flex URL", i)
1352 j = find_end_of_inset(document.body, i)
1354 document.warning("Can't find end of inset in revert_url!")
1356 k = find_default_layout(document, i, j)
1358 document.warning("Can't find default layout in revert_url!")
1361 l = find_end_of(document.body, k, "\\begin_layout", "\\end_layout")
1362 if l == -1 or l >= j:
1363 document.warning("Can't find end of default layout in revert_url!")
1366 # OK, so the inset's data is between lines k and l.
1367 data = " ".join(document.body[k+1:l])
1369 newinset = ["\\begin_inset LatexCommand url", "target \"" + data + "\"",\
1371 document.body[i:j+1] = newinset
1372 i = i + len(newinset)
1375 def convert_include(document):
1376 'Converts include insets to new format.'
1378 r = re.compile(r'\\begin_inset Include\s+\\([^{]+){([^}]*)}(?:\[(.*)\])?')
1380 i = find_token(document.body, "\\begin_inset Include", i)
1383 line = document.body[i]
1384 previewline = document.body[i + 1]
1387 document.warning("Unable to match line " + str(i) + " of body!")
1393 insertion = ["\\begin_inset CommandInset include",
1394 "LatexCommand " + cmd, previewline,
1395 "filename \"" + fn + "\""]
1398 insertion.append("lstparams " + '"' + opt + '"')
1400 document.body[i : i + 2] = insertion
1404 def revert_include(document):
1405 'Reverts include insets to old format.'
1407 r0 = re.compile('preview.*')
1408 r1 = re.compile('LatexCommand (.+)')
1409 r2 = re.compile('filename "(.+)"')
1410 r3 = re.compile('lstparams "(.*)"')
1412 i = find_token(document.body, "\\begin_inset CommandInset include", i)
1416 if r0.match(document.body[nextline]):
1417 previewline = document.body[nextline]
1421 m = r1.match(document.body[nextline])
1423 document.warning("Malformed LyX document: No LatexCommand line for `" +
1424 document.body[i] + "' on line " + str(i) + ".")
1429 m = r2.match(document.body[nextline])
1431 document.warning("Malformed LyX document: No filename line for `" + \
1432 document.body[i] + "' on line " + str(i) + ".")
1438 if (cmd == "lstinputlisting"):
1439 m = r3.match(document.body[nextline])
1441 options = m.group(1)
1444 newline = "\\begin_inset Include \\" + cmd + "{" + fn + "}"
1446 newline += ("[" + options + "]")
1447 insertion = [newline]
1448 if previewline != "":
1449 insertion.append(previewline)
1450 document.body[i : nextline] = insertion
1454 def revert_albanian(document):
1455 "Set language Albanian to English"
1457 if document.language == "albanian":
1458 document.language = "english"
1459 i = find_token(document.header, "\\language", 0)
1461 document.header[i] = "\\language english"
1464 j = find_token(document.body, "\\lang albanian", j)
1467 document.body[j] = document.body[j].replace("\\lang albanian", "\\lang english")
1471 def revert_lowersorbian(document):
1472 "Set language lower Sorbian to English"
1474 if document.language == "lowersorbian":
1475 document.language = "english"
1476 i = find_token(document.header, "\\language", 0)
1478 document.header[i] = "\\language english"
1481 j = find_token(document.body, "\\lang lowersorbian", j)
1484 document.body[j] = document.body[j].replace("\\lang lowersorbian", "\\lang english")
1488 def revert_uppersorbian(document):
1489 "Set language uppersorbian to usorbian as this was used in LyX 1.5"
1491 if document.language == "uppersorbian":
1492 document.language = "usorbian"
1493 i = find_token(document.header, "\\language", 0)
1495 document.header[i] = "\\language usorbian"
1498 j = find_token(document.body, "\\lang uppersorbian", j)
1501 document.body[j] = document.body[j].replace("\\lang uppersorbian", "\\lang usorbian")
1505 def convert_usorbian(document):
1506 "Set language usorbian to uppersorbian"
1508 if document.language == "usorbian":
1509 document.language = "uppersorbian"
1510 i = find_token(document.header, "\\language", 0)
1512 document.header[i] = "\\language uppersorbian"
1515 j = find_token(document.body, "\\lang usorbian", j)
1518 document.body[j] = document.body[j].replace("\\lang usorbian", "\\lang uppersorbian")
1522 def revert_macro_optional_params(document):
1523 "Convert macro definitions with optional parameters into ERTs"
1524 # Stub to convert macro definitions with one or more optional parameters
1525 # into uninterpreted ERT insets
1528 def revert_hyperlinktype(document):
1529 'Reverts hyperlink type'
1533 i = find_token(document.body, "target", i)
1536 j = find_token(document.body, "type", i)
1540 del document.body[j]
1544 def revert_pagebreak(document):
1545 'Reverts pagebreak to ERT'
1548 i = find_token(document.body, "\\pagebreak", i)
1551 document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1552 '\\begin_layout Standard\n\n\n\\backslash\n' \
1553 'pagebreak{}\n\\end_layout\n\n\\end_inset\n\n'
1557 def revert_linebreak(document):
1558 'Reverts linebreak to ERT'
1561 i = find_token(document.body, "\\linebreak", i)
1564 document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1565 '\\begin_layout Standard\n\n\n\\backslash\n' \
1566 'linebreak{}\n\\end_layout\n\n\\end_inset\n\n'
1570 def revert_latin(document):
1571 "Set language Latin to English"
1573 if document.language == "latin":
1574 document.language = "english"
1575 i = find_token(document.header, "\\language", 0)
1577 document.header[i] = "\\language english"
1580 j = find_token(document.body, "\\lang latin", j)
1583 document.body[j] = document.body[j].replace("\\lang latin", "\\lang english")
1587 def revert_samin(document):
1588 "Set language North Sami to English"
1590 if document.language == "samin":
1591 document.language = "english"
1592 i = find_token(document.header, "\\language", 0)
1594 document.header[i] = "\\language english"
1597 j = find_token(document.body, "\\lang samin", j)
1600 document.body[j] = document.body[j].replace("\\lang samin", "\\lang english")
1604 def convert_serbocroatian(document):
1605 "Set language Serbocroatian to Croatian as this was really Croatian in LyX 1.5"
1607 if document.language == "serbocroatian":
1608 document.language = "croatian"
1609 i = find_token(document.header, "\\language", 0)
1611 document.header[i] = "\\language croatian"
1614 j = find_token(document.body, "\\lang serbocroatian", j)
1617 document.body[j] = document.body[j].replace("\\lang serbocroatian", "\\lang croatian")
1621 def convert_framed_notes(document):
1622 "Convert framed notes to boxes. "
1625 i = find_tokens(document.body, ["\\begin_inset Note Framed", "\\begin_inset Note Shaded"], i)
1628 subst = [document.body[i].replace("\\begin_inset Note", "\\begin_inset Box"),
1637 'height_special "totalheight"']
1638 document.body[i:i+1] = subst
1642 def convert_module_names(document):
1643 modulemap = { 'Braille' : 'braille', 'Endnote' : 'endnotes', 'Foot to End' : 'foottoend',\
1644 'Hanging' : 'hanging', 'Linguistics' : 'linguistics', 'Logical Markup' : 'logicalmkup', \
1645 'Theorems (AMS-Extended)' : 'theorems-ams-extended', 'Theorems (AMS)' : 'theorems-ams', \
1646 'Theorems (Order By Chapter)' : 'theorems-chap', 'Theorems (Order By Section)' : 'theorems-sec', \
1647 'Theorems (Starred)' : 'theorems-starred', 'Theorems' : 'theorems-std' }
1648 modlist = document.get_module_list()
1649 if len(modlist) == 0:
1653 if modulemap.has_key(mod):
1654 newmodlist.append(modulemap[mod])
1656 document.warning("Can't find module %s in the module map!" % mod)
1657 newmodlist.append(mod)
1658 document.set_module_list(newmodlist)
1661 def revert_module_names(document):
1662 modulemap = { 'braille' : 'Braille', 'endnotes' : 'Endnote', 'foottoend' : 'Foot to End',\
1663 'hanging' : 'Hanging', 'linguistics' : 'Linguistics', 'logicalmkup' : 'Logical Markup', \
1664 'theorems-ams-extended' : 'Theorems (AMS-Extended)', 'theorems-ams' : 'Theorems (AMS)', \
1665 'theorems-chap' : 'Theorems (Order By Chapter)', 'theorems-sec' : 'Theorems (Order By Section)', \
1666 'theorems-starred' : 'Theorems (Starred)', 'theorems-std' : 'Theorems'}
1667 modlist = document.get_module_list()
1668 if len(modlist) == 0:
1672 if modulemap.has_key(mod):
1673 newmodlist.append(modulemap[mod])
1675 document.warning("Can't find module %s in the module map!" % mod)
1676 newmodlist.append(mod)
1677 document.set_module_list(newmodlist)
1680 def revert_colsep(document):
1681 i = find_token(document.header, "\\columnsep", 0)
1684 colsepline = document.header[i]
1685 r = re.compile(r'\\columnsep (.*)')
1686 m = r.match(colsepline)
1688 document.warning("Malformed column separation line!")
1691 del document.header[i]
1692 #it seems to be safe to add the package even if it is already used
1693 pretext = ["\\usepackage{geometry}", "\\geometry{columnsep=" + colsep + "}"]
1695 add_to_preamble(document, pretext)
1698 def revert_framed_notes(document):
1699 "Revert framed boxes to notes. "
1702 i = find_tokens(document.body, ["\\begin_inset Box Framed", "\\begin_inset Box Shaded"], i)
1706 j = find_end_of_inset(document.body, i + 1)
1709 document.warning("Malformed LyX document: Could not find end of Box inset.")
1710 k = find_token(document.body, "status", i + 1, j)
1712 document.warning("Malformed LyX document: Missing `status' tag in Box inset.")
1714 status = document.body[k]
1715 l = find_default_layout(document, i + 1, j)
1717 document.warning("Malformed LyX document: Missing `\\begin_layout' in Box inset.")
1719 m = find_token(document.body, "\\end_layout", i + 1, j)
1721 document.warning("Malformed LyX document: Missing `\\end_layout' in Box inset.")
1723 ibox = find_token(document.body, "has_inner_box 1", i + 1, k)
1724 pbox = find_token(document.body, "use_parbox 1", i + 1, k)
1725 if ibox == -1 and pbox == -1:
1726 document.body[i] = document.body[i].replace("\\begin_inset Box", "\\begin_inset Note")
1727 del document.body[i+1:k]
1729 document.body[i] = document.body[i].replace("\\begin_inset Box Shaded", "\\begin_inset Box Frameless")
1730 subst1 = [document.body[l],
1731 "\\begin_inset Note Shaded",
1733 '\\begin_layout Standard']
1734 document.body[l:l + 1] = subst1
1735 subst2 = [document.body[m], "\\end_layout", "\\end_inset"]
1736 document.body[m:m + 1] = subst2
1740 def revert_slash(document):
1741 'Revert \\SpecialChar \\slash{} to ERT'
1742 r = re.compile(r'\\SpecialChar \\slash{}')
1744 while i < len(document.body):
1745 m = r.match(document.body[i])
1747 subst = ['\\begin_inset ERT',
1748 'status collapsed', '',
1749 '\\begin_layout Standard',
1750 '', '', '\\backslash',
1754 document.body[i: i+1] = subst
1760 def revert_nobreakdash(document):
1761 'Revert \\SpecialChar \\nobreakdash- to ERT'
1763 while i < len(document.body):
1764 line = document.body[i]
1765 r = re.compile(r'\\SpecialChar \\nobreakdash-')
1768 subst = ['\\begin_inset ERT',
1769 'status collapsed', '',
1770 '\\begin_layout Standard', '', '',
1775 document.body[i:i+1] = subst
1777 j = find_token(document.header, "\\use_amsmath", 0)
1779 document.warning("Malformed LyX document: Missing '\\use_amsmath'.")
1781 document.header[j] = "\\use_amsmath 2"
1786 #Returns number of lines added/removed
1787 def revert_nocite_key(body, start, end):
1788 'key "..." -> \nocite{...}'
1789 r = re.compile(r'^key "(.*)"')
1793 m = r.match(body[i])
1795 body[i:i+1] = ["\\backslash", "nocite{" + m.group(1) + "}"]
1796 j += 1 # because we added a line
1797 i += 2 # skip that line
1800 j -= 1 # because we deleted a line
1801 # no need to change i, since it now points to the next line
1805 def revert_nocite(document):
1806 "Revert LatexCommand nocite to ERT"
1809 i = find_token(document.body, "\\begin_inset CommandInset citation", i)
1812 if (document.body[i+1] != "LatexCommand nocite"):
1813 # note that we already incremented i
1816 insetEnd = find_end_of_inset(document.body, i)
1818 #this should not happen
1819 document.warning("End of CommandInset citation not found in revert_nocite!")
1822 paramLocation = i + 2 #start of the inset's parameters
1824 document.body[i:i+2] = \
1825 ["\\begin_inset ERT", "status collapsed", "", "\\begin_layout Standard"]
1826 # that added two lines
1829 #print insetEnd, document.body[i: insetEnd + 1]
1830 insetEnd += revert_nocite_key(document.body, paramLocation, insetEnd)
1831 #print insetEnd, document.body[i: insetEnd + 1]
1832 document.body.insert(insetEnd, "\\end_layout")
1833 document.body.insert(insetEnd + 1, "")
1837 def revert_btprintall(document):
1838 "Revert (non-bibtopic) btPrintAll option to ERT \nocite{*}"
1839 i = find_token(document.header, '\\use_bibtopic', 0)
1841 document.warning("Malformed lyx document: Missing '\\use_bibtopic'.")
1843 if get_value(document.header, '\\use_bibtopic', 0) == "false":
1845 while i < len(document.body):
1846 i = find_token(document.body, "\\begin_inset CommandInset bibtex", i)
1849 j = find_end_of_inset(document.body, i + 1)
1851 #this should not happen
1852 document.warning("End of CommandInset bibtex not found in revert_btprintall!")
1853 j = len(document.body)
1854 # this range isn't really right, but it should be OK, since we shouldn't
1855 # see more than one matching line in each inset
1857 for k in range(i, j):
1858 if (document.body[k] == 'btprint "btPrintAll"'):
1859 del document.body[k]
1860 subst = ["\\begin_inset ERT",
1861 "status collapsed", "",
1862 "\\begin_layout Standard", "",
1867 document.body[i:i] = subst
1868 addlines = addedlines + len(subst) - 1
1872 def revert_bahasam(document):
1873 "Set language Bahasa Malaysia to Bahasa Indonesia"
1875 if document.language == "bahasam":
1876 document.language = "bahasa"
1877 i = find_token(document.header, "\\language", 0)
1879 document.header[i] = "\\language bahasa"
1882 j = find_token(document.body, "\\lang bahasam", j)
1885 document.body[j] = document.body[j].replace("\\lang bahasam", "\\lang bahasa")
1889 def revert_interlingua(document):
1890 "Set language Interlingua to English"
1892 if document.language == "interlingua":
1893 document.language = "english"
1894 i = find_token(document.header, "\\language", 0)
1896 document.header[i] = "\\language english"
1899 j = find_token(document.body, "\\lang interlingua", j)
1902 document.body[j] = document.body[j].replace("\\lang interlingua", "\\lang english")
1906 def revert_serbianlatin(document):
1907 "Set language Serbian-Latin to Croatian"
1909 if document.language == "serbian-latin":
1910 document.language = "croatian"
1911 i = find_token(document.header, "\\language", 0)
1913 document.header[i] = "\\language croatian"
1916 j = find_token(document.body, "\\lang serbian-latin", j)
1919 document.body[j] = document.body[j].replace("\\lang serbian-latin", "\\lang croatian")
1923 def revert_rotfloat(document):
1924 " Revert sideways custom floats. "
1927 # whitespace intended (exclude \\begin_inset FloatList)
1928 i = find_token(document.body, "\\begin_inset Float ", i)
1931 line = document.body[i]
1932 r = re.compile(r'\\begin_inset Float (.*)$')
1935 document.warning("Unable to match line " + str(i) + " of body!")
1938 floattype = m.group(1)
1939 if floattype == "figure" or floattype == "table":
1942 j = find_end_of_inset(document.body, i)
1944 document.warning("Malformed lyx document: Missing '\\end_inset' in revert_rotfloat.")
1948 if get_value(document.body, 'sideways', i, j) == "false":
1951 l = find_default_layout(document, i + 1, j)
1953 document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
1955 subst = ['\\begin_layout Standard',
1956 '\\begin_inset ERT',
1957 'status collapsed', '',
1958 '\\begin_layout Standard', '', '',
1960 'end{sideways' + floattype + '}',
1961 '\\end_layout', '', '\\end_inset']
1962 document.body[j : j+1] = subst
1963 addedLines = len(subst) - 1
1964 del document.body[i+1 : l]
1965 addedLines -= (l-1) - (i+1)
1966 subst = ['\\begin_inset ERT', 'status collapsed', '',
1967 '\\begin_layout Standard', '', '', '\\backslash',
1968 'begin{sideways' + floattype + '}',
1969 '\\end_layout', '', '\\end_inset', '',
1971 document.body[i : i+1] = subst
1972 addedLines += len(subst) - 1
1973 if floattype == "algorithm":
1974 add_to_preamble(document,
1975 ['% Commands inserted by lyx2lyx for sideways algorithm float',
1976 '\\usepackage{rotfloat}',
1977 '\\floatstyle{ruled}',
1978 '\\newfloat{algorithm}{tbp}{loa}',
1979 '\\floatname{algorithm}{Algorithm}'])
1981 document.warning("Cannot create preamble definition for custom float" + floattype + ".")
1985 def revert_widesideways(document):
1986 " Revert wide sideways floats. "
1989 # whitespace intended (exclude \\begin_inset FloatList)
1990 i = find_token(document.body, '\\begin_inset Float ', i)
1993 line = document.body[i]
1994 r = re.compile(r'\\begin_inset Float (.*)$')
1997 document.warning("Unable to match line " + str(i) + " of body!")
2000 floattype = m.group(1)
2001 if floattype != "figure" and floattype != "table":
2004 j = find_end_of_inset(document.body, i)
2006 document.warning("Malformed lyx document: Missing '\\end_inset' in revert_widesideways.")
2009 if get_value(document.body, 'sideways', i, j) == "false" or \
2010 get_value(document.body, 'wide', i, j) == "false":
2013 l = find_default_layout(document, i + 1, j)
2015 document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
2017 subst = ['\\begin_layout Standard', '\\begin_inset ERT',
2018 'status collapsed', '',
2019 '\\begin_layout Standard', '', '', '\\backslash',
2020 'end{sideways' + floattype + '*}',
2021 '\\end_layout', '', '\\end_inset']
2022 document.body[j : j+1] = subst
2023 addedLines = len(subst) - 1
2024 del document.body[i+1:l-1]
2025 addedLines -= (l-1) - (i+1)
2026 subst = ['\\begin_inset ERT', 'status collapsed', '',
2027 '\\begin_layout Standard', '', '', '\\backslash',
2028 'begin{sideways' + floattype + '*}', '\\end_layout', '',
2029 '\\end_inset', '', '\\end_layout', '']
2030 document.body[i : i+1] = subst
2031 addedLines += len(subst) - 1
2032 add_to_preamble(document, ['\\usepackage{rotfloat}\n'])
2036 def revert_inset_embedding(document, type):
2037 ' Remove embed tag from certain type of insets'
2040 i = find_token(document.body, "\\begin_inset %s" % type, i)
2043 j = find_end_of_inset(document.body, i)
2045 document.warning("Malformed lyx document: Missing '\\end_inset' in revert_inset_embedding.")
2048 k = find_token(document.body, "\tembed", i, j)
2050 k = find_token(document.body, "embed", i, j)
2052 del document.body[k]
2056 def revert_external_embedding(document):
2057 ' Remove embed tag from external inset '
2058 revert_inset_embedding(document, 'External')
2061 def convert_subfig(document):
2062 " Convert subfigures to subfloats. "
2065 i = find_token(document.body, '\\begin_inset Graphics', i)
2068 endInset = find_end_of_inset(document.body, i)
2070 document.warning("Malformed lyx document: Missing '\\end_inset' in convert_subfig.")
2073 k = find_token(document.body, '\tsubcaption', i, endInset)
2077 l = find_token(document.body, '\tsubcaptionText', i, endInset)
2079 document.warning("Malformed lyx document: Can't find subcaptionText!")
2082 caption = document.body[l][16:].strip('"')
2083 del document.body[l]
2084 del document.body[k]
2086 subst = ['\\begin_inset Float figure', 'wide false', 'sideways false',
2087 'status open', '', '\\begin_layout Plain Layout', '\\begin_inset Caption',
2088 '', '\\begin_layout Plain Layout'] + latex2lyx(caption) + \
2089 [ '\\end_layout', '', '\\end_inset', '',
2090 '\\end_layout', '', '\\begin_layout Plain Layout']
2091 document.body[i : i] = subst
2092 addedLines += len(subst)
2093 endInset += addedLines
2094 subst = ['', '\\end_inset', '', '\\end_layout']
2095 document.body[endInset : endInset] = subst
2096 addedLines += len(subst)
2100 def revert_subfig(document):
2101 " Revert subfloats. "
2104 # whitespace intended (exclude \\begin_inset FloatList)
2105 i = find_tokens(document.body, ['\\begin_inset Float ', '\\begin_inset Wrap'], i)
2111 j = find_end_of_inset(document.body, i)
2113 document.warning("Malformed lyx document: Missing '\\end_inset' (float) at line " + str(i + len(document.header)) + ".\n\t" + document.body[i])
2114 # document.warning(document.body[i-1] + "\n" + document.body[i+1])
2116 continue # this will get us back to the outer loop, since j == -1
2117 # look for embedded float (= subfloat)
2118 # whitespace intended (exclude \\begin_inset FloatList)
2119 k = find_token(document.body, '\\begin_inset Float ', i + 1, j)
2122 l = find_end_of_inset(document.body, k)
2124 document.warning("Malformed lyx document: Missing '\\end_inset' (embedded float).")
2127 continue # escape to the outer loop
2128 m = find_default_layout(document, k + 1, l)
2130 cap = find_token(document.body, '\\begin_inset Caption', k + 1, l)
2135 capend = find_end_of_inset(document.body, cap)
2137 document.warning("Malformed lyx document: Missing '\\end_inset' (caption).")
2141 lbl = find_token(document.body, '\\begin_inset CommandInset label', cap, capend)
2143 lblend = find_end_of_inset(document.body, lbl + 1)
2145 document.warning("Malformed lyx document: Missing '\\end_inset' (label).")
2147 for line in document.body[lbl:lblend + 1]:
2148 if line.startswith('name '):
2149 label = line.split()[1].strip('"')
2156 opt = find_token(document.body, '\\begin_inset OptArg', cap, capend)
2158 optend = find_end_of_inset(document.body, opt)
2160 document.warning("Malformed lyx document: Missing '\\end_inset' (OptArg).")
2162 optc = find_default_layout(document, opt, optend)
2164 document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
2166 optcend = find_end_of(document.body, optc, "\\begin_layout", "\\end_layout")
2167 for line in document.body[optc:optcend]:
2168 if not line.startswith('\\'):
2169 shortcap += line.strip()
2173 for line in document.body[cap:capend]:
2174 if line in document.body[lbl:lblend]:
2176 elif line in document.body[opt:optend]:
2178 elif not line.startswith('\\'):
2179 caption += line.strip()
2181 caption += "\\backslash\nlabel{" + label + "}"
2182 subst = '\\begin_layout Plain Layout\n\\begin_inset ERT\nstatus collapsed\n\n' \
2183 '\\begin_layout Plain Layout\n\n}\n\\end_layout\n\n\\end_inset\n\n' \
2184 '\\end_layout\n\n\\begin_layout Plain Layout\n'
2185 subst = subst.split('\n')
2186 document.body[l : l+1] = subst
2187 addedLines = len(subst) - 1
2188 # this is before l and so is unchanged by the multiline insertion
2190 del document.body[cap:capend+1]
2191 addedLines -= (capend + 1 - cap)
2192 del document.body[k+1:m-1]
2193 addedLines -= (m - 1 - (k + 1))
2194 insertion = '\\begin_inset ERT\nstatus collapsed\n\n' \
2195 '\\begin_layout Plain Layout\n\n\\backslash\n' \
2197 if len(shortcap) > 0:
2198 insertion = insertion + "[" + shortcap + "]"
2199 if len(caption) > 0:
2200 insertion = insertion + "[" + caption + "]"
2201 insertion = insertion + '{%\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n'
2202 insertion = insertion.split('\n')
2203 document.body[k : k + 1] = insertion
2204 addedLines += len(insertion) - 1
2205 add_to_preamble(document, ['\\usepackage{subfig}\n'])
2209 def revert_wrapplacement(document):
2210 " Revert placement options wrap floats (wrapfig). "
2213 i = find_token(document.body, "\\begin_inset Wrap figure", i)
2216 e = find_end_of_inset(document.body, i)
2217 j = find_token(document.body, "placement", i + 1, e)
2219 document.warning("Malformed LyX document: Couldn't find placement parameter of wrap float.")
2222 r = re.compile("placement (o|i|l|r)")
2223 m = r.match(document.body[j])
2225 document.warning("Malformed LyX document: Placement option isn't O|I|R|L!")
2226 document.body[j] = "placement " + m.group(1).lower()
2230 def remove_extra_embedded_files(document):
2231 " Remove \extra_embedded_files from buffer params "
2232 i = find_token(document.header, '\\extra_embedded_files', 0)
2235 document.header.pop(i)
2238 def convert_spaceinset(document):
2239 " Convert '\\InsetSpace foo' to '\\begin_inset Space foo\n\\end_inset' "
2241 while i < len(document.body):
2242 m = re.match(r'(.*)\\InsetSpace (.*)', document.body[i])
2246 subst = [before, "\\begin_inset Space " + after, "\\end_inset"]
2247 document.body[i: i+1] = subst
2253 def revert_spaceinset(document):
2254 " Revert '\\begin_inset Space foo\n\\end_inset' to '\\InsetSpace foo' "
2257 i = find_token(document.body, "\\begin_inset Space", i)
2260 j = find_end_of_inset(document.body, i)
2262 document.warning("Malformed LyX document: Could not find end of space inset.")
2264 document.body[i] = document.body[i].replace('\\begin_inset Space', '\\InsetSpace')
2265 del document.body[j]
2268 def convert_hfill(document):
2269 " Convert hfill to space inset "
2272 i = find_token(document.body, "\\hfill", i)
2275 subst = document.body[i].replace('\\hfill', \
2276 '\n\\begin_inset Space \\hfill{}\n\\end_inset')
2277 subst = subst.split('\n')
2278 document.body[i : i+1] = subst
2282 def revert_hfills(document):
2283 ' Revert \\hfill commands '
2284 hfill = re.compile(r'\\hfill')
2285 dotfill = re.compile(r'\\dotfill')
2286 hrulefill = re.compile(r'\\hrulefill')
2289 i = find_token(document.body, "\\InsetSpace", i)
2292 if hfill.search(document.body[i]):
2293 document.body[i] = \
2294 document.body[i].replace('\\InsetSpace \\hfill{}', '\\hfill')
2297 if dotfill.search(document.body[i]):
2298 subst = document.body[i].replace('\\InsetSpace \\dotfill{}', \
2299 '\\begin_inset ERT\nstatus collapsed\n\n' \
2300 '\\begin_layout Standard\n\n\n\\backslash\n' \
2301 'dotfill{}\n\\end_layout\n\n\\end_inset\n\n')
2302 subst = subst.split('\n')
2303 document.body[i : i+1] = subst
2306 if hrulefill.search(document.body[i]):
2307 subst = document.body[i].replace('\\InsetSpace \\hrulefill{}', \
2308 '\\begin_inset ERT\nstatus collapsed\n\n' \
2309 '\\begin_layout Standard\n\n\n\\backslash\n' \
2310 'hrulefill{}\n\\end_layout\n\n\\end_inset\n\n')
2311 subst = subst.split('\n')
2312 document.body[i : i+1] = subst
2317 def revert_hspace(document):
2318 ' Revert \\InsetSpace \\hspace{} to ERT '
2320 hspace = re.compile(r'\\hspace{}')
2321 hstar = re.compile(r'\\hspace\*{}')
2323 i = find_token(document.body, "\\InsetSpace \\hspace", i)
2326 length = get_value(document.body, '\\length', i+1)
2328 document.warning("Malformed lyx document: Missing '\\length' in Space inset.")
2330 del document.body[i+1]
2332 if hstar.search(document.body[i]):
2333 subst = document.body[i].replace('\\InsetSpace \\hspace*{}', \
2334 '\\begin_inset ERT\nstatus collapsed\n\n' \
2335 '\\begin_layout Standard\n\n\n\\backslash\n' \
2336 'hspace*{' + length + '}\n\\end_layout\n\n\\end_inset\n\n')
2337 subst = subst.split('\n')
2338 document.body[i : i+1] = subst
2339 addedLines += len(subst) - 1
2342 if hspace.search(document.body[i]):
2343 subst = document.body[i].replace('\\InsetSpace \\hspace{}', \
2344 '\\begin_inset ERT\nstatus collapsed\n\n' \
2345 '\\begin_layout Standard\n\n\n\\backslash\n' \
2346 'hspace{' + length + '}\n\\end_layout\n\n\\end_inset\n\n')
2347 subst = subst.split('\n')
2348 document.body[i : i+1] = subst
2349 addedLines += len(subst) - 1
2355 def revert_protected_hfill(document):
2356 ' Revert \\begin_inset Space \\hspace*{\\fill} to ERT '
2359 i = find_token(document.body, '\\begin_inset Space \\hspace*{\\fill}', i)
2362 j = find_end_of_inset(document.body, i)
2364 document.warning("Malformed LyX document: Could not find end of space inset.")
2366 del document.body[j]
2367 subst = document.body[i].replace('\\begin_inset Space \\hspace*{\\fill}', \
2368 '\\begin_inset ERT\nstatus collapsed\n\n' \
2369 '\\begin_layout Standard\n\n\n\\backslash\n' \
2370 'hspace*{\n\\backslash\nfill}\n\\end_layout\n\n\\end_inset\n\n')
2371 subst = subst.split('\n')
2372 document.body[i : i+1] = subst
2376 def revert_leftarrowfill(document):
2377 ' Revert \\begin_inset Space \\leftarrowfill{} to ERT '
2380 i = find_token(document.body, '\\begin_inset Space \\leftarrowfill{}', i)
2383 j = find_end_of_inset(document.body, i)
2385 document.warning("Malformed LyX document: Could not find end of space inset.")
2387 del document.body[j]
2388 subst = document.body[i].replace('\\begin_inset Space \\leftarrowfill{}', \
2389 '\\begin_inset ERT\nstatus collapsed\n\n' \
2390 '\\begin_layout Standard\n\n\n\\backslash\n' \
2391 'leftarrowfill{}\n\\end_layout\n\n\\end_inset\n\n')
2392 subst = subst.split('\n')
2393 document.body[i : i+1] = subst
2397 def revert_rightarrowfill(document):
2398 ' Revert \\begin_inset Space \\rightarrowfill{} to ERT '
2401 i = find_token(document.body, '\\begin_inset Space \\rightarrowfill{}', i)
2404 j = find_end_of_inset(document.body, i)
2406 document.warning("Malformed LyX document: Could not find end of space inset.")
2408 del document.body[j]
2409 subst = document.body[i].replace('\\begin_inset Space \\rightarrowfill{}', \
2410 '\\begin_inset ERT\nstatus collapsed\n\n' \
2411 '\\begin_layout Standard\n\n\n\\backslash\n' \
2412 'rightarrowfill{}\n\\end_layout\n\n\\end_inset\n\n')
2413 subst = subst.split('\n')
2414 document.body[i : i+1] = subst
2418 def revert_upbracefill(document):
2419 ' Revert \\begin_inset Space \\upbracefill{} to ERT '
2422 i = find_token(document.body, '\\begin_inset Space \\upbracefill{}', i)
2425 j = find_end_of_inset(document.body, i)
2427 document.warning("Malformed LyX document: Could not find end of space inset.")
2429 del document.body[j]
2430 subst = document.body[i].replace('\\begin_inset Space \\upbracefill{}', \
2431 '\\begin_inset ERT\nstatus collapsed\n\n' \
2432 '\\begin_layout Standard\n\n\n\\backslash\n' \
2433 'upbracefill{}\n\\end_layout\n\n\\end_inset\n\n')
2434 subst = subst.split('\n')
2435 document.body[i : i+1] = subst
2439 def revert_downbracefill(document):
2440 ' Revert \\begin_inset Space \\downbracefill{} to ERT '
2443 i = find_token(document.body, '\\begin_inset Space \\downbracefill{}', i)
2446 j = find_end_of_inset(document.body, i)
2448 document.warning("Malformed LyX document: Could not find end of space inset.")
2450 del document.body[j]
2451 subst = document.body[i].replace('\\begin_inset Space \\downbracefill{}', \
2452 '\\begin_inset ERT\nstatus collapsed\n\n' \
2453 '\\begin_layout Standard\n\n\n\\backslash\n' \
2454 'downbracefill{}\n\\end_layout\n\n\\end_inset\n\n')
2455 subst = subst.split('\n')
2456 document.body[i : i+1] = subst
2460 def revert_local_layout(document):
2461 ' Revert local layout headers.'
2464 i = find_token(document.header, "\\begin_local_layout", i)
2467 j = find_end_of(document.header, i, "\\begin_local_layout", "\\end_local_layout")
2469 # this should not happen
2471 document.header[i : j + 1] = []
2474 def convert_pagebreaks(document):
2475 ' Convert inline Newpage insets to new format '
2478 i = find_token(document.body, '\\newpage', i)
2481 document.body[i:i+1] = ['\\begin_inset Newpage newpage',
2485 i = find_token(document.body, '\\pagebreak', i)
2488 document.body[i:i+1] = ['\\begin_inset Newpage pagebreak',
2492 i = find_token(document.body, '\\clearpage', i)
2495 document.body[i:i+1] = ['\\begin_inset Newpage clearpage',
2499 i = find_token(document.body, '\\cleardoublepage', i)
2502 document.body[i:i+1] = ['\\begin_inset Newpage cleardoublepage',
2506 def revert_pagebreaks(document):
2507 ' Revert \\begin_inset Newpage to previous inline format '
2510 i = find_token(document.body, '\\begin_inset Newpage', i)
2513 j = find_end_of_inset(document.body, i)
2515 document.warning("Malformed LyX document: Could not find end of Newpage inset.")
2517 del document.body[j]
2518 document.body[i] = document.body[i].replace('\\begin_inset Newpage newpage', '\\newpage')
2519 document.body[i] = document.body[i].replace('\\begin_inset Newpage pagebreak', '\\pagebreak')
2520 document.body[i] = document.body[i].replace('\\begin_inset Newpage clearpage', '\\clearpage')
2521 document.body[i] = document.body[i].replace('\\begin_inset Newpage cleardoublepage', '\\cleardoublepage')
2524 def convert_linebreaks(document):
2525 ' Convert inline Newline insets to new format '
2528 i = find_token(document.body, '\\newline', i)
2531 document.body[i:i+1] = ['\\begin_inset Newline newline',
2535 i = find_token(document.body, '\\linebreak', i)
2538 document.body[i:i+1] = ['\\begin_inset Newline linebreak',
2542 def revert_linebreaks(document):
2543 ' Revert \\begin_inset Newline to previous inline format '
2546 i = find_token(document.body, '\\begin_inset Newline', i)
2549 j = find_end_of_inset(document.body, i)
2551 document.warning("Malformed LyX document: Could not find end of Newline inset.")
2553 del document.body[j]
2554 document.body[i] = document.body[i].replace('\\begin_inset Newline newline', '\\newline')
2555 document.body[i] = document.body[i].replace('\\begin_inset Newline linebreak', '\\linebreak')
2558 def convert_japanese_plain(document):
2559 ' Set language japanese-plain to japanese '
2561 if document.language == "japanese-plain":
2562 document.language = "japanese"
2563 i = find_token(document.header, "\\language", 0)
2565 document.header[i] = "\\language japanese"
2568 j = find_token(document.body, "\\lang japanese-plain", j)
2571 document.body[j] = document.body[j].replace("\\lang japanese-plain", "\\lang japanese")
2575 def revert_pdfpages(document):
2576 ' Revert pdfpages external inset to ERT '
2579 i = find_token(document.body, "\\begin_inset External", i)
2582 j = find_end_of_inset(document.body, i)
2584 document.warning("Malformed lyx document: Missing '\\end_inset' in revert_pdfpages.")
2587 if get_value(document.body, 'template', i, j) == "PDFPages":
2588 filename = get_value(document.body, 'filename', i, j)
2590 r = re.compile(r'\textra PDFLaTeX \"(.*)\"$')
2591 for k in range(i, j):
2592 m = r.match(document.body[k])
2595 angle = get_value(document.body, 'rotateAngle', i, j)
2596 width = get_value(document.body, 'width', i, j)
2597 height = get_value(document.body, 'height', i, j)
2598 scale = get_value(document.body, 'scale', i, j)
2599 keepAspectRatio = find_token(document.body, "\tkeepAspectRatio", i, j)
2603 options += ",angle=" + angle
2605 options += "angle=" + angle
2608 options += ",width=" + convert_len(width)
2610 options += "width=" + convert_len(width)
2613 options += ",height=" + convert_len(height)
2615 options += "height=" + convert_len(height)
2618 options += ",scale=" + scale
2620 options += "scale=" + scale
2621 if keepAspectRatio != '':
2623 options += ",keepaspectratio"
2625 options += "keepaspectratio"
2627 options = '[' + options + ']'
2628 del document.body[i+1:j+1]
2629 document.body[i:i+1] = ['\\begin_inset ERT',
2632 '\\begin_layout Standard',
2635 'includepdf' + options + '{' + filename + '}',
2639 add_to_preamble(document, ['\\usepackage{pdfpages}\n'])
2645 def revert_mexican(document):
2646 ' Set language Spanish(Mexico) to Spanish '
2648 if document.language == "spanish-mexico":
2649 document.language = "spanish"
2650 i = find_token(document.header, "\\language", 0)
2652 document.header[i] = "\\language spanish"
2655 j = find_token(document.body, "\\lang spanish-mexico", j)
2658 document.body[j] = document.body[j].replace("\\lang spanish-mexico", "\\lang spanish")
2662 def remove_embedding(document):
2663 ' Remove embed tag from all insets '
2664 revert_inset_embedding(document, 'Graphics')
2665 revert_inset_embedding(document, 'External')
2666 revert_inset_embedding(document, 'CommandInset include')
2667 revert_inset_embedding(document, 'CommandInset bibtex')
2670 def revert_master(document):
2671 ' Remove master param '
2672 i = find_token(document.header, "\\master", 0)
2674 del document.header[i]
2677 def revert_graphics_group(document):
2678 ' Revert group information from graphics insets '
2681 i = find_token(document.body, "\\begin_inset Graphics", i)
2684 j = find_end_of_inset(document.body, i)
2686 document.warning("Malformed lyx document: Missing '\\end_inset' in revert_graphics_group.")
2689 k = find_token(document.body, " groupId", i, j)
2693 del document.body[k]
2697 def update_apa_styles(document):
2698 ' Replace obsolete styles '
2700 if document.textclass != "apa":
2703 obsoletedby = { "Acknowledgments": "Acknowledgements",
2704 "Section*": "Section",
2705 "Subsection*": "Subsection",
2706 "Subsubsection*": "Subsubsection",
2707 "Paragraph*": "Paragraph",
2708 "Subparagraph*": "Subparagraph"}
2711 i = find_token(document.body, "\\begin_layout", i)
2715 layout = document.body[i][14:]
2716 if layout in obsoletedby:
2717 document.body[i] = "\\begin_layout " + obsoletedby[layout]
2722 def convert_paper_sizes(document):
2723 ' exchange size options legalpaper and executivepaper to correct order '
2724 # routine is needed to fix http://bugzilla.lyx.org/show_bug.cgi?id=4868
2727 i = find_token(document.header, "\\papersize executivepaper", 0)
2729 document.header[i] = "\\papersize legalpaper"
2731 j = find_token(document.header, "\\papersize legalpaper", 0)
2733 document.header[j] = "\\papersize executivepaper"
2736 def revert_paper_sizes(document):
2737 ' exchange size options legalpaper and executivepaper to correct order '
2740 i = find_token(document.header, "\\papersize executivepaper", 0)
2742 document.header[i] = "\\papersize legalpaper"
2744 j = find_token(document.header, "\\papersize legalpaper", 0)
2746 document.header[j] = "\\papersize executivepaper"
2749 def convert_InsetSpace(document):
2750 " Convert '\\begin_inset Space foo' to '\\begin_inset space foo'"
2753 i = find_token(document.body, "\\begin_inset Space", i)
2756 document.body[i] = document.body[i].replace('\\begin_inset Space', '\\begin_inset space')
2759 def revert_InsetSpace(document):
2760 " Revert '\\begin_inset space foo' to '\\begin_inset Space foo'"
2763 i = find_token(document.body, "\\begin_inset space", i)
2766 document.body[i] = document.body[i].replace('\\begin_inset space', '\\begin_inset Space')
2769 def convert_display_enum(document):
2770 " Convert 'display foo' to 'display false/true'"
2773 i = find_token(document.body, "\tdisplay", i)
2776 val = get_value(document.body, 'display', i)
2778 document.body[i] = document.body[i].replace('none', 'false')
2779 if val == "default":
2780 document.body[i] = document.body[i].replace('default', 'true')
2781 if val == "monochrome":
2782 document.body[i] = document.body[i].replace('monochrome', 'true')
2783 if val == "grayscale":
2784 document.body[i] = document.body[i].replace('grayscale', 'true')
2786 document.body[i] = document.body[i].replace('color', 'true')
2787 if val == "preview":
2788 document.body[i] = document.body[i].replace('preview', 'true')
2792 def revert_display_enum(document):
2793 " Revert 'display false/true' to 'display none/color'"
2796 i = find_token(document.body, "\tdisplay", i)
2799 val = get_value(document.body, 'display', i)
2801 document.body[i] = document.body[i].replace('false', 'none')
2803 document.body[i] = document.body[i].replace('true', 'default')
2807 def remove_fontsCJK(document):
2808 ' Remove font_cjk param '
2809 i = find_token(document.header, "\\font_cjk", 0)
2811 del document.header[i]
2814 def convert_plain_layout(document):
2815 " Convert 'PlainLayout' to 'Plain Layout'"
2818 i = find_token(document.body, '\\begin_layout PlainLayout', i)
2821 document.body[i] = document.body[i].replace('\\begin_layout PlainLayout', \
2822 '\\begin_layout Plain Layout')
2826 def revert_plain_layout(document):
2827 " Convert 'PlainLayout' to 'Plain Layout'"
2830 i = find_token(document.body, '\\begin_layout Plain Layout', i)
2833 document.body[i] = document.body[i].replace('\\begin_layout Plain Layout', \
2834 '\\begin_layout PlainLayout')
2838 def revert_plainlayout(document):
2839 " Convert 'PlainLayout' to 'Plain Layout'"
2842 i = find_token(document.body, '\\begin_layout PlainLayout', i)
2845 # This will be incorrect for some document classes, since Standard is not always
2846 # the default. But (a) it is probably the best we can do and (b) it will actually
2847 # work, in fact, since an unknown layout will be converted to default.
2848 document.body[i] = document.body[i].replace('\\begin_layout PlainLayout', \
2849 '\\begin_layout Standard')
2853 def revert_polytonicgreek(document):
2854 "Set language polytonic Greek to Greek"
2856 if document.language == "polutonikogreek":
2857 document.language = "greek"
2858 i = find_token(document.header, "\\language", 0)
2860 document.header[i] = "\\language greek"
2863 j = find_token(document.body, "\\lang polutonikogreek", j)
2866 document.body[j] = document.body[j].replace("\\lang polutonikogreek", "\\lang greek")
2870 def revert_removed_modules(document):
2873 i = find_token(document.header, "\\begin_remove_modules", i)
2876 j = find_end_of(document.header, i, "\\begin_remove_modules", "\\end_remove_modules")
2878 # this should not happen
2880 document.header[i : j + 1] = []
2883 def add_plain_layout(document):
2886 i = find_token(document.body, "\\begin_layout", i)
2889 if len(document.body[i].split()) == 1:
2890 document.body[i] = "\\begin_layout Plain Layout"
2897 supported_versions = ["1.6.0","1.6"]
2898 convert = [[277, [fix_wrong_tables]],
2899 [278, [close_begin_deeper]],
2900 [279, [long_charstyle_names]],
2901 [280, [axe_show_label]],
2904 [283, [convert_flex]],
2908 [287, [convert_wrapfig_options]],
2909 [288, [convert_inset_command]],
2910 [289, [convert_latexcommand_index]],
2913 [292, [convert_japanese_cjk]],
2915 [294, [convert_pdf_options]],
2916 [295, [convert_htmlurl, convert_url]],
2917 [296, [convert_include]],
2918 [297, [convert_usorbian]],
2924 [303, [convert_serbocroatian]],
2925 [304, [convert_framed_notes]],
2932 [311, [convert_ams_classes]],
2934 [313, [convert_module_names]],
2937 [316, [convert_subfig]],
2940 [319, [convert_spaceinset, convert_hfill]],
2942 [321, [convert_tablines]],
2943 [322, [convert_plain_layout]],
2944 [323, [convert_pagebreaks]],
2945 [324, [convert_linebreaks]],
2946 [325, [convert_japanese_plain]],
2949 [328, [remove_embedding, remove_extra_embedded_files, remove_inzip_options]],
2952 [331, [convert_ltcaption]],
2954 [333, [update_apa_styles]],
2955 [334, [convert_paper_sizes]],
2956 [335, [convert_InsetSpace]],
2958 [337, [convert_display_enum]],
2961 [340, [add_plain_layout]]
2964 revert = [[339, []],
2965 [338, [revert_removed_modules]],
2966 [337, [revert_polytonicgreek]],
2967 [336, [revert_display_enum]],
2968 [335, [remove_fontsCJK]],
2969 [334, [revert_InsetSpace]],
2970 [333, [revert_paper_sizes]],
2972 [331, [revert_graphics_group]],
2973 [330, [revert_ltcaption]],
2974 [329, [revert_leftarrowfill, revert_rightarrowfill, revert_upbracefill, revert_downbracefill]],
2975 [328, [revert_master]],
2977 [326, [revert_mexican]],
2978 [325, [revert_pdfpages]],
2980 [323, [revert_linebreaks]],
2981 [322, [revert_pagebreaks]],
2982 [321, [revert_local_layout, revert_plain_layout]],
2983 [320, [revert_tablines]],
2984 [319, [revert_protected_hfill]],
2985 [318, [revert_spaceinset, revert_hfills, revert_hspace]],
2986 [317, [remove_extra_embedded_files]],
2987 [316, [revert_wrapplacement]],
2988 [315, [revert_subfig]],
2989 [314, [revert_colsep, revert_plainlayout]],
2991 [312, [revert_module_names]],
2992 [311, [revert_rotfloat, revert_widesideways]],
2993 [310, [revert_external_embedding]],
2994 [309, [revert_btprintall]],
2995 [308, [revert_nocite]],
2996 [307, [revert_serbianlatin]],
2997 [306, [revert_slash, revert_nobreakdash]],
2998 [305, [revert_interlingua]],
2999 [304, [revert_bahasam]],
3000 [303, [revert_framed_notes]],
3002 [301, [revert_latin, revert_samin]],
3003 [300, [revert_linebreak]],
3004 [299, [revert_pagebreak]],
3005 [298, [revert_hyperlinktype]],
3006 [297, [revert_macro_optional_params]],
3007 [296, [revert_albanian, revert_lowersorbian, revert_uppersorbian]],
3008 [295, [revert_include]],
3009 [294, [revert_href, revert_url]],
3010 [293, [revert_pdf_options_2]],
3011 [292, [revert_inset_info]],
3012 [291, [revert_japanese, revert_japanese_encoding, revert_japanese_cjk]],
3013 [290, [revert_vietnamese]],
3014 [289, [revert_wraptable]],
3015 [288, [revert_latexcommand_index]],
3016 [287, [revert_inset_command]],
3017 [286, [revert_wrapfig_options]],
3018 [285, [revert_pdf_options]],
3019 [284, [remove_inzip_options]],
3021 [282, [revert_flex]],
3023 [280, [revert_begin_modules]],
3024 [279, [revert_show_label]],
3025 [278, [revert_long_charstyle_names]],
3031 if __name__ == "__main__":