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 document.warning("Weirdly formed \\begin_layout at line %d of body!" % i)
1322 if layouts.count(m) != 0:
1323 document.add_module("Theorems (AMS-Extended)")
1327 def revert_href(document):
1328 'Reverts hyperlink insets (href) to url insets (url)'
1331 i = find_token(document.body, "\\begin_inset CommandInset href", i)
1334 document.body[i : i + 2] = \
1335 ["\\begin_inset CommandInset url", "LatexCommand url"]
1338 def revert_url(document):
1339 'Reverts Flex URL insets to old-style URL insets'
1342 i = find_token(document.body, "\\begin_inset Flex URL", i)
1345 j = find_end_of_inset(document.body, i)
1347 document.warning("Can't find end of inset in revert_url!")
1349 k = find_default_layout(document, i, j)
1351 document.warning("Can't find default layout in revert_url!")
1354 l = find_end_of(document.body, k, "\\begin_layout", "\\end_layout")
1355 if l == -1 or l >= j:
1356 document.warning("Can't find end of default layout in revert_url!")
1359 # OK, so the inset's data is between lines k and l.
1360 data = " ".join(document.body[k+1:l])
1362 newinset = ["\\begin_inset LatexCommand url", "target \"" + data + "\"",\
1364 document.body[i:j+1] = newinset
1365 i = i + len(newinset)
1368 def convert_include(document):
1369 'Converts include insets to new format.'
1371 r = re.compile(r'\\begin_inset Include\s+\\([^{]+){([^}]*)}(?:\[(.*)\])?')
1373 i = find_token(document.body, "\\begin_inset Include", i)
1376 line = document.body[i]
1377 previewline = document.body[i + 1]
1380 document.warning("Unable to match line " + str(i) + " of body!")
1386 insertion = ["\\begin_inset CommandInset include",
1387 "LatexCommand " + cmd, previewline,
1388 "filename \"" + fn + "\""]
1391 insertion.append("lstparams " + '"' + opt + '"')
1393 document.body[i : i + 2] = insertion
1397 def revert_include(document):
1398 'Reverts include insets to old format.'
1400 r0 = re.compile('preview.*')
1401 r1 = re.compile('LatexCommand (.+)')
1402 r2 = re.compile('filename "(.+)"')
1403 r3 = re.compile('lstparams "(.*)"')
1405 i = find_token(document.body, "\\begin_inset CommandInset include", i)
1409 if r0.match(document.body[nextline]):
1410 previewline = document.body[nextline]
1414 m = r1.match(document.body[nextline])
1416 document.warning("Malformed LyX document: No LatexCommand line for `" +
1417 document.body[i] + "' on line " + str(i) + ".")
1422 m = r2.match(document.body[nextline])
1424 document.warning("Malformed LyX document: No filename line for `" + \
1425 document.body[i] + "' on line " + str(i) + ".")
1431 if (cmd == "lstinputlisting"):
1432 m = r3.match(document.body[nextline])
1434 options = m.group(1)
1437 newline = "\\begin_inset Include \\" + cmd + "{" + fn + "}"
1439 newline += ("[" + options + "]")
1440 insertion = [newline]
1441 if previewline != "":
1442 insertion.append(previewline)
1443 document.body[i : nextline] = insertion
1447 def revert_albanian(document):
1448 "Set language Albanian to English"
1450 if document.language == "albanian":
1451 document.language = "english"
1452 i = find_token(document.header, "\\language", 0)
1454 document.header[i] = "\\language english"
1457 j = find_token(document.body, "\\lang albanian", j)
1460 document.body[j] = document.body[j].replace("\\lang albanian", "\\lang english")
1464 def revert_lowersorbian(document):
1465 "Set language lower Sorbian to English"
1467 if document.language == "lowersorbian":
1468 document.language = "english"
1469 i = find_token(document.header, "\\language", 0)
1471 document.header[i] = "\\language english"
1474 j = find_token(document.body, "\\lang lowersorbian", j)
1477 document.body[j] = document.body[j].replace("\\lang lowersorbian", "\\lang english")
1481 def revert_uppersorbian(document):
1482 "Set language uppersorbian to usorbian as this was used in LyX 1.5"
1484 if document.language == "uppersorbian":
1485 document.language = "usorbian"
1486 i = find_token(document.header, "\\language", 0)
1488 document.header[i] = "\\language usorbian"
1491 j = find_token(document.body, "\\lang uppersorbian", j)
1494 document.body[j] = document.body[j].replace("\\lang uppersorbian", "\\lang usorbian")
1498 def convert_usorbian(document):
1499 "Set language usorbian to uppersorbian"
1501 if document.language == "usorbian":
1502 document.language = "uppersorbian"
1503 i = find_token(document.header, "\\language", 0)
1505 document.header[i] = "\\language uppersorbian"
1508 j = find_token(document.body, "\\lang usorbian", j)
1511 document.body[j] = document.body[j].replace("\\lang usorbian", "\\lang uppersorbian")
1515 def revert_macro_optional_params(document):
1516 "Convert macro definitions with optional parameters into ERTs"
1517 # Stub to convert macro definitions with one or more optional parameters
1518 # into uninterpreted ERT insets
1521 def revert_hyperlinktype(document):
1522 'Reverts hyperlink type'
1526 i = find_token(document.body, "target", i)
1529 j = find_token(document.body, "type", i)
1533 del document.body[j]
1537 def revert_pagebreak(document):
1538 'Reverts pagebreak to ERT'
1541 i = find_token(document.body, "\\pagebreak", i)
1544 document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1545 '\\begin_layout Standard\n\n\n\\backslash\n' \
1546 'pagebreak{}\n\\end_layout\n\n\\end_inset\n\n'
1550 def revert_linebreak(document):
1551 'Reverts linebreak to ERT'
1554 i = find_token(document.body, "\\linebreak", i)
1557 document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1558 '\\begin_layout Standard\n\n\n\\backslash\n' \
1559 'linebreak{}\n\\end_layout\n\n\\end_inset\n\n'
1563 def revert_latin(document):
1564 "Set language Latin to English"
1566 if document.language == "latin":
1567 document.language = "english"
1568 i = find_token(document.header, "\\language", 0)
1570 document.header[i] = "\\language english"
1573 j = find_token(document.body, "\\lang latin", j)
1576 document.body[j] = document.body[j].replace("\\lang latin", "\\lang english")
1580 def revert_samin(document):
1581 "Set language North Sami to English"
1583 if document.language == "samin":
1584 document.language = "english"
1585 i = find_token(document.header, "\\language", 0)
1587 document.header[i] = "\\language english"
1590 j = find_token(document.body, "\\lang samin", j)
1593 document.body[j] = document.body[j].replace("\\lang samin", "\\lang english")
1597 def convert_serbocroatian(document):
1598 "Set language Serbocroatian to Croatian as this was really Croatian in LyX 1.5"
1600 if document.language == "serbocroatian":
1601 document.language = "croatian"
1602 i = find_token(document.header, "\\language", 0)
1604 document.header[i] = "\\language croatian"
1607 j = find_token(document.body, "\\lang serbocroatian", j)
1610 document.body[j] = document.body[j].replace("\\lang serbocroatian", "\\lang croatian")
1614 def convert_framed_notes(document):
1615 "Convert framed notes to boxes. "
1618 i = find_tokens(document.body, ["\\begin_inset Note Framed", "\\begin_inset Note Shaded"], i)
1621 subst = [document.body[i].replace("\\begin_inset Note", "\\begin_inset Box"),
1630 'height_special "totalheight"']
1631 document.body[i:i+1] = subst
1635 def convert_module_names(document):
1636 modulemap = { 'Braille' : 'braille', 'Endnote' : 'endnotes', 'Foot to End' : 'foottoend',\
1637 'Hanging' : 'hanging', 'Linguistics' : 'linguistics', 'Logical Markup' : 'logicalmkup', \
1638 'Theorems (AMS-Extended)' : 'theorems-ams-extended', 'Theorems (AMS)' : 'theorems-ams', \
1639 'Theorems (Order By Chapter)' : 'theorems-chap', 'Theorems (Order By Section)' : 'theorems-sec', \
1640 'Theorems (Starred)' : 'theorems-starred', 'Theorems' : 'theorems-std' }
1641 modlist = document.get_module_list()
1642 if len(modlist) == 0:
1646 if modulemap.has_key(mod):
1647 newmodlist.append(modulemap[mod])
1649 document.warning("Can't find module %s in the module map!" % mod)
1650 newmodlist.append(mod)
1651 document.set_module_list(newmodlist)
1654 def revert_module_names(document):
1655 modulemap = { 'braille' : 'Braille', 'endnotes' : 'Endnote', 'foottoend' : 'Foot to End',\
1656 'hanging' : 'Hanging', 'linguistics' : 'Linguistics', 'logicalmkup' : 'Logical Markup', \
1657 'theorems-ams-extended' : 'Theorems (AMS-Extended)', 'theorems-ams' : 'Theorems (AMS)', \
1658 'theorems-chap' : 'Theorems (Order By Chapter)', 'theorems-sec' : 'Theorems (Order By Section)', \
1659 'theorems-starred' : 'Theorems (Starred)', 'theorems-std' : 'Theorems'}
1660 modlist = document.get_module_list()
1661 if len(modlist) == 0:
1665 if modulemap.has_key(mod):
1666 newmodlist.append(modulemap[mod])
1668 document.warning("Can't find module %s in the module map!" % mod)
1669 newmodlist.append(mod)
1670 document.set_module_list(newmodlist)
1673 def revert_colsep(document):
1674 i = find_token(document.header, "\\columnsep", 0)
1677 colsepline = document.header[i]
1678 r = re.compile(r'\\columnsep (.*)')
1679 m = r.match(colsepline)
1681 document.warning("Malformed column separation line!")
1684 del document.header[i]
1685 #it seems to be safe to add the package even if it is already used
1686 pretext = ["\\usepackage{geometry}", "\\geometry{columnsep=" + colsep + "}"]
1688 add_to_preamble(document, pretext)
1691 def revert_framed_notes(document):
1692 "Revert framed boxes to notes. "
1695 i = find_tokens(document.body, ["\\begin_inset Box Framed", "\\begin_inset Box Shaded"], i)
1699 j = find_end_of_inset(document.body, i + 1)
1702 document.warning("Malformed LyX document: Could not find end of Box inset.")
1703 k = find_token(document.body, "status", i + 1, j)
1705 document.warning("Malformed LyX document: Missing `status' tag in Box inset.")
1707 status = document.body[k]
1708 l = find_default_layout(document, i + 1, j)
1710 document.warning("Malformed LyX document: Missing `\\begin_layout' in Box inset.")
1712 m = find_token(document.body, "\\end_layout", i + 1, j)
1714 document.warning("Malformed LyX document: Missing `\\end_layout' in Box inset.")
1716 ibox = find_token(document.body, "has_inner_box 1", i + 1, k)
1717 pbox = find_token(document.body, "use_parbox 1", i + 1, k)
1718 if ibox == -1 and pbox == -1:
1719 document.body[i] = document.body[i].replace("\\begin_inset Box", "\\begin_inset Note")
1720 del document.body[i+1:k]
1722 document.body[i] = document.body[i].replace("\\begin_inset Box Shaded", "\\begin_inset Box Frameless")
1723 subst1 = [document.body[l],
1724 "\\begin_inset Note Shaded",
1726 '\\begin_layout Standard']
1727 document.body[l:l + 1] = subst1
1728 subst2 = [document.body[m], "\\end_layout", "\\end_inset"]
1729 document.body[m:m + 1] = subst2
1733 def revert_slash(document):
1734 'Revert \\SpecialChar \\slash{} to ERT'
1735 r = re.compile(r'\\SpecialChar \\slash{}')
1737 while i < len(document.body):
1738 m = r.match(document.body[i])
1740 subst = ['\\begin_inset ERT',
1741 'status collapsed', '',
1742 '\\begin_layout Standard',
1743 '', '', '\\backslash',
1747 document.body[i: i+1] = subst
1753 def revert_nobreakdash(document):
1754 'Revert \\SpecialChar \\nobreakdash- to ERT'
1756 while i < len(document.body):
1757 line = document.body[i]
1758 r = re.compile(r'\\SpecialChar \\nobreakdash-')
1761 subst = ['\\begin_inset ERT',
1762 'status collapsed', '',
1763 '\\begin_layout Standard', '', '',
1768 document.body[i:i+1] = subst
1770 j = find_token(document.header, "\\use_amsmath", 0)
1772 document.warning("Malformed LyX document: Missing '\\use_amsmath'.")
1774 document.header[j] = "\\use_amsmath 2"
1779 #Returns number of lines added/removed
1780 def revert_nocite_key(body, start, end):
1781 'key "..." -> \nocite{...}'
1782 r = re.compile(r'^key "(.*)"')
1786 m = r.match(body[i])
1788 body[i:i+1] = ["\\backslash", "nocite{" + m.group(1) + "}"]
1789 j += 1 # because we added a line
1790 i += 2 # skip that line
1793 j -= 1 # because we deleted a line
1794 # no need to change i, since it now points to the next line
1798 def revert_nocite(document):
1799 "Revert LatexCommand nocite to ERT"
1802 i = find_token(document.body, "\\begin_inset CommandInset citation", i)
1805 if (document.body[i+1] != "LatexCommand nocite"):
1806 # note that we already incremented i
1809 insetEnd = find_end_of_inset(document.body, i)
1811 #this should not happen
1812 document.warning("End of CommandInset citation not found in revert_nocite!")
1815 paramLocation = i + 2 #start of the inset's parameters
1817 document.body[i:i+2] = \
1818 ["\\begin_inset ERT", "status collapsed", "", "\\begin_layout Standard"]
1819 # that added two lines
1822 #print insetEnd, document.body[i: insetEnd + 1]
1823 insetEnd += revert_nocite_key(document.body, paramLocation, insetEnd)
1824 #print insetEnd, document.body[i: insetEnd + 1]
1825 document.body.insert(insetEnd, "\\end_layout")
1826 document.body.insert(insetEnd + 1, "")
1830 def revert_btprintall(document):
1831 "Revert (non-bibtopic) btPrintAll option to ERT \nocite{*}"
1832 i = find_token(document.header, '\\use_bibtopic', 0)
1834 document.warning("Malformed lyx document: Missing '\\use_bibtopic'.")
1836 if get_value(document.header, '\\use_bibtopic', 0) == "false":
1838 while i < len(document.body):
1839 i = find_token(document.body, "\\begin_inset CommandInset bibtex", i)
1842 j = find_end_of_inset(document.body, i + 1)
1844 #this should not happen
1845 document.warning("End of CommandInset bibtex not found in revert_btprintall!")
1846 j = len(document.body)
1847 # this range isn't really right, but it should be OK, since we shouldn't
1848 # see more than one matching line in each inset
1850 for k in range(i, j):
1851 if (document.body[k] == 'btprint "btPrintAll"'):
1852 del document.body[k]
1853 subst = ["\\begin_inset ERT",
1854 "status collapsed", "",
1855 "\\begin_layout Standard", "",
1860 document.body[i:i] = subst
1861 addlines = addedlines + len(subst) - 1
1865 def revert_bahasam(document):
1866 "Set language Bahasa Malaysia to Bahasa Indonesia"
1868 if document.language == "bahasam":
1869 document.language = "bahasa"
1870 i = find_token(document.header, "\\language", 0)
1872 document.header[i] = "\\language bahasa"
1875 j = find_token(document.body, "\\lang bahasam", j)
1878 document.body[j] = document.body[j].replace("\\lang bahasam", "\\lang bahasa")
1882 def revert_interlingua(document):
1883 "Set language Interlingua to English"
1885 if document.language == "interlingua":
1886 document.language = "english"
1887 i = find_token(document.header, "\\language", 0)
1889 document.header[i] = "\\language english"
1892 j = find_token(document.body, "\\lang interlingua", j)
1895 document.body[j] = document.body[j].replace("\\lang interlingua", "\\lang english")
1899 def revert_serbianlatin(document):
1900 "Set language Serbian-Latin to Croatian"
1902 if document.language == "serbian-latin":
1903 document.language = "croatian"
1904 i = find_token(document.header, "\\language", 0)
1906 document.header[i] = "\\language croatian"
1909 j = find_token(document.body, "\\lang serbian-latin", j)
1912 document.body[j] = document.body[j].replace("\\lang serbian-latin", "\\lang croatian")
1916 def revert_rotfloat(document):
1917 " Revert sideways custom floats. "
1920 # whitespace intended (exclude \\begin_inset FloatList)
1921 i = find_token(document.body, "\\begin_inset Float ", i)
1924 line = document.body[i]
1925 r = re.compile(r'\\begin_inset Float (.*)$')
1928 document.warning("Unable to match line " + str(i) + " of body!")
1931 floattype = m.group(1)
1932 if floattype == "figure" or floattype == "table":
1935 j = find_end_of_inset(document.body, i)
1937 document.warning("Malformed lyx document: Missing '\\end_inset' in revert_rotfloat.")
1941 if get_value(document.body, 'sideways', i, j) == "false":
1944 l = find_default_layout(document, i + 1, j)
1946 document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
1948 subst = ['\\begin_layout Standard',
1949 '\\begin_inset ERT',
1950 'status collapsed', '',
1951 '\\begin_layout Standard', '', '',
1953 'end{sideways' + floattype + '}',
1954 '\\end_layout', '', '\\end_inset']
1955 document.body[j : j+1] = subst
1956 addedLines = len(subst) - 1
1957 del document.body[i+1 : l]
1958 addedLines -= (l-1) - (i+1)
1959 subst = ['\\begin_inset ERT', 'status collapsed', '',
1960 '\\begin_layout Standard', '', '', '\\backslash',
1961 'begin{sideways' + floattype + '}',
1962 '\\end_layout', '', '\\end_inset', '',
1964 document.body[i : i+1] = subst
1965 addedLines += len(subst) - 1
1966 if floattype == "algorithm":
1967 add_to_preamble(document,
1968 ['% Commands inserted by lyx2lyx for sideways algorithm float',
1969 '\\usepackage{rotfloat}',
1970 '\\floatstyle{ruled}',
1971 '\\newfloat{algorithm}{tbp}{loa}',
1972 '\\floatname{algorithm}{Algorithm}'])
1974 document.warning("Cannot create preamble definition for custom float" + floattype + ".")
1978 def revert_widesideways(document):
1979 " Revert wide sideways floats. "
1982 # whitespace intended (exclude \\begin_inset FloatList)
1983 i = find_token(document.body, '\\begin_inset Float ', i)
1986 line = document.body[i]
1987 r = re.compile(r'\\begin_inset Float (.*)$')
1990 document.warning("Unable to match line " + str(i) + " of body!")
1993 floattype = m.group(1)
1994 if floattype != "figure" and floattype != "table":
1997 j = find_end_of_inset(document.body, i)
1999 document.warning("Malformed lyx document: Missing '\\end_inset' in revert_widesideways.")
2002 if get_value(document.body, 'sideways', i, j) == "false" or \
2003 get_value(document.body, 'wide', i, j) == "false":
2006 l = find_default_layout(document, i + 1, j)
2008 document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
2010 subst = ['\\begin_layout Standard', '\\begin_inset ERT',
2011 'status collapsed', '',
2012 '\\begin_layout Standard', '', '', '\\backslash',
2013 'end{sideways' + floattype + '*}',
2014 '\\end_layout', '', '\\end_inset']
2015 document.body[j : j+1] = subst
2016 addedLines = len(subst) - 1
2017 del document.body[i+1:l-1]
2018 addedLines -= (l-1) - (i+1)
2019 subst = ['\\begin_inset ERT', 'status collapsed', '',
2020 '\\begin_layout Standard', '', '', '\\backslash',
2021 'begin{sideways' + floattype + '*}', '\\end_layout', '',
2022 '\\end_inset', '', '\\end_layout', '']
2023 document.body[i : i+1] = subst
2024 addedLines += len(subst) - 1
2025 add_to_preamble(document, ['\\usepackage{rotfloat}\n'])
2029 def revert_inset_embedding(document, type):
2030 ' Remove embed tag from certain type of insets'
2033 i = find_token(document.body, "\\begin_inset %s" % type, i)
2036 j = find_end_of_inset(document.body, i)
2038 document.warning("Malformed lyx document: Missing '\\end_inset' in revert_inset_embedding.")
2041 k = find_token(document.body, "\tembed", i, j)
2043 k = find_token(document.body, "embed", i, j)
2045 del document.body[k]
2049 def revert_external_embedding(document):
2050 ' Remove embed tag from external inset '
2051 revert_inset_embedding(document, 'External')
2054 def convert_subfig(document):
2055 " Convert subfigures to subfloats. "
2058 i = find_token(document.body, '\\begin_inset Graphics', i)
2061 endInset = find_end_of_inset(document.body, i)
2063 document.warning("Malformed lyx document: Missing '\\end_inset' in convert_subfig.")
2066 k = find_token(document.body, '\tsubcaption', i, endInset)
2070 l = find_token(document.body, '\tsubcaptionText', i, endInset)
2072 document.warning("Malformed lyx document: Can't find subcaptionText!")
2075 caption = document.body[l][16:].strip('"')
2076 del document.body[l]
2077 del document.body[k]
2079 subst = ['\\begin_inset Float figure', 'wide false', 'sideways false',
2080 'status open', '', '\\begin_layout Plain Layout', '\\begin_inset Caption',
2081 '', '\\begin_layout Plain Layout'] + latex2lyx(caption) + \
2082 [ '\\end_layout', '', '\\end_inset', '',
2083 '\\end_layout', '', '\\begin_layout Plain Layout']
2084 document.body[i : i] = subst
2085 addedLines += len(subst)
2086 endInset += addedLines
2087 subst = ['', '\\end_inset', '', '\\end_layout']
2088 document.body[endInset : endInset] = subst
2089 addedLines += len(subst)
2093 def revert_subfig(document):
2094 " Revert subfloats. "
2097 # whitespace intended (exclude \\begin_inset FloatList)
2098 i = find_tokens(document.body, ['\\begin_inset Float ', '\\begin_inset Wrap'], i)
2104 j = find_end_of_inset(document.body, i)
2106 document.warning("Malformed lyx document: Missing '\\end_inset' (float) at line " + str(i + len(document.header)) + ".\n\t" + document.body[i])
2107 # document.warning(document.body[i-1] + "\n" + document.body[i+1])
2109 continue # this will get us back to the outer loop, since j == -1
2110 # look for embedded float (= subfloat)
2111 # whitespace intended (exclude \\begin_inset FloatList)
2112 k = find_token(document.body, '\\begin_inset Float ', i + 1, j)
2115 l = find_end_of_inset(document.body, k)
2117 document.warning("Malformed lyx document: Missing '\\end_inset' (embedded float).")
2120 continue # escape to the outer loop
2121 m = find_default_layout(document, k + 1, l)
2123 cap = find_token(document.body, '\\begin_inset Caption', k + 1, l)
2128 capend = find_end_of_inset(document.body, cap)
2130 document.warning("Malformed lyx document: Missing '\\end_inset' (caption).")
2134 lbl = find_token(document.body, '\\begin_inset CommandInset label', cap, capend)
2136 lblend = find_end_of_inset(document.body, lbl + 1)
2138 document.warning("Malformed lyx document: Missing '\\end_inset' (label).")
2140 for line in document.body[lbl:lblend + 1]:
2141 if line.startswith('name '):
2142 label = line.split()[1].strip('"')
2149 opt = find_token(document.body, '\\begin_inset OptArg', cap, capend)
2151 optend = find_end_of_inset(document.body, opt)
2153 document.warning("Malformed lyx document: Missing '\\end_inset' (OptArg).")
2155 optc = find_default_layout(document, opt, optend)
2157 document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
2159 optcend = find_end_of(document.body, optc, "\\begin_layout", "\\end_layout")
2160 for line in document.body[optc:optcend]:
2161 if not line.startswith('\\'):
2162 shortcap += line.strip()
2166 for line in document.body[cap:capend]:
2167 if line in document.body[lbl:lblend]:
2169 elif line in document.body[opt:optend]:
2171 elif not line.startswith('\\'):
2172 caption += line.strip()
2174 caption += "\\backslash\nlabel{" + label + "}"
2175 subst = '\\begin_layout Plain Layout\n\\begin_inset ERT\nstatus collapsed\n\n' \
2176 '\\begin_layout Plain Layout\n\n}\n\\end_layout\n\n\\end_inset\n\n' \
2177 '\\end_layout\n\n\\begin_layout Plain Layout\n'
2178 subst = subst.split('\n')
2179 document.body[l : l+1] = subst
2180 addedLines = len(subst) - 1
2181 # this is before l and so is unchanged by the multiline insertion
2183 del document.body[cap:capend+1]
2184 addedLines -= (capend + 1 - cap)
2185 del document.body[k+1:m-1]
2186 addedLines -= (m - 1 - (k + 1))
2187 insertion = '\\begin_inset ERT\nstatus collapsed\n\n' \
2188 '\\begin_layout Plain Layout\n\n\\backslash\n' \
2190 if len(shortcap) > 0:
2191 insertion = insertion + "[" + shortcap + "]"
2192 if len(caption) > 0:
2193 insertion = insertion + "[" + caption + "]"
2194 insertion = insertion + '{%\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n'
2195 insertion = insertion.split('\n')
2196 document.body[k : k + 1] = insertion
2197 addedLines += len(insertion) - 1
2198 add_to_preamble(document, ['\\usepackage{subfig}\n'])
2202 def revert_wrapplacement(document):
2203 " Revert placement options wrap floats (wrapfig). "
2206 i = find_token(document.body, "\\begin_inset Wrap figure", i)
2209 e = find_end_of_inset(document.body, i)
2210 j = find_token(document.body, "placement", i + 1, e)
2212 document.warning("Malformed LyX document: Couldn't find placement parameter of wrap float.")
2215 r = re.compile("placement (o|i|l|r)")
2216 m = r.match(document.body[j])
2218 document.warning("Malformed LyX document: Placement option isn't O|I|R|L!")
2219 document.body[j] = "placement " + m.group(1).lower()
2223 def remove_extra_embedded_files(document):
2224 " Remove \extra_embedded_files from buffer params "
2225 i = find_token(document.header, '\\extra_embedded_files', 0)
2228 document.header.pop(i)
2231 def convert_spaceinset(document):
2232 " Convert '\\InsetSpace foo' to '\\begin_inset Space foo\n\\end_inset' "
2234 while i < len(document.body):
2235 m = re.match(r'(.*)\\InsetSpace (.*)', document.body[i])
2239 subst = [before, "\\begin_inset Space " + after, "\\end_inset"]
2240 document.body[i: i+1] = subst
2246 def revert_spaceinset(document):
2247 " Revert '\\begin_inset Space foo\n\\end_inset' to '\\InsetSpace foo' "
2250 i = find_token(document.body, "\\begin_inset Space", i)
2253 j = find_end_of_inset(document.body, i)
2255 document.warning("Malformed LyX document: Could not find end of space inset.")
2257 document.body[i] = document.body[i].replace('\\begin_inset Space', '\\InsetSpace')
2258 del document.body[j]
2261 def convert_hfill(document):
2262 " Convert hfill to space inset "
2265 i = find_token(document.body, "\\hfill", i)
2268 subst = document.body[i].replace('\\hfill', \
2269 '\n\\begin_inset Space \\hfill{}\n\\end_inset')
2270 subst = subst.split('\n')
2271 document.body[i : i+1] = subst
2275 def revert_hfills(document):
2276 ' Revert \\hfill commands '
2277 hfill = re.compile(r'\\hfill')
2278 dotfill = re.compile(r'\\dotfill')
2279 hrulefill = re.compile(r'\\hrulefill')
2282 i = find_token(document.body, "\\InsetSpace", i)
2285 if hfill.search(document.body[i]):
2286 document.body[i] = \
2287 document.body[i].replace('\\InsetSpace \\hfill{}', '\\hfill')
2290 if dotfill.search(document.body[i]):
2291 subst = document.body[i].replace('\\InsetSpace \\dotfill{}', \
2292 '\\begin_inset ERT\nstatus collapsed\n\n' \
2293 '\\begin_layout Standard\n\n\n\\backslash\n' \
2294 'dotfill{}\n\\end_layout\n\n\\end_inset\n\n')
2295 subst = subst.split('\n')
2296 document.body[i : i+1] = subst
2299 if hrulefill.search(document.body[i]):
2300 subst = document.body[i].replace('\\InsetSpace \\hrulefill{}', \
2301 '\\begin_inset ERT\nstatus collapsed\n\n' \
2302 '\\begin_layout Standard\n\n\n\\backslash\n' \
2303 'hrulefill{}\n\\end_layout\n\n\\end_inset\n\n')
2304 subst = subst.split('\n')
2305 document.body[i : i+1] = subst
2310 def revert_hspace(document):
2311 ' Revert \\InsetSpace \\hspace{} to ERT '
2313 hspace = re.compile(r'\\hspace{}')
2314 hstar = re.compile(r'\\hspace\*{}')
2316 i = find_token(document.body, "\\InsetSpace \\hspace", i)
2319 length = get_value(document.body, '\\length', i+1)
2321 document.warning("Malformed lyx document: Missing '\\length' in Space inset.")
2323 del document.body[i+1]
2325 if hstar.search(document.body[i]):
2326 subst = document.body[i].replace('\\InsetSpace \\hspace*{}', \
2327 '\\begin_inset ERT\nstatus collapsed\n\n' \
2328 '\\begin_layout Standard\n\n\n\\backslash\n' \
2329 'hspace*{' + length + '}\n\\end_layout\n\n\\end_inset\n\n')
2330 subst = subst.split('\n')
2331 document.body[i : i+1] = subst
2332 addedLines += len(subst) - 1
2335 if hspace.search(document.body[i]):
2336 subst = document.body[i].replace('\\InsetSpace \\hspace{}', \
2337 '\\begin_inset ERT\nstatus collapsed\n\n' \
2338 '\\begin_layout Standard\n\n\n\\backslash\n' \
2339 'hspace{' + length + '}\n\\end_layout\n\n\\end_inset\n\n')
2340 subst = subst.split('\n')
2341 document.body[i : i+1] = subst
2342 addedLines += len(subst) - 1
2348 def revert_protected_hfill(document):
2349 ' Revert \\begin_inset Space \\hspace*{\\fill} to ERT '
2352 i = find_token(document.body, '\\begin_inset Space \\hspace*{\\fill}', i)
2355 j = find_end_of_inset(document.body, i)
2357 document.warning("Malformed LyX document: Could not find end of space inset.")
2359 del document.body[j]
2360 subst = document.body[i].replace('\\begin_inset Space \\hspace*{\\fill}', \
2361 '\\begin_inset ERT\nstatus collapsed\n\n' \
2362 '\\begin_layout Standard\n\n\n\\backslash\n' \
2363 'hspace*{\n\\backslash\nfill}\n\\end_layout\n\n\\end_inset\n\n')
2364 subst = subst.split('\n')
2365 document.body[i : i+1] = subst
2369 def revert_leftarrowfill(document):
2370 ' Revert \\begin_inset Space \\leftarrowfill{} to ERT '
2373 i = find_token(document.body, '\\begin_inset Space \\leftarrowfill{}', i)
2376 j = find_end_of_inset(document.body, i)
2378 document.warning("Malformed LyX document: Could not find end of space inset.")
2380 del document.body[j]
2381 subst = document.body[i].replace('\\begin_inset Space \\leftarrowfill{}', \
2382 '\\begin_inset ERT\nstatus collapsed\n\n' \
2383 '\\begin_layout Standard\n\n\n\\backslash\n' \
2384 'leftarrowfill{}\n\\end_layout\n\n\\end_inset\n\n')
2385 subst = subst.split('\n')
2386 document.body[i : i+1] = subst
2390 def revert_rightarrowfill(document):
2391 ' Revert \\begin_inset Space \\rightarrowfill{} to ERT '
2394 i = find_token(document.body, '\\begin_inset Space \\rightarrowfill{}', i)
2397 j = find_end_of_inset(document.body, i)
2399 document.warning("Malformed LyX document: Could not find end of space inset.")
2401 del document.body[j]
2402 subst = document.body[i].replace('\\begin_inset Space \\rightarrowfill{}', \
2403 '\\begin_inset ERT\nstatus collapsed\n\n' \
2404 '\\begin_layout Standard\n\n\n\\backslash\n' \
2405 'rightarrowfill{}\n\\end_layout\n\n\\end_inset\n\n')
2406 subst = subst.split('\n')
2407 document.body[i : i+1] = subst
2411 def revert_upbracefill(document):
2412 ' Revert \\begin_inset Space \\upbracefill{} to ERT '
2415 i = find_token(document.body, '\\begin_inset Space \\upbracefill{}', i)
2418 j = find_end_of_inset(document.body, i)
2420 document.warning("Malformed LyX document: Could not find end of space inset.")
2422 del document.body[j]
2423 subst = document.body[i].replace('\\begin_inset Space \\upbracefill{}', \
2424 '\\begin_inset ERT\nstatus collapsed\n\n' \
2425 '\\begin_layout Standard\n\n\n\\backslash\n' \
2426 'upbracefill{}\n\\end_layout\n\n\\end_inset\n\n')
2427 subst = subst.split('\n')
2428 document.body[i : i+1] = subst
2432 def revert_downbracefill(document):
2433 ' Revert \\begin_inset Space \\downbracefill{} to ERT '
2436 i = find_token(document.body, '\\begin_inset Space \\downbracefill{}', i)
2439 j = find_end_of_inset(document.body, i)
2441 document.warning("Malformed LyX document: Could not find end of space inset.")
2443 del document.body[j]
2444 subst = document.body[i].replace('\\begin_inset Space \\downbracefill{}', \
2445 '\\begin_inset ERT\nstatus collapsed\n\n' \
2446 '\\begin_layout Standard\n\n\n\\backslash\n' \
2447 'downbracefill{}\n\\end_layout\n\n\\end_inset\n\n')
2448 subst = subst.split('\n')
2449 document.body[i : i+1] = subst
2453 def revert_local_layout(document):
2454 ' Revert local layout headers.'
2457 i = find_token(document.header, "\\begin_local_layout", i)
2460 j = find_end_of(document.header, i, "\\begin_local_layout", "\\end_local_layout")
2462 # this should not happen
2464 document.header[i : j + 1] = []
2467 def convert_pagebreaks(document):
2468 ' Convert inline Newpage insets to new format '
2471 i = find_token(document.body, '\\newpage', i)
2474 document.body[i:i+1] = ['\\begin_inset Newpage newpage',
2478 i = find_token(document.body, '\\pagebreak', i)
2481 document.body[i:i+1] = ['\\begin_inset Newpage pagebreak',
2485 i = find_token(document.body, '\\clearpage', i)
2488 document.body[i:i+1] = ['\\begin_inset Newpage clearpage',
2492 i = find_token(document.body, '\\cleardoublepage', i)
2495 document.body[i:i+1] = ['\\begin_inset Newpage cleardoublepage',
2499 def revert_pagebreaks(document):
2500 ' Revert \\begin_inset Newpage to previous inline format '
2503 i = find_token(document.body, '\\begin_inset Newpage', i)
2506 j = find_end_of_inset(document.body, i)
2508 document.warning("Malformed LyX document: Could not find end of Newpage inset.")
2510 del document.body[j]
2511 document.body[i] = document.body[i].replace('\\begin_inset Newpage newpage', '\\newpage')
2512 document.body[i] = document.body[i].replace('\\begin_inset Newpage pagebreak', '\\pagebreak')
2513 document.body[i] = document.body[i].replace('\\begin_inset Newpage clearpage', '\\clearpage')
2514 document.body[i] = document.body[i].replace('\\begin_inset Newpage cleardoublepage', '\\cleardoublepage')
2517 def convert_linebreaks(document):
2518 ' Convert inline Newline insets to new format '
2521 i = find_token(document.body, '\\newline', i)
2524 document.body[i:i+1] = ['\\begin_inset Newline newline',
2528 i = find_token(document.body, '\\linebreak', i)
2531 document.body[i:i+1] = ['\\begin_inset Newline linebreak',
2535 def revert_linebreaks(document):
2536 ' Revert \\begin_inset Newline to previous inline format '
2539 i = find_token(document.body, '\\begin_inset Newline', i)
2542 j = find_end_of_inset(document.body, i)
2544 document.warning("Malformed LyX document: Could not find end of Newline inset.")
2546 del document.body[j]
2547 document.body[i] = document.body[i].replace('\\begin_inset Newline newline', '\\newline')
2548 document.body[i] = document.body[i].replace('\\begin_inset Newline linebreak', '\\linebreak')
2551 def convert_japanese_plain(document):
2552 ' Set language japanese-plain to japanese '
2554 if document.language == "japanese-plain":
2555 document.language = "japanese"
2556 i = find_token(document.header, "\\language", 0)
2558 document.header[i] = "\\language japanese"
2561 j = find_token(document.body, "\\lang japanese-plain", j)
2564 document.body[j] = document.body[j].replace("\\lang japanese-plain", "\\lang japanese")
2568 def revert_pdfpages(document):
2569 ' Revert pdfpages external inset to ERT '
2572 i = find_token(document.body, "\\begin_inset External", i)
2575 j = find_end_of_inset(document.body, i)
2577 document.warning("Malformed lyx document: Missing '\\end_inset' in revert_pdfpages.")
2580 if get_value(document.body, 'template', i, j) == "PDFPages":
2581 filename = get_value(document.body, 'filename', i, j)
2583 r = re.compile(r'\textra PDFLaTeX \"(.*)\"$')
2584 for k in range(i, j):
2585 m = r.match(document.body[k])
2588 angle = get_value(document.body, 'rotateAngle', i, j)
2589 width = get_value(document.body, 'width', i, j)
2590 height = get_value(document.body, 'height', i, j)
2591 scale = get_value(document.body, 'scale', i, j)
2592 keepAspectRatio = find_token(document.body, "\tkeepAspectRatio", i, j)
2596 options += ",angle=" + angle
2598 options += "angle=" + angle
2601 options += ",width=" + convert_len(width)
2603 options += "width=" + convert_len(width)
2606 options += ",height=" + convert_len(height)
2608 options += "height=" + convert_len(height)
2611 options += ",scale=" + scale
2613 options += "scale=" + scale
2614 if keepAspectRatio != '':
2616 options += ",keepaspectratio"
2618 options += "keepaspectratio"
2620 options = '[' + options + ']'
2621 del document.body[i+1:j+1]
2622 document.body[i:i+1] = ['\\begin_inset ERT',
2625 '\\begin_layout Standard',
2628 'includepdf' + options + '{' + filename + '}',
2632 add_to_preamble(document, ['\\usepackage{pdfpages}\n'])
2638 def revert_mexican(document):
2639 ' Set language Spanish(Mexico) to Spanish '
2641 if document.language == "spanish-mexico":
2642 document.language = "spanish"
2643 i = find_token(document.header, "\\language", 0)
2645 document.header[i] = "\\language spanish"
2648 j = find_token(document.body, "\\lang spanish-mexico", j)
2651 document.body[j] = document.body[j].replace("\\lang spanish-mexico", "\\lang spanish")
2655 def remove_embedding(document):
2656 ' Remove embed tag from all insets '
2657 revert_inset_embedding(document, 'Graphics')
2658 revert_inset_embedding(document, 'External')
2659 revert_inset_embedding(document, 'CommandInset include')
2660 revert_inset_embedding(document, 'CommandInset bibtex')
2663 def revert_master(document):
2664 ' Remove master param '
2665 i = find_token(document.header, "\\master", 0)
2667 del document.header[i]
2670 def revert_graphics_group(document):
2671 ' Revert group information from graphics insets '
2674 i = find_token(document.body, "\\begin_inset Graphics", i)
2677 j = find_end_of_inset(document.body, i)
2679 document.warning("Malformed lyx document: Missing '\\end_inset' in revert_graphics_group.")
2682 k = find_token(document.body, " groupId", i, j)
2686 del document.body[k]
2690 def update_apa_styles(document):
2691 ' Replace obsolete styles '
2693 if document.textclass != "apa":
2696 obsoletedby = { "Acknowledgments": "Acknowledgements",
2697 "Section*": "Section",
2698 "Subsection*": "Subsection",
2699 "Subsubsection*": "Subsubsection",
2700 "Paragraph*": "Paragraph",
2701 "Subparagraph*": "Subparagraph"}
2704 i = find_token(document.body, "\\begin_layout", i)
2708 layout = document.body[i][14:]
2709 if layout in obsoletedby:
2710 document.body[i] = "\\begin_layout " + obsoletedby[layout]
2715 def convert_paper_sizes(document):
2716 ' exchange size options legalpaper and executivepaper to correct order '
2717 # routine is needed to fix http://bugzilla.lyx.org/show_bug.cgi?id=4868
2720 i = find_token(document.header, "\\papersize executivepaper", 0)
2722 document.header[i] = "\\papersize legalpaper"
2724 j = find_token(document.header, "\\papersize legalpaper", 0)
2726 document.header[j] = "\\papersize executivepaper"
2729 def revert_paper_sizes(document):
2730 ' exchange size options legalpaper and executivepaper to correct order '
2733 i = find_token(document.header, "\\papersize executivepaper", 0)
2735 document.header[i] = "\\papersize legalpaper"
2737 j = find_token(document.header, "\\papersize legalpaper", 0)
2739 document.header[j] = "\\papersize executivepaper"
2742 def convert_InsetSpace(document):
2743 " Convert '\\begin_inset Space foo' to '\\begin_inset space foo'"
2746 i = find_token(document.body, "\\begin_inset Space", i)
2749 document.body[i] = document.body[i].replace('\\begin_inset Space', '\\begin_inset space')
2752 def revert_InsetSpace(document):
2753 " Revert '\\begin_inset space foo' to '\\begin_inset Space foo'"
2756 i = find_token(document.body, "\\begin_inset space", i)
2759 document.body[i] = document.body[i].replace('\\begin_inset space', '\\begin_inset Space')
2762 def convert_display_enum(document):
2763 " Convert 'display foo' to 'display false/true'"
2766 i = find_token(document.body, "\tdisplay", i)
2769 val = get_value(document.body, 'display', i)
2771 document.body[i] = document.body[i].replace('none', 'false')
2772 if val == "default":
2773 document.body[i] = document.body[i].replace('default', 'true')
2774 if val == "monochrome":
2775 document.body[i] = document.body[i].replace('monochrome', 'true')
2776 if val == "grayscale":
2777 document.body[i] = document.body[i].replace('grayscale', 'true')
2779 document.body[i] = document.body[i].replace('color', 'true')
2780 if val == "preview":
2781 document.body[i] = document.body[i].replace('preview', 'true')
2785 def revert_display_enum(document):
2786 " Revert 'display false/true' to 'display none/color'"
2789 i = find_token(document.body, "\tdisplay", i)
2792 val = get_value(document.body, 'display', i)
2794 document.body[i] = document.body[i].replace('false', 'none')
2796 document.body[i] = document.body[i].replace('true', 'default')
2800 def remove_fontsCJK(document):
2801 ' Remove font_cjk param '
2802 i = find_token(document.header, "\\font_cjk", 0)
2804 del document.header[i]
2807 def convert_plain_layout(document):
2808 " Convert 'PlainLayout' to 'Plain Layout'"
2811 i = find_token(document.body, '\\begin_layout PlainLayout', i)
2814 document.body[i] = document.body[i].replace('\\begin_layout PlainLayout', \
2815 '\\begin_layout Plain Layout')
2819 def revert_plain_layout(document):
2820 " Convert 'PlainLayout' to 'Plain Layout'"
2823 i = find_token(document.body, '\\begin_layout Plain Layout', i)
2826 document.body[i] = document.body[i].replace('\\begin_layout Plain Layout', \
2827 '\\begin_layout PlainLayout')
2831 def revert_plainlayout(document):
2832 " Convert 'PlainLayout' to 'Plain Layout'"
2835 i = find_token(document.body, '\\begin_layout PlainLayout', i)
2838 # This will be incorrect for some document classes, since Standard is not always
2839 # the default. But (a) it is probably the best we can do and (b) it will actually
2840 # work, in fact, since an unknown layout will be converted to default.
2841 document.body[i] = document.body[i].replace('\\begin_layout PlainLayout', \
2842 '\\begin_layout Standard')
2846 def revert_polytonicgreek(document):
2847 "Set language polytonic Greek to Greek"
2849 if document.language == "polutonikogreek":
2850 document.language = "greek"
2851 i = find_token(document.header, "\\language", 0)
2853 document.header[i] = "\\language greek"
2856 j = find_token(document.body, "\\lang polutonikogreek", j)
2859 document.body[j] = document.body[j].replace("\\lang polutonikogreek", "\\lang greek")
2867 supported_versions = ["1.6.0","1.6"]
2868 convert = [[277, [fix_wrong_tables]],
2869 [278, [close_begin_deeper]],
2870 [279, [long_charstyle_names]],
2871 [280, [axe_show_label]],
2874 [283, [convert_flex]],
2878 [287, [convert_wrapfig_options]],
2879 [288, [convert_inset_command]],
2880 [289, [convert_latexcommand_index]],
2883 [292, [convert_japanese_cjk]],
2885 [294, [convert_pdf_options]],
2886 [295, [convert_htmlurl, convert_url]],
2887 [296, [convert_include]],
2888 [297, [convert_usorbian]],
2894 [303, [convert_serbocroatian]],
2895 [304, [convert_framed_notes]],
2902 [311, [convert_ams_classes]],
2904 [313, [convert_module_names]],
2907 [316, [convert_subfig]],
2910 [319, [convert_spaceinset, convert_hfill]],
2912 [321, [convert_tablines]],
2913 [322, [convert_plain_layout]],
2914 [323, [convert_pagebreaks]],
2915 [324, [convert_linebreaks]],
2916 [325, [convert_japanese_plain]],
2919 [328, [remove_embedding, remove_extra_embedded_files, remove_inzip_options]],
2922 [331, [convert_ltcaption]],
2924 [333, [update_apa_styles]],
2925 [334, [convert_paper_sizes]],
2926 [335, [convert_InsetSpace]],
2928 [337, [convert_display_enum]],
2932 revert = [[337, [revert_polytonicgreek]],
2933 [336, [revert_display_enum]],
2934 [335, [remove_fontsCJK]],
2935 [334, [revert_InsetSpace]],
2936 [333, [revert_paper_sizes]],
2938 [331, [revert_graphics_group]],
2939 [330, [revert_ltcaption]],
2940 [329, [revert_leftarrowfill, revert_rightarrowfill, revert_upbracefill, revert_downbracefill]],
2941 [328, [revert_master]],
2943 [326, [revert_mexican]],
2944 [325, [revert_pdfpages]],
2946 [323, [revert_linebreaks]],
2947 [322, [revert_pagebreaks]],
2948 [321, [revert_local_layout, revert_plain_layout]],
2949 [320, [revert_tablines]],
2950 [319, [revert_protected_hfill]],
2951 [318, [revert_spaceinset, revert_hfills, revert_hspace]],
2952 [317, [remove_extra_embedded_files]],
2953 [316, [revert_wrapplacement]],
2954 [315, [revert_subfig]],
2955 [314, [revert_colsep, revert_plainlayout]],
2957 [312, [revert_module_names]],
2958 [311, [revert_rotfloat, revert_widesideways]],
2959 [310, [revert_external_embedding]],
2960 [309, [revert_btprintall]],
2961 [308, [revert_nocite]],
2962 [307, [revert_serbianlatin]],
2963 [306, [revert_slash, revert_nobreakdash]],
2964 [305, [revert_interlingua]],
2965 [304, [revert_bahasam]],
2966 [303, [revert_framed_notes]],
2968 [301, [revert_latin, revert_samin]],
2969 [300, [revert_linebreak]],
2970 [299, [revert_pagebreak]],
2971 [298, [revert_hyperlinktype]],
2972 [297, [revert_macro_optional_params]],
2973 [296, [revert_albanian, revert_lowersorbian, revert_uppersorbian]],
2974 [295, [revert_include]],
2975 [294, [revert_href, revert_url]],
2976 [293, [revert_pdf_options_2]],
2977 [292, [revert_inset_info]],
2978 [291, [revert_japanese, revert_japanese_encoding, revert_japanese_cjk]],
2979 [290, [revert_vietnamese]],
2980 [289, [revert_wraptable]],
2981 [288, [revert_latexcommand_index]],
2982 [287, [revert_inset_command]],
2983 [286, [revert_wrapfig_options]],
2984 [285, [revert_pdf_options]],
2985 [284, [remove_inzip_options]],
2987 [282, [revert_flex]],
2989 [280, [revert_begin_modules]],
2990 [279, [revert_show_label]],
2991 [278, [revert_long_charstyle_names]],
2997 if __name__ == "__main__":