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
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")
34 def wrap_into_ert(string, src, dst):
35 " Wrap a something into an ERT"
36 return string.replace(src, '\n\\begin_inset ERT\nstatus collapsed\n\\begin_layout Standard\n'
37 + dst + '\n\\end_layout\n\\end_inset\n')
39 def add_to_preamble(document, text):
40 """ Add text to the preamble if it is not already there.
41 Only the first line is checked!"""
43 if find_token(document.preamble, text[0], 0) != -1:
46 document.preamble.extend(text)
48 ####################################################################
50 def get_option(document, m, option, default):
51 l = document.body[m].find(option)
54 val = document.body[m][l:].split('"')[1]
57 def remove_option(document, m, option):
58 l = document.body[m].find(option)
60 val = document.body[m][l:].split('"')[1]
61 document.body[m] = document.body[m][:l-1] + document.body[m][l+len(option + '="' + val + '"'):]
64 def set_option(document, m, option, value):
65 l = document.body[m].find(option)
67 oldval = document.body[m][l:].split('"')[1]
68 l = l + len(option + '="')
69 document.body[m] = document.body[m][:l] + value + document.body[m][l+len(oldval):]
71 document.body[m] = document.body[m][:-1] + ' ' + option + '="' + value + '">'
74 def convert_tablines(document):
77 i = find_token(document.body, "\\begin_inset Tabular", i)
79 # LyX 1.3 inserted an extra space between \begin_inset
80 # and Tabular so let us try if this is the case and fix it.
81 i = find_token(document.body, "\\begin_inset Tabular", i)
85 document.body[i] = "\\begin_inset Tabular"
86 j = find_end_of_inset(document.body, i + 1)
88 document.warning("Malformed LyX document: Could not find end of tabular.")
92 nrows = int(document.body[i+1].split('"')[3])
93 ncols = int(document.body[i+1].split('"')[5])
96 for k in range(ncols):
97 m = find_token(document.body, "<column", m)
98 left = get_option(document, m, 'leftline', 'false')
99 right = get_option(document, m, 'rightline', 'false')
100 col_info.append([left, right])
101 remove_option(document, m, 'leftline')
102 remove_option(document, m, 'rightline')
106 for k in range(nrows):
107 m = find_token(document.body, "<row", m)
108 top = get_option(document, m, 'topline', 'false')
109 bottom = get_option(document, m, 'bottomline', 'false')
110 row_info.append([top, bottom])
111 remove_option(document, m, 'topline')
112 remove_option(document, m, 'bottomline')
117 for k in range(nrows*ncols):
118 m = find_token(document.body, "<cell", m)
119 mc_info.append(get_option(document, m, 'multicolumn', '0'))
122 for l in range(nrows):
123 for k in range(ncols):
124 m = find_token(document.body, '<cell', m)
125 if mc_info[l*ncols + k] == '0':
126 r = set_option(document, m, 'topline', row_info[l][0])
127 r = set_option(document, m, 'bottomline', row_info[l][1])
128 r = set_option(document, m, 'leftline', col_info[k][0])
129 r = set_option(document, m, 'rightline', col_info[k][1])
130 elif mc_info[l*ncols + k] == '1':
132 while s < ncols and mc_info[l*ncols + s] == '2':
134 if s < ncols and mc_info[l*ncols + s] != '1':
135 r = set_option(document, m, 'rightline', col_info[k][1])
136 if k > 0 and mc_info[l*ncols + k - 1] == '0':
137 r = set_option(document, m, 'leftline', col_info[k][0])
142 def revert_tablines(document):
145 i = find_token(document.body, "\\begin_inset Tabular", i)
148 j = find_end_of_inset(document.body, i + 1)
150 document.warning("Malformed LyX document: Could not find end of tabular.")
154 nrows = int(document.body[i+1].split('"')[3])
155 ncols = int(document.body[i+1].split('"')[5])
158 for k in range(nrows*ncols):
159 m = find_token(document.body, "<cell", m)
160 top = get_option(document, m, 'topline', 'false')
161 bottom = get_option(document, m, 'bottomline', 'false')
162 left = get_option(document, m, 'leftline', 'false')
163 right = get_option(document, m, 'rightline', 'false')
164 lines.append([top, bottom, left, right])
169 for k in range(ncols):
170 m = find_token(document.body, "<column", m)
172 for l in range(nrows):
173 left = lines[k*ncols + k][2]
176 set_option(document, m, 'leftline', left)
178 for l in range(nrows):
179 right = lines[k*ncols + k][3]
182 set_option(document, m, 'rightline', right)
186 for k in range(nrows):
187 m = find_token(document.body, "<row", m)
189 for l in range(ncols):
190 top = lines[k*ncols + l][0]
193 set_option(document, m, 'topline', top)
195 for l in range(ncols):
196 bottom = lines[k*ncols + l][1]
197 if bottom == 'false':
199 set_option(document, m, 'bottomline', bottom)
205 def fix_wrong_tables(document):
208 i = find_token(document.body, "\\begin_inset Tabular", i)
211 j = find_end_of_inset(document.body, i + 1)
213 document.warning("Malformed LyX document: Could not find end of tabular.")
217 nrows = int(document.body[i+1].split('"')[3])
218 ncols = int(document.body[i+1].split('"')[5])
220 for l in range(nrows):
222 for k in range(ncols):
223 m = find_token(document.body, '<cell', m)
225 if document.body[m].find('multicolumn') != -1:
226 multicol_cont = int(document.body[m].split('"')[1])
228 if multicol_cont == 2 and (k == 0 or prev_multicolumn == 0):
229 document.body[m] = document.body[m][:5] + document.body[m][21:]
232 prev_multicolumn = multicol_cont
239 def close_begin_deeper(document):
243 i = find_tokens(document.body, ["\\begin_deeper", "\\end_deeper"], i)
248 if document.body[i][:13] == "\\begin_deeper":
255 document.body[-2:-2] = ['\\end_deeper' for i in range(depth)]
258 def long_charstyle_names(document):
261 i = find_token(document.body, "\\begin_inset CharStyle", i)
264 document.body[i] = document.body[i].replace("CharStyle ", "CharStyle CharStyle:")
267 def revert_long_charstyle_names(document):
270 i = find_token(document.body, "\\begin_inset CharStyle", i)
273 document.body[i] = document.body[i].replace("CharStyle CharStyle:", "CharStyle")
277 def axe_show_label(document):
280 i = find_token(document.body, "\\begin_inset CharStyle", i)
283 if document.body[i + 1].find("show_label") != -1:
284 if document.body[i + 1].find("true") != -1:
285 document.body[i + 1] = "status open"
286 del document.body[ i + 2]
288 if document.body[i + 1].find("false") != -1:
289 document.body[i + 1] = "status collapsed"
290 del document.body[ i + 2]
292 document.warning("Malformed LyX document: show_label neither false nor true.")
294 document.warning("Malformed LyX document: show_label missing in CharStyle.")
299 def revert_show_label(document):
302 i = find_token(document.body, "\\begin_inset CharStyle", i)
305 if document.body[i + 1].find("status open") != -1:
306 document.body.insert(i + 1, "show_label true")
308 if document.body[i + 1].find("status collapsed") != -1:
309 document.body.insert(i + 1, "show_label false")
311 document.warning("Malformed LyX document: no legal status line in CharStyle.")
314 def revert_begin_modules(document):
317 i = find_token(document.header, "\\begin_modules", i)
320 j = find_end_of(document.header, i, "\\begin_modules", "\\end_modules")
322 # this should not happen
324 document.header[i : j + 1] = []
326 def convert_flex(document):
327 "Convert CharStyle to Flex"
330 i = find_token(document.body, "\\begin_inset CharStyle", i)
333 document.body[i] = document.body[i].replace('\\begin_inset CharStyle', '\\begin_inset Flex')
335 def revert_flex(document):
336 "Convert Flex to CharStyle"
339 i = find_token(document.body, "\\begin_inset Flex", i)
342 document.body[i] = document.body[i].replace('\\begin_inset Flex', '\\begin_inset CharStyle')
345 # Discard PDF options for hyperref
346 def revert_pdf_options(document):
347 "Revert PDF options for hyperref."
349 i = find_token(document.header, "\\use_hyperref", i)
351 del document.header[i]
352 i = find_token(document.header, "\\pdf_store_options", i)
354 del document.header[i]
355 i = find_token(document.header, "\\pdf_title", 0)
357 del document.header[i]
358 i = find_token(document.header, "\\pdf_author", 0)
360 del document.header[i]
361 i = find_token(document.header, "\\pdf_subject", 0)
363 del document.header[i]
364 i = find_token(document.header, "\\pdf_keywords", 0)
366 del document.header[i]
367 i = find_token(document.header, "\\pdf_bookmarks", 0)
369 del document.header[i]
370 i = find_token(document.header, "\\pdf_bookmarksnumbered", i)
372 del document.header[i]
373 i = find_token(document.header, "\\pdf_bookmarksopen", i)
375 del document.header[i]
376 i = find_token(document.header, "\\pdf_bookmarksopenlevel", i)
378 del document.header[i]
379 i = find_token(document.header, "\\pdf_breaklinks", i)
381 del document.header[i]
382 i = find_token(document.header, "\\pdf_pdfborder", i)
384 del document.header[i]
385 i = find_token(document.header, "\\pdf_colorlinks", i)
387 del document.header[i]
388 i = find_token(document.header, "\\pdf_backref", i)
390 del document.header[i]
391 i = find_token(document.header, "\\pdf_pagebackref", i)
393 del document.header[i]
394 i = find_token(document.header, "\\pdf_pagemode", 0)
396 del document.header[i]
397 i = find_token(document.header, "\\pdf_quoted_options", 0)
399 del document.header[i]
402 def remove_inzip_options(document):
403 "Remove inzipName and embed options from the Graphics inset"
406 i = find_token(document.body, "\\begin_inset Graphics", i)
409 j = find_end_of_inset(document.body, i + 1)
412 document.warning("Malformed LyX document: Could not find end of graphics inset.")
413 # If there's a inzip param, just remove that
414 k = find_token(document.body, "\tinzipName", i + 1, j)
417 # embed option must follow the inzipName option
418 del document.body[k+1]
422 def convert_inset_command(document):
425 \begin_inset LatexCommand cmd
427 \begin_inset CommandInset InsetType
432 i = find_token(document.body, "\\begin_inset LatexCommand", i)
435 line = document.body[i]
436 r = re.compile(r'\\begin_inset LatexCommand (.*)$')
440 #this is adapted from factory.cpp
441 if cmdName[0:4].lower() == "cite":
442 insetName = "citation"
443 elif cmdName == "url" or cmdName == "htmlurl":
445 elif cmdName[-3:] == "ref":
447 elif cmdName == "tableofcontents":
449 elif cmdName == "printnomenclature":
450 insetName = "nomencl_print"
451 elif cmdName == "printindex":
452 insetName = "index_print"
455 insertion = ["\\begin_inset CommandInset " + insetName, "LatexCommand " + cmdName]
456 document.body[i : i+1] = insertion
459 def revert_inset_command(document):
462 \begin_inset CommandInset InsetType
465 \begin_inset LatexCommand cmd
466 Some insets may end up being converted to insets earlier versions of LyX
467 will not be able to recognize. Not sure what to do about that.
471 i = find_token(document.body, "\\begin_inset CommandInset", i)
474 nextline = document.body[i+1]
475 r = re.compile(r'LatexCommand\s+(.*)$')
476 m = r.match(nextline)
478 document.warning("Malformed LyX document: Missing LatexCommand in " + document.body[i] + ".")
481 insertion = ["\\begin_inset LatexCommand " + cmdName]
482 document.body[i : i+2] = insertion
485 def convert_wrapfig_options(document):
486 "Convert optional options for wrap floats (wrapfig)."
487 # adds the tokens "lines", "placement", and "overhang"
490 i = find_token(document.body, "\\begin_inset Wrap figure", i)
493 document.body.insert(i + 1, "lines 0")
494 j = find_token(document.body, "placement", i)
495 # placement can be already set or not; if not, set it
497 document.body.insert(i + 3, "overhang 0col%")
499 document.body.insert(i + 2, "placement o")
500 document.body.insert(i + 3, "overhang 0col%")
504 def revert_wrapfig_options(document):
505 "Revert optional options for wrap floats (wrapfig)."
508 i = find_token(document.body, "lines", i)
511 j = find_token(document.body, "overhang", i+1)
512 if j != i + 2 and j != -1:
513 document.warning("Malformed LyX document: Couldn't find overhang parameter of wrap float.")
517 del document.body[j-1]
521 def convert_latexcommand_index(document):
522 "Convert from LatexCommand form to collapsable form."
525 i = find_token(document.body, "\\begin_inset CommandInset index", i)
528 if document.body[i + 1] != "LatexCommand index": # Might also be index_print
530 fullcontent = document.body[i + 2][6:].strip('"')
531 document.body[i:i + 2] = ["\\begin_inset Index",
533 "\\begin_layout Standard"]
534 # Put here the conversions needed from LaTeX string to LyXText.
535 # Here we do a minimal conversion to prevent crashes and data loss.
536 # Manual patch-up may be needed.
537 # Umlauted characters (most common ones, can be extended):
538 fullcontent = fullcontent.replace(r'\\\"a', u'ä').replace(r'\\\"o', u'ö').replace(r'\\\"u', u'ü')
540 fullcontent = wrap_into_ert(fullcontent, r'\"', '"')
541 #fullcontent = fullcontent.replace(r'\"', '\n\\begin_inset ERT\nstatus collapsed\n\\begin_layout standard\n"\n\\end_layout\n\\end_inset\n')
543 r = re.compile('^(.*?)(\$.*?\$)(.*)')
548 f = m.group(2).replace('\\\\', '\\')
552 s = wrap_into_ert(s, r'\\', '\\backslash')
553 s = wrap_into_ert(s, '{', '{')
554 s = wrap_into_ert(s, '}', '}')
555 document.body.insert(i + 3, s)
557 document.body.insert(i + 3, "\\begin_inset Formula " + f)
558 document.body.insert(i + 4, "\\end_inset")
560 # Generic, \\ -> \backslash:
561 g = wrap_into_ert(g, r'\\', '\\backslash{}')
562 g = wrap_into_ert(g, '{', '{')
563 g = wrap_into_ert(g, '}', '}')
564 document.body.insert(i + 3, g)
565 document.body[i + 4] = "\\end_layout"
569 def revert_latexcommand_index(document):
570 "Revert from collapsable form to LatexCommand form."
573 i = find_token(document.body, "\\begin_inset Index", i)
576 j = find_end_of_inset(document.body, i + 1)
579 del document.body[j - 1]
580 del document.body[j - 2] # \end_layout
581 document.body[i] = "\\begin_inset CommandInset index"
582 document.body[i + 1] = "LatexCommand index"
583 # clean up multiline stuff
585 for k in range(i + 3, j - 2):
586 line = document.body[k]
587 if line.startswith("\\begin_inset ERT"):
589 if line.startswith("\\begin_inset Formula"):
591 if line.startswith("\\begin_layout Standard"):
593 if line.startswith("\\end_layout"):
595 if line.startswith("\\end_inset"):
597 if line.startswith("status collapsed"):
599 line = line.replace(u'ä', r'\\\"a').replace(u'ö', r'\\\"o').replace(u'ü', r'\\\"u')
600 content = content + line;
601 document.body[i + 3] = "name " + '"' + content + '"'
602 for k in range(i + 4, j - 2):
603 del document.body[i + 4]
604 document.body.insert(i + 4, "")
605 del document.body[i + 2] # \begin_layout standard
609 def revert_wraptable(document):
610 "Revert wrap table to wrap figure."
613 i = find_token(document.body, "\\begin_inset Wrap table", i)
616 document.body[i] = document.body[i].replace('\\begin_inset Wrap table', '\\begin_inset Wrap figure')
620 def revert_vietnamese(document):
621 "Set language Vietnamese to English"
622 # Set document language from Vietnamese to English
624 if document.language == "vietnamese":
625 document.language = "english"
626 i = find_token(document.header, "\\language", 0)
628 document.header[i] = "\\language english"
631 j = find_token(document.body, "\\lang vietnamese", j)
634 document.body[j] = document.body[j].replace("\\lang vietnamese", "\\lang english")
638 def revert_japanese(document):
639 "Set language japanese-plain to japanese"
640 # Set document language from japanese-plain to japanese
642 if document.language == "japanese-plain":
643 document.language = "japanese"
644 i = find_token(document.header, "\\language", 0)
646 document.header[i] = "\\language japanese"
649 j = find_token(document.body, "\\lang japanese-plain", j)
652 document.body[j] = document.body[j].replace("\\lang japanese-plain", "\\lang japanese")
656 def revert_japanese_encoding(document):
657 "Set input encoding form EUC-JP-plain to EUC-JP etc."
658 # Set input encoding form EUC-JP-plain to EUC-JP etc.
660 i = find_token(document.header, "\\inputencoding EUC-JP-plain", 0)
662 document.header[i] = "\\inputencoding EUC-JP"
664 j = find_token(document.header, "\\inputencoding JIS-plain", 0)
666 document.header[j] = "\\inputencoding JIS"
668 k = find_token(document.header, "\\inputencoding SJIS-plain", 0)
669 if k != -1: # convert to UTF8 since there is currently no SJIS encoding
670 document.header[k] = "\\inputencoding UTF8"
673 def revert_inset_info(document):
674 'Replace info inset with its content'
677 i = find_token(document.body, '\\begin_inset Info', i)
680 j = find_end_of_inset(document.body, i + 1)
683 document.warning("Malformed LyX document: Could not find end of Info inset.")
686 for k in range(i, j+1):
687 if document.body[k].startswith("arg"):
688 arg = document.body[k][3:].strip().strip('"')
689 if document.body[k].startswith("type"):
690 type = document.body[k][4:].strip().strip('"')
691 # I think there is a newline after \\end_inset, which should be removed.
692 if document.body[j + 1].strip() == "":
693 document.body[i : (j + 2)] = [type + ':' + arg]
695 document.body[i : (j + 1)] = [type + ':' + arg]
698 def convert_pdf_options(document):
699 # Set the pdfusetitle tag, delete the pdf_store_options,
700 # set quotes for bookmarksopenlevel"
701 has_hr = get_value(document.header, "\\use_hyperref", 0, default = "0")
703 k = find_token(document.header, "\\use_hyperref", 0)
704 document.header.insert(k + 1, "\\pdf_pdfusetitle true")
705 k = find_token(document.header, "\\pdf_store_options", 0)
707 del document.header[k]
708 i = find_token(document.header, "\\pdf_bookmarksopenlevel", k)
710 document.header[i] = document.header[i].replace('"', '')
713 def revert_pdf_options_2(document):
714 # reset the pdfusetitle tag, set quotes for bookmarksopenlevel"
715 k = find_token(document.header, "\\use_hyperref", 0)
716 i = find_token(document.header, "\\pdf_pdfusetitle", k)
718 del document.header[i]
719 i = find_token(document.header, "\\pdf_bookmarksopenlevel", k)
721 values = document.header[i].split()
722 values[1] = ' "' + values[1] + '"'
723 document.header[i] = ''.join(values)
726 def convert_htmlurl(document):
727 'Convert "htmlurl" to "href" insets for docbook'
728 if document.backend != "docbook":
732 i = find_token(document.body, "\\begin_inset CommandInset url", i)
735 document.body[i] = "\\begin_inset CommandInset href"
736 document.body[i + 1] = "LatexCommand href"
740 def convert_url(document):
741 'Convert url insets to url charstyles'
742 if document.backend == "docbook":
746 i = find_token(document.body, "\\begin_inset CommandInset url", i)
749 n = find_token(document.body, "name", i)
751 # place the URL name in typewriter before the new URL insert
752 # grab the name 'bla' from the e.g. the line 'name "bla"',
753 # therefore start with the 6th character
754 name = document.body[n][6:-1]
755 newname = [name + " "]
756 document.body[i:i] = newname
758 j = find_token(document.body, "target", i)
760 document.warning("Malformed LyX document: Can't find target for url inset")
763 target = document.body[j][8:-1]
764 k = find_token(document.body, "\\end_inset", j)
766 document.warning("Malformed LyX document: Can't find end of url inset")
769 newstuff = ["\\begin_inset Flex URL",
770 "status collapsed", "",
771 "\\begin_layout Standard",
776 document.body[i:k] = newstuff
779 def convert_ams_classes(document):
780 tc = document.textclass
781 if (tc != "amsart" and tc != "amsart-plain" and
782 tc != "amsart-seq" and tc != "amsbook"):
784 if tc == "amsart-plain":
785 document.textclass = "amsart"
786 document.set_textclass()
787 document.add_module("Theorems (Starred)")
789 if tc == "amsart-seq":
790 document.textclass = "amsart"
791 document.set_textclass()
792 document.add_module("Theorems (AMS)")
794 #Now we want to see if any of the environments in the extended theorems
795 #module were used in this document. If so, we'll add that module, too.
796 layouts = ["Criterion", "Algorithm", "Axiom", "Condition", "Note", \
797 "Notation", "Summary", "Acknowledgement", "Conclusion", "Fact", \
800 r = re.compile(r'^\\begin_layout (.*?)\*?\s*$')
803 i = find_token(document.body, "\\begin_layout", i)
806 m = r.match(document.body[i])
808 document.warning("Weirdly formed \\begin_layout at line " + i + " of body!")
812 if layouts.count(m) != 0:
813 document.add_module("Theorems (AMS-Extended)")
817 def revert_href(document):
818 'Reverts hyperlink insets (href) to url insets (url)'
821 i = find_token(document.body, "\\begin_inset CommandInset href", i)
824 document.body[i : i + 2] = \
825 ["\\begin_inset CommandInset url", "LatexCommand url"]
829 def convert_include(document):
830 'Converts include insets to new format.'
832 r = re.compile(r'\\begin_inset Include\s+\\([^{]+){([^}]*)}(?:\[(.*)\])?')
834 i = find_token(document.body, "\\begin_inset Include", i)
837 line = document.body[i]
838 previewline = document.body[i + 1]
841 document.warning("Unable to match line " + str(i) + " of body!")
847 insertion = ["\\begin_inset CommandInset include",
848 "LatexCommand " + cmd, previewline,
849 "filename \"" + fn + "\""]
852 insertion.append("lstparams " + '"' + opt + '"')
854 document.body[i : i + 2] = insertion
858 def revert_include(document):
859 'Reverts include insets to old format.'
861 r1 = re.compile('LatexCommand (.+)')
862 r2 = re.compile('filename (.+)')
863 r3 = re.compile('options (.*)')
865 i = find_token(document.body, "\\begin_inset CommandInset include", i)
868 previewline = document.body[i + 1]
869 m = r1.match(document.body[i + 2])
871 document.warning("Malformed LyX document: No LatexCommand line for `" +
872 document.body[i] + "' on line " + str(i) + ".")
876 m = r2.match(document.body[i + 3])
878 document.warning("Malformed LyX document: No filename line for `" + \
879 document.body[i] + "' on line " + str(i) + ".")
885 if (cmd == "lstinputlisting"):
886 m = r3.match(document.body[i + 4])
890 newline = "\\begin_inset Include \\" + cmd + "{" + fn + "}"
892 newline += ("[" + options + "]")
893 insertion = [newline, previewline]
894 document.body[i : i + numlines] = insertion
898 def revert_albanian(document):
899 "Set language Albanian to English"
901 if document.language == "albanian":
902 document.language = "english"
903 i = find_token(document.header, "\\language", 0)
905 document.header[i] = "\\language english"
908 j = find_token(document.body, "\\lang albanian", j)
911 document.body[j] = document.body[j].replace("\\lang albanian", "\\lang english")
915 def revert_lowersorbian(document):
916 "Set language lower Sorbian to English"
918 if document.language == "lowersorbian":
919 document.language = "english"
920 i = find_token(document.header, "\\language", 0)
922 document.header[i] = "\\language english"
925 j = find_token(document.body, "\\lang lowersorbian", j)
928 document.body[j] = document.body[j].replace("\\lang lowersorbian", "\\lang english")
932 def revert_uppersorbian(document):
933 "Set language uppersorbian to usorbian as this was used in LyX 1.5"
935 if document.language == "uppersorbian":
936 document.language = "usorbian"
937 i = find_token(document.header, "\\language", 0)
939 document.header[i] = "\\language usorbian"
942 j = find_token(document.body, "\\lang uppersorbian", j)
945 document.body[j] = document.body[j].replace("\\lang uppersorbian", "\\lang usorbian")
949 def convert_usorbian(document):
950 "Set language usorbian to uppersorbian"
952 if document.language == "usorbian":
953 document.language = "uppersorbian"
954 i = find_token(document.header, "\\language", 0)
956 document.header[i] = "\\language uppersorbian"
959 j = find_token(document.body, "\\lang usorbian", j)
962 document.body[j] = document.body[j].replace("\\lang usorbian", "\\lang uppersorbian")
966 def revert_macro_optional_params(document):
967 "Convert macro definitions with optional parameters into ERTs"
968 # Stub to convert macro definitions with one or more optional parameters
969 # into uninterpreted ERT insets
972 def revert_hyperlinktype(document):
973 'Reverts hyperlink type'
977 i = find_token(document.body, "target", i)
980 j = find_token(document.body, "type", i)
988 def revert_pagebreak(document):
989 'Reverts pagebreak to ERT'
992 i = find_token(document.body, "\\pagebreak", i)
995 document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
996 '\\begin_layout Standard\n\n\n\\backslash\n' \
997 'pagebreak{}\n\\end_layout\n\n\\end_inset\n\n'
1001 def revert_linebreak(document):
1002 'Reverts linebreak to ERT'
1005 i = find_token(document.body, "\\linebreak", i)
1008 document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1009 '\\begin_layout Standard\n\n\n\\backslash\n' \
1010 'linebreak{}\n\\end_layout\n\n\\end_inset\n\n'
1014 def revert_latin(document):
1015 "Set language Latin to English"
1017 if document.language == "latin":
1018 document.language = "english"
1019 i = find_token(document.header, "\\language", 0)
1021 document.header[i] = "\\language english"
1024 j = find_token(document.body, "\\lang latin", j)
1027 document.body[j] = document.body[j].replace("\\lang latin", "\\lang english")
1031 def revert_samin(document):
1032 "Set language North Sami to English"
1034 if document.language == "samin":
1035 document.language = "english"
1036 i = find_token(document.header, "\\language", 0)
1038 document.header[i] = "\\language english"
1041 j = find_token(document.body, "\\lang samin", j)
1044 document.body[j] = document.body[j].replace("\\lang samin", "\\lang english")
1048 def convert_serbocroatian(document):
1049 "Set language Serbocroatian to Croatian as this was really Croatian in LyX 1.5"
1051 if document.language == "serbocroatian":
1052 document.language = "croatian"
1053 i = find_token(document.header, "\\language", 0)
1055 document.header[i] = "\\language croatian"
1058 j = find_token(document.body, "\\lang serbocroatian", j)
1061 document.body[j] = document.body[j].replace("\\lang serbocroatian", "\\lang croatian")
1065 def convert_framed_notes(document):
1066 "Convert framed notes to boxes. "
1069 i = find_tokens(document.body, ["\\begin_inset Note Framed", "\\begin_inset Note Shaded"], i)
1073 document.body[i] = document.body[i].replace("\\begin_inset Note", "\\begin_inset Box")
1074 document.body.insert(i + 1, 'position "t"\nhor_pos "c"\nhas_inner_box 0\ninner_pos "t"\n' \
1075 'use_parbox 0\nwidth "100col%"\nspecial "none"\nheight "1in"\n' \
1076 'height_special "totalheight"')
1080 def convert_module_names(document):
1081 modulemap = { 'Braille' : 'braille', 'Endnote' : 'endnotes', 'Foot to End' : 'foottoend',\
1082 'Hanging' : 'hanging', 'Linguistics' : 'linguistics', 'Logical Markup' : 'logicalmkup', \
1083 'Theorems (AMS-Extended)' : 'theorems-ams-extended', 'Theorems (AMS)' : 'theorems-ams', \
1084 'Theorems (Order By Chapter)' : 'theorems-chap', 'Theorems (Order By Section)' : 'theorems-sec', \
1085 'Theorems (Starred)' : 'theorems-starred', 'Theorems' : 'theorems-std' }
1086 modlist = document.get_module_list()
1087 if len(modlist) == 0:
1091 if modulemap.has_key(mod):
1092 newmodlist.append(modulemap[mod])
1094 document.warning("Can't find module %s in the module map!" % mod)
1095 newmodlist.append(mod)
1096 document.set_module_list(newmodlist)
1099 def revert_module_names(document):
1100 modulemap = { 'braille' : 'Braille', 'endnotes' : 'Endnote', 'foottoend' : 'Foot to End',\
1101 'hanging' : 'Hanging', 'linguistics' : 'Linguistics', 'logicalmkup' : 'Logical Markup', \
1102 'theorems-ams-extended' : 'Theorems (AMS-Extended)', 'theorems-ams' : 'Theorems (AMS)', \
1103 'theorems-chap' : 'Theorems (Order By Chapter)', 'theorems-sec' : 'Theorems (Order By Section)', \
1104 'theorems-starred' : 'Theorems (Starred)', 'theorems-std' : 'Theorems'}
1105 modlist = document.get_module_list()
1106 if len(modlist) == 0:
1110 if modulemap.has_key(mod):
1111 newmodlist.append(modulemap[mod])
1113 document.warning("Can't find module %s in the module map!" % mod)
1114 newmodlist.append(mod)
1115 document.set_module_list(newmodlist)
1118 def revert_colsep(document):
1119 i = find_token(document.header, "\\columnsep", 0)
1122 colsepline = document.header[i]
1123 r = re.compile(r'\\columnsep (.*)')
1124 m = r.match(colsepline)
1126 document.warning("Malformed column separation line!")
1129 del document.header[i]
1130 #it seems to be safe to add the package even if it is already used
1131 pretext = ["\\usepackage{geometry}", "\\geometry{columnsep=" + colsep + "}"]
1133 add_to_preamble(document, pretext)
1136 def revert_framed_notes(document):
1137 "Revert framed boxes to notes. "
1140 i = find_tokens(document.body, ["\\begin_inset Box Framed", "\\begin_inset Box Shaded"], i)
1144 j = find_end_of_inset(document.body, i + 1)
1147 document.warning("Malformed LyX document: Could not find end of Box inset.")
1148 k = find_token(document.body, "status", i + 1, j)
1150 document.warning("Malformed LyX document: Missing `status' tag in Box inset.")
1152 status = document.body[k]
1153 l = find_token(document.body, "\\begin_layout Standard", i + 1, j)
1155 document.warning("Malformed LyX document: Missing `\\begin_layout Standard' in Box inset.")
1157 m = find_token(document.body, "\\end_layout", i + 1, j)
1159 document.warning("Malformed LyX document: Missing `\\end_layout' in Box inset.")
1161 ibox = find_token(document.body, "has_inner_box 1", i + 1, k)
1162 pbox = find_token(document.body, "use_parbox 1", i + 1, k)
1163 if ibox == -1 and pbox == -1:
1164 document.body[i] = document.body[i].replace("\\begin_inset Box", "\\begin_inset Note")
1165 del document.body[i+1:k]
1167 document.body[i] = document.body[i].replace("\\begin_inset Box Shaded", "\\begin_inset Box Frameless")
1168 document.body.insert(l + 1, "\\begin_inset Note Shaded\n" + status + "\n\\begin_layout Standard\n")
1169 document.body.insert(m + 1, "\\end_layout\n\\end_inset")
1173 def revert_slash(document):
1174 'Revert \\SpecialChar \\slash{} to ERT'
1175 for i in range(len(document.body)):
1176 document.body[i] = document.body[i].replace('\\SpecialChar \\slash{}', \
1177 '\\begin_inset ERT\nstatus collapsed\n\n' \
1178 '\\begin_layout Standard\n\n\n\\backslash\n' \
1179 'slash{}\n\\end_layout\n\n\\end_inset\n\n')
1182 def revert_nobreakdash(document):
1183 'Revert \\SpecialChar \\nobreakdash- to ERT'
1185 for i in range(len(document.body)):
1186 line = document.body[i]
1187 r = re.compile(r'\\SpecialChar \\nobreakdash-')
1191 document.body[i] = document.body[i].replace('\\SpecialChar \\nobreakdash-', \
1192 '\\begin_inset ERT\nstatus collapsed\n\n' \
1193 '\\begin_layout Standard\n\n\n\\backslash\n' \
1194 'nobreakdash-\n\\end_layout\n\n\\end_inset\n\n')
1197 j = find_token(document.header, "\\use_amsmath", 0)
1199 document.warning("Malformed LyX document: Missing '\\use_amsmath'.")
1201 document.header[j] = "\\use_amsmath 2"
1204 def revert_nocite_key(body, start, end):
1205 'key "..." -> \nocite{...}'
1206 for i in range(start, end):
1207 if (body[i][0:5] == 'key "'):
1208 body[i] = body[i].replace('key "', "\\backslash\nnocite{")
1209 body[i] = body[i].replace('"', "}")
1214 def revert_nocite(document):
1215 "Revert LatexCommand nocite to ERT"
1218 i = find_token(document.body, "\\begin_inset CommandInset citation", i)
1222 if (document.body[i] == "LatexCommand nocite"):
1223 j = find_end_of_inset(document.body, i + 1)
1225 #this should not happen
1226 document.warning("End of CommandInset citation not found in revert_nocite!")
1227 revert_nocite_key(document.body, i + 1, len(document.body))
1229 revert_nocite_key(document.body, i + 1, j)
1230 document.body[i-1] = "\\begin_inset ERT"
1231 document.body[i] = "status collapsed\n\n" \
1232 "\\begin_layout Standard"
1233 document.body.insert(j, "\\end_layout\n");
1237 def revert_btprintall(document):
1238 "Revert (non-bibtopic) btPrintAll option to ERT \nocite{*}"
1239 i = find_token(document.header, '\\use_bibtopic', 0)
1241 document.warning("Malformed lyx document: Missing '\\use_bibtopic'.")
1243 if get_value(document.header, '\\use_bibtopic', 0) == "false":
1245 while i < len(document.body):
1246 i = find_token(document.body, "\\begin_inset CommandInset bibtex", i)
1249 j = find_end_of_inset(document.body, i + 1)
1251 #this should not happen
1252 document.warning("End of CommandInset bibtex not found in revert_btprintall!")
1253 j = len(document.body)
1254 for k in range(i, j):
1255 if (document.body[k] == 'btprint "btPrintAll"'):
1256 del document.body[k]
1257 document.body.insert(i, "\\begin_inset ERT\n" \
1258 "status collapsed\n\n\\begin_layout Standard\n\n" \
1259 "\\backslash\nnocite{*}\n" \
1260 "\\end_layout\n\\end_inset\n")
1264 def revert_bahasam(document):
1265 "Set language Bahasa Malaysia to Bahasa Indonesia"
1267 if document.language == "bahasam":
1268 document.language = "bahasa"
1269 i = find_token(document.header, "\\language", 0)
1271 document.header[i] = "\\language bahasa"
1274 j = find_token(document.body, "\\lang bahasam", j)
1277 document.body[j] = document.body[j].replace("\\lang bahasam", "\\lang bahasa")
1281 def revert_interlingua(document):
1282 "Set language Interlingua to English"
1284 if document.language == "interlingua":
1285 document.language = "english"
1286 i = find_token(document.header, "\\language", 0)
1288 document.header[i] = "\\language english"
1291 j = find_token(document.body, "\\lang interlingua", j)
1294 document.body[j] = document.body[j].replace("\\lang interlingua", "\\lang english")
1298 def revert_serbianlatin(document):
1299 "Set language Serbian-Latin to Croatian"
1301 if document.language == "serbian-latin":
1302 document.language = "croatian"
1303 i = find_token(document.header, "\\language", 0)
1305 document.header[i] = "\\language croatian"
1308 j = find_token(document.body, "\\lang serbian-latin", j)
1311 document.body[j] = document.body[j].replace("\\lang serbian-latin", "\\lang croatian")
1315 def revert_rotfloat(document):
1316 " Revert sideways custom floats. "
1319 i = find_token(document.body, "\\begin_inset Float", i)
1322 line = document.body[i]
1323 r = re.compile(r'\\begin_inset Float (.*)$')
1325 floattype = m.group(1)
1326 if floattype == "figure" or floattype == "table":
1329 j = find_end_of_inset(document.body, i)
1331 document.warning("Malformed lyx document: Missing '\\end_inset'.")
1334 if get_value(document.body, 'sideways', i, j) != "false":
1335 l = find_token(document.body, "\\begin_layout Standard", i + 1, j)
1337 document.warning("Malformed LyX document: Missing `\\begin_layout Standard' in Float inset.")
1339 document.body[j] = '\\begin_layout Standard\n\\begin_inset ERT\nstatus collapsed\n\n' \
1340 '\\begin_layout Standard\n\n\n\\backslash\n' \
1341 'end{sideways' + floattype + '}\n\\end_layout\n\n\\end_inset\n'
1342 del document.body[i+1:l-1]
1343 document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1344 '\\begin_layout Standard\n\n\n\\backslash\n' \
1345 'begin{sideways' + floattype + '}\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n\n'
1346 if floattype == "algorithm":
1347 add_to_preamble(document,
1348 ['% Commands inserted by lyx2lyx for sideways algorithm float',
1349 '\\usepackage{rotfloat}\n'
1350 '\\floatstyle{ruled}\n'
1351 '\\newfloat{algorithm}{tbp}{loa}\n'
1352 '\\floatname{algorithm}{Algorithm}\n'])
1354 document.warning("Cannot create preamble definition for custom float" + floattype + ".")
1360 def revert_widesideways(document):
1361 " Revert wide sideways floats. "
1364 i = find_token(document.body, '\\begin_inset Float', i)
1367 line = document.body[i]
1368 r = re.compile(r'\\begin_inset Float (.*)$')
1370 floattype = m.group(1)
1371 if floattype != "figure" and floattype != "table":
1374 j = find_end_of_inset(document.body, i)
1376 document.warning("Malformed lyx document: Missing '\\end_inset'.")
1379 if get_value(document.body, 'sideways', i, j) != "false":
1380 if get_value(document.body, 'wide', i, j) != "false":
1381 l = find_token(document.body, "\\begin_layout Standard", i + 1, j)
1383 document.warning("Malformed LyX document: Missing `\\begin_layout Standard' in Float inset.")
1385 document.body[j] = '\\begin_layout Standard\n\\begin_inset ERT\nstatus collapsed\n\n' \
1386 '\\begin_layout Standard\n\n\n\\backslash\n' \
1387 'end{sideways' + floattype + '*}\n\\end_layout\n\n\\end_inset\n'
1388 del document.body[i+1:l-1]
1389 document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1390 '\\begin_layout Standard\n\n\n\\backslash\n' \
1391 'begin{sideways' + floattype + '*}\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n\n'
1392 add_to_preamble(document,
1393 ['\\usepackage{rotfloat}\n'])
1399 def convert_subfig(document):
1400 " Convert subfigures to subfloats. "
1403 i = find_token(document.body, '\\begin_inset Graphics', i)
1406 j = find_end_of_inset(document.body, i)
1408 document.warning("Malformed lyx document: Missing '\\end_inset'.")
1411 k = find_token(document.body, '\tsubcaption', i, j)
1415 l = find_token(document.body, '\tsubcaptionText', i, j)
1416 caption = document.body[l][16:].strip('"')
1417 savestr = document.body[i]
1418 del document.body[l]
1419 del document.body[k]
1420 document.body[i] = '\\begin_inset Float figure\nwide false\nsideways false\n' \
1421 'status open\n\n\\begin_layout PlainLayout\n\\begin_inset Caption\n\n\\begin_layout PlainLayout\n' \
1422 + caption + '\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n\n\\begin_layout PlainLayout\n' + savestr
1423 savestr = document.body[j]
1424 document.body[j] = '\n\\end_layout\n\n\\end_inset\n' + savestr
1427 def revert_subfig(document):
1428 " Revert subfloats. "
1431 i = find_token(document.body, '\\begin_inset Float', i)
1435 j = find_end_of_inset(document.body, i)
1437 document.warning("Malformed lyx document: Missing '\\end_inset' (float).")
1440 # look for embedded float (= subfloat)
1441 k = find_token(document.body, '\\begin_inset Float', i + 1, j)
1444 l = find_end_of_inset(document.body, k)
1446 document.warning("Malformed lyx document: Missing '\\end_inset' (embedded float).")
1449 m = find_token(document.body, "\\begin_layout PlainLayout", k + 1, l)
1451 cap = find_token(document.body, '\\begin_inset Caption', k + 1, l)
1455 capend = find_end_of_inset(document.body, cap)
1457 document.warning("Malformed lyx document: Missing '\\end_inset' (caption).")
1461 lbl = find_token(document.body, '\\begin_inset CommandInset label', cap, capend)
1463 lblend = find_end_of_inset(document.body, lbl + 1)
1465 document.warning("Malformed lyx document: Missing '\\end_inset' (label).")
1467 for line in document.body[lbl:lblend + 1]:
1468 if line.startswith('name '):
1469 label = line.split()[1].strip('"')
1476 opt = find_token(document.body, '\\begin_inset OptArg', cap, capend)
1478 optend = find_end_of_inset(document.body, opt)
1480 document.warning("Malformed lyx document: Missing '\\end_inset' (OptArg).")
1482 optc = find_token(document.body, "\\begin_layout PlainLayout", opt, optend)
1484 document.warning("Malformed LyX document: Missing `\\begin_layout PlainLayout' in Float inset.")
1486 optcend = find_end_of(document.body, optc, "\\begin_layout", "\\end_layout")
1487 for line in document.body[optc:optcend]:
1488 if not line.startswith('\\'):
1489 shortcap += line.strip()
1493 for line in document.body[cap:capend]:
1494 if line in document.body[lbl:lblend]:
1496 elif line in document.body[opt:optend]:
1498 elif not line.startswith('\\'):
1499 caption += line.strip()
1501 caption += "\\backslash\nlabel{" + label + "}"
1502 document.body[l] = '\\begin_layout PlainLayout\n\\begin_inset ERT\nstatus collapsed\n\n' \
1503 '\\begin_layout PlainLayout\n\n}\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n\n\\begin_layout PlainLayout\n'
1504 del document.body[cap:capend+1]
1505 del document.body[k+1:m-1]
1506 insertion = '\\begin_inset ERT\nstatus collapsed\n\n' \
1507 '\\begin_layout PlainLayout\n\n\\backslash\n' \
1509 if len(shortcap) > 0:
1510 insertion = insertion + "[" + shortcap + "]"
1511 if len(caption) > 0:
1512 insertion = insertion + "[" + caption + "]"
1513 insertion = insertion + '{%\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n'
1514 document.body[k] = insertion
1515 add_to_preamble(document,
1516 ['\\usepackage{subfig}\n'])
1520 def revert_wrapplacement(document):
1521 " Revert placement options wrap floats (wrapfig). "
1524 i = find_token(document.body, "lines", i)
1527 j = find_token(document.body, "placement", i+1)
1529 document.warning("Malformed LyX document: Couldn't find placement parameter of wrap float.")
1531 document.body[j] = document.body[j].replace("placement O", "placement o")
1532 document.body[j] = document.body[j].replace("placement I", "placement i")
1533 document.body[j] = document.body[j].replace("placement L", "placement l")
1534 document.body[j] = document.body[j].replace("placement R", "placement r")
1538 def remove_extra_embedded_files(document):
1539 " Remove \extra_embedded_files from buffer params "
1540 i = find_token(document.header, '\\extra_embedded_files', 0)
1542 document.warning("Malformed lyx document: Missing '\\extra_embedded_files'.")
1544 document.header.pop(i)
1547 def convert_spaceinset(document):
1548 " Convert '\\InsetSpace foo' to '\\begin_inset Space foo\n\\end_inset' "
1549 for i in range(len(document.body)):
1550 if re.search(r'\InsetSpace', document.body[i]):
1551 document.body[i] = document.body[i].replace('\\InsetSpace', '\n\\begin_inset Space')
1552 document.body[i] = document.body[i] + "\n\\end_inset"
1555 def revert_spaceinset(document):
1556 " Revert '\\begin_inset Space foo\n\\end_inset' to '\\InsetSpace foo' "
1559 i = find_token(document.body, "\\begin_inset Space", i)
1562 j = find_end_of_inset(document.body, i)
1564 document.warning("Malformed LyX document: Could not find end of space inset.")
1566 document.body[i] = document.body[i].replace('\\begin_inset Space', '\\InsetSpace')
1567 del document.body[j]
1570 def convert_hfill(document):
1571 " Convert hfill to space inset "
1574 i = find_token(document.body, "\\hfill", i)
1577 document.body[i] = document.body[i].replace('\\hfill', '\n\\begin_inset Space \\hfill{}\n\\end_inset')
1580 def revert_hfills(document):
1581 ' Revert \\hfill commands '
1582 for i in range(len(document.body)):
1583 document.body[i] = document.body[i].replace('\\InsetSpace \\hfill{}', '\\hfill')
1584 document.body[i] = document.body[i].replace('\\InsetSpace \\dotfill{}', \
1585 '\\begin_inset ERT\nstatus collapsed\n\n' \
1586 '\\begin_layout Standard\n\n\n\\backslash\n' \
1587 'dotfill{}\n\\end_layout\n\n\\end_inset\n\n')
1588 document.body[i] = document.body[i].replace('\\InsetSpace \\hrulefill{}', \
1589 '\\begin_inset ERT\nstatus collapsed\n\n' \
1590 '\\begin_layout Standard\n\n\n\\backslash\n' \
1591 'hrulefill{}\n\\end_layout\n\n\\end_inset\n\n')
1594 def revert_hspace(document):
1595 ' Revert \\InsetSpace \\hspace{} to ERT '
1598 i = find_token(document.body, "\\InsetSpace \\hspace", i)
1601 length = get_value(document.body, '\\length', i+1)
1603 document.warning("Malformed lyx document: Missing '\\length' in Space inset.")
1605 del document.body[i+1]
1606 document.body[i] = document.body[i].replace('\\InsetSpace \\hspace*{}', \
1607 '\\begin_inset ERT\nstatus collapsed\n\n' \
1608 '\\begin_layout Standard\n\n\n\\backslash\n' \
1609 'hspace*{' + length + '}\n\\end_layout\n\n\\end_inset\n\n')
1610 document.body[i] = document.body[i].replace('\\InsetSpace \\hspace{}', \
1611 '\\begin_inset ERT\nstatus collapsed\n\n' \
1612 '\\begin_layout Standard\n\n\n\\backslash\n' \
1613 'hspace{' + length + '}\n\\end_layout\n\n\\end_inset\n\n')
1616 def revert_protected_hfill(document):
1617 ' Revert \\begin_inset Space \\hspace*{\\fill} to ERT '
1620 i = find_token(document.body, '\\begin_inset Space \\hspace*{\\fill}', i)
1623 j = find_end_of_inset(document.body, i)
1625 document.warning("Malformed LyX document: Could not find end of space inset.")
1627 del document.body[j]
1628 document.body[i] = document.body[i].replace('\\begin_inset Space \\hspace*{\\fill}', \
1629 '\\begin_inset ERT\nstatus collapsed\n\n' \
1630 '\\begin_layout Standard\n\n\n\\backslash\n' \
1631 'hspace*{\n\\backslash\nfill}\n\\end_layout\n\n\\end_inset\n\n')
1638 supported_versions = ["1.6.0","1.6"]
1639 convert = [[277, [fix_wrong_tables]],
1640 [278, [close_begin_deeper]],
1641 [279, [long_charstyle_names]],
1642 [280, [axe_show_label]],
1645 [283, [convert_flex]],
1649 [287, [convert_wrapfig_options]],
1650 [288, [convert_inset_command]],
1651 [289, [convert_latexcommand_index]],
1656 [294, [convert_pdf_options]],
1657 [295, [convert_htmlurl, convert_url]],
1658 [296, [convert_include]],
1659 [297, [convert_usorbian]],
1665 [303, [convert_serbocroatian]],
1666 [304, [convert_framed_notes]],
1673 [311, [convert_ams_classes]],
1675 [313, [convert_module_names]],
1678 [316, [convert_subfig]],
1681 [319, [convert_spaceinset, convert_hfill]],
1683 [321, [convert_tablines]]
1686 revert = [[320, [revert_tablines]],
1687 [319, [revert_protected_hfill]],
1688 [318, [revert_spaceinset, revert_hfills, revert_hspace]],
1689 [317, [remove_extra_embedded_files]],
1690 [316, [revert_wrapplacement]],
1691 [315, [revert_subfig]],
1692 [314, [revert_colsep]],
1694 [312, [revert_module_names]],
1695 [311, [revert_rotfloat, revert_widesideways]],
1697 [309, [revert_btprintall]],
1698 [308, [revert_nocite]],
1699 [307, [revert_serbianlatin]],
1700 [306, [revert_slash, revert_nobreakdash]],
1701 [305, [revert_interlingua]],
1702 [304, [revert_bahasam]],
1703 [303, [revert_framed_notes]],
1705 [301, [revert_latin, revert_samin]],
1706 [300, [revert_linebreak]],
1707 [299, [revert_pagebreak]],
1708 [298, [revert_hyperlinktype]],
1709 [297, [revert_macro_optional_params]],
1710 [296, [revert_albanian, revert_lowersorbian, revert_uppersorbian]],
1711 [295, [revert_include]],
1712 [294, [revert_href]],
1713 [293, [revert_pdf_options_2]],
1714 [292, [revert_inset_info]],
1715 [291, [revert_japanese, revert_japanese_encoding]],
1716 [290, [revert_vietnamese]],
1717 [289, [revert_wraptable]],
1718 [288, [revert_latexcommand_index]],
1719 [287, [revert_inset_command]],
1720 [286, [revert_wrapfig_options]],
1721 [285, [revert_pdf_options]],
1722 [284, [remove_inzip_options]],
1724 [282, [revert_flex]],
1726 [280, [revert_begin_modules]],
1727 [279, [revert_show_label]],
1728 [278, [revert_long_charstyle_names]],
1734 if __name__ == "__main__":