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)
245 unicode_reps = read_unicodesymbols()
248 #Might should do latex2ert first, then deal with stuff that DOESN'T
249 #end up inside ERT. That routine could be modified so that it returned
250 #a list of lines, and we could then skip ERT bits and only deal with
253 '''Takes a string, possibly multi-line, and returns the result of
254 converting LaTeX constructs into LyX constructs. Returns a list of
255 lines, suitable for insertion into document.body.'''
261 # Convert LaTeX to Unicode
262 # Commands of this sort need to be checked to make sure they are
263 # followed by a non-alpha character, lest we replace too much.
264 hardone = re.compile(r'^\\\\[a-zA-Z]+$')
266 for rep in unicode_reps:
267 if hardone.match(rep[0]):
270 pos = data.find(rep[0], pos)
273 nextpos = pos + len(rep[0])
274 if nextpos < len(data) and data[nextpos].isalpha():
275 # not the end of that command
278 data = data[:pos] + rep[1] + data[nextpos:]
281 data = data.replace(rep[0], rep[1])
284 data = wrap_into_ert(data, r'\"', '"')
287 mathre = re.compile('^(.*?)(\$.*?\$)(.*)')
288 lines = data.split('\n')
290 #document.warning("LINE: " + line)
291 #document.warning(str(i) + ":" + document.body[i])
292 #document.warning("LAST: " + document.body[-1])
297 f = m.group(2).replace('\\\\', '\\')
302 subst = s.split('\n')
304 retval.append("\\begin_inset Formula " + f)
305 retval.append("\\end_inset")
307 # Handle whatever is left, which is just text
309 subst = g.split('\n')
314 def lyx2latex(document, lines):
315 'Convert some LyX stuff into corresponding LaTeX stuff, as best we can.'
316 # clean up multiline stuff
320 for curline in range(len(lines)):
321 line = lines[curline]
322 if line.startswith("\\begin_inset ERT"):
323 # We don't want to replace things inside ERT, so figure out
324 # where the end of the inset is.
325 ert_end = find_end_of_inset(lines, curline + 1)
327 elif line.startswith("\\begin_inset Formula"):
329 elif line.startswith("\\begin_inset Quotes"):
330 # For now, we do a very basic reversion. Someone who understands
331 # quotes is welcome to fix it up.
332 qtype = line[20:].strip()
346 elif line.isspace() or \
347 line.startswith("\\begin_layout") or \
348 line.startswith("\\end_layout") or \
349 line.startswith("\\begin_inset") or \
350 line.startswith("\\end_inset") or \
351 line.startswith("\\lang") or \
352 line.strip() == "status collapsed" or \
353 line.strip() == "status open":
357 # this needs to be added to the preamble because of cases like
358 # \textmu, \textbackslash, etc.
359 add_to_preamble(document, ['% added by lyx2lyx for converted index entries',
360 '\\@ifundefined{textmu}',
361 ' {\\usepackage{textcomp}}{}'])
362 # a lossless reversion is not possible
363 # try at least to handle some common insets and settings
364 if ert_end >= curline:
365 line = line.replace(r'\backslash', r'\\')
367 line = line.replace('&', '\\&{}')
368 line = line.replace('#', '\\#{}')
369 line = line.replace('^', '\\^{}')
370 line = line.replace('%', '\\%{}')
371 line = line.replace('_', '\\_{}')
372 line = line.replace('$', '\\${}')
374 # Do the LyX text --> LaTeX conversion
375 for rep in unicode_reps:
376 line = line.replace(rep[1], rep[0] + "{}")
377 line = line.replace(r'\backslash', r'\textbackslash{}')
378 line = line.replace(r'\series bold', r'\bfseries{}').replace(r'\series default', r'\mdseries{}')
379 line = line.replace(r'\shape italic', r'\itshape{}').replace(r'\shape smallcaps', r'\scshape{}')
380 line = line.replace(r'\shape slanted', r'\slshape{}').replace(r'\shape default', r'\upshape{}')
381 line = line.replace(r'\emph on', r'\em{}').replace(r'\emph default', r'\em{}')
382 line = line.replace(r'\noun on', r'\scshape{}').replace(r'\noun default', r'\upshape{}')
383 line = line.replace(r'\bar under', r'\underbar{').replace(r'\bar default', r'}')
384 line = line.replace(r'\family sans', r'\sffamily{}').replace(r'\family default', r'\normalfont{}')
385 line = line.replace(r'\family typewriter', r'\ttfamily{}').replace(r'\family roman', r'\rmfamily{}')
386 line = line.replace(r'\InsetSpace ', r'').replace(r'\SpecialChar ', r'')
391 ####################################################################
393 def convert_ltcaption(document):
396 i = find_token(document.body, "\\begin_inset Tabular", i)
399 j = find_end_of_inset(document.body, i + 1)
401 document.warning("Malformed LyX document: Could not find end of tabular.")
404 nrows = int(document.body[i+1].split('"')[3])
405 ncols = int(document.body[i+1].split('"')[5])
408 for k in range(nrows):
409 m = find_token(document.body, "<row", m)
412 for k in range(ncols):
413 m = find_token(document.body, "<cell", m)
415 mend = find_token(document.body, "</cell>", m + 1)
416 # first look for caption insets
417 mcap = find_token(document.body, "\\begin_inset Caption", m + 1, mend)
418 # then look for ERT captions
420 mcap = find_token(document.body, "caption", m + 1, mend)
422 mcap = find_token(document.body, "\\backslash", mcap - 1, mcap)
425 if caption == 'true':
427 set_option(document, r, 'caption', 'true')
428 set_option(document, m, 'multicolumn', '1')
429 set_option(document, m, 'bottomline', 'false')
430 set_option(document, m, 'topline', 'false')
431 set_option(document, m, 'rightline', 'false')
432 set_option(document, m, 'leftline', 'false')
433 #j = find_end_of_inset(document.body, j + 1)
435 set_option(document, m, 'multicolumn', '2')
442 #FIXME Use of wrap_into_ert can confuse lyx2lyx
443 def revert_ltcaption(document):
446 i = find_token(document.body, "\\begin_inset Tabular", i)
449 j = find_end_of_inset(document.body, i + 1)
451 document.warning("Malformed LyX document: Could not find end of tabular.")
455 nrows = int(document.body[i+1].split('"')[3])
456 ncols = int(document.body[i+1].split('"')[5])
458 for k in range(nrows):
459 m = find_token(document.body, "<row", m)
460 caption = get_option(document, m, 'caption', 'false')
461 if caption == 'true':
462 remove_option(document, m, 'caption')
463 for k in range(ncols):
464 m = find_token(document.body, "<cell", m)
465 remove_option(document, m, 'multicolumn')
467 m = find_token(document.body, "\\begin_inset Caption", m)
470 m = find_end_of_inset(document.body, m + 1)
471 document.body[m] += wrap_into_ert("","","\\backslash\n\\backslash\n%")
477 def convert_tablines(document):
480 i = find_token(document.body, "\\begin_inset Tabular", i)
482 # LyX 1.3 inserted an extra space between \begin_inset
483 # and Tabular so let us try if this is the case and fix it.
484 i = find_token(document.body, "\\begin_inset Tabular", i)
488 document.body[i] = "\\begin_inset Tabular"
489 j = find_end_of_inset(document.body, i + 1)
491 document.warning("Malformed LyX document: Could not find end of tabular.")
495 nrows = int(document.body[i+1].split('"')[3])
496 ncols = int(document.body[i+1].split('"')[5])
499 for k in range(ncols):
500 m = find_token(document.body, "<column", m)
501 left = get_option(document, m, 'leftline', 'false')
502 right = get_option(document, m, 'rightline', 'false')
503 col_info.append([left, right])
504 remove_option(document, m, 'leftline')
505 remove_option(document, m, 'rightline')
509 for k in range(nrows):
510 m = find_token(document.body, "<row", m)
511 top = get_option(document, m, 'topline', 'false')
512 bottom = get_option(document, m, 'bottomline', 'false')
513 row_info.append([top, bottom])
514 remove_option(document, m, 'topline')
515 remove_option(document, m, 'bottomline')
520 for k in range(nrows*ncols):
521 m = find_token(document.body, "<cell", m)
522 mc_info.append(get_option(document, m, 'multicolumn', '0'))
525 for l in range(nrows):
526 for k in range(ncols):
527 m = find_token(document.body, '<cell', m)
528 if mc_info[l*ncols + k] == '0':
529 r = set_option(document, m, 'topline', row_info[l][0])
530 r = set_option(document, m, 'bottomline', row_info[l][1])
531 r = set_option(document, m, 'leftline', col_info[k][0])
532 r = set_option(document, m, 'rightline', col_info[k][1])
533 elif mc_info[l*ncols + k] == '1':
535 while s < ncols and mc_info[l*ncols + s] == '2':
537 if s < ncols and mc_info[l*ncols + s] != '1':
538 r = set_option(document, m, 'rightline', col_info[k][1])
539 if k > 0 and mc_info[l*ncols + k - 1] == '0':
540 r = set_option(document, m, 'leftline', col_info[k][0])
545 def revert_tablines(document):
548 i = find_token(document.body, "\\begin_inset Tabular", i)
551 j = find_end_of_inset(document.body, i + 1)
553 document.warning("Malformed LyX document: Could not find end of tabular.")
557 nrows = int(document.body[i+1].split('"')[3])
558 ncols = int(document.body[i+1].split('"')[5])
561 for k in range(nrows*ncols):
562 m = find_token(document.body, "<cell", m)
563 top = get_option(document, m, 'topline', 'false')
564 bottom = get_option(document, m, 'bottomline', 'false')
565 left = get_option(document, m, 'leftline', 'false')
566 right = get_option(document, m, 'rightline', 'false')
567 lines.append([top, bottom, left, right])
570 # we will want to ignore longtable captions
573 for k in range(nrows):
574 m = find_token(document.body, "<row", m)
575 caption = get_option(document, m, 'caption', 'false')
576 caption_info.append([caption])
581 for k in range(ncols):
582 m = find_token(document.body, "<column", m)
584 for l in range(nrows):
585 left = lines[l*ncols + k][2]
586 if left == 'false' and caption_info[l] == 'false':
588 set_option(document, m, 'leftline', left)
590 for l in range(nrows):
591 right = lines[l*ncols + k][3]
592 if right == 'false' and caption_info[l] == 'false':
594 set_option(document, m, 'rightline', right)
598 for k in range(nrows):
599 m = find_token(document.body, "<row", m)
601 for l in range(ncols):
602 top = lines[k*ncols + l][0]
605 if caption_info[k] == 'false':
607 set_option(document, m, 'topline', top)
609 for l in range(ncols):
610 bottom = lines[k*ncols + l][1]
611 if bottom == 'false':
613 if caption_info[k] == 'false':
615 set_option(document, m, 'bottomline', bottom)
621 def fix_wrong_tables(document):
624 i = find_token(document.body, "\\begin_inset Tabular", i)
627 j = find_end_of_inset(document.body, i + 1)
629 document.warning("Malformed LyX document: Could not find end of tabular.")
633 nrows = int(document.body[i+1].split('"')[3])
634 ncols = int(document.body[i+1].split('"')[5])
636 for l in range(nrows):
638 for k in range(ncols):
639 m = find_token(document.body, '<cell', m)
641 if document.body[m].find('multicolumn') != -1:
642 multicol_cont = int(document.body[m].split('"')[1])
644 if multicol_cont == 2 and (k == 0 or prev_multicolumn == 0):
645 document.body[m] = document.body[m][:5] + document.body[m][21:]
648 prev_multicolumn = multicol_cont
655 def close_begin_deeper(document):
659 i = find_tokens(document.body, ["\\begin_deeper", "\\end_deeper"], i)
664 if document.body[i][:13] == "\\begin_deeper":
671 document.body[-2:-2] = ['\\end_deeper' for i in range(depth)]
674 def long_charstyle_names(document):
677 i = find_token(document.body, "\\begin_inset CharStyle", i)
680 document.body[i] = document.body[i].replace("CharStyle ", "CharStyle CharStyle:")
683 def revert_long_charstyle_names(document):
686 i = find_token(document.body, "\\begin_inset CharStyle", i)
689 document.body[i] = document.body[i].replace("CharStyle CharStyle:", "CharStyle ")
693 def axe_show_label(document):
696 i = find_token(document.body, "\\begin_inset CharStyle", i)
699 if document.body[i + 1].find("show_label") != -1:
700 if document.body[i + 1].find("true") != -1:
701 document.body[i + 1] = "status open"
702 del document.body[ i + 2]
704 if document.body[i + 1].find("false") != -1:
705 document.body[i + 1] = "status collapsed"
706 del document.body[ i + 2]
708 document.warning("Malformed LyX document: show_label neither false nor true.")
710 document.warning("Malformed LyX document: show_label missing in CharStyle.")
715 def revert_show_label(document):
718 i = find_token(document.body, "\\begin_inset CharStyle", i)
721 if document.body[i + 1].find("status open") != -1:
722 document.body.insert(i + 1, "show_label true")
724 if document.body[i + 1].find("status collapsed") != -1:
725 document.body.insert(i + 1, "show_label false")
727 document.warning("Malformed LyX document: no legal status line in CharStyle.")
730 def revert_begin_modules(document):
733 i = find_token(document.header, "\\begin_modules", i)
736 j = find_end_of(document.header, i, "\\begin_modules", "\\end_modules")
738 # this should not happen
740 document.header[i : j + 1] = []
742 def convert_flex(document):
743 "Convert CharStyle to Flex"
746 i = find_token(document.body, "\\begin_inset CharStyle", i)
749 document.body[i] = document.body[i].replace('\\begin_inset CharStyle', '\\begin_inset Flex')
751 def revert_flex(document):
752 "Convert Flex to CharStyle"
755 i = find_token(document.body, "\\begin_inset Flex", i)
758 document.body[i] = document.body[i].replace('\\begin_inset Flex', '\\begin_inset CharStyle')
761 # Discard PDF options for hyperref
762 def revert_pdf_options(document):
763 "Revert PDF options for hyperref."
764 # store the PDF options and delete the entries from the Lyx file
772 bookmarksnumbered = ""
774 bookmarksopenlevel = ""
782 i = find_token(document.header, "\\use_hyperref", i)
784 hyperref = get_value(document.header, "\\use_hyperref", i) == 'true'
785 del document.header[i]
786 i = find_token(document.header, "\\pdf_store_options", i)
788 del document.header[i]
789 i = find_token(document.header, "\\pdf_title", 0)
791 title = get_value_string(document.header, '\\pdf_title', 0, 0, True)
792 title = ' pdftitle={' + title + '}'
793 del document.header[i]
794 i = find_token(document.header, "\\pdf_author", 0)
796 author = get_value_string(document.header, '\\pdf_author', 0, 0, True)
798 author = ' pdfauthor={' + author + '}'
800 author = ',\n pdfauthor={' + author + '}'
801 del document.header[i]
802 i = find_token(document.header, "\\pdf_subject", 0)
804 subject = get_value_string(document.header, '\\pdf_subject', 0, 0, True)
805 if title == "" and author == "":
806 subject = ' pdfsubject={' + subject + '}'
808 subject = ',\n pdfsubject={' + subject + '}'
809 del document.header[i]
810 i = find_token(document.header, "\\pdf_keywords", 0)
812 keywords = get_value_string(document.header, '\\pdf_keywords', 0, 0, True)
813 if title == "" and author == "" and subject == "":
814 keywords = ' pdfkeywords={' + keywords + '}'
816 keywords = ',\n pdfkeywords={' + keywords + '}'
817 del document.header[i]
818 i = find_token(document.header, "\\pdf_bookmarks", 0)
820 bookmarks = get_value_string(document.header, '\\pdf_bookmarks', 0)
821 bookmarks = ',\n bookmarks=' + bookmarks
822 del document.header[i]
823 i = find_token(document.header, "\\pdf_bookmarksnumbered", i)
825 bookmarksnumbered = get_value_string(document.header, '\\pdf_bookmarksnumbered', 0)
826 bookmarksnumbered = ',\n bookmarksnumbered=' + bookmarksnumbered
827 del document.header[i]
828 i = find_token(document.header, "\\pdf_bookmarksopen", i)
830 bookmarksopen = get_value_string(document.header, '\\pdf_bookmarksopen', 0)
831 bookmarksopen = ',\n bookmarksopen=' + bookmarksopen
832 del document.header[i]
833 i = find_token(document.header, "\\pdf_bookmarksopenlevel", i)
835 bookmarksopenlevel = get_value_string(document.header, '\\pdf_bookmarksopenlevel', 0, 0, True)
836 bookmarksopenlevel = ',\n bookmarksopenlevel=' + bookmarksopenlevel
837 del document.header[i]
838 i = find_token(document.header, "\\pdf_breaklinks", i)
840 breaklinks = get_value_string(document.header, '\\pdf_breaklinks', 0)
841 breaklinks = ',\n breaklinks=' + breaklinks
842 del document.header[i]
843 i = find_token(document.header, "\\pdf_pdfborder", i)
845 pdfborder = get_value_string(document.header, '\\pdf_pdfborder', 0)
846 if pdfborder == 'true':
847 pdfborder = ',\n pdfborder={0 0 0}'
849 pdfborder = ',\n pdfborder={0 0 1}'
850 del document.header[i]
851 i = find_token(document.header, "\\pdf_colorlinks", i)
853 colorlinks = get_value_string(document.header, '\\pdf_colorlinks', 0)
854 colorlinks = ',\n colorlinks=' + colorlinks
855 del document.header[i]
856 i = find_token(document.header, "\\pdf_backref", i)
858 backref = get_value_string(document.header, '\\pdf_backref', 0)
859 backref = ',\n backref=' + backref
860 del document.header[i]
861 i = find_token(document.header, "\\pdf_pagebackref", i)
863 pagebackref = get_value_string(document.header, '\\pdf_pagebackref', 0)
864 pagebackref = ',\n pagebackref=' + pagebackref
865 del document.header[i]
866 i = find_token(document.header, "\\pdf_pagemode", 0)
868 pagemode = get_value_string(document.header, '\\pdf_pagemode', 0)
869 pagemode = ',\n pdfpagemode=' + pagemode
870 del document.header[i]
871 i = find_token(document.header, "\\pdf_quoted_options", 0)
873 otheroptions = get_value_string(document.header, '\\pdf_quoted_options', 0, 0, True)
874 if title == "" and author == "" and subject == "" and keywords == "":
875 otheroptions = ' ' + otheroptions
877 otheroptions = ',\n ' + otheroptions
878 del document.header[i]
880 # write to the preamble when hyperref was used
882 # preamble write preparations
883 # bookmark numbers are only output when they are turned on
884 if bookmarksopen == ',\n bookmarksopen=true':
885 bookmarksopen = bookmarksopen + bookmarksopenlevel
886 if bookmarks == ',\n bookmarks=true':
887 bookmarks = bookmarks + bookmarksnumbered + bookmarksopen
889 bookmarks = bookmarks
890 # hypersetup is only output when there are things to be set up
891 setupstart = '\\hypersetup{%\n'
893 if otheroptions == "" and title == "" and author == ""\
894 and subject == "" and keywords == "":
898 # babel must be loaded before hyperref and hyperref the first part
899 # of the preamble, like in LyX 1.6
900 insert_to_preamble(0, document,
901 '% Commands inserted by lyx2lyx for PDF properties\n'
902 + '\\usepackage{babel}\n'
903 + '\\usepackage[unicode=true'
922 def remove_inzip_options(document):
923 "Remove inzipName and embed options from the Graphics inset"
926 i = find_token(document.body, "\\begin_inset Graphics", i)
929 j = find_end_of_inset(document.body, i + 1)
932 document.warning("Malformed LyX document: Could not find end of graphics inset.")
933 # If there's a inzip param, just remove that
934 k = find_token(document.body, "\tinzipName", i + 1, j)
937 # embed option must follow the inzipName option
938 del document.body[k+1]
942 def convert_inset_command(document):
945 \begin_inset LatexCommand cmd
947 \begin_inset CommandInset InsetType
952 i = find_token(document.body, "\\begin_inset LatexCommand", i)
955 line = document.body[i]
956 r = re.compile(r'\\begin_inset LatexCommand (.*)$')
960 #this is adapted from factory.cpp
961 if cmdName[0:4].lower() == "cite":
962 insetName = "citation"
963 elif cmdName == "url" or cmdName == "htmlurl":
965 elif cmdName[-3:] == "ref":
967 elif cmdName == "tableofcontents":
969 elif cmdName == "printnomenclature":
970 insetName = "nomencl_print"
971 elif cmdName == "printindex":
972 insetName = "index_print"
975 insertion = ["\\begin_inset CommandInset " + insetName, "LatexCommand " + cmdName]
976 document.body[i : i+1] = insertion
979 def revert_inset_command(document):
982 \begin_inset CommandInset InsetType
985 \begin_inset LatexCommand cmd
986 Some insets may end up being converted to insets earlier versions of LyX
987 will not be able to recognize. Not sure what to do about that.
991 i = find_token(document.body, "\\begin_inset CommandInset", i)
994 nextline = document.body[i+1]
995 r = re.compile(r'LatexCommand\s+(.*)$')
996 m = r.match(nextline)
998 document.warning("Malformed LyX document: Missing LatexCommand in " + document.body[i] + ".")
1000 cmdName = m.group(1)
1001 insertion = ["\\begin_inset LatexCommand " + cmdName]
1002 document.body[i : i+2] = insertion
1005 def convert_wrapfig_options(document):
1006 "Convert optional options for wrap floats (wrapfig)."
1007 # adds the tokens "lines", "placement", and "overhang"
1010 i = find_token(document.body, "\\begin_inset Wrap figure", i)
1013 document.body.insert(i + 1, "lines 0")
1014 j = find_token(document.body, "placement", i)
1015 # placement can be already set or not; if not, set it
1017 document.body.insert(i + 3, "overhang 0col%")
1019 document.body.insert(i + 2, "placement o")
1020 document.body.insert(i + 3, "overhang 0col%")
1024 def revert_wrapfig_options(document):
1025 "Revert optional options for wrap floats (wrapfig)."
1028 i = find_token(document.body, "\\begin_inset Wrap figure", i)
1031 j = find_end_of_inset(document.body, i)
1033 document.warning("Can't find end of Wrap inset at line " + str(i))
1036 k = find_default_layout(document, i, j)
1038 document.warning("Can't find default layout for Wrap figure!")
1041 # Options should be between i and k now
1042 l = find_token(document.body, "lines", i, k)
1044 document.warning("Can't find lines option for Wrap figure!")
1047 m = find_token(document.body, "overhang", i + 1, k)
1049 document.warning("Malformed LyX document: Couldn't find overhang parameter of wrap float!")
1052 # Do these in reverse order
1053 del document.body[m]
1054 del document.body[l]
1058 def convert_latexcommand_index(document):
1059 "Convert from LatexCommand form to collapsable form."
1061 r1 = re.compile('name "(.*)"')
1063 i = find_token(document.body, "\\begin_inset CommandInset index", i)
1066 if document.body[i + 1] != "LatexCommand index": # Might also be index_print
1068 j = find_end_of_inset(document.body, i + 2)
1070 document.warning("Unable to find end of index inset at line " + i + "!")
1073 m = r1.match(document.body[i + 2])
1075 document.warning("Unable to match: " + document.body[i+2])
1076 # this can happen with empty index insets!
1079 fullcontent = m.group(1)
1080 linelist = latex2lyx(fullcontent)
1081 #document.warning(fullcontent)
1083 linelist = ["\\begin_inset Index", "status collapsed", "\\begin_layout Standard", ""] + \
1084 linelist + ["\\end_layout"]
1085 document.body[i : j] = linelist
1086 i += len(linelist) - (j - i)
1089 def revert_latexcommand_index(document):
1090 "Revert from collapsable form to LatexCommand form."
1093 i = find_token(document.body, "\\begin_inset Index", i)
1096 j = find_end_of_inset(document.body, i + 1)
1100 content = lyx2latex(document, document.body[i:j])
1102 content = content.replace('"', r'\"')
1103 document.body[i:j] = ["\\begin_inset CommandInset index", "LatexCommand index",
1104 "name " + '"' + content + '"', ""]
1108 def revert_wraptable(document):
1109 "Revert wrap table to wrap figure."
1112 i = find_token(document.body, "\\begin_inset Wrap table", i)
1115 document.body[i] = document.body[i].replace('\\begin_inset Wrap table', '\\begin_inset Wrap figure')
1119 def revert_vietnamese(document):
1120 "Set language Vietnamese to English"
1121 # Set document language from Vietnamese to English
1123 if document.language == "vietnamese":
1124 document.language = "english"
1125 i = find_token(document.header, "\\language", 0)
1127 document.header[i] = "\\language english"
1130 j = find_token(document.body, "\\lang vietnamese", j)
1133 document.body[j] = document.body[j].replace("\\lang vietnamese", "\\lang english")
1137 def convert_japanese_cjk(document):
1138 "Set language japanese to japanese-cjk"
1139 # Set document language from japanese-plain to japanese
1141 if document.language == "japanese":
1142 document.language = "japanese-cjk"
1143 i = find_token(document.header, "\\language", 0)
1145 document.header[i] = "\\language japanese-cjk"
1148 j = find_token(document.body, "\\lang japanese", j)
1151 document.body[j] = document.body[j].replace("\\lang japanese", "\\lang japanese-cjk")
1155 def revert_japanese(document):
1156 "Set language japanese-plain to japanese"
1157 # Set document language from japanese-plain to japanese
1159 if document.language == "japanese-plain":
1160 document.language = "japanese"
1161 i = find_token(document.header, "\\language", 0)
1163 document.header[i] = "\\language japanese"
1166 j = find_token(document.body, "\\lang japanese-plain", j)
1169 document.body[j] = document.body[j].replace("\\lang japanese-plain", "\\lang japanese")
1173 def revert_japanese_cjk(document):
1174 "Set language japanese-cjk to japanese"
1175 # Set document language from japanese-plain to japanese
1177 if document.language == "japanese-cjk":
1178 document.language = "japanese"
1179 i = find_token(document.header, "\\language", 0)
1181 document.header[i] = "\\language japanese"
1184 j = find_token(document.body, "\\lang japanese-cjk", j)
1187 document.body[j] = document.body[j].replace("\\lang japanese-cjk", "\\lang japanese")
1191 def revert_japanese_encoding(document):
1192 "Set input encoding form EUC-JP-plain to EUC-JP etc."
1193 # Set input encoding form EUC-JP-plain to EUC-JP etc.
1195 i = find_token(document.header, "\\inputencoding EUC-JP-plain", 0)
1197 document.header[i] = "\\inputencoding EUC-JP"
1199 j = find_token(document.header, "\\inputencoding JIS-plain", 0)
1201 document.header[j] = "\\inputencoding JIS"
1203 k = find_token(document.header, "\\inputencoding SJIS-plain", 0)
1204 if k != -1: # convert to UTF8 since there is currently no SJIS encoding
1205 document.header[k] = "\\inputencoding UTF8"
1208 def revert_inset_info(document):
1209 'Replace info inset with its content'
1212 i = find_token(document.body, '\\begin_inset Info', i)
1215 j = find_end_of_inset(document.body, i + 1)
1218 document.warning("Malformed LyX document: Could not find end of Info inset.")
1221 for k in range(i, j+1):
1222 if document.body[k].startswith("arg"):
1223 arg = document.body[k][3:].strip()
1224 # remove embracing quotation marks
1227 if arg[len(arg) - 1] == '"':
1228 arg = arg[:len(arg) - 1]
1229 # \" to straight quote
1230 arg = arg.replace(r'\"','"')
1231 if document.body[k].startswith("type"):
1232 type = document.body[k][4:].strip().strip('"')
1233 # I think there is a newline after \\end_inset, which should be removed.
1234 if document.body[j + 1].strip() == "":
1235 document.body[i : (j + 2)] = [type + ':' + arg]
1237 document.body[i : (j + 1)] = [type + ':' + arg]
1240 def convert_pdf_options(document):
1241 # Set the pdfusetitle tag, delete the pdf_store_options,
1242 # set quotes for bookmarksopenlevel"
1243 has_hr = get_value(document.header, "\\use_hyperref", 0, default = "0")
1245 k = find_token(document.header, "\\use_hyperref", 0)
1246 document.header.insert(k + 1, "\\pdf_pdfusetitle true")
1247 k = find_token(document.header, "\\pdf_store_options", 0)
1249 del document.header[k]
1250 i = find_token(document.header, "\\pdf_bookmarksopenlevel", k)
1252 document.header[i] = document.header[i].replace('"', '')
1255 def revert_pdf_options_2(document):
1256 # reset the pdfusetitle tag, set quotes for bookmarksopenlevel"
1257 k = find_token(document.header, "\\use_hyperref", 0)
1258 i = find_token(document.header, "\\pdf_pdfusetitle", k)
1260 del document.header[i]
1261 i = find_token(document.header, "\\pdf_bookmarksopenlevel", k)
1263 values = document.header[i].split()
1264 values[1] = ' "' + values[1] + '"'
1265 document.header[i] = ''.join(values)
1268 def convert_htmlurl(document):
1269 'Convert "htmlurl" to "href" insets for docbook'
1270 if document.backend != "docbook":
1274 i = find_token(document.body, "\\begin_inset CommandInset url", i)
1277 document.body[i] = "\\begin_inset CommandInset href"
1278 document.body[i + 1] = "LatexCommand href"
1282 def convert_url(document):
1283 'Convert url insets to url charstyles'
1284 if document.backend == "docbook":
1288 i = find_token(document.body, "\\begin_inset CommandInset url", i)
1291 n = find_token(document.body, "name", i)
1293 # place the URL name in typewriter before the new URL insert
1294 # grab the name 'bla' from the e.g. the line 'name "bla"',
1295 # therefore start with the 6th character
1296 name = document.body[n][6:-1]
1297 newname = [name + " "]
1298 document.body[i:i] = newname
1300 j = find_token(document.body, "target", i)
1302 document.warning("Malformed LyX document: Can't find target for url inset")
1305 target = document.body[j][8:-1]
1306 k = find_token(document.body, "\\end_inset", j)
1308 document.warning("Malformed LyX document: Can't find end of url inset")
1311 newstuff = ["\\begin_inset Flex URL",
1312 "status collapsed", "",
1313 "\\begin_layout Standard",
1318 document.body[i:k] = newstuff
1321 def convert_ams_classes(document):
1322 tc = document.textclass
1323 if (tc != "amsart" and tc != "amsart-plain" and
1324 tc != "amsart-seq" and tc != "amsbook"):
1326 if tc == "amsart-plain":
1327 document.textclass = "amsart"
1328 document.set_textclass()
1329 document.add_module("Theorems (Starred)")
1331 if tc == "amsart-seq":
1332 document.textclass = "amsart"
1333 document.set_textclass()
1334 document.add_module("Theorems (AMS)")
1336 #Now we want to see if any of the environments in the extended theorems
1337 #module were used in this document. If so, we'll add that module, too.
1338 layouts = ["Criterion", "Algorithm", "Axiom", "Condition", "Note", \
1339 "Notation", "Summary", "Acknowledgement", "Conclusion", "Fact", \
1342 r = re.compile(r'^\\begin_layout (.*?)\*?\s*$')
1345 i = find_token(document.body, "\\begin_layout", i)
1348 m = r.match(document.body[i])
1350 # This is an empty layout
1351 # document.warning("Weirdly formed \\begin_layout at line %d of body!" % i)
1355 if layouts.count(m) != 0:
1356 document.add_module("Theorems (AMS-Extended)")
1360 def revert_href(document):
1361 'Reverts hyperlink insets (href) to url insets (url)'
1364 i = find_token(document.body, "\\begin_inset CommandInset href", i)
1367 document.body[i : i + 2] = \
1368 ["\\begin_inset CommandInset url", "LatexCommand url"]
1371 def revert_url(document):
1372 'Reverts Flex URL insets to old-style URL insets'
1375 i = find_token(document.body, "\\begin_inset Flex URL", i)
1378 j = find_end_of_inset(document.body, i)
1380 document.warning("Can't find end of inset in revert_url!")
1382 k = find_default_layout(document, i, j)
1384 document.warning("Can't find default layout in revert_url!")
1387 l = find_end_of(document.body, k, "\\begin_layout", "\\end_layout")
1388 if l == -1 or l >= j:
1389 document.warning("Can't find end of default layout in revert_url!")
1392 # OK, so the inset's data is between lines k and l.
1393 data = " ".join(document.body[k+1:l])
1395 newinset = ["\\begin_inset LatexCommand url", "target \"" + data + "\"",\
1397 document.body[i:j+1] = newinset
1398 i = i + len(newinset)
1401 def convert_include(document):
1402 'Converts include insets to new format.'
1404 r = re.compile(r'\\begin_inset Include\s+\\([^{]+){([^}]*)}(?:\[(.*)\])?')
1406 i = find_token(document.body, "\\begin_inset Include", i)
1409 line = document.body[i]
1410 previewline = document.body[i + 1]
1413 document.warning("Unable to match line " + str(i) + " of body!")
1419 insertion = ["\\begin_inset CommandInset include",
1420 "LatexCommand " + cmd, previewline,
1421 "filename \"" + fn + "\""]
1424 insertion.append("lstparams " + '"' + opt + '"')
1426 document.body[i : i + 2] = insertion
1430 def revert_include(document):
1431 'Reverts include insets to old format.'
1433 r0 = re.compile('preview.*')
1434 r1 = re.compile('LatexCommand (.+)')
1435 r2 = re.compile('filename "(.+)"')
1436 r3 = re.compile('lstparams "(.*)"')
1438 i = find_token(document.body, "\\begin_inset CommandInset include", i)
1442 m = r1.match(document.body[nextline])
1444 document.warning("Malformed LyX document: No LatexCommand line for `" +
1445 document.body[i] + "' on line " + str(i) + ".")
1450 if r0.match(document.body[nextline]):
1451 previewline = document.body[nextline]
1455 m = r2.match(document.body[nextline])
1457 document.warning("Malformed LyX document: No filename line for `" + \
1458 document.body[i] + "' on line " + str(i) + ".")
1464 if (cmd == "lstinputlisting"):
1465 m = r3.match(document.body[nextline])
1467 options = m.group(1)
1470 newline = "\\begin_inset Include \\" + cmd + "{" + fn + "}"
1472 newline += ("[" + options + "]")
1473 insertion = [newline]
1474 if previewline != "":
1475 insertion.append(previewline)
1476 document.body[i : nextline] = insertion
1480 def revert_albanian(document):
1481 "Set language Albanian to English"
1483 if document.language == "albanian":
1484 document.language = "english"
1485 i = find_token(document.header, "\\language", 0)
1487 document.header[i] = "\\language english"
1490 j = find_token(document.body, "\\lang albanian", j)
1493 document.body[j] = document.body[j].replace("\\lang albanian", "\\lang english")
1497 def revert_lowersorbian(document):
1498 "Set language lower Sorbian to English"
1500 if document.language == "lowersorbian":
1501 document.language = "english"
1502 i = find_token(document.header, "\\language", 0)
1504 document.header[i] = "\\language english"
1507 j = find_token(document.body, "\\lang lowersorbian", j)
1510 document.body[j] = document.body[j].replace("\\lang lowersorbian", "\\lang english")
1514 def revert_uppersorbian(document):
1515 "Set language uppersorbian to usorbian as this was used in LyX 1.5"
1517 if document.language == "uppersorbian":
1518 document.language = "usorbian"
1519 i = find_token(document.header, "\\language", 0)
1521 document.header[i] = "\\language usorbian"
1524 j = find_token(document.body, "\\lang uppersorbian", j)
1527 document.body[j] = document.body[j].replace("\\lang uppersorbian", "\\lang usorbian")
1531 def convert_usorbian(document):
1532 "Set language usorbian to uppersorbian"
1534 if document.language == "usorbian":
1535 document.language = "uppersorbian"
1536 i = find_token(document.header, "\\language", 0)
1538 document.header[i] = "\\language uppersorbian"
1541 j = find_token(document.body, "\\lang usorbian", j)
1544 document.body[j] = document.body[j].replace("\\lang usorbian", "\\lang uppersorbian")
1548 def convert_macro_global(document):
1549 "Remove TeX code command \global when it is in front of a macro"
1550 # math macros are nowadays already defined \global, so that an additional
1551 # \global would make the document uncompilable, see
1552 # http://bugzilla.lyx.org/show_bug.cgi?id=5371
1553 # We're looking for something like this:
1557 # \begin_layout Plain Layout
1567 # \begin_inset FormulaMacro
1568 # \renewcommand{\foo}{123}
1572 i = find_token(document.body, "\\begin_inset FormulaMacro", i)
1575 # if i <= 13, then there isn't enough room for the ERT
1579 if document.body[i-6] == "global":
1580 del document.body[i-13 : i]
1586 def revert_macro_optional_params(document):
1587 "Convert macro definitions with optional parameters into ERTs"
1588 # Stub to convert macro definitions with one or more optional parameters
1589 # into uninterpreted ERT insets
1592 def revert_hyperlinktype(document):
1593 'Reverts hyperlink type'
1597 i = find_token(document.body, "target", i)
1600 j = find_token(document.body, "type", i)
1604 del document.body[j]
1608 def revert_pagebreak(document):
1609 'Reverts pagebreak to ERT'
1612 i = find_token(document.body, "\\pagebreak", i)
1615 document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1616 '\\begin_layout Standard\n\n\n\\backslash\n' \
1617 'pagebreak{}\n\\end_layout\n\n\\end_inset\n\n'
1621 def revert_linebreak(document):
1622 'Reverts linebreak to ERT'
1625 i = find_token(document.body, "\\linebreak", i)
1628 document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1629 '\\begin_layout Standard\n\n\n\\backslash\n' \
1630 'linebreak{}\n\\end_layout\n\n\\end_inset\n\n'
1634 def revert_latin(document):
1635 "Set language Latin to English"
1637 if document.language == "latin":
1638 document.language = "english"
1639 i = find_token(document.header, "\\language", 0)
1641 document.header[i] = "\\language english"
1644 j = find_token(document.body, "\\lang latin", j)
1647 document.body[j] = document.body[j].replace("\\lang latin", "\\lang english")
1651 def revert_samin(document):
1652 "Set language North Sami to English"
1654 if document.language == "samin":
1655 document.language = "english"
1656 i = find_token(document.header, "\\language", 0)
1658 document.header[i] = "\\language english"
1661 j = find_token(document.body, "\\lang samin", j)
1664 document.body[j] = document.body[j].replace("\\lang samin", "\\lang english")
1668 def convert_serbocroatian(document):
1669 "Set language Serbocroatian to Croatian as this was really Croatian in LyX 1.5"
1671 if document.language == "serbocroatian":
1672 document.language = "croatian"
1673 i = find_token(document.header, "\\language", 0)
1675 document.header[i] = "\\language croatian"
1678 j = find_token(document.body, "\\lang serbocroatian", j)
1681 document.body[j] = document.body[j].replace("\\lang serbocroatian", "\\lang croatian")
1685 def convert_framed_notes(document):
1686 "Convert framed notes to boxes. "
1689 i = find_tokens(document.body, ["\\begin_inset Note Framed", "\\begin_inset Note Shaded"], i)
1692 subst = [document.body[i].replace("\\begin_inset Note", "\\begin_inset Box"),
1701 'height_special "totalheight"']
1702 document.body[i:i+1] = subst
1706 def convert_module_names(document):
1707 modulemap = { 'Braille' : 'braille', 'Endnote' : 'endnotes', 'Foot to End' : 'foottoend',\
1708 'Hanging' : 'hanging', 'Linguistics' : 'linguistics', 'Logical Markup' : 'logicalmkup', \
1709 'Theorems (AMS-Extended)' : 'theorems-ams-extended', 'Theorems (AMS)' : 'theorems-ams', \
1710 'Theorems (Order By Chapter)' : 'theorems-chap', 'Theorems (Order By Section)' : 'theorems-sec', \
1711 'Theorems (Starred)' : 'theorems-starred', 'Theorems' : 'theorems-std' }
1712 modlist = document.get_module_list()
1713 if len(modlist) == 0:
1717 if modulemap.has_key(mod):
1718 newmodlist.append(modulemap[mod])
1720 document.warning("Can't find module %s in the module map!" % mod)
1721 newmodlist.append(mod)
1722 document.set_module_list(newmodlist)
1725 def revert_module_names(document):
1726 modulemap = { 'braille' : 'Braille', 'endnotes' : 'Endnote', 'foottoend' : 'Foot to End',\
1727 'hanging' : 'Hanging', 'linguistics' : 'Linguistics', 'logicalmkup' : 'Logical Markup', \
1728 'theorems-ams-extended' : 'Theorems (AMS-Extended)', 'theorems-ams' : 'Theorems (AMS)', \
1729 'theorems-chap' : 'Theorems (Order By Chapter)', 'theorems-sec' : 'Theorems (Order By Section)', \
1730 'theorems-starred' : 'Theorems (Starred)', 'theorems-std' : 'Theorems'}
1731 modlist = document.get_module_list()
1732 if len(modlist) == 0:
1736 if modulemap.has_key(mod):
1737 newmodlist.append(modulemap[mod])
1739 document.warning("Can't find module %s in the module map!" % mod)
1740 newmodlist.append(mod)
1741 document.set_module_list(newmodlist)
1744 def revert_colsep(document):
1745 i = find_token(document.header, "\\columnsep", 0)
1748 colsepline = document.header[i]
1749 r = re.compile(r'\\columnsep (.*)')
1750 m = r.match(colsepline)
1752 document.warning("Malformed column separation line!")
1755 del document.header[i]
1756 #it seems to be safe to add the package even if it is already used
1757 pretext = ["\\usepackage{geometry}", "\\geometry{columnsep=" + colsep + "}"]
1759 add_to_preamble(document, pretext)
1762 def revert_framed_notes(document):
1763 "Revert framed boxes to notes. "
1766 i = find_tokens(document.body, ["\\begin_inset Box Framed", "\\begin_inset Box Shaded"], i)
1770 j = find_end_of_inset(document.body, i + 1)
1773 document.warning("Malformed LyX document: Could not find end of Box inset.")
1774 k = find_token(document.body, "status", i + 1, j)
1776 document.warning("Malformed LyX document: Missing `status' tag in Box inset.")
1778 status = document.body[k]
1779 l = find_default_layout(document, i + 1, j)
1781 document.warning("Malformed LyX document: Missing `\\begin_layout' in Box inset.")
1783 m = find_token(document.body, "\\end_layout", i + 1, j)
1785 document.warning("Malformed LyX document: Missing `\\end_layout' in Box inset.")
1787 ibox = find_token(document.body, "has_inner_box 1", i + 1, k)
1788 pbox = find_token(document.body, "use_parbox 1", i + 1, k)
1789 if ibox == -1 and pbox == -1:
1790 document.body[i] = document.body[i].replace("\\begin_inset Box", "\\begin_inset Note")
1791 del document.body[i+1:k]
1793 document.body[i] = document.body[i].replace("\\begin_inset Box Shaded", "\\begin_inset Box Frameless")
1794 subst1 = [document.body[l],
1795 "\\begin_inset Note Shaded",
1797 '\\begin_layout Standard']
1798 document.body[l:l + 1] = subst1
1799 subst2 = [document.body[m], "\\end_layout", "\\end_inset"]
1800 document.body[m:m + 1] = subst2
1804 def revert_slash(document):
1805 'Revert \\SpecialChar \\slash{} to ERT'
1806 r = re.compile(r'\\SpecialChar \\slash{}')
1808 while i < len(document.body):
1809 m = r.match(document.body[i])
1811 subst = ['\\begin_inset ERT',
1812 'status collapsed', '',
1813 '\\begin_layout Standard',
1814 '', '', '\\backslash',
1818 document.body[i: i+1] = subst
1824 def revert_nobreakdash(document):
1825 'Revert \\SpecialChar \\nobreakdash- to ERT'
1827 while i < len(document.body):
1828 line = document.body[i]
1829 r = re.compile(r'\\SpecialChar \\nobreakdash-')
1832 subst = ['\\begin_inset ERT',
1833 'status collapsed', '',
1834 '\\begin_layout Standard', '', '',
1839 document.body[i:i+1] = subst
1841 j = find_token(document.header, "\\use_amsmath", 0)
1843 document.warning("Malformed LyX document: Missing '\\use_amsmath'.")
1845 document.header[j] = "\\use_amsmath 2"
1850 #Returns number of lines added/removed
1851 def revert_nocite_key(body, start, end):
1852 'key "..." -> \nocite{...}'
1853 r = re.compile(r'^key "(.*)"')
1857 m = r.match(body[i])
1859 body[i:i+1] = ["\\backslash", "nocite{" + m.group(1) + "}"]
1860 j += 1 # because we added a line
1861 i += 2 # skip that line
1864 j -= 1 # because we deleted a line
1865 # no need to change i, since it now points to the next line
1869 def revert_nocite(document):
1870 "Revert LatexCommand nocite to ERT"
1873 i = find_token(document.body, "\\begin_inset CommandInset citation", i)
1876 if (document.body[i+1] != "LatexCommand nocite"):
1877 # note that we already incremented i
1880 insetEnd = find_end_of_inset(document.body, i)
1882 #this should not happen
1883 document.warning("End of CommandInset citation not found in revert_nocite!")
1886 paramLocation = i + 2 #start of the inset's parameters
1888 document.body[i:i+2] = \
1889 ["\\begin_inset ERT", "status collapsed", "", "\\begin_layout Standard"]
1890 # that added two lines
1893 #print insetEnd, document.body[i: insetEnd + 1]
1894 insetEnd += revert_nocite_key(document.body, paramLocation, insetEnd)
1895 #print insetEnd, document.body[i: insetEnd + 1]
1896 document.body.insert(insetEnd, "\\end_layout")
1897 document.body.insert(insetEnd + 1, "")
1901 def revert_btprintall(document):
1902 "Revert (non-bibtopic) btPrintAll option to ERT \nocite{*}"
1903 i = find_token(document.header, '\\use_bibtopic', 0)
1905 document.warning("Malformed lyx document: Missing '\\use_bibtopic'.")
1907 if get_value(document.header, '\\use_bibtopic', 0) == "false":
1909 while i < len(document.body):
1910 i = find_token(document.body, "\\begin_inset CommandInset bibtex", i)
1913 j = find_end_of_inset(document.body, i + 1)
1915 #this should not happen
1916 document.warning("End of CommandInset bibtex not found in revert_btprintall!")
1917 j = len(document.body)
1918 # this range isn't really right, but it should be OK, since we shouldn't
1919 # see more than one matching line in each inset
1921 for k in range(i, j):
1922 if (document.body[k] == 'btprint "btPrintAll"'):
1923 del document.body[k]
1924 subst = ["\\begin_inset ERT",
1925 "status collapsed", "",
1926 "\\begin_layout Standard", "",
1931 document.body[i:i] = subst
1932 addlines = addedlines + len(subst) - 1
1936 def revert_bahasam(document):
1937 "Set language Bahasa Malaysia to Bahasa Indonesia"
1939 if document.language == "bahasam":
1940 document.language = "bahasa"
1941 i = find_token(document.header, "\\language", 0)
1943 document.header[i] = "\\language bahasa"
1946 j = find_token(document.body, "\\lang bahasam", j)
1949 document.body[j] = document.body[j].replace("\\lang bahasam", "\\lang bahasa")
1953 def revert_interlingua(document):
1954 "Set language Interlingua to English"
1956 if document.language == "interlingua":
1957 document.language = "english"
1958 i = find_token(document.header, "\\language", 0)
1960 document.header[i] = "\\language english"
1963 j = find_token(document.body, "\\lang interlingua", j)
1966 document.body[j] = document.body[j].replace("\\lang interlingua", "\\lang english")
1970 def revert_serbianlatin(document):
1971 "Set language Serbian-Latin to Croatian"
1973 if document.language == "serbian-latin":
1974 document.language = "croatian"
1975 i = find_token(document.header, "\\language", 0)
1977 document.header[i] = "\\language croatian"
1980 j = find_token(document.body, "\\lang serbian-latin", j)
1983 document.body[j] = document.body[j].replace("\\lang serbian-latin", "\\lang croatian")
1987 def revert_rotfloat(document):
1988 " Revert sideways custom floats. "
1991 # whitespace intended (exclude \\begin_inset FloatList)
1992 i = find_token(document.body, "\\begin_inset Float ", i)
1995 line = document.body[i]
1996 r = re.compile(r'\\begin_inset Float (.*)$')
1999 document.warning("Unable to match line " + str(i) + " of body!")
2002 floattype = m.group(1)
2003 if floattype == "figure" or floattype == "table":
2006 j = find_end_of_inset(document.body, i)
2008 document.warning("Malformed lyx document: Missing '\\end_inset' in revert_rotfloat.")
2012 if get_value(document.body, 'sideways', i, j) == "false":
2015 l = find_default_layout(document, i + 1, j)
2017 document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
2019 subst = ['\\begin_layout Standard',
2020 '\\begin_inset ERT',
2021 'status collapsed', '',
2022 '\\begin_layout Standard', '', '',
2024 'end{sideways' + floattype + '}',
2025 '\\end_layout', '', '\\end_inset']
2026 document.body[j : j+1] = subst
2027 addedLines = len(subst) - 1
2028 del document.body[i+1 : l]
2029 addedLines -= (l-1) - (i+1)
2030 subst = ['\\begin_inset ERT', 'status collapsed', '',
2031 '\\begin_layout Standard', '', '', '\\backslash',
2032 'begin{sideways' + floattype + '}',
2033 '\\end_layout', '', '\\end_inset', '',
2035 document.body[i : i+1] = subst
2036 addedLines += len(subst) - 1
2037 if floattype == "algorithm":
2038 add_to_preamble(document,
2039 ['% Commands inserted by lyx2lyx for sideways algorithm float',
2040 '\\usepackage{rotfloat}',
2041 '\\floatstyle{ruled}',
2042 '\\newfloat{algorithm}{tbp}{loa}',
2043 '\\floatname{algorithm}{Algorithm}'])
2045 document.warning("Cannot create preamble definition for custom float" + floattype + ".")
2049 def revert_widesideways(document):
2050 " Revert wide sideways floats. "
2053 # whitespace intended (exclude \\begin_inset FloatList)
2054 i = find_token(document.body, '\\begin_inset Float ', i)
2057 line = document.body[i]
2058 r = re.compile(r'\\begin_inset Float (.*)$')
2061 document.warning("Unable to match line " + str(i) + " of body!")
2064 floattype = m.group(1)
2065 if floattype != "figure" and floattype != "table":
2068 j = find_end_of_inset(document.body, i)
2070 document.warning("Malformed lyx document: Missing '\\end_inset' in revert_widesideways.")
2073 if get_value(document.body, 'sideways', i, j) == "false" or \
2074 get_value(document.body, 'wide', i, j) == "false":
2077 l = find_default_layout(document, i + 1, j)
2079 document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
2081 subst = ['\\begin_layout Standard', '\\begin_inset ERT',
2082 'status collapsed', '',
2083 '\\begin_layout Standard', '', '', '\\backslash',
2084 'end{sideways' + floattype + '*}',
2085 '\\end_layout', '', '\\end_inset']
2086 document.body[j : j+1] = subst
2087 addedLines = len(subst) - 1
2088 del document.body[i+1:l-1]
2089 addedLines -= (l-1) - (i+1)
2090 subst = ['\\begin_inset ERT', 'status collapsed', '',
2091 '\\begin_layout Standard', '', '', '\\backslash',
2092 'begin{sideways' + floattype + '*}', '\\end_layout', '',
2093 '\\end_inset', '', '\\end_layout', '']
2094 document.body[i : i+1] = subst
2095 addedLines += len(subst) - 1
2096 add_to_preamble(document, ['\\usepackage{rotfloat}\n'])
2100 def revert_inset_embedding(document, type):
2101 ' Remove embed tag from certain type of insets'
2104 i = find_token(document.body, "\\begin_inset %s" % type, i)
2107 j = find_end_of_inset(document.body, i)
2109 document.warning("Malformed lyx document: Missing '\\end_inset' in revert_inset_embedding.")
2112 k = find_token(document.body, "\tembed", i, j)
2114 k = find_token(document.body, "embed", i, j)
2116 del document.body[k]
2120 def revert_external_embedding(document):
2121 ' Remove embed tag from external inset '
2122 revert_inset_embedding(document, 'External')
2125 def convert_subfig(document):
2126 " Convert subfigures to subfloats. "
2130 i = find_token(document.body, '\\begin_inset Graphics', i)
2133 endInset = find_end_of_inset(document.body, i)
2135 document.warning("Malformed lyx document: Missing '\\end_inset' in convert_subfig.")
2138 k = find_token(document.body, '\tsubcaption', i, endInset)
2142 l = find_token(document.body, '\tsubcaptionText', i, endInset)
2146 caption = document.body[l][16:].strip('"')
2147 del document.body[l]
2149 del document.body[k]
2151 subst = ['\\begin_inset Float figure', 'wide false', 'sideways false',
2152 'status open', '', '\\begin_layout Plain Layout', '\\begin_inset Caption',
2153 '', '\\begin_layout Plain Layout'] + latex2lyx(caption) + \
2154 [ '\\end_layout', '', '\\end_inset', '',
2155 '\\end_layout', '', '\\begin_layout Plain Layout']
2156 document.body[i : i] = subst
2157 addedLines += len(subst)
2158 endInset += addedLines
2159 subst = ['', '\\end_inset', '', '\\end_layout']
2160 document.body[endInset : endInset] = subst
2161 addedLines += len(subst)
2165 def revert_subfig(document):
2166 " Revert subfloats. "
2169 # whitespace intended (exclude \\begin_inset FloatList)
2170 i = find_tokens(document.body, ['\\begin_inset Float ', '\\begin_inset Wrap'], i)
2176 j = find_end_of_inset(document.body, i)
2178 document.warning("Malformed lyx document: Missing '\\end_inset' (float) at line " + str(i + len(document.header)) + ".\n\t" + document.body[i])
2179 # document.warning(document.body[i-1] + "\n" + document.body[i+1])
2181 continue # this will get us back to the outer loop, since j == -1
2182 # look for embedded float (= subfloat)
2183 # whitespace intended (exclude \\begin_inset FloatList)
2184 k = find_token(document.body, '\\begin_inset Float ', i + 1, j)
2187 # is the subfloat aligned?
2188 al = find_token(document.body, '\\align ', k - 1)
2192 if get_value(document.body, '\\align', al) == "center":
2193 alignment_beg = "\\backslash\nbegin{centering}"
2194 alignment_end = "\\backslash\npar\\backslash\nend{centering}"
2195 elif get_value(document.body, '\\align', al) == "left":
2196 alignment_beg = "\\backslash\nbegin{raggedright}"
2197 alignment_end = "\\backslash\npar\\backslash\nend{raggedright}"
2198 elif get_value(document.body, '\\align', al) == "right":
2199 alignment_beg = "\\backslash\nbegin{raggedleft}"
2200 alignment_end = "\\backslash\npar\\backslash\nend{raggedleft}"
2201 l = find_end_of_inset(document.body, k)
2203 document.warning("Malformed lyx document: Missing '\\end_inset' (embedded float).")
2206 continue # escape to the outer loop
2207 m = find_default_layout(document, k + 1, l)
2209 cap = find_token(document.body, '\\begin_inset Caption', k + 1, l)
2214 capend = find_end_of_inset(document.body, cap)
2216 document.warning("Malformed lyx document: Missing '\\end_inset' (caption).")
2220 lbl = find_token(document.body, '\\begin_inset CommandInset label', cap, capend)
2222 lblend = find_end_of_inset(document.body, lbl + 1)
2224 document.warning("Malformed lyx document: Missing '\\end_inset' (label).")
2226 for line in document.body[lbl:lblend + 1]:
2227 if line.startswith('name '):
2228 label = line.split()[1].strip('"')
2235 opt = find_token(document.body, '\\begin_inset OptArg', cap, capend)
2237 optend = find_end_of_inset(document.body, opt)
2239 document.warning("Malformed lyx document: Missing '\\end_inset' (OptArg).")
2241 optc = find_default_layout(document, opt, optend)
2243 document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
2245 optcend = find_end_of(document.body, optc, "\\begin_layout", "\\end_layout")
2246 for line in document.body[optc:optcend]:
2247 if not line.startswith('\\'):
2248 shortcap += line.strip()
2252 for line in document.body[cap:capend]:
2253 if line in document.body[lbl:lblend]:
2255 elif line in document.body[opt:optend]:
2257 elif not line.startswith('\\'):
2258 caption += line.strip()
2260 caption += "\\backslash\nlabel{" + label + "}"
2261 subst = '\\begin_layout Plain Layout\n\\begin_inset ERT\nstatus collapsed\n\n' \
2262 '\\begin_layout Plain Layout\n\n}' + alignment_end + \
2263 '\n\\end_layout\n\n\\end_inset\n\n' \
2264 '\\end_layout\n\n\\begin_layout Plain Layout\n'
2265 subst = subst.split('\n')
2266 document.body[l : l+1] = subst
2267 addedLines = len(subst) - 1
2268 # this is before l and so is unchanged by the multiline insertion
2270 del document.body[cap:capend+1]
2271 addedLines -= (capend + 1 - cap)
2272 del document.body[k+1:m-1]
2273 addedLines -= (m - 1 - (k + 1))
2274 insertion = '\\begin_inset ERT\nstatus collapsed\n\n' \
2275 '\\begin_layout Plain Layout\n\n' + alignment_beg + '\\backslash\n' \
2277 if len(shortcap) > 0:
2278 insertion = insertion + "[" + shortcap + "]"
2279 if len(caption) > 0:
2280 insertion = insertion + "[" + caption + "]"
2281 insertion = insertion + '{%\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n'
2282 insertion = insertion.split('\n')
2283 document.body[k : k + 1] = insertion
2284 addedLines += len(insertion) - 1
2286 del document.body[al]
2288 add_to_preamble(document, ['\\usepackage{subfig}\n'])
2292 def revert_wrapplacement(document):
2293 " Revert placement options wrap floats (wrapfig). "
2296 i = find_token(document.body, "\\begin_inset Wrap figure", i)
2299 e = find_end_of_inset(document.body, i)
2300 j = find_token(document.body, "placement", i + 1, e)
2302 document.warning("Malformed LyX document: Couldn't find placement parameter of wrap float.")
2305 r = re.compile("placement (o|i|l|r)")
2306 m = r.match(document.body[j])
2308 document.warning("Malformed LyX document: Placement option isn't O|I|R|L!")
2309 document.body[j] = "placement " + m.group(1).lower()
2313 def remove_extra_embedded_files(document):
2314 " Remove \extra_embedded_files from buffer params "
2315 i = find_token(document.header, '\\extra_embedded_files', 0)
2318 document.header.pop(i)
2321 def convert_spaceinset(document):
2322 " Convert '\\InsetSpace foo' to '\\begin_inset Space foo\n\\end_inset' "
2324 while i < len(document.body):
2325 m = re.match(r'(.*)\\InsetSpace (.*)', document.body[i])
2329 subst = [before, "\\begin_inset Space " + after, "\\end_inset"]
2330 document.body[i: i+1] = subst
2336 def revert_spaceinset(document):
2337 " Revert '\\begin_inset Space foo\n\\end_inset' to '\\InsetSpace foo' "
2340 i = find_token(document.body, "\\begin_inset Space", i)
2343 j = find_end_of_inset(document.body, i)
2345 document.warning("Malformed LyX document: Could not find end of space inset.")
2347 document.body[i] = document.body[i].replace('\\begin_inset Space', '\\InsetSpace')
2348 del document.body[j]
2351 def convert_hfill(document):
2352 " Convert hfill to space inset "
2355 i = find_token(document.body, "\\hfill", i)
2358 subst = document.body[i].replace('\\hfill', \
2359 '\n\\begin_inset Space \\hfill{}\n\\end_inset')
2360 subst = subst.split('\n')
2361 document.body[i : i+1] = subst
2365 def revert_hfills(document):
2366 ' Revert \\hfill commands '
2367 hfill = re.compile(r'\\hfill')
2368 dotfill = re.compile(r'\\dotfill')
2369 hrulefill = re.compile(r'\\hrulefill')
2372 i = find_token(document.body, "\\InsetSpace", i)
2375 if hfill.search(document.body[i]):
2376 document.body[i] = \
2377 document.body[i].replace('\\InsetSpace \\hfill{}', '\\hfill')
2380 if dotfill.search(document.body[i]):
2381 subst = document.body[i].replace('\\InsetSpace \\dotfill{}', \
2382 '\\begin_inset ERT\nstatus collapsed\n\n' \
2383 '\\begin_layout Standard\n\n\n\\backslash\n' \
2384 'dotfill{}\n\\end_layout\n\n\\end_inset\n\n')
2385 subst = subst.split('\n')
2386 document.body[i : i+1] = subst
2389 if hrulefill.search(document.body[i]):
2390 subst = document.body[i].replace('\\InsetSpace \\hrulefill{}', \
2391 '\\begin_inset ERT\nstatus collapsed\n\n' \
2392 '\\begin_layout Standard\n\n\n\\backslash\n' \
2393 'hrulefill{}\n\\end_layout\n\n\\end_inset\n\n')
2394 subst = subst.split('\n')
2395 document.body[i : i+1] = subst
2400 def revert_hspace(document):
2401 ' Revert \\InsetSpace \\hspace{} to ERT '
2403 hspace = re.compile(r'\\hspace{}')
2404 hstar = re.compile(r'\\hspace\*{}')
2406 i = find_token(document.body, "\\InsetSpace \\hspace", i)
2409 length = get_value(document.body, '\\length', i+1)
2411 document.warning("Malformed lyx document: Missing '\\length' in Space inset.")
2413 del document.body[i+1]
2415 if hstar.search(document.body[i]):
2416 subst = document.body[i].replace('\\InsetSpace \\hspace*{}', \
2417 '\\begin_inset ERT\nstatus collapsed\n\n' \
2418 '\\begin_layout Standard\n\n\n\\backslash\n' \
2419 'hspace*{' + length + '}\n\\end_layout\n\n\\end_inset\n\n')
2420 subst = subst.split('\n')
2421 document.body[i : i+1] = subst
2422 addedLines += len(subst) - 1
2425 if hspace.search(document.body[i]):
2426 subst = document.body[i].replace('\\InsetSpace \\hspace{}', \
2427 '\\begin_inset ERT\nstatus collapsed\n\n' \
2428 '\\begin_layout Standard\n\n\n\\backslash\n' \
2429 'hspace{' + length + '}\n\\end_layout\n\n\\end_inset\n\n')
2430 subst = subst.split('\n')
2431 document.body[i : i+1] = subst
2432 addedLines += len(subst) - 1
2438 def revert_protected_hfill(document):
2439 ' Revert \\begin_inset Space \\hspace*{\\fill} to ERT '
2442 i = find_token(document.body, '\\begin_inset Space \\hspace*{\\fill}', i)
2445 j = find_end_of_inset(document.body, i)
2447 document.warning("Malformed LyX document: Could not find end of space inset.")
2449 del document.body[j]
2450 subst = document.body[i].replace('\\begin_inset Space \\hspace*{\\fill}', \
2451 '\\begin_inset ERT\nstatus collapsed\n\n' \
2452 '\\begin_layout Standard\n\n\n\\backslash\n' \
2453 'hspace*{\n\\backslash\nfill}\n\\end_layout\n\n\\end_inset\n\n')
2454 subst = subst.split('\n')
2455 document.body[i : i+1] = subst
2459 def revert_leftarrowfill(document):
2460 ' Revert \\begin_inset Space \\leftarrowfill{} to ERT '
2463 i = find_token(document.body, '\\begin_inset Space \\leftarrowfill{}', i)
2466 j = find_end_of_inset(document.body, i)
2468 document.warning("Malformed LyX document: Could not find end of space inset.")
2470 del document.body[j]
2471 subst = document.body[i].replace('\\begin_inset Space \\leftarrowfill{}', \
2472 '\\begin_inset ERT\nstatus collapsed\n\n' \
2473 '\\begin_layout Standard\n\n\n\\backslash\n' \
2474 'leftarrowfill{}\n\\end_layout\n\n\\end_inset\n\n')
2475 subst = subst.split('\n')
2476 document.body[i : i+1] = subst
2480 def revert_rightarrowfill(document):
2481 ' Revert \\begin_inset Space \\rightarrowfill{} to ERT '
2484 i = find_token(document.body, '\\begin_inset Space \\rightarrowfill{}', i)
2487 j = find_end_of_inset(document.body, i)
2489 document.warning("Malformed LyX document: Could not find end of space inset.")
2491 del document.body[j]
2492 subst = document.body[i].replace('\\begin_inset Space \\rightarrowfill{}', \
2493 '\\begin_inset ERT\nstatus collapsed\n\n' \
2494 '\\begin_layout Standard\n\n\n\\backslash\n' \
2495 'rightarrowfill{}\n\\end_layout\n\n\\end_inset\n\n')
2496 subst = subst.split('\n')
2497 document.body[i : i+1] = subst
2501 def revert_upbracefill(document):
2502 ' Revert \\begin_inset Space \\upbracefill{} to ERT '
2505 i = find_token(document.body, '\\begin_inset Space \\upbracefill{}', i)
2508 j = find_end_of_inset(document.body, i)
2510 document.warning("Malformed LyX document: Could not find end of space inset.")
2512 del document.body[j]
2513 subst = document.body[i].replace('\\begin_inset Space \\upbracefill{}', \
2514 '\\begin_inset ERT\nstatus collapsed\n\n' \
2515 '\\begin_layout Standard\n\n\n\\backslash\n' \
2516 'upbracefill{}\n\\end_layout\n\n\\end_inset\n\n')
2517 subst = subst.split('\n')
2518 document.body[i : i+1] = subst
2522 def revert_downbracefill(document):
2523 ' Revert \\begin_inset Space \\downbracefill{} to ERT '
2526 i = find_token(document.body, '\\begin_inset Space \\downbracefill{}', i)
2529 j = find_end_of_inset(document.body, i)
2531 document.warning("Malformed LyX document: Could not find end of space inset.")
2533 del document.body[j]
2534 subst = document.body[i].replace('\\begin_inset Space \\downbracefill{}', \
2535 '\\begin_inset ERT\nstatus collapsed\n\n' \
2536 '\\begin_layout Standard\n\n\n\\backslash\n' \
2537 'downbracefill{}\n\\end_layout\n\n\\end_inset\n\n')
2538 subst = subst.split('\n')
2539 document.body[i : i+1] = subst
2543 def revert_local_layout(document):
2544 ' Revert local layout headers.'
2547 i = find_token(document.header, "\\begin_local_layout", i)
2550 j = find_end_of(document.header, i, "\\begin_local_layout", "\\end_local_layout")
2552 # this should not happen
2554 document.header[i : j + 1] = []
2557 def convert_pagebreaks(document):
2558 ' Convert inline Newpage insets to new format '
2561 i = find_token(document.body, '\\newpage', i)
2564 document.body[i:i+1] = ['\\begin_inset Newpage newpage',
2568 i = find_token(document.body, '\\pagebreak', i)
2571 document.body[i:i+1] = ['\\begin_inset Newpage pagebreak',
2575 i = find_token(document.body, '\\clearpage', i)
2578 document.body[i:i+1] = ['\\begin_inset Newpage clearpage',
2582 i = find_token(document.body, '\\cleardoublepage', i)
2585 document.body[i:i+1] = ['\\begin_inset Newpage cleardoublepage',
2589 def revert_pagebreaks(document):
2590 ' Revert \\begin_inset Newpage to previous inline format '
2593 i = find_token(document.body, '\\begin_inset Newpage', i)
2596 j = find_end_of_inset(document.body, i)
2598 document.warning("Malformed LyX document: Could not find end of Newpage inset.")
2600 del document.body[j]
2601 document.body[i] = document.body[i].replace('\\begin_inset Newpage newpage', '\\newpage')
2602 document.body[i] = document.body[i].replace('\\begin_inset Newpage pagebreak', '\\pagebreak')
2603 document.body[i] = document.body[i].replace('\\begin_inset Newpage clearpage', '\\clearpage')
2604 document.body[i] = document.body[i].replace('\\begin_inset Newpage cleardoublepage', '\\cleardoublepage')
2607 def convert_linebreaks(document):
2608 ' Convert inline Newline insets to new format '
2611 i = find_token(document.body, '\\newline', i)
2614 document.body[i:i+1] = ['\\begin_inset Newline newline',
2618 i = find_token(document.body, '\\linebreak', i)
2621 document.body[i:i+1] = ['\\begin_inset Newline linebreak',
2625 def revert_linebreaks(document):
2626 ' Revert \\begin_inset Newline to previous inline format '
2629 i = find_token(document.body, '\\begin_inset Newline', i)
2632 j = find_end_of_inset(document.body, i)
2634 document.warning("Malformed LyX document: Could not find end of Newline inset.")
2636 del document.body[j]
2637 document.body[i] = document.body[i].replace('\\begin_inset Newline newline', '\\newline')
2638 document.body[i] = document.body[i].replace('\\begin_inset Newline linebreak', '\\linebreak')
2641 def convert_japanese_plain(document):
2642 ' Set language japanese-plain to japanese '
2644 if document.language == "japanese-plain":
2645 document.language = "japanese"
2646 i = find_token(document.header, "\\language", 0)
2648 document.header[i] = "\\language japanese"
2651 j = find_token(document.body, "\\lang japanese-plain", j)
2654 document.body[j] = document.body[j].replace("\\lang japanese-plain", "\\lang japanese")
2658 def revert_pdfpages(document):
2659 ' Revert pdfpages external inset to ERT '
2662 i = find_token(document.body, "\\begin_inset External", i)
2665 j = find_end_of_inset(document.body, i)
2667 document.warning("Malformed lyx document: Missing '\\end_inset' in revert_pdfpages.")
2670 if get_value(document.body, 'template', i, j) == "PDFPages":
2671 filename = get_value(document.body, 'filename', i, j)
2673 r = re.compile(r'\textra PDFLaTeX \"(.*)\"$')
2674 for k in range(i, j):
2675 m = r.match(document.body[k])
2678 angle = get_value(document.body, 'rotateAngle', i, j)
2679 width = get_value(document.body, 'width', i, j)
2680 height = get_value(document.body, 'height', i, j)
2681 scale = get_value(document.body, 'scale', i, j)
2682 keepAspectRatio = find_token(document.body, "\tkeepAspectRatio", i, j)
2686 options += ",angle=" + angle
2688 options += "angle=" + angle
2691 options += ",width=" + convert_len(width)
2693 options += "width=" + convert_len(width)
2696 options += ",height=" + convert_len(height)
2698 options += "height=" + convert_len(height)
2701 options += ",scale=" + scale
2703 options += "scale=" + scale
2704 if keepAspectRatio != '':
2706 options += ",keepaspectratio"
2708 options += "keepaspectratio"
2710 options = '[' + options + ']'
2711 del document.body[i+1:j+1]
2712 document.body[i:i+1] = ['\\begin_inset ERT',
2715 '\\begin_layout Standard',
2718 'includepdf' + options + '{' + filename + '}',
2722 add_to_preamble(document, ['\\usepackage{pdfpages}\n'])
2728 def revert_mexican(document):
2729 ' Set language Spanish(Mexico) to Spanish '
2731 if document.language == "spanish-mexico":
2732 document.language = "spanish"
2733 i = find_token(document.header, "\\language", 0)
2735 document.header[i] = "\\language spanish"
2738 j = find_token(document.body, "\\lang spanish-mexico", j)
2741 document.body[j] = document.body[j].replace("\\lang spanish-mexico", "\\lang spanish")
2745 def remove_embedding(document):
2746 ' Remove embed tag from all insets '
2747 revert_inset_embedding(document, 'Graphics')
2748 revert_inset_embedding(document, 'External')
2749 revert_inset_embedding(document, 'CommandInset include')
2750 revert_inset_embedding(document, 'CommandInset bibtex')
2753 def revert_master(document):
2754 ' Remove master param '
2755 i = find_token(document.header, "\\master", 0)
2757 del document.header[i]
2760 def revert_graphics_group(document):
2761 ' Revert group information from graphics insets '
2764 i = find_token(document.body, "\\begin_inset Graphics", i)
2767 j = find_end_of_inset(document.body, i)
2769 document.warning("Malformed lyx document: Missing '\\end_inset' in revert_graphics_group.")
2772 k = find_token(document.body, " groupId", i, j)
2776 del document.body[k]
2780 def update_apa_styles(document):
2781 ' Replace obsolete styles '
2783 if document.textclass != "apa":
2786 obsoletedby = { "Acknowledgments": "Acknowledgements",
2787 "Section*": "Section",
2788 "Subsection*": "Subsection",
2789 "Subsubsection*": "Subsubsection",
2790 "Paragraph*": "Paragraph",
2791 "Subparagraph*": "Subparagraph"}
2794 i = find_token(document.body, "\\begin_layout", i)
2798 layout = document.body[i][14:]
2799 if layout in obsoletedby:
2800 document.body[i] = "\\begin_layout " + obsoletedby[layout]
2805 def convert_paper_sizes(document):
2806 ' exchange size options legalpaper and executivepaper to correct order '
2807 # routine is needed to fix http://bugzilla.lyx.org/show_bug.cgi?id=4868
2810 i = find_token(document.header, "\\papersize executivepaper", 0)
2812 document.header[i] = "\\papersize legalpaper"
2814 j = find_token(document.header, "\\papersize legalpaper", 0)
2816 document.header[j] = "\\papersize executivepaper"
2819 def revert_paper_sizes(document):
2820 ' exchange size options legalpaper and executivepaper to correct order '
2823 i = find_token(document.header, "\\papersize executivepaper", 0)
2825 document.header[i] = "\\papersize legalpaper"
2827 j = find_token(document.header, "\\papersize legalpaper", 0)
2829 document.header[j] = "\\papersize executivepaper"
2832 def convert_InsetSpace(document):
2833 " Convert '\\begin_inset Space foo' to '\\begin_inset space foo'"
2836 i = find_token(document.body, "\\begin_inset Space", i)
2839 document.body[i] = document.body[i].replace('\\begin_inset Space', '\\begin_inset space')
2842 def revert_InsetSpace(document):
2843 " Revert '\\begin_inset space foo' to '\\begin_inset Space foo'"
2846 i = find_token(document.body, "\\begin_inset space", i)
2849 document.body[i] = document.body[i].replace('\\begin_inset space', '\\begin_inset Space')
2852 def convert_display_enum(document):
2853 " Convert 'display foo' to 'display false/true'"
2856 i = find_token(document.body, "\tdisplay", i)
2859 val = get_value(document.body, 'display', i)
2861 document.body[i] = document.body[i].replace('none', 'false')
2862 if val == "default":
2863 document.body[i] = document.body[i].replace('default', 'true')
2864 if val == "monochrome":
2865 document.body[i] = document.body[i].replace('monochrome', 'true')
2866 if val == "grayscale":
2867 document.body[i] = document.body[i].replace('grayscale', 'true')
2869 document.body[i] = document.body[i].replace('color', 'true')
2870 if val == "preview":
2871 document.body[i] = document.body[i].replace('preview', 'true')
2875 def revert_display_enum(document):
2876 " Revert 'display false/true' to 'display none/color'"
2879 i = find_token(document.body, "\tdisplay", i)
2882 val = get_value(document.body, 'display', i)
2884 document.body[i] = document.body[i].replace('false', 'none')
2886 document.body[i] = document.body[i].replace('true', 'default')
2890 def remove_fontsCJK(document):
2891 ' Remove font_cjk param '
2892 i = find_token(document.header, "\\font_cjk", 0)
2894 del document.header[i]
2897 def convert_plain_layout(document):
2898 " Convert 'PlainLayout' to 'Plain Layout'"
2901 i = find_token(document.body, '\\begin_layout PlainLayout', i)
2904 document.body[i] = document.body[i].replace('\\begin_layout PlainLayout', \
2905 '\\begin_layout Plain Layout')
2909 def revert_plain_layout(document):
2910 " Convert 'PlainLayout' to 'Plain Layout'"
2913 i = find_token(document.body, '\\begin_layout Plain Layout', i)
2916 document.body[i] = document.body[i].replace('\\begin_layout Plain Layout', \
2917 '\\begin_layout PlainLayout')
2921 def revert_plainlayout(document):
2922 " Convert 'PlainLayout' to 'Plain Layout'"
2925 i = find_token(document.body, '\\begin_layout PlainLayout', i)
2928 # This will be incorrect for some document classes, since Standard is not always
2929 # the default. But (a) it is probably the best we can do and (b) it will actually
2930 # work, in fact, since an unknown layout will be converted to default.
2931 document.body[i] = document.body[i].replace('\\begin_layout PlainLayout', \
2932 '\\begin_layout Standard')
2936 def revert_polytonicgreek(document):
2937 "Set language polytonic Greek to Greek"
2939 if document.language == "polutonikogreek":
2940 document.language = "greek"
2941 i = find_token(document.header, "\\language", 0)
2943 document.header[i] = "\\language greek"
2946 j = find_token(document.body, "\\lang polutonikogreek", j)
2949 document.body[j] = document.body[j].replace("\\lang polutonikogreek", "\\lang greek")
2953 def revert_removed_modules(document):
2956 i = find_token(document.header, "\\begin_remove_modules", i)
2959 j = find_end_of(document.header, i, "\\begin_remove_modules", "\\end_remove_modules")
2961 # this should not happen
2963 document.header[i : j + 1] = []
2966 def add_plain_layout(document):
2969 i = find_token(document.body, "\\begin_layout", i)
2972 if len(document.body[i].split()) == 1:
2973 document.body[i] = "\\begin_layout Plain Layout"
2977 def revert_tabulators(document):
2978 "Revert tabulators to 4 spaces"
2981 i = find_token(document.body, "\t", i)
2984 document.body[i] = document.body[i].replace("\t", " ")
2988 def revert_tabsize(document):
2989 "Revert the tabsize parameter of listings"
2993 # either it is the only parameter
2994 i = find_token(document.body, 'lstparams "tabsize=4"', i)
2996 del document.body[i]
2998 j = find_token(document.body, "lstparams", j)
3001 pos = document.body[j].find(",tabsize=")
3002 document.body[j] = document.body[j][:pos] + '"'
3007 def revert_mongolian(document):
3008 "Set language Mongolian to English"
3010 if document.language == "mongolian":
3011 document.language = "english"
3012 i = find_token(document.header, "\\language", 0)
3014 document.header[i] = "\\language english"
3017 j = find_token(document.body, "\\lang mongolian", j)
3020 document.body[j] = document.body[j].replace("\\lang mongolian", "\\lang english")
3024 def revert_default_options(document):
3025 ' Remove param use_default_options '
3026 i = find_token(document.header, "\\use_default_options", 0)
3028 del document.header[i]
3031 def convert_default_options(document):
3032 ' Add param use_default_options and set it to false '
3033 i = find_token(document.header, "\\textclass", 0)
3035 document.warning("Malformed LyX document: Missing `\\textclass'.")
3037 document.header.insert(i, '\\use_default_options false')
3040 def revert_backref_options(document):
3041 ' Revert option pdf_backref=page to pagebackref '
3042 i = find_token(document.header, "\\pdf_backref page", 0)
3044 document.header[i] = "\\pdf_pagebackref true"
3047 def convert_backref_options(document):
3048 ' We have changed the option pagebackref to backref=true '
3049 i = find_token(document.header, "\\pdf_pagebackref true", 0)
3051 document.header[i] = "\\pdf_backref page"
3052 j = find_token(document.header, "\\pdf_pagebackref false", 0)
3054 del document.header[j]
3055 # backref=true was not a valid option, we meant backref=section
3056 k = find_token(document.header, "\\pdf_backref true", 0)
3057 if k != -1 and i != -1:
3058 del document.header[k]
3059 elif k != -1 and j != -1:
3060 document.header[k] = "\\pdf_backref section"
3063 def convert_charstyle_element(document):
3064 "Convert CharStyle to Element for docbook backend"
3065 if document.backend != "docbook":
3069 i = find_token(document.body, "\\begin_inset Flex CharStyle:", i)
3072 document.body[i] = document.body[i].replace('\\begin_inset Flex CharStyle:',
3073 '\\begin_inset Flex Element:')
3075 def revert_charstyle_element(document):
3076 "Convert Element to CharStyle for docbook backend"
3077 if document.backend != "docbook":
3081 i = find_token(document.body, "\\begin_inset Flex Element:", i)
3084 document.body[i] = document.body[i].replace('\\begin_inset Flex Element:',
3085 '\\begin_inset Flex CharStyle:')
3091 supported_versions = ["1.6.0","1.6"]
3092 convert = [[277, [fix_wrong_tables]],
3093 [278, [close_begin_deeper]],
3094 [279, [long_charstyle_names]],
3095 [280, [axe_show_label]],
3098 [283, [convert_flex]],
3102 [287, [convert_wrapfig_options]],
3103 [288, [convert_inset_command]],
3104 [289, [convert_latexcommand_index]],
3107 [292, [convert_japanese_cjk]],
3109 [294, [convert_pdf_options]],
3110 [295, [convert_htmlurl, convert_url]],
3111 [296, [convert_include]],
3112 [297, [convert_usorbian]],
3113 [298, [convert_macro_global]],
3118 [303, [convert_serbocroatian]],
3119 [304, [convert_framed_notes]],
3126 [311, [convert_ams_classes]],
3128 [313, [convert_module_names]],
3131 [316, [convert_subfig]],
3134 [319, [convert_spaceinset, convert_hfill]],
3136 [321, [convert_tablines]],
3137 [322, [convert_plain_layout]],
3138 [323, [convert_pagebreaks]],
3139 [324, [convert_linebreaks]],
3140 [325, [convert_japanese_plain]],
3143 [328, [remove_embedding, remove_extra_embedded_files, remove_inzip_options]],
3146 [331, [convert_ltcaption]],
3148 [333, [update_apa_styles]],
3149 [334, [convert_paper_sizes]],
3150 [335, [convert_InsetSpace]],
3152 [337, [convert_display_enum]],
3155 [340, [add_plain_layout]],
3158 [343, [convert_default_options]],
3159 [344, [convert_backref_options]],
3160 [345, [convert_charstyle_element]]
3163 revert = [[344, [revert_charstyle_element]],
3164 [343, [revert_backref_options]],
3165 [342, [revert_default_options]],
3166 [341, [revert_mongolian]],
3167 [340, [revert_tabulators, revert_tabsize]],
3169 [338, [revert_removed_modules]],
3170 [337, [revert_polytonicgreek]],
3171 [336, [revert_display_enum]],
3172 [335, [remove_fontsCJK]],
3173 [334, [revert_InsetSpace]],
3174 [333, [revert_paper_sizes]],
3176 [331, [revert_graphics_group]],
3177 [330, [revert_ltcaption]],
3178 [329, [revert_leftarrowfill, revert_rightarrowfill, revert_upbracefill, revert_downbracefill]],
3179 [328, [revert_master]],
3181 [326, [revert_mexican]],
3182 [325, [revert_pdfpages]],
3184 [323, [revert_linebreaks]],
3185 [322, [revert_pagebreaks]],
3186 [321, [revert_local_layout, revert_plain_layout]],
3187 [320, [revert_tablines]],
3188 [319, [revert_protected_hfill]],
3189 [318, [revert_spaceinset, revert_hfills, revert_hspace]],
3190 [317, [remove_extra_embedded_files]],
3191 [316, [revert_wrapplacement]],
3192 [315, [revert_subfig]],
3193 [314, [revert_colsep, revert_plainlayout]],
3195 [312, [revert_module_names]],
3196 [311, [revert_rotfloat, revert_widesideways]],
3197 [310, [revert_external_embedding]],
3198 [309, [revert_btprintall]],
3199 [308, [revert_nocite]],
3200 [307, [revert_serbianlatin]],
3201 [306, [revert_slash, revert_nobreakdash]],
3202 [305, [revert_interlingua]],
3203 [304, [revert_bahasam]],
3204 [303, [revert_framed_notes]],
3206 [301, [revert_latin, revert_samin]],
3207 [300, [revert_linebreak]],
3208 [299, [revert_pagebreak]],
3209 [298, [revert_hyperlinktype]],
3210 [297, [revert_macro_optional_params]],
3211 [296, [revert_albanian, revert_lowersorbian, revert_uppersorbian]],
3212 [295, [revert_include]],
3213 [294, [revert_href, revert_url]],
3214 [293, [revert_pdf_options_2]],
3215 [292, [revert_inset_info]],
3216 [291, [revert_japanese, revert_japanese_encoding, revert_japanese_cjk]],
3217 [290, [revert_vietnamese]],
3218 [289, [revert_wraptable]],
3219 [288, [revert_latexcommand_index]],
3220 [287, [revert_inset_command]],
3221 [286, [revert_wrapfig_options]],
3222 [285, [revert_pdf_options]],
3223 [284, [remove_inzip_options]],
3225 [282, [revert_flex]],
3227 [280, [revert_begin_modules]],
3228 [279, [revert_show_label]],
3229 [278, [revert_long_charstyle_names]],
3235 if __name__ == "__main__":