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 # Convert a LyX length into a LaTeX length
69 units = {"text%":"\\backslash\ntextwidth", "col%":"\\backslash\ncolumnwidth",
70 "page%":"\\backslash\npagewidth", "line%":"\\backslash\nlinewidth",
71 "theight%":"\\backslash\ntextheight", "pheight%":"\\backslash\npageheight"}
73 # Convert LyX units to LaTeX units
74 for unit in units.keys():
75 if len.find(unit) != -1:
76 len = '%f' % (len2value(len) / 100)
77 len = len.strip('0') + units[unit]
82 # Return the value of len without the unit in numerical form.
84 result = re.search('([+-]?[0-9.]+)', len)
86 return float(result.group(1))
90 # Unfortunately, this doesn't really work, since Standard isn't always default.
91 # But it's as good as we can do right now.
92 def find_default_layout(document, start, end):
93 l = find_token(document.body, "\\begin_layout Standard", start, end)
95 l = find_token(document.body, "\\begin_layout PlainLayout", start, end)
97 l = find_token(document.body, "\\begin_layout Plain Layout", start, end)
100 def get_option(document, m, option, default):
101 l = document.body[m].find(option)
104 val = document.body[m][l:].split('"')[1]
107 def remove_option(document, m, option):
108 l = document.body[m].find(option)
110 val = document.body[m][l:].split('"')[1]
111 document.body[m] = document.body[m][:l-1] + document.body[m][l+len(option + '="' + val + '"'):]
114 def set_option(document, m, option, value):
115 l = document.body[m].find(option)
117 oldval = document.body[m][l:].split('"')[1]
118 l = l + len(option + '="')
119 document.body[m] = document.body[m][:l] + value + document.body[m][l+len(oldval):]
121 document.body[m] = document.body[m][:-1] + ' ' + option + '="' + value + '">'
125 def read_unicodesymbols():
126 " Read the unicodesymbols list of unicode characters and corresponding commands."
127 pathname = os.path.abspath(os.path.dirname(sys.argv[0]))
128 fp = open(os.path.join(pathname.strip('lyx2lyx'), 'unicodesymbols'))
130 # Two backslashes, followed by some non-word character, and then a character
131 # in brackets. The idea is to check for constructs like: \"{u}, which is how
132 # they are written in the unicodesymbols file; but they can also be written
134 r = re.compile(r'\\\\(\W)\{(\w)\}')
135 for line in fp.readlines():
136 if line[0] != '#' and line.strip() != "":
137 line=line.replace(' "',' ') # remove all quotation marks with spaces before
138 line=line.replace('" ',' ') # remove all quotation marks with spaces after
139 line=line.replace(r'\"','"') # replace \" by " (for characters with diaeresis)
141 [ucs4,command,dead] = line.split(None,2)
142 if command[0:1] != "\\":
144 spec_chars.append([command, unichr(eval(ucs4))])
150 # If the character is a double-quote, then we need to escape it, too,
151 # since it is done that way in the LyX file.
152 if m.group(1) == "\"":
154 command += m.group(1) + m.group(2)
155 spec_chars.append([command, unichr(eval(ucs4))])
160 def extract_argument(line):
161 'Extracts a LaTeX argument from the start of line. Returns (arg, rest).'
166 bracere = re.compile("(\s*)(.*)")
167 n = bracere.match(line)
168 whitespace = n.group(1)
171 if brace != "[" and brace != "{":
195 # We never found the matching brace
196 # So, to be on the safe side, let's just return everything
197 # which will then get wrapped as ERT
199 return (line[:pos + 1], line[pos + 1:])
203 '''Converts LaTeX commands into ERT. line may well be a multi-line
204 string when it is returned.'''
209 ## FIXME Escaped \ ??
210 # This regex looks for a LaTeX command---i.e., something of the form
211 # "\alPhaStuFF", or "\X", where X is any character---where the command
212 # may also be preceded by an additional backslash, which is how it would
213 # appear (e.g.) in an InsetIndex.
214 labelre = re.compile(r'(.*?)\\?(\\(?:[a-zA-Z]+|.))(.*)')
216 m = labelre.match(line)
223 (arg, rest) = extract_argument(end)
228 # If we wanted to put labels into an InsetLabel, for example, then we
229 # would just need to test here for cmd == "label" and then take some
230 # appropriate action, i.e., to use arg to get the content and then
231 # wrap it appropriately.
232 cmd = put_cmd_in_ert(cmd)
233 retval += "\n" + cmd + "\n"
235 m = labelre.match(line)
241 '''Takes a string, possibly multi-line, and returns the result of
242 converting LaTeX constructs into LyX constructs. Returns a list of
243 lines, suitable for insertion into document.body.'''
247 # Convert LaTeX to Unicode
248 reps = read_unicodesymbols()
249 # Commands of this sort need to be checked to make sure they are
250 # followed by a non-alpha character, lest we replace too much.
251 hardone = re.compile(r'^\\\\[a-zA-Z]+$')
254 if hardone.match(rep[0]):
257 pos = data.find(rep[0], pos)
260 nextpos = pos + len(rep[0])
261 if nextpos < len(data) and data[nextpos].isalpha():
262 # not the end of that command
265 data = data[:pos] + rep[1] + data[nextpos:]
268 data = data.replace(rep[0], rep[1])
271 data = wrap_into_ert(data, r'\"', '"')
274 mathre = re.compile('^(.*?)(\$.*?\$)(.*)')
275 lines = data.split('\n')
277 #document.warning("LINE: " + line)
278 #document.warning(str(i) + ":" + document.body[i])
279 #document.warning("LAST: " + document.body[-1])
284 f = m.group(2).replace('\\\\', '\\')
289 subst = s.split('\n')
291 retval.append("\\begin_inset Formula " + f)
292 retval.append("\\end_inset")
294 # Handle whatever is left, which is just text
296 subst = g.split('\n')
301 def lyx2latex(lines):
302 'Convert some LyX stuff into corresponding LaTeX stuff, as best we can.'
303 # clean up multiline stuff
306 reps = read_unicodesymbols()
308 for curline in range(len(lines)):
309 line = lines[curline]
310 if line.startswith("\\begin_inset ERT"):
311 # We don't want to replace things inside ERT, so figure out
312 # where the end of the inset is.
313 ert_end = find_end_of_inset(lines, curline + 1)
315 elif line.startswith("\\begin_inset Formula"):
317 elif line.startswith("\\begin_inset Quotes"):
318 # For now, we do a very basic reversion. Someone who understands
319 # quotes is welcome to fix it up.
320 qtype = line[20:].strip()
334 elif line.isspace() or \
335 line.startswith("\\begin_layout") or \
336 line.startswith("\\end_layout") or \
337 line.startswith("\\begin_inset") or \
338 line.startswith("\\end_inset") or \
339 line.startswith("\\lang") or \
340 line.strip() == "status collapsed" or \
341 line.strip() == "status open":
345 # a lossless reversion is not possible
346 # try at least to handle some common insets and settings
347 # do not replace inside ERTs
348 if ert_end >= curline:
349 line = line.replace(r'\backslash', r'\\')
351 # Do the LyX text --> LaTeX conversion
353 line = line.replace(rep[1], rep[0])
354 line = line.replace(r'\backslash', r'\textbackslash{}')
355 line = line.replace(r'\series bold', r'\bfseries{}').replace(r'\series default', r'\mdseries{}')
356 line = line.replace(r'\shape italic', r'\itshape{}').replace(r'\shape smallcaps', r'\scshape{}')
357 line = line.replace(r'\shape slanted', r'\slshape{}').replace(r'\shape default', r'\upshape{}')
358 line = line.replace(r'\emph on', r'\em{}').replace(r'\emph default', r'\em{}')
359 line = line.replace(r'\noun on', r'\scshape{}').replace(r'\noun default', r'\upshape{}')
360 line = line.replace(r'\bar under', r'\underbar{').replace(r'\bar default', r'}')
361 line = line.replace(r'\family sans', r'\sffamily{}').replace(r'\family default', r'\normalfont{}')
362 line = line.replace(r'\family typewriter', r'\ttfamily{}').replace(r'\family roman', r'\rmfamily{}')
363 line = line.replace(r'\InsetSpace ', r'').replace(r'\SpecialChar ', r'')
368 ####################################################################
370 def convert_ltcaption(document):
373 i = find_token(document.body, "\\begin_inset Tabular", i)
376 j = find_end_of_inset(document.body, i + 1)
378 document.warning("Malformed LyX document: Could not find end of tabular.")
381 nrows = int(document.body[i+1].split('"')[3])
382 ncols = int(document.body[i+1].split('"')[5])
385 for k in range(nrows):
386 m = find_token(document.body, "<row", m)
389 for k in range(ncols):
390 m = find_token(document.body, "<cell", m)
392 mend = find_token(document.body, "</cell>", m + 1)
393 # first look for caption insets
394 mcap = find_token(document.body, "\\begin_inset Caption", m + 1, mend)
395 # then look for ERT captions
397 mcap = find_token(document.body, "caption", m + 1, mend)
399 mcap = find_token(document.body, "\\backslash", mcap - 1, mcap)
402 if caption == 'true':
404 set_option(document, r, 'caption', 'true')
405 set_option(document, m, 'multicolumn', '1')
406 set_option(document, m, 'bottomline', 'false')
407 set_option(document, m, 'topline', 'false')
408 set_option(document, m, 'rightline', 'false')
409 set_option(document, m, 'leftline', 'false')
410 #j = find_end_of_inset(document.body, j + 1)
412 set_option(document, m, 'multicolumn', '2')
419 #FIXME Use of wrap_into_ert can confuse lyx2lyx
420 def revert_ltcaption(document):
423 i = find_token(document.body, "\\begin_inset Tabular", i)
426 j = find_end_of_inset(document.body, i + 1)
428 document.warning("Malformed LyX document: Could not find end of tabular.")
432 nrows = int(document.body[i+1].split('"')[3])
433 ncols = int(document.body[i+1].split('"')[5])
435 for k in range(nrows):
436 m = find_token(document.body, "<row", m)
437 caption = get_option(document, m, 'caption', 'false')
438 if caption == 'true':
439 remove_option(document, m, 'caption')
440 for k in range(ncols):
441 m = find_token(document.body, "<cell", m)
442 remove_option(document, m, 'multicolumn')
444 m = find_token(document.body, "\\begin_inset Caption", m)
447 m = find_end_of_inset(document.body, m + 1)
448 document.body[m] += wrap_into_ert("","","\\backslash\n\\backslash\n%")
454 def convert_tablines(document):
457 i = find_token(document.body, "\\begin_inset Tabular", i)
459 # LyX 1.3 inserted an extra space between \begin_inset
460 # and Tabular so let us try if this is the case and fix it.
461 i = find_token(document.body, "\\begin_inset Tabular", i)
465 document.body[i] = "\\begin_inset Tabular"
466 j = find_end_of_inset(document.body, i + 1)
468 document.warning("Malformed LyX document: Could not find end of tabular.")
472 nrows = int(document.body[i+1].split('"')[3])
473 ncols = int(document.body[i+1].split('"')[5])
476 for k in range(ncols):
477 m = find_token(document.body, "<column", m)
478 left = get_option(document, m, 'leftline', 'false')
479 right = get_option(document, m, 'rightline', 'false')
480 col_info.append([left, right])
481 remove_option(document, m, 'leftline')
482 remove_option(document, m, 'rightline')
486 for k in range(nrows):
487 m = find_token(document.body, "<row", m)
488 top = get_option(document, m, 'topline', 'false')
489 bottom = get_option(document, m, 'bottomline', 'false')
490 row_info.append([top, bottom])
491 remove_option(document, m, 'topline')
492 remove_option(document, m, 'bottomline')
497 for k in range(nrows*ncols):
498 m = find_token(document.body, "<cell", m)
499 mc_info.append(get_option(document, m, 'multicolumn', '0'))
502 for l in range(nrows):
503 for k in range(ncols):
504 m = find_token(document.body, '<cell', m)
505 if mc_info[l*ncols + k] == '0':
506 r = set_option(document, m, 'topline', row_info[l][0])
507 r = set_option(document, m, 'bottomline', row_info[l][1])
508 r = set_option(document, m, 'leftline', col_info[k][0])
509 r = set_option(document, m, 'rightline', col_info[k][1])
510 elif mc_info[l*ncols + k] == '1':
512 while s < ncols and mc_info[l*ncols + s] == '2':
514 if s < ncols and mc_info[l*ncols + s] != '1':
515 r = set_option(document, m, 'rightline', col_info[k][1])
516 if k > 0 and mc_info[l*ncols + k - 1] == '0':
517 r = set_option(document, m, 'leftline', col_info[k][0])
522 def revert_tablines(document):
525 i = find_token(document.body, "\\begin_inset Tabular", i)
528 j = find_end_of_inset(document.body, i + 1)
530 document.warning("Malformed LyX document: Could not find end of tabular.")
534 nrows = int(document.body[i+1].split('"')[3])
535 ncols = int(document.body[i+1].split('"')[5])
538 for k in range(nrows*ncols):
539 m = find_token(document.body, "<cell", m)
540 top = get_option(document, m, 'topline', 'false')
541 bottom = get_option(document, m, 'bottomline', 'false')
542 left = get_option(document, m, 'leftline', 'false')
543 right = get_option(document, m, 'rightline', 'false')
544 lines.append([top, bottom, left, right])
547 # we will want to ignore longtable captions
550 for k in range(nrows):
551 m = find_token(document.body, "<row", m)
552 caption = get_option(document, m, 'caption', 'false')
553 caption_info.append([caption])
558 for k in range(ncols):
559 m = find_token(document.body, "<column", m)
561 for l in range(nrows):
562 left = lines[l*ncols + k][2]
563 if left == 'false' and caption_info[l] == 'false':
565 set_option(document, m, 'leftline', left)
567 for l in range(nrows):
568 right = lines[l*ncols + k][3]
569 if right == 'false' and caption_info[l] == 'false':
571 set_option(document, m, 'rightline', right)
575 for k in range(nrows):
576 m = find_token(document.body, "<row", m)
578 for l in range(ncols):
579 top = lines[k*ncols + l][0]
582 if caption_info[k] == 'false':
584 set_option(document, m, 'topline', top)
586 for l in range(ncols):
587 bottom = lines[k*ncols + l][1]
588 if bottom == 'false':
590 if caption_info[k] == 'false':
592 set_option(document, m, 'bottomline', bottom)
598 def fix_wrong_tables(document):
601 i = find_token(document.body, "\\begin_inset Tabular", i)
604 j = find_end_of_inset(document.body, i + 1)
606 document.warning("Malformed LyX document: Could not find end of tabular.")
610 nrows = int(document.body[i+1].split('"')[3])
611 ncols = int(document.body[i+1].split('"')[5])
613 for l in range(nrows):
615 for k in range(ncols):
616 m = find_token(document.body, '<cell', m)
618 if document.body[m].find('multicolumn') != -1:
619 multicol_cont = int(document.body[m].split('"')[1])
621 if multicol_cont == 2 and (k == 0 or prev_multicolumn == 0):
622 document.body[m] = document.body[m][:5] + document.body[m][21:]
625 prev_multicolumn = multicol_cont
632 def close_begin_deeper(document):
636 i = find_tokens(document.body, ["\\begin_deeper", "\\end_deeper"], i)
641 if document.body[i][:13] == "\\begin_deeper":
648 document.body[-2:-2] = ['\\end_deeper' for i in range(depth)]
651 def long_charstyle_names(document):
654 i = find_token(document.body, "\\begin_inset CharStyle", i)
657 document.body[i] = document.body[i].replace("CharStyle ", "CharStyle CharStyle:")
660 def revert_long_charstyle_names(document):
663 i = find_token(document.body, "\\begin_inset CharStyle", i)
666 document.body[i] = document.body[i].replace("CharStyle CharStyle:", "CharStyle ")
670 def axe_show_label(document):
673 i = find_token(document.body, "\\begin_inset CharStyle", i)
676 if document.body[i + 1].find("show_label") != -1:
677 if document.body[i + 1].find("true") != -1:
678 document.body[i + 1] = "status open"
679 del document.body[ i + 2]
681 if document.body[i + 1].find("false") != -1:
682 document.body[i + 1] = "status collapsed"
683 del document.body[ i + 2]
685 document.warning("Malformed LyX document: show_label neither false nor true.")
687 document.warning("Malformed LyX document: show_label missing in CharStyle.")
692 def revert_show_label(document):
695 i = find_token(document.body, "\\begin_inset CharStyle", i)
698 if document.body[i + 1].find("status open") != -1:
699 document.body.insert(i + 1, "show_label true")
701 if document.body[i + 1].find("status collapsed") != -1:
702 document.body.insert(i + 1, "show_label false")
704 document.warning("Malformed LyX document: no legal status line in CharStyle.")
707 def revert_begin_modules(document):
710 i = find_token(document.header, "\\begin_modules", i)
713 j = find_end_of(document.header, i, "\\begin_modules", "\\end_modules")
715 # this should not happen
717 document.header[i : j + 1] = []
719 def convert_flex(document):
720 "Convert CharStyle to Flex"
723 i = find_token(document.body, "\\begin_inset CharStyle", i)
726 document.body[i] = document.body[i].replace('\\begin_inset CharStyle', '\\begin_inset Flex')
728 def revert_flex(document):
729 "Convert Flex to CharStyle"
732 i = find_token(document.body, "\\begin_inset Flex", i)
735 document.body[i] = document.body[i].replace('\\begin_inset Flex', '\\begin_inset CharStyle')
738 # Discard PDF options for hyperref
739 def revert_pdf_options(document):
740 "Revert PDF options for hyperref."
741 # store the PDF options and delete the entries from the Lyx file
749 bookmarksnumbered = ""
751 bookmarksopenlevel = ""
759 i = find_token(document.header, "\\use_hyperref", i)
761 hyperref = get_value(document.header, "\\use_hyperref", i) == 'true'
762 del document.header[i]
763 i = find_token(document.header, "\\pdf_store_options", i)
765 del document.header[i]
766 i = find_token(document.header, "\\pdf_title", 0)
768 title = get_value_string(document.header, '\\pdf_title', 0, 0, True)
769 title = ' pdftitle={' + title + '}'
770 del document.header[i]
771 i = find_token(document.header, "\\pdf_author", 0)
773 author = get_value_string(document.header, '\\pdf_author', 0, 0, True)
775 author = ' pdfauthor={' + author + '}'
777 author = ',\n pdfauthor={' + author + '}'
778 del document.header[i]
779 i = find_token(document.header, "\\pdf_subject", 0)
781 subject = get_value_string(document.header, '\\pdf_subject', 0, 0, True)
782 if title == "" and author == "":
783 subject = ' pdfsubject={' + subject + '}'
785 subject = ',\n pdfsubject={' + subject + '}'
786 del document.header[i]
787 i = find_token(document.header, "\\pdf_keywords", 0)
789 keywords = get_value_string(document.header, '\\pdf_keywords', 0, 0, True)
790 if title == "" and author == "" and subject == "":
791 keywords = ' pdfkeywords={' + keywords + '}'
793 keywords = ',\n pdfkeywords={' + keywords + '}'
794 del document.header[i]
795 i = find_token(document.header, "\\pdf_bookmarks", 0)
797 bookmarks = get_value_string(document.header, '\\pdf_bookmarks', 0)
798 bookmarks = ',\n bookmarks=' + bookmarks
799 del document.header[i]
800 i = find_token(document.header, "\\pdf_bookmarksnumbered", i)
802 bookmarksnumbered = get_value_string(document.header, '\\pdf_bookmarksnumbered', 0)
803 bookmarksnumbered = ',\n bookmarksnumbered=' + bookmarksnumbered
804 del document.header[i]
805 i = find_token(document.header, "\\pdf_bookmarksopen", i)
807 bookmarksopen = get_value_string(document.header, '\\pdf_bookmarksopen', 0)
808 bookmarksopen = ',\n bookmarksopen=' + bookmarksopen
809 del document.header[i]
810 i = find_token(document.header, "\\pdf_bookmarksopenlevel", i)
812 bookmarksopenlevel = get_value_string(document.header, '\\pdf_bookmarksopenlevel', 0, 0, True)
813 bookmarksopenlevel = ',\n bookmarksopenlevel=' + bookmarksopenlevel
814 del document.header[i]
815 i = find_token(document.header, "\\pdf_breaklinks", i)
817 breaklinks = get_value_string(document.header, '\\pdf_breaklinks', 0)
818 breaklinks = ',\n breaklinks=' + breaklinks
819 del document.header[i]
820 i = find_token(document.header, "\\pdf_pdfborder", i)
822 pdfborder = get_value_string(document.header, '\\pdf_pdfborder', 0)
823 if pdfborder == 'true':
824 pdfborder = ',\n pdfborder={0 0 0}'
826 pdfborder = ',\n pdfborder={0 0 1}'
827 del document.header[i]
828 i = find_token(document.header, "\\pdf_colorlinks", i)
830 colorlinks = get_value_string(document.header, '\\pdf_colorlinks', 0)
831 colorlinks = ',\n colorlinks=' + colorlinks
832 del document.header[i]
833 i = find_token(document.header, "\\pdf_backref", i)
835 backref = get_value_string(document.header, '\\pdf_backref', 0)
836 backref = ',\n backref=' + backref
837 del document.header[i]
838 i = find_token(document.header, "\\pdf_pagebackref", i)
840 pagebackref = get_value_string(document.header, '\\pdf_pagebackref', 0)
841 pagebackref = ',\n pagebackref=' + pagebackref
842 del document.header[i]
843 i = find_token(document.header, "\\pdf_pagemode", 0)
845 pagemode = get_value_string(document.header, '\\pdf_pagemode', 0)
846 pagemode = ',\n pdfpagemode=' + pagemode
847 del document.header[i]
848 i = find_token(document.header, "\\pdf_quoted_options", 0)
850 otheroptions = get_value_string(document.header, '\\pdf_quoted_options', 0, 0, True)
851 if title == "" and author == "" and subject == "" and keywords == "":
852 otheroptions = ' ' + otheroptions
854 otheroptions = ',\n ' + otheroptions
855 del document.header[i]
857 # write to the preamble when hyperref was used
859 # preamble write preparations
860 # bookmark numbers are only output when they are turned on
861 if bookmarksopen == ',\n bookmarksopen=true':
862 bookmarksopen = bookmarksopen + bookmarksopenlevel
863 if bookmarks == ',\n bookmarks=true':
864 bookmarks = bookmarks + bookmarksnumbered + bookmarksopen
866 bookmarks = bookmarks
867 # hypersetup is only output when there are things to be set up
868 setupstart = '\\hypersetup{%\n'
870 if otheroptions == "" and title == "" and author == ""\
871 and subject == "" and keywords == "":
875 add_to_preamble(document,
876 ['% Commands inserted by lyx2lyx for PDF properties',
877 '\\usepackage[unicode=true'
896 def remove_inzip_options(document):
897 "Remove inzipName and embed options from the Graphics inset"
900 i = find_token(document.body, "\\begin_inset Graphics", i)
903 j = find_end_of_inset(document.body, i + 1)
906 document.warning("Malformed LyX document: Could not find end of graphics inset.")
907 # If there's a inzip param, just remove that
908 k = find_token(document.body, "\tinzipName", i + 1, j)
911 # embed option must follow the inzipName option
912 del document.body[k+1]
916 def convert_inset_command(document):
919 \begin_inset LatexCommand cmd
921 \begin_inset CommandInset InsetType
926 i = find_token(document.body, "\\begin_inset LatexCommand", i)
929 line = document.body[i]
930 r = re.compile(r'\\begin_inset LatexCommand (.*)$')
934 #this is adapted from factory.cpp
935 if cmdName[0:4].lower() == "cite":
936 insetName = "citation"
937 elif cmdName == "url" or cmdName == "htmlurl":
939 elif cmdName[-3:] == "ref":
941 elif cmdName == "tableofcontents":
943 elif cmdName == "printnomenclature":
944 insetName = "nomencl_print"
945 elif cmdName == "printindex":
946 insetName = "index_print"
949 insertion = ["\\begin_inset CommandInset " + insetName, "LatexCommand " + cmdName]
950 document.body[i : i+1] = insertion
953 def revert_inset_command(document):
956 \begin_inset CommandInset InsetType
959 \begin_inset LatexCommand cmd
960 Some insets may end up being converted to insets earlier versions of LyX
961 will not be able to recognize. Not sure what to do about that.
965 i = find_token(document.body, "\\begin_inset CommandInset", i)
968 nextline = document.body[i+1]
969 r = re.compile(r'LatexCommand\s+(.*)$')
970 m = r.match(nextline)
972 document.warning("Malformed LyX document: Missing LatexCommand in " + document.body[i] + ".")
975 insertion = ["\\begin_inset LatexCommand " + cmdName]
976 document.body[i : i+2] = insertion
979 def convert_wrapfig_options(document):
980 "Convert optional options for wrap floats (wrapfig)."
981 # adds the tokens "lines", "placement", and "overhang"
984 i = find_token(document.body, "\\begin_inset Wrap figure", i)
987 document.body.insert(i + 1, "lines 0")
988 j = find_token(document.body, "placement", i)
989 # placement can be already set or not; if not, set it
991 document.body.insert(i + 3, "overhang 0col%")
993 document.body.insert(i + 2, "placement o")
994 document.body.insert(i + 3, "overhang 0col%")
998 def revert_wrapfig_options(document):
999 "Revert optional options for wrap floats (wrapfig)."
1002 i = find_token(document.body, "\\begin_inset Wrap figure", i)
1005 j = find_end_of_inset(document.body, i)
1007 document.warning("Can't find end of Wrap inset at line " + str(i))
1010 k = find_default_layout(document, i, j)
1012 document.warning("Can't find default layout for Wrap figure!")
1015 # Options should be between i and k now
1016 l = find_token(document.body, "lines", i, k)
1018 document.warning("Can't find lines option for Wrap figure!")
1021 m = find_token(document.body, "overhang", i + 1, k)
1023 document.warning("Malformed LyX document: Couldn't find overhang parameter of wrap float!")
1026 # Do these in reverse order
1027 del document.body[m]
1028 del document.body[l]
1032 def convert_latexcommand_index(document):
1033 "Convert from LatexCommand form to collapsable form."
1035 r1 = re.compile('name "(.*)"')
1037 i = find_token(document.body, "\\begin_inset CommandInset index", i)
1040 if document.body[i + 1] != "LatexCommand index": # Might also be index_print
1042 m = r1.match(document.body[i + 2])
1044 document.warning("Unable to match: " + document.body[i+2])
1047 fullcontent = m.group(1)
1048 #document.warning(fullcontent)
1049 document.body[i:i + 3] = ["\\begin_inset Index",
1051 "\\begin_layout Standard"]
1053 # We are now on the blank line preceding "\end_inset"
1054 # We will write the content here, into the inset.
1056 linelist = latex2lyx(fullcontent)
1057 document.body[i+1:i+1] = linelist
1060 document.body.insert(i + 1, "\\end_layout")
1064 def revert_latexcommand_index(document):
1065 "Revert from collapsable form to LatexCommand form."
1068 i = find_token(document.body, "\\begin_inset Index", i)
1071 j = find_end_of_inset(document.body, i + 1)
1075 content = lyx2latex(document.body[i:j])
1077 content = content.replace('"', r'\"')
1078 document.body[i:j] = ["\\begin_inset CommandInset index", "LatexCommand index",
1079 "name " + '"' + content + '"', ""]
1083 def revert_wraptable(document):
1084 "Revert wrap table to wrap figure."
1087 i = find_token(document.body, "\\begin_inset Wrap table", i)
1090 document.body[i] = document.body[i].replace('\\begin_inset Wrap table', '\\begin_inset Wrap figure')
1094 def revert_vietnamese(document):
1095 "Set language Vietnamese to English"
1096 # Set document language from Vietnamese to English
1098 if document.language == "vietnamese":
1099 document.language = "english"
1100 i = find_token(document.header, "\\language", 0)
1102 document.header[i] = "\\language english"
1105 j = find_token(document.body, "\\lang vietnamese", j)
1108 document.body[j] = document.body[j].replace("\\lang vietnamese", "\\lang english")
1112 def convert_japanese_cjk(document):
1113 "Set language japanese to japanese-cjk"
1114 # Set document language from japanese-plain to japanese
1116 if document.language == "japanese":
1117 document.language = "japanese-cjk"
1118 i = find_token(document.header, "\\language", 0)
1120 document.header[i] = "\\language japanese-cjk"
1123 j = find_token(document.body, "\\lang japanese", j)
1126 document.body[j] = document.body[j].replace("\\lang japanese", "\\lang japanese-cjk")
1130 def revert_japanese(document):
1131 "Set language japanese-plain to japanese"
1132 # Set document language from japanese-plain to japanese
1134 if document.language == "japanese-plain":
1135 document.language = "japanese"
1136 i = find_token(document.header, "\\language", 0)
1138 document.header[i] = "\\language japanese"
1141 j = find_token(document.body, "\\lang japanese-plain", j)
1144 document.body[j] = document.body[j].replace("\\lang japanese-plain", "\\lang japanese")
1148 def revert_japanese_cjk(document):
1149 "Set language japanese-cjk to japanese"
1150 # Set document language from japanese-plain to japanese
1152 if document.language == "japanese-cjk":
1153 document.language = "japanese"
1154 i = find_token(document.header, "\\language", 0)
1156 document.header[i] = "\\language japanese"
1159 j = find_token(document.body, "\\lang japanese-cjk", j)
1162 document.body[j] = document.body[j].replace("\\lang japanese-cjk", "\\lang japanese")
1166 def revert_japanese_encoding(document):
1167 "Set input encoding form EUC-JP-plain to EUC-JP etc."
1168 # Set input encoding form EUC-JP-plain to EUC-JP etc.
1170 i = find_token(document.header, "\\inputencoding EUC-JP-plain", 0)
1172 document.header[i] = "\\inputencoding EUC-JP"
1174 j = find_token(document.header, "\\inputencoding JIS-plain", 0)
1176 document.header[j] = "\\inputencoding JIS"
1178 k = find_token(document.header, "\\inputencoding SJIS-plain", 0)
1179 if k != -1: # convert to UTF8 since there is currently no SJIS encoding
1180 document.header[k] = "\\inputencoding UTF8"
1183 def revert_inset_info(document):
1184 'Replace info inset with its content'
1187 i = find_token(document.body, '\\begin_inset Info', i)
1190 j = find_end_of_inset(document.body, i + 1)
1193 document.warning("Malformed LyX document: Could not find end of Info inset.")
1196 for k in range(i, j+1):
1197 if document.body[k].startswith("arg"):
1198 arg = document.body[k][3:].strip().strip('"')
1199 if document.body[k].startswith("type"):
1200 type = document.body[k][4:].strip().strip('"')
1201 # I think there is a newline after \\end_inset, which should be removed.
1202 if document.body[j + 1].strip() == "":
1203 document.body[i : (j + 2)] = [type + ':' + arg]
1205 document.body[i : (j + 1)] = [type + ':' + arg]
1208 def convert_pdf_options(document):
1209 # Set the pdfusetitle tag, delete the pdf_store_options,
1210 # set quotes for bookmarksopenlevel"
1211 has_hr = get_value(document.header, "\\use_hyperref", 0, default = "0")
1213 k = find_token(document.header, "\\use_hyperref", 0)
1214 document.header.insert(k + 1, "\\pdf_pdfusetitle true")
1215 k = find_token(document.header, "\\pdf_store_options", 0)
1217 del document.header[k]
1218 i = find_token(document.header, "\\pdf_bookmarksopenlevel", k)
1220 document.header[i] = document.header[i].replace('"', '')
1223 def revert_pdf_options_2(document):
1224 # reset the pdfusetitle tag, set quotes for bookmarksopenlevel"
1225 k = find_token(document.header, "\\use_hyperref", 0)
1226 i = find_token(document.header, "\\pdf_pdfusetitle", k)
1228 del document.header[i]
1229 i = find_token(document.header, "\\pdf_bookmarksopenlevel", k)
1231 values = document.header[i].split()
1232 values[1] = ' "' + values[1] + '"'
1233 document.header[i] = ''.join(values)
1236 def convert_htmlurl(document):
1237 'Convert "htmlurl" to "href" insets for docbook'
1238 if document.backend != "docbook":
1242 i = find_token(document.body, "\\begin_inset CommandInset url", i)
1245 document.body[i] = "\\begin_inset CommandInset href"
1246 document.body[i + 1] = "LatexCommand href"
1250 def convert_url(document):
1251 'Convert url insets to url charstyles'
1252 if document.backend == "docbook":
1256 i = find_token(document.body, "\\begin_inset CommandInset url", i)
1259 n = find_token(document.body, "name", i)
1261 # place the URL name in typewriter before the new URL insert
1262 # grab the name 'bla' from the e.g. the line 'name "bla"',
1263 # therefore start with the 6th character
1264 name = document.body[n][6:-1]
1265 newname = [name + " "]
1266 document.body[i:i] = newname
1268 j = find_token(document.body, "target", i)
1270 document.warning("Malformed LyX document: Can't find target for url inset")
1273 target = document.body[j][8:-1]
1274 k = find_token(document.body, "\\end_inset", j)
1276 document.warning("Malformed LyX document: Can't find end of url inset")
1279 newstuff = ["\\begin_inset Flex URL",
1280 "status collapsed", "",
1281 "\\begin_layout Standard",
1286 document.body[i:k] = newstuff
1289 def convert_ams_classes(document):
1290 tc = document.textclass
1291 if (tc != "amsart" and tc != "amsart-plain" and
1292 tc != "amsart-seq" and tc != "amsbook"):
1294 if tc == "amsart-plain":
1295 document.textclass = "amsart"
1296 document.set_textclass()
1297 document.add_module("Theorems (Starred)")
1299 if tc == "amsart-seq":
1300 document.textclass = "amsart"
1301 document.set_textclass()
1302 document.add_module("Theorems (AMS)")
1304 #Now we want to see if any of the environments in the extended theorems
1305 #module were used in this document. If so, we'll add that module, too.
1306 layouts = ["Criterion", "Algorithm", "Axiom", "Condition", "Note", \
1307 "Notation", "Summary", "Acknowledgement", "Conclusion", "Fact", \
1310 r = re.compile(r'^\\begin_layout (.*?)\*?\s*$')
1313 i = find_token(document.body, "\\begin_layout", i)
1316 m = r.match(document.body[i])
1318 # This is an empty layout
1319 # document.warning("Weirdly formed \\begin_layout at line %d of body!" % i)
1323 if layouts.count(m) != 0:
1324 document.add_module("Theorems (AMS-Extended)")
1328 def revert_href(document):
1329 'Reverts hyperlink insets (href) to url insets (url)'
1332 i = find_token(document.body, "\\begin_inset CommandInset href", i)
1335 document.body[i : i + 2] = \
1336 ["\\begin_inset CommandInset url", "LatexCommand url"]
1339 def revert_url(document):
1340 'Reverts Flex URL insets to old-style URL insets'
1343 i = find_token(document.body, "\\begin_inset Flex URL", i)
1346 j = find_end_of_inset(document.body, i)
1348 document.warning("Can't find end of inset in revert_url!")
1350 k = find_default_layout(document, i, j)
1352 document.warning("Can't find default layout in revert_url!")
1355 l = find_end_of(document.body, k, "\\begin_layout", "\\end_layout")
1356 if l == -1 or l >= j:
1357 document.warning("Can't find end of default layout in revert_url!")
1360 # OK, so the inset's data is between lines k and l.
1361 data = " ".join(document.body[k+1:l])
1363 newinset = ["\\begin_inset LatexCommand url", "target \"" + data + "\"",\
1365 document.body[i:j+1] = newinset
1366 i = i + len(newinset)
1369 def convert_include(document):
1370 'Converts include insets to new format.'
1372 r = re.compile(r'\\begin_inset Include\s+\\([^{]+){([^}]*)}(?:\[(.*)\])?')
1374 i = find_token(document.body, "\\begin_inset Include", i)
1377 line = document.body[i]
1378 previewline = document.body[i + 1]
1381 document.warning("Unable to match line " + str(i) + " of body!")
1387 insertion = ["\\begin_inset CommandInset include",
1388 "LatexCommand " + cmd, previewline,
1389 "filename \"" + fn + "\""]
1392 insertion.append("lstparams " + '"' + opt + '"')
1394 document.body[i : i + 2] = insertion
1398 def revert_include(document):
1399 'Reverts include insets to old format.'
1401 r0 = re.compile('preview.*')
1402 r1 = re.compile('LatexCommand (.+)')
1403 r2 = re.compile('filename "(.+)"')
1404 r3 = re.compile('lstparams "(.*)"')
1406 i = find_token(document.body, "\\begin_inset CommandInset include", i)
1410 if r0.match(document.body[nextline]):
1411 previewline = document.body[nextline]
1415 m = r1.match(document.body[nextline])
1417 document.warning("Malformed LyX document: No LatexCommand line for `" +
1418 document.body[i] + "' on line " + str(i) + ".")
1423 m = r2.match(document.body[nextline])
1425 document.warning("Malformed LyX document: No filename line for `" + \
1426 document.body[i] + "' on line " + str(i) + ".")
1432 if (cmd == "lstinputlisting"):
1433 m = r3.match(document.body[nextline])
1435 options = m.group(1)
1438 newline = "\\begin_inset Include \\" + cmd + "{" + fn + "}"
1440 newline += ("[" + options + "]")
1441 insertion = [newline]
1442 if previewline != "":
1443 insertion.append(previewline)
1444 document.body[i : nextline] = insertion
1448 def revert_albanian(document):
1449 "Set language Albanian to English"
1451 if document.language == "albanian":
1452 document.language = "english"
1453 i = find_token(document.header, "\\language", 0)
1455 document.header[i] = "\\language english"
1458 j = find_token(document.body, "\\lang albanian", j)
1461 document.body[j] = document.body[j].replace("\\lang albanian", "\\lang english")
1465 def revert_lowersorbian(document):
1466 "Set language lower Sorbian to English"
1468 if document.language == "lowersorbian":
1469 document.language = "english"
1470 i = find_token(document.header, "\\language", 0)
1472 document.header[i] = "\\language english"
1475 j = find_token(document.body, "\\lang lowersorbian", j)
1478 document.body[j] = document.body[j].replace("\\lang lowersorbian", "\\lang english")
1482 def revert_uppersorbian(document):
1483 "Set language uppersorbian to usorbian as this was used in LyX 1.5"
1485 if document.language == "uppersorbian":
1486 document.language = "usorbian"
1487 i = find_token(document.header, "\\language", 0)
1489 document.header[i] = "\\language usorbian"
1492 j = find_token(document.body, "\\lang uppersorbian", j)
1495 document.body[j] = document.body[j].replace("\\lang uppersorbian", "\\lang usorbian")
1499 def convert_usorbian(document):
1500 "Set language usorbian to uppersorbian"
1502 if document.language == "usorbian":
1503 document.language = "uppersorbian"
1504 i = find_token(document.header, "\\language", 0)
1506 document.header[i] = "\\language uppersorbian"
1509 j = find_token(document.body, "\\lang usorbian", j)
1512 document.body[j] = document.body[j].replace("\\lang usorbian", "\\lang uppersorbian")
1516 def revert_macro_optional_params(document):
1517 "Convert macro definitions with optional parameters into ERTs"
1518 # Stub to convert macro definitions with one or more optional parameters
1519 # into uninterpreted ERT insets
1522 def revert_hyperlinktype(document):
1523 'Reverts hyperlink type'
1527 i = find_token(document.body, "target", i)
1530 j = find_token(document.body, "type", i)
1534 del document.body[j]
1538 def revert_pagebreak(document):
1539 'Reverts pagebreak to ERT'
1542 i = find_token(document.body, "\\pagebreak", i)
1545 document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1546 '\\begin_layout Standard\n\n\n\\backslash\n' \
1547 'pagebreak{}\n\\end_layout\n\n\\end_inset\n\n'
1551 def revert_linebreak(document):
1552 'Reverts linebreak to ERT'
1555 i = find_token(document.body, "\\linebreak", i)
1558 document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1559 '\\begin_layout Standard\n\n\n\\backslash\n' \
1560 'linebreak{}\n\\end_layout\n\n\\end_inset\n\n'
1564 def revert_latin(document):
1565 "Set language Latin to English"
1567 if document.language == "latin":
1568 document.language = "english"
1569 i = find_token(document.header, "\\language", 0)
1571 document.header[i] = "\\language english"
1574 j = find_token(document.body, "\\lang latin", j)
1577 document.body[j] = document.body[j].replace("\\lang latin", "\\lang english")
1581 def revert_samin(document):
1582 "Set language North Sami to English"
1584 if document.language == "samin":
1585 document.language = "english"
1586 i = find_token(document.header, "\\language", 0)
1588 document.header[i] = "\\language english"
1591 j = find_token(document.body, "\\lang samin", j)
1594 document.body[j] = document.body[j].replace("\\lang samin", "\\lang english")
1598 def convert_serbocroatian(document):
1599 "Set language Serbocroatian to Croatian as this was really Croatian in LyX 1.5"
1601 if document.language == "serbocroatian":
1602 document.language = "croatian"
1603 i = find_token(document.header, "\\language", 0)
1605 document.header[i] = "\\language croatian"
1608 j = find_token(document.body, "\\lang serbocroatian", j)
1611 document.body[j] = document.body[j].replace("\\lang serbocroatian", "\\lang croatian")
1615 def convert_framed_notes(document):
1616 "Convert framed notes to boxes. "
1619 i = find_tokens(document.body, ["\\begin_inset Note Framed", "\\begin_inset Note Shaded"], i)
1622 subst = [document.body[i].replace("\\begin_inset Note", "\\begin_inset Box"),
1631 'height_special "totalheight"']
1632 document.body[i:i+1] = subst
1636 def convert_module_names(document):
1637 modulemap = { 'Braille' : 'braille', 'Endnote' : 'endnotes', 'Foot to End' : 'foottoend',\
1638 'Hanging' : 'hanging', 'Linguistics' : 'linguistics', 'Logical Markup' : 'logicalmkup', \
1639 'Theorems (AMS-Extended)' : 'theorems-ams-extended', 'Theorems (AMS)' : 'theorems-ams', \
1640 'Theorems (Order By Chapter)' : 'theorems-chap', 'Theorems (Order By Section)' : 'theorems-sec', \
1641 'Theorems (Starred)' : 'theorems-starred', 'Theorems' : 'theorems-std' }
1642 modlist = document.get_module_list()
1643 if len(modlist) == 0:
1647 if modulemap.has_key(mod):
1648 newmodlist.append(modulemap[mod])
1650 document.warning("Can't find module %s in the module map!" % mod)
1651 newmodlist.append(mod)
1652 document.set_module_list(newmodlist)
1655 def revert_module_names(document):
1656 modulemap = { 'braille' : 'Braille', 'endnotes' : 'Endnote', 'foottoend' : 'Foot to End',\
1657 'hanging' : 'Hanging', 'linguistics' : 'Linguistics', 'logicalmkup' : 'Logical Markup', \
1658 'theorems-ams-extended' : 'Theorems (AMS-Extended)', 'theorems-ams' : 'Theorems (AMS)', \
1659 'theorems-chap' : 'Theorems (Order By Chapter)', 'theorems-sec' : 'Theorems (Order By Section)', \
1660 'theorems-starred' : 'Theorems (Starred)', 'theorems-std' : 'Theorems'}
1661 modlist = document.get_module_list()
1662 if len(modlist) == 0:
1666 if modulemap.has_key(mod):
1667 newmodlist.append(modulemap[mod])
1669 document.warning("Can't find module %s in the module map!" % mod)
1670 newmodlist.append(mod)
1671 document.set_module_list(newmodlist)
1674 def revert_colsep(document):
1675 i = find_token(document.header, "\\columnsep", 0)
1678 colsepline = document.header[i]
1679 r = re.compile(r'\\columnsep (.*)')
1680 m = r.match(colsepline)
1682 document.warning("Malformed column separation line!")
1685 del document.header[i]
1686 #it seems to be safe to add the package even if it is already used
1687 pretext = ["\\usepackage{geometry}", "\\geometry{columnsep=" + colsep + "}"]
1689 add_to_preamble(document, pretext)
1692 def revert_framed_notes(document):
1693 "Revert framed boxes to notes. "
1696 i = find_tokens(document.body, ["\\begin_inset Box Framed", "\\begin_inset Box Shaded"], i)
1700 j = find_end_of_inset(document.body, i + 1)
1703 document.warning("Malformed LyX document: Could not find end of Box inset.")
1704 k = find_token(document.body, "status", i + 1, j)
1706 document.warning("Malformed LyX document: Missing `status' tag in Box inset.")
1708 status = document.body[k]
1709 l = find_default_layout(document, i + 1, j)
1711 document.warning("Malformed LyX document: Missing `\\begin_layout' in Box inset.")
1713 m = find_token(document.body, "\\end_layout", i + 1, j)
1715 document.warning("Malformed LyX document: Missing `\\end_layout' in Box inset.")
1717 ibox = find_token(document.body, "has_inner_box 1", i + 1, k)
1718 pbox = find_token(document.body, "use_parbox 1", i + 1, k)
1719 if ibox == -1 and pbox == -1:
1720 document.body[i] = document.body[i].replace("\\begin_inset Box", "\\begin_inset Note")
1721 del document.body[i+1:k]
1723 document.body[i] = document.body[i].replace("\\begin_inset Box Shaded", "\\begin_inset Box Frameless")
1724 subst1 = [document.body[l],
1725 "\\begin_inset Note Shaded",
1727 '\\begin_layout Standard']
1728 document.body[l:l + 1] = subst1
1729 subst2 = [document.body[m], "\\end_layout", "\\end_inset"]
1730 document.body[m:m + 1] = subst2
1734 def revert_slash(document):
1735 'Revert \\SpecialChar \\slash{} to ERT'
1736 r = re.compile(r'\\SpecialChar \\slash{}')
1738 while i < len(document.body):
1739 m = r.match(document.body[i])
1741 subst = ['\\begin_inset ERT',
1742 'status collapsed', '',
1743 '\\begin_layout Standard',
1744 '', '', '\\backslash',
1748 document.body[i: i+1] = subst
1754 def revert_nobreakdash(document):
1755 'Revert \\SpecialChar \\nobreakdash- to ERT'
1757 while i < len(document.body):
1758 line = document.body[i]
1759 r = re.compile(r'\\SpecialChar \\nobreakdash-')
1762 subst = ['\\begin_inset ERT',
1763 'status collapsed', '',
1764 '\\begin_layout Standard', '', '',
1769 document.body[i:i+1] = subst
1771 j = find_token(document.header, "\\use_amsmath", 0)
1773 document.warning("Malformed LyX document: Missing '\\use_amsmath'.")
1775 document.header[j] = "\\use_amsmath 2"
1780 #Returns number of lines added/removed
1781 def revert_nocite_key(body, start, end):
1782 'key "..." -> \nocite{...}'
1783 r = re.compile(r'^key "(.*)"')
1787 m = r.match(body[i])
1789 body[i:i+1] = ["\\backslash", "nocite{" + m.group(1) + "}"]
1790 j += 1 # because we added a line
1791 i += 2 # skip that line
1794 j -= 1 # because we deleted a line
1795 # no need to change i, since it now points to the next line
1799 def revert_nocite(document):
1800 "Revert LatexCommand nocite to ERT"
1803 i = find_token(document.body, "\\begin_inset CommandInset citation", i)
1806 if (document.body[i+1] != "LatexCommand nocite"):
1807 # note that we already incremented i
1810 insetEnd = find_end_of_inset(document.body, i)
1812 #this should not happen
1813 document.warning("End of CommandInset citation not found in revert_nocite!")
1816 paramLocation = i + 2 #start of the inset's parameters
1818 document.body[i:i+2] = \
1819 ["\\begin_inset ERT", "status collapsed", "", "\\begin_layout Standard"]
1820 # that added two lines
1823 #print insetEnd, document.body[i: insetEnd + 1]
1824 insetEnd += revert_nocite_key(document.body, paramLocation, insetEnd)
1825 #print insetEnd, document.body[i: insetEnd + 1]
1826 document.body.insert(insetEnd, "\\end_layout")
1827 document.body.insert(insetEnd + 1, "")
1831 def revert_btprintall(document):
1832 "Revert (non-bibtopic) btPrintAll option to ERT \nocite{*}"
1833 i = find_token(document.header, '\\use_bibtopic', 0)
1835 document.warning("Malformed lyx document: Missing '\\use_bibtopic'.")
1837 if get_value(document.header, '\\use_bibtopic', 0) == "false":
1839 while i < len(document.body):
1840 i = find_token(document.body, "\\begin_inset CommandInset bibtex", i)
1843 j = find_end_of_inset(document.body, i + 1)
1845 #this should not happen
1846 document.warning("End of CommandInset bibtex not found in revert_btprintall!")
1847 j = len(document.body)
1848 # this range isn't really right, but it should be OK, since we shouldn't
1849 # see more than one matching line in each inset
1851 for k in range(i, j):
1852 if (document.body[k] == 'btprint "btPrintAll"'):
1853 del document.body[k]
1854 subst = ["\\begin_inset ERT",
1855 "status collapsed", "",
1856 "\\begin_layout Standard", "",
1861 document.body[i:i] = subst
1862 addlines = addedlines + len(subst) - 1
1866 def revert_bahasam(document):
1867 "Set language Bahasa Malaysia to Bahasa Indonesia"
1869 if document.language == "bahasam":
1870 document.language = "bahasa"
1871 i = find_token(document.header, "\\language", 0)
1873 document.header[i] = "\\language bahasa"
1876 j = find_token(document.body, "\\lang bahasam", j)
1879 document.body[j] = document.body[j].replace("\\lang bahasam", "\\lang bahasa")
1883 def revert_interlingua(document):
1884 "Set language Interlingua to English"
1886 if document.language == "interlingua":
1887 document.language = "english"
1888 i = find_token(document.header, "\\language", 0)
1890 document.header[i] = "\\language english"
1893 j = find_token(document.body, "\\lang interlingua", j)
1896 document.body[j] = document.body[j].replace("\\lang interlingua", "\\lang english")
1900 def revert_serbianlatin(document):
1901 "Set language Serbian-Latin to Croatian"
1903 if document.language == "serbian-latin":
1904 document.language = "croatian"
1905 i = find_token(document.header, "\\language", 0)
1907 document.header[i] = "\\language croatian"
1910 j = find_token(document.body, "\\lang serbian-latin", j)
1913 document.body[j] = document.body[j].replace("\\lang serbian-latin", "\\lang croatian")
1917 def revert_rotfloat(document):
1918 " Revert sideways custom floats. "
1921 # whitespace intended (exclude \\begin_inset FloatList)
1922 i = find_token(document.body, "\\begin_inset Float ", i)
1925 line = document.body[i]
1926 r = re.compile(r'\\begin_inset Float (.*)$')
1929 document.warning("Unable to match line " + str(i) + " of body!")
1932 floattype = m.group(1)
1933 if floattype == "figure" or floattype == "table":
1936 j = find_end_of_inset(document.body, i)
1938 document.warning("Malformed lyx document: Missing '\\end_inset' in revert_rotfloat.")
1942 if get_value(document.body, 'sideways', i, j) == "false":
1945 l = find_default_layout(document, i + 1, j)
1947 document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
1949 subst = ['\\begin_layout Standard',
1950 '\\begin_inset ERT',
1951 'status collapsed', '',
1952 '\\begin_layout Standard', '', '',
1954 'end{sideways' + floattype + '}',
1955 '\\end_layout', '', '\\end_inset']
1956 document.body[j : j+1] = subst
1957 addedLines = len(subst) - 1
1958 del document.body[i+1 : l]
1959 addedLines -= (l-1) - (i+1)
1960 subst = ['\\begin_inset ERT', 'status collapsed', '',
1961 '\\begin_layout Standard', '', '', '\\backslash',
1962 'begin{sideways' + floattype + '}',
1963 '\\end_layout', '', '\\end_inset', '',
1965 document.body[i : i+1] = subst
1966 addedLines += len(subst) - 1
1967 if floattype == "algorithm":
1968 add_to_preamble(document,
1969 ['% Commands inserted by lyx2lyx for sideways algorithm float',
1970 '\\usepackage{rotfloat}',
1971 '\\floatstyle{ruled}',
1972 '\\newfloat{algorithm}{tbp}{loa}',
1973 '\\floatname{algorithm}{Algorithm}'])
1975 document.warning("Cannot create preamble definition for custom float" + floattype + ".")
1979 def revert_widesideways(document):
1980 " Revert wide sideways floats. "
1983 # whitespace intended (exclude \\begin_inset FloatList)
1984 i = find_token(document.body, '\\begin_inset Float ', i)
1987 line = document.body[i]
1988 r = re.compile(r'\\begin_inset Float (.*)$')
1991 document.warning("Unable to match line " + str(i) + " of body!")
1994 floattype = m.group(1)
1995 if floattype != "figure" and floattype != "table":
1998 j = find_end_of_inset(document.body, i)
2000 document.warning("Malformed lyx document: Missing '\\end_inset' in revert_widesideways.")
2003 if get_value(document.body, 'sideways', i, j) == "false" or \
2004 get_value(document.body, 'wide', i, j) == "false":
2007 l = find_default_layout(document, i + 1, j)
2009 document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
2011 subst = ['\\begin_layout Standard', '\\begin_inset ERT',
2012 'status collapsed', '',
2013 '\\begin_layout Standard', '', '', '\\backslash',
2014 'end{sideways' + floattype + '*}',
2015 '\\end_layout', '', '\\end_inset']
2016 document.body[j : j+1] = subst
2017 addedLines = len(subst) - 1
2018 del document.body[i+1:l-1]
2019 addedLines -= (l-1) - (i+1)
2020 subst = ['\\begin_inset ERT', 'status collapsed', '',
2021 '\\begin_layout Standard', '', '', '\\backslash',
2022 'begin{sideways' + floattype + '*}', '\\end_layout', '',
2023 '\\end_inset', '', '\\end_layout', '']
2024 document.body[i : i+1] = subst
2025 addedLines += len(subst) - 1
2026 add_to_preamble(document, ['\\usepackage{rotfloat}\n'])
2030 def revert_inset_embedding(document, type):
2031 ' Remove embed tag from certain type of insets'
2034 i = find_token(document.body, "\\begin_inset %s" % type, i)
2037 j = find_end_of_inset(document.body, i)
2039 document.warning("Malformed lyx document: Missing '\\end_inset' in revert_inset_embedding.")
2042 k = find_token(document.body, "\tembed", i, j)
2044 k = find_token(document.body, "embed", i, j)
2046 del document.body[k]
2050 def revert_external_embedding(document):
2051 ' Remove embed tag from external inset '
2052 revert_inset_embedding(document, 'External')
2055 def convert_subfig(document):
2056 " Convert subfigures to subfloats. "
2059 i = find_token(document.body, '\\begin_inset Graphics', i)
2062 endInset = find_end_of_inset(document.body, i)
2064 document.warning("Malformed lyx document: Missing '\\end_inset' in convert_subfig.")
2067 k = find_token(document.body, '\tsubcaption', i, endInset)
2071 l = find_token(document.body, '\tsubcaptionText', i, endInset)
2073 document.warning("Malformed lyx document: Can't find subcaptionText!")
2076 caption = document.body[l][16:].strip('"')
2077 del document.body[l]
2078 del document.body[k]
2080 subst = ['\\begin_inset Float figure', 'wide false', 'sideways false',
2081 'status open', '', '\\begin_layout Plain Layout', '\\begin_inset Caption',
2082 '', '\\begin_layout Plain Layout'] + latex2lyx(caption) + \
2083 [ '\\end_layout', '', '\\end_inset', '',
2084 '\\end_layout', '', '\\begin_layout Plain Layout']
2085 document.body[i : i] = subst
2086 addedLines += len(subst)
2087 endInset += addedLines
2088 subst = ['', '\\end_inset', '', '\\end_layout']
2089 document.body[endInset : endInset] = subst
2090 addedLines += len(subst)
2094 def revert_subfig(document):
2095 " Revert subfloats. "
2098 # whitespace intended (exclude \\begin_inset FloatList)
2099 i = find_tokens(document.body, ['\\begin_inset Float ', '\\begin_inset Wrap'], i)
2105 j = find_end_of_inset(document.body, i)
2107 document.warning("Malformed lyx document: Missing '\\end_inset' (float) at line " + str(i + len(document.header)) + ".\n\t" + document.body[i])
2108 # document.warning(document.body[i-1] + "\n" + document.body[i+1])
2110 continue # this will get us back to the outer loop, since j == -1
2111 # look for embedded float (= subfloat)
2112 # whitespace intended (exclude \\begin_inset FloatList)
2113 k = find_token(document.body, '\\begin_inset Float ', i + 1, j)
2116 l = find_end_of_inset(document.body, k)
2118 document.warning("Malformed lyx document: Missing '\\end_inset' (embedded float).")
2121 continue # escape to the outer loop
2122 m = find_default_layout(document, k + 1, l)
2124 cap = find_token(document.body, '\\begin_inset Caption', k + 1, l)
2129 capend = find_end_of_inset(document.body, cap)
2131 document.warning("Malformed lyx document: Missing '\\end_inset' (caption).")
2135 lbl = find_token(document.body, '\\begin_inset CommandInset label', cap, capend)
2137 lblend = find_end_of_inset(document.body, lbl + 1)
2139 document.warning("Malformed lyx document: Missing '\\end_inset' (label).")
2141 for line in document.body[lbl:lblend + 1]:
2142 if line.startswith('name '):
2143 label = line.split()[1].strip('"')
2150 opt = find_token(document.body, '\\begin_inset OptArg', cap, capend)
2152 optend = find_end_of_inset(document.body, opt)
2154 document.warning("Malformed lyx document: Missing '\\end_inset' (OptArg).")
2156 optc = find_default_layout(document, opt, optend)
2158 document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
2160 optcend = find_end_of(document.body, optc, "\\begin_layout", "\\end_layout")
2161 for line in document.body[optc:optcend]:
2162 if not line.startswith('\\'):
2163 shortcap += line.strip()
2167 for line in document.body[cap:capend]:
2168 if line in document.body[lbl:lblend]:
2170 elif line in document.body[opt:optend]:
2172 elif not line.startswith('\\'):
2173 caption += line.strip()
2175 caption += "\\backslash\nlabel{" + label + "}"
2176 subst = '\\begin_layout Plain Layout\n\\begin_inset ERT\nstatus collapsed\n\n' \
2177 '\\begin_layout Plain Layout\n\n}\n\\end_layout\n\n\\end_inset\n\n' \
2178 '\\end_layout\n\n\\begin_layout Plain Layout\n'
2179 subst = subst.split('\n')
2180 document.body[l : l+1] = subst
2181 addedLines = len(subst) - 1
2182 # this is before l and so is unchanged by the multiline insertion
2184 del document.body[cap:capend+1]
2185 addedLines -= (capend + 1 - cap)
2186 del document.body[k+1:m-1]
2187 addedLines -= (m - 1 - (k + 1))
2188 insertion = '\\begin_inset ERT\nstatus collapsed\n\n' \
2189 '\\begin_layout Plain Layout\n\n\\backslash\n' \
2191 if len(shortcap) > 0:
2192 insertion = insertion + "[" + shortcap + "]"
2193 if len(caption) > 0:
2194 insertion = insertion + "[" + caption + "]"
2195 insertion = insertion + '{%\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n'
2196 insertion = insertion.split('\n')
2197 document.body[k : k + 1] = insertion
2198 addedLines += len(insertion) - 1
2199 add_to_preamble(document, ['\\usepackage{subfig}\n'])
2203 def revert_wrapplacement(document):
2204 " Revert placement options wrap floats (wrapfig). "
2207 i = find_token(document.body, "\\begin_inset Wrap figure", i)
2210 e = find_end_of_inset(document.body, i)
2211 j = find_token(document.body, "placement", i + 1, e)
2213 document.warning("Malformed LyX document: Couldn't find placement parameter of wrap float.")
2216 r = re.compile("placement (o|i|l|r)")
2217 m = r.match(document.body[j])
2219 document.warning("Malformed LyX document: Placement option isn't O|I|R|L!")
2220 document.body[j] = "placement " + m.group(1).lower()
2224 def remove_extra_embedded_files(document):
2225 " Remove \extra_embedded_files from buffer params "
2226 i = find_token(document.header, '\\extra_embedded_files', 0)
2229 document.header.pop(i)
2232 def convert_spaceinset(document):
2233 " Convert '\\InsetSpace foo' to '\\begin_inset Space foo\n\\end_inset' "
2235 while i < len(document.body):
2236 m = re.match(r'(.*)\\InsetSpace (.*)', document.body[i])
2240 subst = [before, "\\begin_inset Space " + after, "\\end_inset"]
2241 document.body[i: i+1] = subst
2247 def revert_spaceinset(document):
2248 " Revert '\\begin_inset Space foo\n\\end_inset' to '\\InsetSpace foo' "
2251 i = find_token(document.body, "\\begin_inset Space", i)
2254 j = find_end_of_inset(document.body, i)
2256 document.warning("Malformed LyX document: Could not find end of space inset.")
2258 document.body[i] = document.body[i].replace('\\begin_inset Space', '\\InsetSpace')
2259 del document.body[j]
2262 def convert_hfill(document):
2263 " Convert hfill to space inset "
2266 i = find_token(document.body, "\\hfill", i)
2269 subst = document.body[i].replace('\\hfill', \
2270 '\n\\begin_inset Space \\hfill{}\n\\end_inset')
2271 subst = subst.split('\n')
2272 document.body[i : i+1] = subst
2276 def revert_hfills(document):
2277 ' Revert \\hfill commands '
2278 hfill = re.compile(r'\\hfill')
2279 dotfill = re.compile(r'\\dotfill')
2280 hrulefill = re.compile(r'\\hrulefill')
2283 i = find_token(document.body, "\\InsetSpace", i)
2286 if hfill.search(document.body[i]):
2287 document.body[i] = \
2288 document.body[i].replace('\\InsetSpace \\hfill{}', '\\hfill')
2291 if dotfill.search(document.body[i]):
2292 subst = document.body[i].replace('\\InsetSpace \\dotfill{}', \
2293 '\\begin_inset ERT\nstatus collapsed\n\n' \
2294 '\\begin_layout Standard\n\n\n\\backslash\n' \
2295 'dotfill{}\n\\end_layout\n\n\\end_inset\n\n')
2296 subst = subst.split('\n')
2297 document.body[i : i+1] = subst
2300 if hrulefill.search(document.body[i]):
2301 subst = document.body[i].replace('\\InsetSpace \\hrulefill{}', \
2302 '\\begin_inset ERT\nstatus collapsed\n\n' \
2303 '\\begin_layout Standard\n\n\n\\backslash\n' \
2304 'hrulefill{}\n\\end_layout\n\n\\end_inset\n\n')
2305 subst = subst.split('\n')
2306 document.body[i : i+1] = subst
2311 def revert_hspace(document):
2312 ' Revert \\InsetSpace \\hspace{} to ERT '
2314 hspace = re.compile(r'\\hspace{}')
2315 hstar = re.compile(r'\\hspace\*{}')
2317 i = find_token(document.body, "\\InsetSpace \\hspace", i)
2320 length = get_value(document.body, '\\length', i+1)
2322 document.warning("Malformed lyx document: Missing '\\length' in Space inset.")
2324 del document.body[i+1]
2326 if hstar.search(document.body[i]):
2327 subst = document.body[i].replace('\\InsetSpace \\hspace*{}', \
2328 '\\begin_inset ERT\nstatus collapsed\n\n' \
2329 '\\begin_layout Standard\n\n\n\\backslash\n' \
2330 'hspace*{' + length + '}\n\\end_layout\n\n\\end_inset\n\n')
2331 subst = subst.split('\n')
2332 document.body[i : i+1] = subst
2333 addedLines += len(subst) - 1
2336 if hspace.search(document.body[i]):
2337 subst = document.body[i].replace('\\InsetSpace \\hspace{}', \
2338 '\\begin_inset ERT\nstatus collapsed\n\n' \
2339 '\\begin_layout Standard\n\n\n\\backslash\n' \
2340 'hspace{' + length + '}\n\\end_layout\n\n\\end_inset\n\n')
2341 subst = subst.split('\n')
2342 document.body[i : i+1] = subst
2343 addedLines += len(subst) - 1
2349 def revert_protected_hfill(document):
2350 ' Revert \\begin_inset Space \\hspace*{\\fill} to ERT '
2353 i = find_token(document.body, '\\begin_inset Space \\hspace*{\\fill}', i)
2356 j = find_end_of_inset(document.body, i)
2358 document.warning("Malformed LyX document: Could not find end of space inset.")
2360 del document.body[j]
2361 subst = document.body[i].replace('\\begin_inset Space \\hspace*{\\fill}', \
2362 '\\begin_inset ERT\nstatus collapsed\n\n' \
2363 '\\begin_layout Standard\n\n\n\\backslash\n' \
2364 'hspace*{\n\\backslash\nfill}\n\\end_layout\n\n\\end_inset\n\n')
2365 subst = subst.split('\n')
2366 document.body[i : i+1] = subst
2370 def revert_leftarrowfill(document):
2371 ' Revert \\begin_inset Space \\leftarrowfill{} to ERT '
2374 i = find_token(document.body, '\\begin_inset Space \\leftarrowfill{}', i)
2377 j = find_end_of_inset(document.body, i)
2379 document.warning("Malformed LyX document: Could not find end of space inset.")
2381 del document.body[j]
2382 subst = document.body[i].replace('\\begin_inset Space \\leftarrowfill{}', \
2383 '\\begin_inset ERT\nstatus collapsed\n\n' \
2384 '\\begin_layout Standard\n\n\n\\backslash\n' \
2385 'leftarrowfill{}\n\\end_layout\n\n\\end_inset\n\n')
2386 subst = subst.split('\n')
2387 document.body[i : i+1] = subst
2391 def revert_rightarrowfill(document):
2392 ' Revert \\begin_inset Space \\rightarrowfill{} to ERT '
2395 i = find_token(document.body, '\\begin_inset Space \\rightarrowfill{}', i)
2398 j = find_end_of_inset(document.body, i)
2400 document.warning("Malformed LyX document: Could not find end of space inset.")
2402 del document.body[j]
2403 subst = document.body[i].replace('\\begin_inset Space \\rightarrowfill{}', \
2404 '\\begin_inset ERT\nstatus collapsed\n\n' \
2405 '\\begin_layout Standard\n\n\n\\backslash\n' \
2406 'rightarrowfill{}\n\\end_layout\n\n\\end_inset\n\n')
2407 subst = subst.split('\n')
2408 document.body[i : i+1] = subst
2412 def revert_upbracefill(document):
2413 ' Revert \\begin_inset Space \\upbracefill{} to ERT '
2416 i = find_token(document.body, '\\begin_inset Space \\upbracefill{}', i)
2419 j = find_end_of_inset(document.body, i)
2421 document.warning("Malformed LyX document: Could not find end of space inset.")
2423 del document.body[j]
2424 subst = document.body[i].replace('\\begin_inset Space \\upbracefill{}', \
2425 '\\begin_inset ERT\nstatus collapsed\n\n' \
2426 '\\begin_layout Standard\n\n\n\\backslash\n' \
2427 'upbracefill{}\n\\end_layout\n\n\\end_inset\n\n')
2428 subst = subst.split('\n')
2429 document.body[i : i+1] = subst
2433 def revert_downbracefill(document):
2434 ' Revert \\begin_inset Space \\downbracefill{} to ERT '
2437 i = find_token(document.body, '\\begin_inset Space \\downbracefill{}', i)
2440 j = find_end_of_inset(document.body, i)
2442 document.warning("Malformed LyX document: Could not find end of space inset.")
2444 del document.body[j]
2445 subst = document.body[i].replace('\\begin_inset Space \\downbracefill{}', \
2446 '\\begin_inset ERT\nstatus collapsed\n\n' \
2447 '\\begin_layout Standard\n\n\n\\backslash\n' \
2448 'downbracefill{}\n\\end_layout\n\n\\end_inset\n\n')
2449 subst = subst.split('\n')
2450 document.body[i : i+1] = subst
2454 def revert_local_layout(document):
2455 ' Revert local layout headers.'
2458 i = find_token(document.header, "\\begin_local_layout", i)
2461 j = find_end_of(document.header, i, "\\begin_local_layout", "\\end_local_layout")
2463 # this should not happen
2465 document.header[i : j + 1] = []
2468 def convert_pagebreaks(document):
2469 ' Convert inline Newpage insets to new format '
2472 i = find_token(document.body, '\\newpage', i)
2475 document.body[i:i+1] = ['\\begin_inset Newpage newpage',
2479 i = find_token(document.body, '\\pagebreak', i)
2482 document.body[i:i+1] = ['\\begin_inset Newpage pagebreak',
2486 i = find_token(document.body, '\\clearpage', i)
2489 document.body[i:i+1] = ['\\begin_inset Newpage clearpage',
2493 i = find_token(document.body, '\\cleardoublepage', i)
2496 document.body[i:i+1] = ['\\begin_inset Newpage cleardoublepage',
2500 def revert_pagebreaks(document):
2501 ' Revert \\begin_inset Newpage to previous inline format '
2504 i = find_token(document.body, '\\begin_inset Newpage', i)
2507 j = find_end_of_inset(document.body, i)
2509 document.warning("Malformed LyX document: Could not find end of Newpage inset.")
2511 del document.body[j]
2512 document.body[i] = document.body[i].replace('\\begin_inset Newpage newpage', '\\newpage')
2513 document.body[i] = document.body[i].replace('\\begin_inset Newpage pagebreak', '\\pagebreak')
2514 document.body[i] = document.body[i].replace('\\begin_inset Newpage clearpage', '\\clearpage')
2515 document.body[i] = document.body[i].replace('\\begin_inset Newpage cleardoublepage', '\\cleardoublepage')
2518 def convert_linebreaks(document):
2519 ' Convert inline Newline insets to new format '
2522 i = find_token(document.body, '\\newline', i)
2525 document.body[i:i+1] = ['\\begin_inset Newline newline',
2529 i = find_token(document.body, '\\linebreak', i)
2532 document.body[i:i+1] = ['\\begin_inset Newline linebreak',
2536 def revert_linebreaks(document):
2537 ' Revert \\begin_inset Newline to previous inline format '
2540 i = find_token(document.body, '\\begin_inset Newline', i)
2543 j = find_end_of_inset(document.body, i)
2545 document.warning("Malformed LyX document: Could not find end of Newline inset.")
2547 del document.body[j]
2548 document.body[i] = document.body[i].replace('\\begin_inset Newline newline', '\\newline')
2549 document.body[i] = document.body[i].replace('\\begin_inset Newline linebreak', '\\linebreak')
2552 def convert_japanese_plain(document):
2553 ' Set language japanese-plain to japanese '
2555 if document.language == "japanese-plain":
2556 document.language = "japanese"
2557 i = find_token(document.header, "\\language", 0)
2559 document.header[i] = "\\language japanese"
2562 j = find_token(document.body, "\\lang japanese-plain", j)
2565 document.body[j] = document.body[j].replace("\\lang japanese-plain", "\\lang japanese")
2569 def revert_pdfpages(document):
2570 ' Revert pdfpages external inset to ERT '
2573 i = find_token(document.body, "\\begin_inset External", i)
2576 j = find_end_of_inset(document.body, i)
2578 document.warning("Malformed lyx document: Missing '\\end_inset' in revert_pdfpages.")
2581 if get_value(document.body, 'template', i, j) == "PDFPages":
2582 filename = get_value(document.body, 'filename', i, j)
2584 r = re.compile(r'\textra PDFLaTeX \"(.*)\"$')
2585 for k in range(i, j):
2586 m = r.match(document.body[k])
2589 angle = get_value(document.body, 'rotateAngle', i, j)
2590 width = get_value(document.body, 'width', i, j)
2591 height = get_value(document.body, 'height', i, j)
2592 scale = get_value(document.body, 'scale', i, j)
2593 keepAspectRatio = find_token(document.body, "\tkeepAspectRatio", i, j)
2597 options += ",angle=" + angle
2599 options += "angle=" + angle
2602 options += ",width=" + convert_len(width)
2604 options += "width=" + convert_len(width)
2607 options += ",height=" + convert_len(height)
2609 options += "height=" + convert_len(height)
2612 options += ",scale=" + scale
2614 options += "scale=" + scale
2615 if keepAspectRatio != '':
2617 options += ",keepaspectratio"
2619 options += "keepaspectratio"
2621 options = '[' + options + ']'
2622 del document.body[i+1:j+1]
2623 document.body[i:i+1] = ['\\begin_inset ERT',
2626 '\\begin_layout Standard',
2629 'includepdf' + options + '{' + filename + '}',
2633 add_to_preamble(document, ['\\usepackage{pdfpages}\n'])
2639 def revert_mexican(document):
2640 ' Set language Spanish(Mexico) to Spanish '
2642 if document.language == "spanish-mexico":
2643 document.language = "spanish"
2644 i = find_token(document.header, "\\language", 0)
2646 document.header[i] = "\\language spanish"
2649 j = find_token(document.body, "\\lang spanish-mexico", j)
2652 document.body[j] = document.body[j].replace("\\lang spanish-mexico", "\\lang spanish")
2656 def remove_embedding(document):
2657 ' Remove embed tag from all insets '
2658 revert_inset_embedding(document, 'Graphics')
2659 revert_inset_embedding(document, 'External')
2660 revert_inset_embedding(document, 'CommandInset include')
2661 revert_inset_embedding(document, 'CommandInset bibtex')
2664 def revert_master(document):
2665 ' Remove master param '
2666 i = find_token(document.header, "\\master", 0)
2668 del document.header[i]
2671 def revert_graphics_group(document):
2672 ' Revert group information from graphics insets '
2675 i = find_token(document.body, "\\begin_inset Graphics", i)
2678 j = find_end_of_inset(document.body, i)
2680 document.warning("Malformed lyx document: Missing '\\end_inset' in revert_graphics_group.")
2683 k = find_token(document.body, " groupId", i, j)
2687 del document.body[k]
2691 def update_apa_styles(document):
2692 ' Replace obsolete styles '
2694 if document.textclass != "apa":
2697 obsoletedby = { "Acknowledgments": "Acknowledgements",
2698 "Section*": "Section",
2699 "Subsection*": "Subsection",
2700 "Subsubsection*": "Subsubsection",
2701 "Paragraph*": "Paragraph",
2702 "Subparagraph*": "Subparagraph"}
2705 i = find_token(document.body, "\\begin_layout", i)
2709 layout = document.body[i][14:]
2710 if layout in obsoletedby:
2711 document.body[i] = "\\begin_layout " + obsoletedby[layout]
2716 def convert_paper_sizes(document):
2717 ' exchange size options legalpaper and executivepaper to correct order '
2718 # routine is needed to fix http://bugzilla.lyx.org/show_bug.cgi?id=4868
2721 i = find_token(document.header, "\\papersize executivepaper", 0)
2723 document.header[i] = "\\papersize legalpaper"
2725 j = find_token(document.header, "\\papersize legalpaper", 0)
2727 document.header[j] = "\\papersize executivepaper"
2730 def revert_paper_sizes(document):
2731 ' exchange size options legalpaper and executivepaper to correct order '
2734 i = find_token(document.header, "\\papersize executivepaper", 0)
2736 document.header[i] = "\\papersize legalpaper"
2738 j = find_token(document.header, "\\papersize legalpaper", 0)
2740 document.header[j] = "\\papersize executivepaper"
2743 def convert_InsetSpace(document):
2744 " Convert '\\begin_inset Space foo' to '\\begin_inset space foo'"
2747 i = find_token(document.body, "\\begin_inset Space", i)
2750 document.body[i] = document.body[i].replace('\\begin_inset Space', '\\begin_inset space')
2753 def revert_InsetSpace(document):
2754 " Revert '\\begin_inset space foo' to '\\begin_inset Space foo'"
2757 i = find_token(document.body, "\\begin_inset space", i)
2760 document.body[i] = document.body[i].replace('\\begin_inset space', '\\begin_inset Space')
2763 def convert_display_enum(document):
2764 " Convert 'display foo' to 'display false/true'"
2767 i = find_token(document.body, "\tdisplay", i)
2770 val = get_value(document.body, 'display', i)
2772 document.body[i] = document.body[i].replace('none', 'false')
2773 if val == "default":
2774 document.body[i] = document.body[i].replace('default', 'true')
2775 if val == "monochrome":
2776 document.body[i] = document.body[i].replace('monochrome', 'true')
2777 if val == "grayscale":
2778 document.body[i] = document.body[i].replace('grayscale', 'true')
2780 document.body[i] = document.body[i].replace('color', 'true')
2781 if val == "preview":
2782 document.body[i] = document.body[i].replace('preview', 'true')
2786 def revert_display_enum(document):
2787 " Revert 'display false/true' to 'display none/color'"
2790 i = find_token(document.body, "\tdisplay", i)
2793 val = get_value(document.body, 'display', i)
2795 document.body[i] = document.body[i].replace('false', 'none')
2797 document.body[i] = document.body[i].replace('true', 'default')
2801 def remove_fontsCJK(document):
2802 ' Remove font_cjk param '
2803 i = find_token(document.header, "\\font_cjk", 0)
2805 del document.header[i]
2808 def convert_plain_layout(document):
2809 " Convert 'PlainLayout' to 'Plain Layout'"
2812 i = find_token(document.body, '\\begin_layout PlainLayout', i)
2815 document.body[i] = document.body[i].replace('\\begin_layout PlainLayout', \
2816 '\\begin_layout Plain Layout')
2820 def revert_plain_layout(document):
2821 " Convert 'PlainLayout' to 'Plain Layout'"
2824 i = find_token(document.body, '\\begin_layout Plain Layout', i)
2827 document.body[i] = document.body[i].replace('\\begin_layout Plain Layout', \
2828 '\\begin_layout PlainLayout')
2832 def revert_plainlayout(document):
2833 " Convert 'PlainLayout' to 'Plain Layout'"
2836 i = find_token(document.body, '\\begin_layout PlainLayout', i)
2839 # This will be incorrect for some document classes, since Standard is not always
2840 # the default. But (a) it is probably the best we can do and (b) it will actually
2841 # work, in fact, since an unknown layout will be converted to default.
2842 document.body[i] = document.body[i].replace('\\begin_layout PlainLayout', \
2843 '\\begin_layout Standard')
2847 def revert_polytonicgreek(document):
2848 "Set language polytonic Greek to Greek"
2850 if document.language == "polutonikogreek":
2851 document.language = "greek"
2852 i = find_token(document.header, "\\language", 0)
2854 document.header[i] = "\\language greek"
2857 j = find_token(document.body, "\\lang polutonikogreek", j)
2860 document.body[j] = document.body[j].replace("\\lang polutonikogreek", "\\lang greek")
2864 def revert_removed_modules(document):
2867 i = find_token(document.header, "\\begin_remove_modules", i)
2870 j = find_end_of(document.header, i, "\\begin_remove_modules", "\\end_remove_modules")
2872 # this should not happen
2874 document.header[i : j + 1] = []
2877 def add_plain_layout(document):
2880 i = find_token(document.body, "\\begin_layout", i)
2883 if len(document.body[i].split()) == 1:
2884 document.body[i] = "\\begin_layout Plain Layout"
2891 supported_versions = ["1.6.0","1.6"]
2892 convert = [[277, [fix_wrong_tables]],
2893 [278, [close_begin_deeper]],
2894 [279, [long_charstyle_names]],
2895 [280, [axe_show_label]],
2898 [283, [convert_flex]],
2902 [287, [convert_wrapfig_options]],
2903 [288, [convert_inset_command]],
2904 [289, [convert_latexcommand_index]],
2907 [292, [convert_japanese_cjk]],
2909 [294, [convert_pdf_options]],
2910 [295, [convert_htmlurl, convert_url]],
2911 [296, [convert_include]],
2912 [297, [convert_usorbian]],
2918 [303, [convert_serbocroatian]],
2919 [304, [convert_framed_notes]],
2926 [311, [convert_ams_classes]],
2928 [313, [convert_module_names]],
2931 [316, [convert_subfig]],
2934 [319, [convert_spaceinset, convert_hfill]],
2936 [321, [convert_tablines]],
2937 [322, [convert_plain_layout]],
2938 [323, [convert_pagebreaks]],
2939 [324, [convert_linebreaks]],
2940 [325, [convert_japanese_plain]],
2943 [328, [remove_embedding, remove_extra_embedded_files, remove_inzip_options]],
2946 [331, [convert_ltcaption]],
2948 [333, [update_apa_styles]],
2949 [334, [convert_paper_sizes]],
2950 [335, [convert_InsetSpace]],
2952 [337, [convert_display_enum]],
2955 [340, [add_plain_layout]]
2958 revert = [[339, []],
2959 [338, [revert_removed_modules]],
2960 [337, [revert_polytonicgreek]],
2961 [336, [revert_display_enum]],
2962 [335, [remove_fontsCJK]],
2963 [334, [revert_InsetSpace]],
2964 [333, [revert_paper_sizes]],
2966 [331, [revert_graphics_group]],
2967 [330, [revert_ltcaption]],
2968 [329, [revert_leftarrowfill, revert_rightarrowfill, revert_upbracefill, revert_downbracefill]],
2969 [328, [revert_master]],
2971 [326, [revert_mexican]],
2972 [325, [revert_pdfpages]],
2974 [323, [revert_linebreaks]],
2975 [322, [revert_pagebreaks]],
2976 [321, [revert_local_layout, revert_plain_layout]],
2977 [320, [revert_tablines]],
2978 [319, [revert_protected_hfill]],
2979 [318, [revert_spaceinset, revert_hfills, revert_hspace]],
2980 [317, [remove_extra_embedded_files]],
2981 [316, [revert_wrapplacement]],
2982 [315, [revert_subfig]],
2983 [314, [revert_colsep, revert_plainlayout]],
2985 [312, [revert_module_names]],
2986 [311, [revert_rotfloat, revert_widesideways]],
2987 [310, [revert_external_embedding]],
2988 [309, [revert_btprintall]],
2989 [308, [revert_nocite]],
2990 [307, [revert_serbianlatin]],
2991 [306, [revert_slash, revert_nobreakdash]],
2992 [305, [revert_interlingua]],
2993 [304, [revert_bahasam]],
2994 [303, [revert_framed_notes]],
2996 [301, [revert_latin, revert_samin]],
2997 [300, [revert_linebreak]],
2998 [299, [revert_pagebreak]],
2999 [298, [revert_hyperlinktype]],
3000 [297, [revert_macro_optional_params]],
3001 [296, [revert_albanian, revert_lowersorbian, revert_uppersorbian]],
3002 [295, [revert_include]],
3003 [294, [revert_href, revert_url]],
3004 [293, [revert_pdf_options_2]],
3005 [292, [revert_inset_info]],
3006 [291, [revert_japanese, revert_japanese_encoding, revert_japanese_cjk]],
3007 [290, [revert_vietnamese]],
3008 [289, [revert_wraptable]],
3009 [288, [revert_latexcommand_index]],
3010 [287, [revert_inset_command]],
3011 [286, [revert_wrapfig_options]],
3012 [285, [revert_pdf_options]],
3013 [284, [remove_inzip_options]],
3015 [282, [revert_flex]],
3017 [280, [revert_begin_modules]],
3018 [279, [revert_show_label]],
3019 [278, [revert_long_charstyle_names]],
3025 if __name__ == "__main__":