1 # This file is part of lyx2lyx
2 # Copyright (C) 2011 The LyX team
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 """Convert files to the file format generated by lyx 2.0"""
22 from lyx2lyx_tools import (
34 from parser_tools import (
50 ####################################################################
51 # Private helper functions
54 def remove_option(lines, m, option):
55 """removes option from line m. returns whether we did anything"""
56 l = lines[m].find(option)
59 val = lines[m][l:].split('"')[1]
60 lines[m] = lines[m][: l - 1] + lines[m][l + len(option + '="' + val + '"') :]
64 ###############################################################################
66 ### Conversion and reversion routines
68 ###############################################################################
71 def revert_swiss(document):
72 "Set language german-ch to ngerman"
74 if document.language == "german-ch":
75 document.language = "ngerman"
76 i = find_token(document.header, "\\language", 0)
78 document.header[i] = "\\language ngerman"
81 j = find_token(document.body, "\\lang german-ch", j)
84 document.body[j] = document.body[j].replace("\\lang german-ch", "\\lang ngerman")
88 def revert_tabularvalign(document):
89 "Revert the tabular valign option"
92 i = find_token(document.body, "\\begin_inset Tabular", i)
95 end = find_end_of_inset(document.body, i)
97 document.warning("Can't find end of inset at line " + str(i))
100 fline = find_token(document.body, "<features", i, end)
102 document.warning("Can't find features for inset at line " + str(i))
105 p = document.body[fline].find("islongtable")
107 q = document.body[fline].find("tabularvalignment")
109 document.body[fline] = re.sub(
110 r" tabularvalignment=\"[a-z]+\"", "", document.body[fline]
116 tabularvalignment = "c"
117 # which valignment is specified?
118 m = document.body[fline].find('tabularvalignment="top"')
120 tabularvalignment = "t"
121 m = document.body[fline].find('tabularvalignment="bottom"')
123 tabularvalignment = "b"
124 # delete tabularvalignment
125 q = document.body[fline].find("tabularvalignment")
127 document.body[fline] = re.sub(
128 r" tabularvalignment=\"[a-z]+\"", "", document.body[fline]
131 # don't add a box when centered
132 if tabularvalignment == "c":
135 subst = ["\\end_inset", "\\end_layout"]
136 document.body[end:end] = subst # just inserts those lines
138 "\\begin_inset Box Frameless",
139 'position "' + tabularvalignment + '"',
144 # we don't know the width, assume 50%
148 'height_special "totalheight"',
151 "\\begin_layout Plain Layout",
153 document.body[i:i] = subst # this just inserts the array at i
154 # since there could be a tabular inside a tabular, we cannot
159 def revert_phantom_types(document, ptype, cmd):
160 "Reverts phantom to ERT"
163 i = find_token(document.body, "\\begin_inset Phantom " + ptype, i)
166 end = find_end_of_inset(document.body, i)
168 document.warning("Can't find end of inset at line " + str(i))
171 blay = find_token(document.body, "\\begin_layout Plain Layout", i, end)
173 document.warning("Can't find layout for inset at line " + str(i))
176 bend = find_end_of_layout(document.body, blay)
179 "Malformed LyX document: Could not find end of Phantom inset's layout."
187 "\\begin_layout Plain Layout",
202 "\\begin_layout Plain Layout",
209 # do the later one first so as not to mess up the numbering
210 document.body[bend : end + 1] = substj
211 document.body[i : blay + 1] = substi
212 i = end + len(substi) + len(substj) - (end - bend) - (blay - i) - 2
215 def revert_phantom(document):
216 revert_phantom_types(document, "Phantom", "phantom")
219 def revert_hphantom(document):
220 revert_phantom_types(document, "HPhantom", "hphantom")
223 def revert_vphantom(document):
224 revert_phantom_types(document, "VPhantom", "vphantom")
227 def revert_xetex(document):
228 "Reverts documents that use XeTeX"
230 i = find_token(document.header, "\\use_xetex", 0)
232 document.warning("Malformed LyX document: Missing \\use_xetex.")
234 if not str2bool(get_value(document.header, "\\use_xetex", i)):
235 del document.header[i]
237 del document.header[i]
239 # 1.) set doc encoding to utf8-plain
240 i = find_token(document.header, "\\inputencoding", 0)
242 document.warning("Malformed LyX document: Missing \\inputencoding.")
244 document.header[i] = "\\inputencoding utf8-plain"
246 # 2.) check font settings
248 roman = sans = typew = "default"
250 sf_scale = tt_scale = 100.0
252 i = find_token(document.header, "\\font_roman", 0)
254 document.warning("Malformed LyX document: Missing \\font_roman.")
256 roman = get_value(document.header, "\\font_roman", i)
257 document.header[i] = "\\font_roman default"
259 i = find_token(document.header, "\\font_sans", 0)
261 document.warning("Malformed LyX document: Missing \\font_sans.")
263 sans = get_value(document.header, "\\font_sans", i)
264 document.header[i] = "\\font_sans default"
266 i = find_token(document.header, "\\font_typewriter", 0)
268 document.warning("Malformed LyX document: Missing \\font_typewriter.")
270 typew = get_value(document.header, "\\font_typewriter", i)
271 document.header[i] = "\\font_typewriter default"
273 i = find_token(document.header, "\\font_osf", 0)
275 document.warning("Malformed LyX document: Missing \\font_osf.")
277 osf = str2bool(get_value(document.header, "\\font_osf", i))
278 document.header[i] = "\\font_osf false"
280 i = find_token(document.header, "\\font_sc", 0)
282 document.warning("Malformed LyX document: Missing \\font_sc.")
284 # we do not need this value.
285 document.header[i] = "\\font_sc false"
287 i = find_token(document.header, "\\font_sf_scale", 0)
289 document.warning("Malformed LyX document: Missing \\font_sf_scale.")
291 val = get_value(document.header, "\\font_sf_scale", i)
294 sf_scale = float(val)
296 document.warning("Invalid font_sf_scale value: " + val)
297 document.header[i] = "\\font_sf_scale 100"
299 i = find_token(document.header, "\\font_tt_scale", 0)
301 document.warning("Malformed LyX document: Missing \\font_tt_scale.")
303 val = get_value(document.header, "\\font_tt_scale", i)
306 tt_scale = float(val)
308 document.warning("Invalid font_tt_scale value: " + val)
309 document.header[i] = "\\font_tt_scale 100"
311 # 3.) set preamble stuff
312 pretext = ["%% This document must be processed with xelatex!"]
313 pretext.append("\\usepackage{fontspec}")
314 if roman != "default":
315 pretext.append("\\setmainfont[Mapping=tex-text]{" + roman + "}")
316 if sans != "default":
317 sf = "\\setsansfont["
318 if sf_scale != 100.0:
319 sf += "Scale=" + str(sf_scale / 100.0) + ","
320 sf += "Mapping=tex-text]{" + sans + "}"
322 if typew != "default":
324 if tt_scale != 100.0:
325 tw += "[Scale=" + str(tt_scale / 100.0) + "]"
326 tw += "{" + typew + "}"
329 pretext.append("\\defaultfontfeatures{Numbers=OldStyle}")
330 pretext.append("\\usepackage{xunicode}")
331 pretext.append("\\usepackage{xltxtra}")
332 insert_to_preamble(document, pretext)
335 def revert_outputformat(document):
336 "Remove default output format param"
338 if not del_token(document.header, "\\default_output_format", 0):
339 document.warning("Malformed LyX document: Missing \\default_output_format.")
342 def revert_backgroundcolor(document):
343 "Reverts background color to preamble code"
344 i = find_token(document.header, "\\backgroundcolor", 0)
347 colorcode = get_value(document.header, "\\backgroundcolor", i)
348 del document.header[i]
349 # don't clutter the preamble if backgroundcolor is not set
350 if colorcode == "#ffffff":
352 red = hex2ratio(colorcode[1:3])
353 green = hex2ratio(colorcode[3:5])
354 blue = hex2ratio(colorcode[5:7])
358 "% To set the background color",
359 "\\@ifundefined{definecolor}{\\usepackage{color}}{}",
360 "\\definecolor{page_backgroundcolor}{rgb}{" + red + "," + green + "," + blue + "}",
361 "\\pagecolor{page_backgroundcolor}",
366 def add_use_indices(document):
367 "Add \\use_indices if it is missing"
368 i = find_token(document.header, "\\use_indices", 0)
371 i = find_token(document.header, "\\use_bibtopic", 0)
373 i = find_token(document.header, "\\cite_engine", 0)
375 i = find_token(document.header, "\\use_mathdots", 0)
377 i = find_token(document.header, "\\use_mhchem", 0)
379 i = find_token(document.header, "\\use_esint", 0)
381 i = find_token(document.header, "\\use_amsmath", 0)
383 document.warning("Malformed LyX document: Missing \\use_indices.")
385 document.header.insert(i + 1, "\\use_indices 0")
389 def revert_splitindex(document):
390 "Reverts splitindex-aware documents"
391 i = add_use_indices(document)
394 useindices = str2bool(get_value(document.header, "\\use_indices", i))
395 del document.header[i]
398 preamble.append("\\usepackage{splitidx})")
400 # deal with index declarations in the preamble
403 i = find_token(document.header, "\\index", i)
406 k = find_token(document.header, "\\end_index", i)
408 document.warning("Malformed LyX document: Missing \\end_index.")
411 line = document.header[i]
412 l = re.compile(r"\\index (.*)$")
415 ishortcut = get_value(document.header, "\\shortcut", i, k)
417 preamble.append("\\newindex[" + iname + "]{" + ishortcut + "}")
418 del document.header[i : k + 1]
420 insert_to_preamble(document, preamble)
422 # deal with index insets
423 # these need to have the argument removed
426 i = find_token(document.body, "\\begin_inset Index", i)
429 line = document.body[i]
430 l = re.compile(r"\\begin_inset Index (.*)$")
433 if itype == "idx" or useindices == "false":
434 document.body[i] = "\\begin_inset Index"
436 k = find_end_of_inset(document.body, i)
438 document.warning("Can't find end of index inset!")
441 content = lyx2latex(document, document.body[i:k])
443 content = content.replace('"', r"\"")
444 subst = put_cmd_in_ert("\\sindex[" + itype + "]{" + content + "}")
445 document.body[i : k + 1] = subst
448 # deal with index_print insets
451 i = find_token(document.body, "\\begin_inset CommandInset index_print", i)
454 k = find_end_of_inset(document.body, i)
455 ptype = get_quoted_value(document.body, "type", i, k)
457 j = find_token(document.body, "type", i, k)
460 del document.body[i : k + 1]
462 subst = put_cmd_in_ert("\\printindex[" + ptype + "]{}")
463 document.body[i : k + 1] = subst
467 def convert_splitindex(document):
468 "Converts index and printindex insets to splitindex-aware format"
469 add_use_indices(document)
472 i = find_token(document.body, "\\begin_inset Index", i)
475 document.body[i] = document.body[i].replace(
476 "\\begin_inset Index", "\\begin_inset Index idx"
481 i = find_token(document.body, "\\begin_inset CommandInset index_print", i)
484 if document.body[i + 1].find("LatexCommand printindex") == -1:
485 document.warning("Malformed LyX document: Incomplete printindex inset.")
487 subst = ["LatexCommand printindex", 'type "idx"']
488 document.body[i + 1 : i + 2] = subst
492 def revert_subindex(document):
493 "Reverts \\printsubindex CommandInset types"
494 i = add_use_indices(document)
497 useindices = str2bool(get_value(document.header, "\\use_indices", i))
500 i = find_token(document.body, "\\begin_inset CommandInset index_print", i)
503 k = find_end_of_inset(document.body, i)
504 ctype = get_value(document.body, "LatexCommand", i, k)
505 if ctype != "printsubindex":
508 ptype = get_quoted_value(document.body, "type", i, k)
510 del document.body[i : k + 1]
512 subst = put_cmd_in_ert("\\printsubindex[" + ptype + "]{}")
513 document.body[i : k + 1] = subst
517 def revert_printindexall(document):
518 "Reverts \\print[sub]index* CommandInset types"
519 i = add_use_indices(document)
522 useindices = str2bool(get_value(document.header, "\\use_indices", i))
525 i = find_token(document.body, "\\begin_inset CommandInset index_print", i)
528 k = find_end_of_inset(document.body, i)
529 ctype = get_value(document.body, "LatexCommand", i, k)
530 if ctype != "printindex*" and ctype != "printsubindex*":
534 del document.body[i : k + 1]
536 subst = put_cmd_in_ert("\\" + ctype + "{}")
537 document.body[i : k + 1] = subst
541 strikeout_preamble = [
542 "% for proper underlining",
543 r"\PassOptionsToPackage{normalem}{ulem}",
544 r"\usepackage{ulem}",
548 def convert_strikeout(document):
549 "Remove preamble code loading 'ulem' package."
550 del_complete_lines(document.preamble, ["% Added by lyx2lyx"] + strikeout_preamble)
553 def revert_strikeout(document):
554 "Reverts \\strikeout font attribute"
555 changed = revert_font_attrs(document.body, "\\uuline", "\\uuline")
556 changed = revert_font_attrs(document.body, "\\uwave", "\\uwave") or changed
557 changed = revert_font_attrs(document.body, "\\strikeout", "\\sout") or changed
559 insert_to_preamble(document, strikeout_preamble)
562 ulinelatex_preamble = [
563 "% fix underbar in citations",
564 r"\let\cite@rig\cite",
565 r"\newcommand{\b@xcite}[2][\%]{\def\def@pt{\%}\def\pas@pt{#1}",
566 r" \mbox{\ifx\def@pt\pas@pt\cite@rig{#2}\else\cite@rig[#1]{#2}\fi}}",
567 r"\renewcommand{\underbar}[1]{{\let\cite\b@xcite\uline{#1}}}",
571 def convert_ulinelatex(document):
572 "Remove preamble code for \\uline font attribute."
573 del_complete_lines(document.preamble, ["% Added by lyx2lyx"] + ulinelatex_preamble)
576 def revert_ulinelatex(document):
577 "Add preamble code for \\uline font attribute in citations."
578 i = find_token(document.body, "\\bar under", 0)
582 document.preamble.index(r"\usepackage{ulem}")
584 insert_to_preamble(document, strikeout_preamble)
585 insert_to_preamble(document, ulinelatex_preamble)
588 def revert_custom_processors(document):
589 "Remove bibtex_command and index_command params"
591 if not del_token(document.header, "\\bibtex_command", 0):
592 document.warning("Malformed LyX document: Missing \\bibtex_command.")
594 if not del_token(document.header, "\\index_command", 0):
595 document.warning("Malformed LyX document: Missing \\index_command.")
598 def convert_nomencl_width(document):
599 "Add set_width param to nomencl_print"
602 i = find_token(document.body, "\\begin_inset CommandInset nomencl_print", i)
605 document.body.insert(i + 2, 'set_width "none"')
609 def revert_nomencl_width(document):
610 "Remove set_width param from nomencl_print"
613 i = find_token(document.body, "\\begin_inset CommandInset nomencl_print", i)
616 j = find_end_of_inset(document.body, i)
617 if not del_token(document.body, "set_width", i, j):
618 document.warning("Can't find set_width option for nomencl_print!")
622 def revert_nomencl_cwidth(document):
623 "Remove width param from nomencl_print"
626 i = find_token(document.body, "\\begin_inset CommandInset nomencl_print", i)
629 j = find_end_of_inset(document.body, i)
630 l = find_token(document.body, "width", i, j)
634 width = get_quoted_value(document.body, "width", i, j)
636 insert_to_preamble(document, ["\\setlength{\\nomlabelwidth}{" + width + "}"])
640 def revert_applemac(document):
641 "Revert applemac encoding to auto"
642 if document.encoding != "applemac":
644 document.encoding = "auto"
645 i = find_token(document.header, "\\encoding", 0)
647 document.header[i] = "\\encoding auto"
650 def revert_longtable_align(document):
651 "Remove longtable alignment setting"
654 i = find_token(document.body, "\\begin_inset Tabular", i)
657 end = find_end_of_inset(document.body, i)
659 document.warning("Can't find end of inset at line " + str(i))
662 fline = find_token(document.body, "<features", i, end)
664 document.warning("Can't find features for inset at line " + str(i))
667 j = document.body[fline].find("longtabularalignment")
671 # FIXME Is this correct? It wipes out everything after the
673 document.body[fline] = document.body[fline][: j - 1] + ">"
674 # since there could be a tabular inside this one, we
675 # cannot jump to end.
679 def revert_branch_filename(document):
680 "Remove \\filename_suffix parameter from branches"
683 i = find_token(document.header, "\\filename_suffix", i)
686 del document.header[i]
689 def revert_paragraph_indentation(document):
690 "Revert custom paragraph indentation to preamble code"
691 i = find_token(document.header, "\\paragraph_indentation", 0)
694 length = get_value(document.header, "\\paragraph_indentation", i)
695 # we need only remove the line if indentation is default
696 if length != "default":
697 # handle percent lengths
698 length = latex_length(length)[1]
699 insert_to_preamble(document, ["\\setlength{\\parindent}{" + length + "}"])
700 del document.header[i]
703 def revert_percent_skip_lengths(document):
704 "Revert relative lengths for paragraph skip separation to preamble code"
705 i = find_token(document.header, "\\defskip", 0)
708 length = get_value(document.header, "\\defskip", i)
709 # only revert when a custom length was set and when
710 # it used a percent length
711 if length in ("smallskip", "medskip", "bigskip"):
713 # handle percent lengths
714 percent, length = latex_length(length)
716 insert_to_preamble(document, ["\\setlength{\\parskip}{" + length + "}"])
717 # set defskip to medskip as default
718 document.header[i] = "\\defskip medskip"
721 def revert_percent_vspace_lengths(document):
722 "Revert relative VSpace lengths to ERT"
725 i = find_token(document.body, "\\begin_inset VSpace", i)
728 # only revert if a custom length was set and if
729 # it used a percent length
730 r = re.compile(r"\\begin_inset VSpace (.*)$")
731 m = r.match(document.body[i])
733 if length in ("defskip", "smallskip", "medskip", "bigskip", "vfill"):
736 # check if the space has a star (protected space)
737 protected = document.body[i].rfind("*") != -1
739 length = length.rstrip("*")
740 # handle percent lengths
741 percent, length = latex_length(length)
742 # revert the VSpace inset to ERT
745 subst = put_cmd_in_ert("\\vspace*{" + length + "}")
747 subst = put_cmd_in_ert("\\vspace{" + length + "}")
748 document.body[i : i + 2] = subst
752 def revert_percent_hspace_lengths(document):
753 "Revert relative HSpace lengths to ERT"
756 i = find_token_exact(document.body, "\\begin_inset space \\hspace", i)
759 j = find_end_of_inset(document.body, i)
761 document.warning("Can't find end of inset at line " + str(i))
764 # only revert if a custom length was set...
765 length = get_value(document.body, "\\length", i + 1, j)
767 document.warning("Malformed lyx document: Missing '\\length' in Space inset.")
771 if document.body[i].find("\\hspace*{}") != -1:
773 # ...and if it used a percent length
774 percent, length = latex_length(length)
775 # revert the HSpace inset to ERT
777 subst = put_cmd_in_ert("\\hspace" + protected + "{" + length + "}")
778 document.body[i : j + 1] = subst
779 # if we did a substitution, this will still be ok
783 def revert_hspace_glue_lengths(document):
784 "Revert HSpace glue lengths to ERT"
787 i = find_token_exact(document.body, "\\begin_inset space \\hspace", i)
790 j = find_end_of_inset(document.body, i)
792 document.warning("Can't find end of inset at line " + str(i))
795 length = get_value(document.body, "\\length", i + 1, j)
797 document.warning("Malformed lyx document: Missing '\\length' in Space inset.")
801 if document.body[i].find("\\hspace*{}") != -1:
803 # only revert if the length contains a plus or minus at pos != 0
804 if length.find("-", 1) != -1 or length.find("+", 1) != -1:
805 # handle percent lengths
806 length = latex_length(length)[1]
807 # revert the HSpace inset to ERT
808 subst = put_cmd_in_ert("\\hspace" + protected + "{" + length + "}")
809 document.body[i : j + 1] = subst
813 def convert_author_id(document):
814 "Add the author_id to the \\author definition and make sure 0 is not used"
817 re_author = re.compile(r"(\\author) (\".*\")\s*(.*)$")
820 i = find_token(document.header, "\\author", i)
823 m = re_author.match(document.header[i])
827 document.header[i] = "\\author %i %s %s" % (anum, name, email)
833 i = find_token(document.body, "\\change_", i)
836 change = document.body[i].split(" ")
839 author_id = int(change[1])
841 document.body[i] = "%s %i %s" % (type, author_id + 1, time)
845 def revert_author_id(document):
846 "Remove the author_id from the \\author definition"
849 rx = re.compile(r"(\\author)\s+(-?\d+)\s+(\".*\")\s*(.*)$")
853 i = find_token(document.header, "\\author", i)
856 m = rx.match(document.header[i])
858 author_id = int(m.group(2))
859 idmap[author_id] = anum
862 document.header[i] = f"\\author {name} {email}"
864 # FIXME Should this be incremented if we didn't match?
869 i = find_token(document.body, "\\change_", i)
872 change = document.body[i].split(" ")
875 author_id = int(change[1])
877 document.body[i] = "%s %i %s" % (type, idmap[author_id], time)
881 def revert_suppress_date(document):
882 "Revert suppressing of default document date to preamble code"
883 i = find_token(document.header, "\\suppress_date", 0)
886 # remove the preamble line and write to the preamble
887 # when suppress_date was true
888 date = str2bool(get_value(document.header, "\\suppress_date", i))
890 add_to_preamble(document, ["\\date{}"])
891 del document.header[i]
894 mhchem_preamble = [r"\PassOptionsToPackage{version=3}{mhchem}", r"\usepackage{mhchem}"]
897 def convert_mhchem(document):
898 "Set mhchem to off for versions older than 1.6.x"
899 if document.initial_format < 277:
900 # LyX 1.5.x and older did never load mhchem.
901 # Therefore we must switch it off: Documents that use mhchem have
902 # a manual \usepackage anyway, and documents not using mhchem but
903 # custom macros with the same names as mhchem commands might get
904 # corrupted if mhchem is automatically loaded.
907 # LyX 1.6.x did always load mhchem automatically.
909 i = find_token(document.header, "\\use_esint", 0)
912 i = find_token(document.header, "\\use_amsmath", 0)
914 document.warning("Malformed LyX document: " "Could not find amsmath or esint setting.")
916 document.header.insert(i + 1, "\\use_mhchem %d" % mhchem)
917 # remove LyX-inserted preamble
919 del_complete_lines(document.preamble, ["% Added by lyx2lyx"] + mhchem_preamble)
922 def revert_mhchem(document):
923 "Revert mhchem loading to preamble code."
925 mhchem = get_value(document.header, "\\use_mhchem", delete=True)
929 document.warning("Malformed LyX document: " "Could not find mhchem setting.")
931 # mhchem in {0: "off", 1: "auto", 2: "on"}
933 if mhchem == 1: # "auto"
935 while i != 1 and mhchem == 1:
936 i = find_token(document.body, "\\begin_inset Formula", i)
937 j = find_end_of_inset(document.body, i)
940 if (True for line in document.body[i:j] if r"\ce{" in line or r"\cf{" in line):
947 and find_token(document.preamble, r"\usepackage{mhchem}") == -1
949 insert_to_preamble(document, mhchem_preamble)
952 def revert_fontenc(document):
953 "Remove fontencoding param"
954 if not del_token(document.header, "\\fontencoding", 0):
955 document.warning("Malformed LyX document: Missing \\fontencoding.")
958 def merge_gbrief(document):
959 "Merge g-brief-en and g-brief-de to one class"
961 if document.textclass != "g-brief-de":
962 if document.textclass == "g-brief-en":
963 document.textclass = "g-brief"
964 document.set_textclass()
968 "Brieftext": "Letter",
969 "Unterschrift": "Signature",
971 "Zusatz": "Addition",
974 "RetourAdresse": "ReturnAddress",
975 "MeinZeichen": "MyRef",
976 "IhrZeichen": "YourRef",
977 "IhrSchreiben": "YourMail",
980 "Konto": "BankAccount",
981 "Postvermerk": "PostalComment",
982 "Adresse": "Address",
984 "Betreff": "Reference",
992 i = find_token(document.body, "\\begin_layout", i)
996 layout = document.body[i][14:]
997 if layout in obsoletedby:
998 document.body[i] = "\\begin_layout " + obsoletedby[layout]
1002 document.textclass = "g-brief"
1003 document.set_textclass()
1006 def revert_gbrief(document):
1007 "Revert g-brief to g-brief-en"
1008 if document.textclass == "g-brief":
1009 document.textclass = "g-brief-en"
1010 document.set_textclass()
1013 def revert_html_options(document):
1014 "Remove html options"
1015 del_token(document.header, "\\html_use_mathml", 0)
1016 del_token(document.header, "\\html_be_strict", 0)
1019 def revert_includeonly(document):
1022 i = find_token(document.header, "\\begin_includeonly", i)
1025 j = find_end_of(document.header, i, "\\begin_includeonly", "\\end_includeonly")
1027 document.warning("Unable to find end of includeonly section!!")
1029 document.header[i : j + 1] = []
1032 def convert_includeall(document):
1033 "Add maintain_unincluded_children param"
1036 i = find_token(document.header, "\\maintain_unincluded_children", 0)
1038 i = find_token(document.header, "\\textclass", 0)
1040 document.warning("Malformed LyX document! Missing \\textclass header.")
1042 document.header.insert(i, "\\maintain_unincluded_children false")
1046 def revert_includeall(document):
1047 "Remove maintain_unincluded_children param"
1048 del_token(document.header, "\\maintain_unincluded_children", 0)
1051 def revert_multirow(document):
1052 "Revert multirow cells in tables to TeX-code"
1054 # first, let's find out if we need to do anything
1055 # cell type 3 is multirow begin cell
1056 i = find_token(document.body, '<cell multirow="3"', 0)
1060 add_to_preamble(document, ["\\usepackage{multirow}"])
1064 # find begin/end of table
1065 begin_table = find_token(document.body, "<lyxtabular version=", begin_table)
1066 if begin_table == -1:
1068 end_table = find_end_of(document.body, begin_table, "<lyxtabular", "</lyxtabular>")
1070 document.warning("Malformed LyX document: Could not find end of table.")
1073 # does this table have multirow?
1074 i = find_token(document.body, '<cell multirow="3"', begin_table, end_table)
1076 begin_table = end_table
1079 # store the number of rows and columns
1080 numrows = get_option_value(document.body[begin_table], "rows")
1081 numcols = get_option_value(document.body[begin_table], "columns")
1083 numrows = int(numrows)
1084 numcols = int(numcols)
1086 document.warning("Unable to determine rows and columns!")
1087 begin_table = end_table
1092 # collect info on rows and columns of this table.
1093 begin_row = begin_table
1094 for row in range(numrows):
1095 begin_row = find_token(document.body, "<row>", begin_row, end_table)
1097 document.warning("Can't find row " + str(row + 1))
1099 end_row = find_end_of(document.body, begin_row, "<row>", "</row>")
1101 document.warning("Can't find end of row " + str(row + 1))
1103 begin_cell = begin_row
1104 multirows.append([])
1105 for column in range(numcols):
1106 begin_cell = find_token(document.body, "<cell ", begin_cell, end_row)
1107 if begin_cell == -1:
1109 "Can't find column " + str(column + 1) + "in row " + str(row + 1)
1113 # this will fail if someone puts "</cell>" in a cell, but
1114 # that seems fairly unlikely.
1115 end_cell = find_end_of(document.body, begin_cell, "<cell", "</cell>")
1118 "Can't find end of column " + str(column + 1) + "in row " + str(row + 1)
1121 multirows[row].append([begin_cell, end_cell, 0])
1122 if document.body[begin_cell].find('multirow="3"') != -1:
1123 multirows[row][column][2] = 3 # begin multirow
1124 mrstarts.append([row, column])
1125 elif document.body[begin_cell].find('multirow="4"') != -1:
1126 multirows[row][column][2] = 4 # in multirow
1127 begin_cell = end_cell
1129 # end of table info collection
1131 # work from the back to avoid messing up numbering
1137 col_width = get_option_value(document.body[begin_table + 2 + col], "width")
1138 # "0pt" means that no width is specified
1139 if not col_width or col_width == "0pt":
1141 # determine the number of cells that are part of the multirow
1143 for r in range(row + 1, numrows):
1144 if multirows[r][col][2] != 4:
1147 # take the opportunity to revert this line
1148 lineno = multirows[r][col][0]
1149 document.body[lineno] = (
1150 document.body[lineno]
1151 .replace(' multirow="4" ', " ")
1152 .replace('valignment="middle"', 'valignment="top"')
1153 .replace(' topline="true" ', " ")
1155 # remove bottom line of previous multirow-part cell
1156 lineno = multirows[r - 1][col][0]
1157 document.body[lineno] = document.body[lineno].replace(
1158 ' bottomline="true" ', " "
1160 # revert beginning cell
1161 bcell = multirows[row][col][0]
1162 ecell = multirows[row][col][1]
1163 document.body[bcell] = (
1164 document.body[bcell]
1165 .replace(' multirow="3" ', " ")
1166 .replace('valignment="middle"', 'valignment="top"')
1168 blay = find_token(document.body, "\\begin_layout", bcell, ecell)
1170 document.warning("Can't find layout for cell!")
1172 bend = find_end_of_layout(document.body, blay)
1174 document.warning("Can't find end of layout for cell!")
1176 # do the later one first, so as not to mess up the numbering
1177 # we are wrapping the whole cell in this ert
1178 # so before the end of the layout...
1179 document.body[bend:bend] = put_cmd_in_ert("}")
1180 # ...and after the beginning
1181 document.body[blay + 1 : blay + 1] = put_cmd_in_ert(
1182 "\\multirow{" + str(nummrs) + "}{" + col_width + "}{"
1185 begin_table = end_table
1188 def convert_math_output(document):
1189 r"Convert \html_use_mathml to \html_math_output"
1190 i = find_token(document.header, "\\html_use_mathml", 0)
1193 rgx = re.compile(r"\\html_use_mathml\s+(\w+)")
1194 m = rgx.match(document.header[i])
1195 newval = "0" # MathML
1197 val = str2bool(m.group(1))
1199 newval = "2" # Images
1201 document.warning("Can't match " + document.header[i])
1202 document.header[i] = "\\html_math_output " + newval
1205 def revert_math_output(document):
1206 r"Revert \html_math_output to \html_use_mathml"
1207 i = find_token(document.header, "\\html_math_output", 0)
1210 rgx = re.compile(r"\\html_math_output\s+(\d)")
1211 m = rgx.match(document.header[i])
1215 if val == "1" or val == "2":
1218 document.warning("Unable to match " + document.header[i])
1219 document.header[i] = "\\html_use_mathml " + newval
1222 def revert_inset_preview(document):
1223 "Dissolves the preview inset"
1226 i = find_token(document.body, "\\begin_inset Preview", i)
1229 iend = find_end_of_inset(document.body, i)
1231 document.warning("Malformed LyX document: Could not find end of Preview inset.")
1235 # This has several issues.
1236 # We need to do something about the layouts inside InsetPreview.
1237 # If we just leave the first one, then we have something like:
1238 # \begin_layout Standard
1240 # \begin_layout Standard
1241 # and we get a "no \end_layout" error. So something has to be done.
1242 # Ideally, we would check if it is the same as the layout we are in.
1243 # If so, we just remove it; if not, we end the active one. But it is
1244 # not easy to know what layout we are in, due to depth changes, etc,
1245 # and it is not clear to me how much work it is worth doing. In most
1246 # cases, the layout will probably be the same.
1248 # For the same reason, we have to remove the \end_layout tag at the
1249 # end of the last layout in the inset. Again, that will sometimes be
1250 # wrong, but it will usually be right. To know what to do, we would
1251 # again have to know what layout the inset is in.
1253 blay = find_token(document.body, "\\begin_layout", i, iend)
1255 document.warning("Can't find layout for preview inset!")
1256 # always do the later one first...
1257 del document.body[iend]
1258 del document.body[i]
1259 # deletions mean we do not need to reset i
1262 # This is where we would check what layout we are in.
1263 # The check for Standard is definitely wrong.
1265 # lay = document.body[blay].split(None, 1)[1]
1266 # if lay != oldlayout:
1267 # # record a boolean to tell us what to do later....
1268 # # better to do it later, since (a) it won't mess up
1269 # # the numbering and (b) we only modify at the end.
1271 # we want to delete the last \\end_layout in this inset, too.
1272 # note that this may not be the \\end_layout that goes with blay!!
1273 bend = find_end_of_layout(document.body, blay)
1275 tmp = find_token(document.body, "\\end_layout", bend + 1, iend)
1280 document.warning("Unable to find last layout in preview inset!")
1281 del document.body[iend]
1282 del document.body[i]
1283 # deletions mean we do not need to reset i
1285 # always do the later one first...
1286 del document.body[iend]
1287 del document.body[bend]
1288 del document.body[i : blay + 1]
1289 # we do not need to reset i
1292 def revert_equalspacing_xymatrix(document):
1293 "Revert a Formula with xymatrix@! to an ERT inset"
1295 has_preamble = False
1296 has_equal_spacing = False
1299 i = find_token(document.body, "\\begin_inset Formula", i)
1302 j = find_end_of_inset(document.body, i)
1304 document.warning("Malformed LyX document: Could not find end of Formula inset.")
1308 for curline in range(i, j):
1309 found = document.body[curline].find("\\xymatrix@!")
1314 has_equal_spacing = True
1315 content = [document.body[i][21:]]
1316 content += document.body[i + 1 : j]
1317 subst = put_cmd_in_ert(content)
1318 document.body[i : j + 1] = subst
1319 i += len(subst) - (j - i) + 1
1321 for curline in range(i, j):
1322 l = document.body[curline].find("\\xymatrix")
1328 if has_equal_spacing and not has_preamble:
1329 add_to_preamble(document, ["\\usepackage[all]{xy}"])
1332 def revert_notefontcolor(document):
1333 "Reverts greyed-out note font color to preamble code"
1335 i = find_token(document.header, "\\notefontcolor", 0)
1339 colorcode = get_value(document.header, "\\notefontcolor", i)
1340 del document.header[i]
1342 # are there any grey notes?
1343 if find_token(document.body, "\\begin_inset Note Greyedout", 0) == -1:
1344 # no need to do anything else, and \renewcommand will throw
1345 # an error since lyxgreyedout will not exist.
1348 # the color code is in the form #rrggbb where every character denotes a hex number
1349 red = hex2ratio(colorcode[1:3])
1350 green = hex2ratio(colorcode[3:5])
1351 blue = hex2ratio(colorcode[5:7])
1352 # write the preamble
1356 "% for greyed-out notes",
1357 "\\@ifundefined{definecolor}{\\usepackage{color}}{}"
1358 "\\definecolor{note_fontcolor}{rgb}{%s,%s,%s}" % (red, green, blue),
1359 "\\renewenvironment{lyxgreyedout}",
1360 " {\\textcolor{note_fontcolor}\\bgroup}{\\egroup}",
1365 def revert_turkmen(document):
1366 "Set language Turkmen to English"
1368 revert_language(document, "turkmen", "turkmen", "turkmen")
1371 def revert_fontcolor(document):
1372 "Reverts font color to preamble code"
1373 i = find_token(document.header, "\\fontcolor", 0)
1376 colorcode = get_value(document.header, "\\fontcolor", i)
1377 del document.header[i]
1378 # don't clutter the preamble if font color is not set
1379 if colorcode == "#000000":
1381 # the color code is in the form #rrggbb where every character denotes a hex number
1382 red = hex2ratio(colorcode[1:3])
1383 green = hex2ratio(colorcode[3:5])
1384 blue = hex2ratio(colorcode[5:7])
1385 # write the preamble
1389 "% Set the font color",
1390 "\\@ifundefined{definecolor}{\\usepackage{color}}{}",
1391 f"\\definecolor{{document_fontcolor}}{{rgb}}{{{red},{green},{blue}}}",
1392 "\\color{document_fontcolor}",
1397 def revert_shadedboxcolor(document):
1398 "Reverts shaded box color to preamble code"
1399 i = find_token(document.header, "\\boxbgcolor", 0)
1402 colorcode = get_value(document.header, "\\boxbgcolor", i)
1403 del document.header[i]
1404 # the color code is in the form #rrggbb
1405 red = hex2ratio(colorcode[1:3])
1406 green = hex2ratio(colorcode[3:5])
1407 blue = hex2ratio(colorcode[5:7])
1408 # write the preamble
1412 "% Set the color of boxes with shaded background",
1413 "\\@ifundefined{definecolor}{\\usepackage{color}}{}",
1414 f"\\definecolor{{shadecolor}}{{rgb}}{{{red},{green},{blue}}}",
1419 def revert_lyx_version(document):
1420 "Reverts LyX Version information from Inset Info"
1421 version = "LyX version"
1423 import lyx2lyx_version
1425 version = lyx2lyx_version.version
1431 i = find_token(document.body, "\\begin_inset Info", i)
1434 j = find_end_of_inset(document.body, i + 1)
1436 document.warning("Malformed LyX document: Could not find end of Info inset.")
1445 typ = get_quoted_value(document.body, "type", i, j)
1446 arg = get_quoted_value(document.body, "arg", i, j)
1447 if arg != "version" or typ != "lyxinfo":
1451 # We do not actually know the version of LyX used to produce the document.
1452 # But we can use our version, since we are reverting.
1454 # Now we want to check if the line after "\end_inset" is empty. It normally
1455 # is, so we want to remove it, too.
1457 if document.body[j + 1].strip() == "":
1459 document.body[i:lastline] = s
1463 def revert_math_scale(document):
1464 "Remove math scaling and LaTeX options"
1465 del_token(document.header, "\\html_math_img_scale", 0)
1466 del_token(document.header, "\\html_latex_start", 0)
1467 del_token(document.header, "\\html_latex_end", 0)
1470 def revert_pagesizes(document):
1471 "Revert page sizes to default"
1472 i = find_token(document.header, "\\papersize", 0)
1474 size = document.header[i][11:]
1477 or size == "a1paper"
1478 or size == "a2paper"
1479 or size == "a6paper"
1480 or size == "b0paper"
1481 or size == "b1paper"
1482 or size == "b2paper"
1483 or size == "b6paper"
1492 del document.header[i]
1495 def revert_DIN_C_pagesizes(document):
1496 "Revert DIN C page sizes to default"
1497 i = find_token(document.header, "\\papersize", 0)
1499 size = document.header[i][11:]
1502 or size == "c1paper"
1503 or size == "c2paper"
1504 or size == "c3paper"
1505 or size == "c4paper"
1506 or size == "c5paper"
1507 or size == "c6paper"
1509 del document.header[i]
1512 def convert_html_quotes(document):
1513 "Remove quotes around html_latex_start and html_latex_end"
1515 i = find_token(document.header, "\\html_latex_start", 0)
1517 line = document.header[i]
1518 l = re.compile(r'\\html_latex_start\s+"(.*)"')
1521 document.header[i] = "\\html_latex_start " + m.group(1)
1523 i = find_token(document.header, "\\html_latex_end", 0)
1525 line = document.header[i]
1526 l = re.compile(r'\\html_latex_end\s+"(.*)"')
1529 document.header[i] = "\\html_latex_end " + m.group(1)
1532 def revert_html_quotes(document):
1533 "Remove quotes around html_latex_start and html_latex_end"
1535 i = find_token(document.header, "\\html_latex_start", 0)
1537 line = document.header[i]
1538 l = re.compile(r"\\html_latex_start\s+(.*)")
1541 document.warning("Weird html_latex_start line: " + line)
1542 del document.header[i]
1544 document.header[i] = '\\html_latex_start "' + m.group(1) + '"'
1546 i = find_token(document.header, "\\html_latex_end", 0)
1548 line = document.header[i]
1549 l = re.compile(r"\\html_latex_end\s+(.*)")
1552 document.warning("Weird html_latex_end line: " + line)
1553 del document.header[i]
1555 document.header[i] = '\\html_latex_end "' + m.group(1) + '"'
1558 def revert_output_sync(document):
1559 "Remove forward search options"
1560 del_token(document.header, "\\output_sync_macro", 0)
1561 del_token(document.header, "\\output_sync", 0)
1564 def revert_align_decimal(document):
1567 i = find_token(document.body, "\\begin_inset Tabular", i)
1570 j = find_end_of_inset(document.body, i)
1572 document.warning("Unable to find end of Tabular inset at line " + str(i))
1575 cell = find_token(document.body, "<cell", i, j)
1577 document.warning("Can't find any cells in Tabular inset at line " + str(i))
1582 k = find_token(document.body, "<column", k, cell)
1585 if document.body[k].find('alignment="decimal"') == -1:
1588 remove_option(document.body, k, "decimal_point")
1589 document.body[k] = document.body[k].replace(
1590 'alignment="decimal"', 'alignment="center"'
1595 def convert_optarg(document):
1596 "Convert \\begin_inset OptArg to \\begin_inset Argument"
1599 i = find_token(document.body, "\\begin_inset OptArg", i)
1602 document.body[i] = "\\begin_inset Argument"
1606 def revert_argument(document):
1607 "Convert \\begin_inset Argument to \\begin_inset OptArg"
1610 i = find_token(document.body, "\\begin_inset Argument", i)
1613 document.body[i] = "\\begin_inset OptArg"
1617 def revert_makebox(document):
1618 "Convert \\makebox to TeX code"
1621 i = find_token(document.body, "\\begin_inset Box", i)
1624 z = find_end_of_inset(document.body, i)
1626 document.warning("Malformed LyX document: Can't find end of box inset.")
1629 blay = find_token(document.body, "\\begin_layout", i, z)
1631 document.warning("Malformed LyX document: Can't find layout in box.")
1634 j = find_token(document.body, "use_makebox", i)
1635 if j == -1 or j != i + 6:
1636 document.warning("Malformed LyX document: Can't find use_makebox statement in box.")
1639 # delete use_makebox
1641 not check_token(document.body[i], "\\begin_inset Box Frameless")
1642 or get_value(document.body, "use_makebox", j) != 1
1644 del document.body[j]
1647 bend = find_end_of_layout(document.body, blay)
1648 if bend == -1 or bend > z:
1649 document.warning("Malformed LyX document: Can't find end of layout in box.")
1652 # determine the alignment
1653 align = get_quoted_value(document.body, "hor_pos", i, blay, "c")
1654 # determine the width
1655 length = get_quoted_value(document.body, "width", i, blay, "50col%")
1656 length = latex_length(length)[1]
1657 # remove the \end_layout \end_inset pair
1658 document.body[bend : z + 1] = put_cmd_in_ert("}")
1659 subst = "\\makebox[" + length + "][" + align + "]{"
1660 document.body[i : blay + 1] = put_cmd_in_ert(subst)
1664 def convert_use_makebox(document):
1665 "Adds use_makebox option for boxes"
1668 i = find_token(document.body, "\\begin_inset Box", i)
1671 k = find_token(document.body, "use_parbox", i)
1672 if k == -1 or k != i + 5:
1673 document.warning("Malformed LyX document: Can't find use_parbox statement in box.")
1677 document.body.insert(k + 1, "use_makebox 0")
1681 def revert_IEEEtran(document):
1682 "Convert IEEEtran layouts and styles to TeX code"
1684 if document.textclass != "IEEEtran":
1687 revert_flex_inset(document, "IEEE membership", "\\IEEEmembership")
1688 revert_flex_inset(document, "Lowercase", "\\MakeLowercase")
1691 "Special Paper Notice",
1695 "Biography without photo",
1698 "Special Paper Notice": "\\IEEEspecialpapernotice",
1699 "After Title Text": "\\IEEEaftertitletext",
1700 "Publication ID": "\\IEEEpubid",
1703 "Page headings": "MarkBoth",
1704 "Biography without photo": "BiographyNoPhoto",
1707 for layout in layouts:
1710 i = find_token(document.body, "\\begin_layout " + layout, i)
1713 j = find_end_of_layout(document.body, i)
1716 "Malformed LyX document: Can't find end of " + layout + " layout."
1720 if layout in list(obsoletedby.keys()):
1721 document.body[i] = "\\begin_layout " + obsoletedby[layout]
1724 content = lyx2latex(document, document.body[i : j + 1])
1725 add_to_preamble(document, [latexcmd[layout] + "{" + content + "}"])
1726 del document.body[i : j + 1]
1727 # no need to reset i
1730 def convert_prettyref(document):
1731 "Converts prettyref references to neutral formatted refs"
1732 re_ref = re.compile('^\\s*reference\\s+"(\\w+):(\\S+)"')
1733 nm_ref = re.compile('^\\s*name\\s+"(\\w+):(\\S+)"')
1737 i = find_token(document.body, "\\begin_inset CommandInset ref", i)
1740 j = find_end_of_inset(document.body, i)
1742 document.warning("Malformed LyX document: No end of InsetRef!")
1745 k = find_token(document.body, "LatexCommand prettyref", i, j)
1747 document.body[k] = "LatexCommand formatted"
1749 document.header.insert(-1, "\\use_refstyle 0")
1752 def revert_refstyle(document):
1753 "Reverts neutral formatted refs to prettyref"
1754 re_ref = re.compile('^reference\\s+"(\\w+):(\\S+)"')
1755 nm_ref = re.compile('^\\s*name\\s+"(\\w+):(\\S+)"')
1759 i = find_token(document.body, "\\begin_inset CommandInset ref", i)
1762 j = find_end_of_inset(document.body, i)
1764 document.warning("Malformed LyX document: No end of InsetRef")
1767 k = find_token(document.body, "LatexCommand formatted", i, j)
1769 document.body[k] = "LatexCommand prettyref"
1771 i = find_token(document.header, "\\use_refstyle", 0)
1773 document.header.pop(i)
1776 def revert_nameref(document):
1777 "Convert namerefs to regular references"
1778 cmds = ["Nameref", "nameref"]
1780 rx = re.compile(r'reference "(.*)"')
1783 oldcmd = "LatexCommand " + cmd
1785 # It seems better to look for this, as most of the reference
1786 # insets won't be ones we care about.
1787 i = find_token(document.body, oldcmd, i)
1792 # Make sure it is actually in an inset!
1793 # A normal line could begin with "LatexCommand nameref"!
1794 stins, endins = is_in_inset(document.body, cmdloc, "\\begin_inset CommandInset ref")
1797 # ok, so it is in an InsetRef
1798 refline = find_token(document.body, "reference", stins, endins)
1800 document.warning("Can't find reference for inset at line " + stinst + "!!")
1802 m = rx.match(document.body[refline])
1804 document.warning("Can't match reference line: " + document.body[ref])
1808 newcontent = put_cmd_in_ert("\\" + cmd + "{" + ref + "}")
1809 document.body[stins : endins + 1] = newcontent
1812 add_to_preamble(document, ["\\usepackage{nameref}"])
1815 def remove_Nameref(document):
1816 "Convert Nameref commands to nameref commands"
1819 # It seems better to look for this, as most of the reference
1820 # insets won't be ones we care about.
1821 i = find_token(document.body, "LatexCommand Nameref", i)
1826 # Make sure it is actually in an inset!
1828 document.body, cmdloc, "\\begin_inset CommandInset ref", default=False
1832 document.body[cmdloc] = "LatexCommand nameref"
1835 def revert_mathrsfs(document):
1836 r"Load mathrsfs if \mathrsfs us use in the document"
1838 for line in document.body:
1839 if line.find("\\mathscr{") != -1:
1840 add_to_preamble(document, ["\\usepackage{mathrsfs}"])
1844 def convert_flexnames(document):
1845 "Convert \\begin_inset Flex Custom:Style to \\begin_inset Flex Style and similarly for CharStyle and Element."
1848 rx = re.compile(r"^\\begin_inset Flex (?:Custom|CharStyle|Element):(.+)$")
1850 i = find_token(document.body, "\\begin_inset Flex", i)
1853 m = rx.match(document.body[i])
1855 document.body[i] = "\\begin_inset Flex " + m.group(1)
1860 "Alert": "CharStyle:Alert",
1861 "Code": "CharStyle:Code",
1862 "Concepts": "CharStyle:Concepts",
1863 "E-Mail": "CharStyle:E-Mail",
1864 "Emph": "CharStyle:Emph",
1865 "Expression": "CharStyle:Expression",
1866 "Initial": "CharStyle:Initial",
1867 "Institute": "CharStyle:Institute",
1868 "Meaning": "CharStyle:Meaning",
1869 "Noun": "CharStyle:Noun",
1870 "Strong": "CharStyle:Strong",
1871 "Structure": "CharStyle:Structure",
1872 "ArticleMode": "Custom:ArticleMode",
1873 "Endnote": "Custom:Endnote",
1874 "Glosse": "Custom:Glosse",
1875 "PresentationMode": "Custom:PresentationMode",
1876 "Tri-Glosse": "Custom:Tri-Glosse",
1880 "Abbrev": "Element:Abbrev",
1881 "CCC-Code": "Element:CCC-Code",
1882 "Citation-number": "Element:Citation-number",
1883 "City": "Element:City",
1884 "Code": "Element:Code",
1885 "CODEN": "Element:CODEN",
1886 "Country": "Element:Country",
1887 "Day": "Element:Day",
1888 "Directory": "Element:Directory",
1889 "Dscr": "Element:Dscr",
1890 "Email": "Element:Email",
1891 "Emph": "Element:Emph",
1892 "Filename": "Element:Filename",
1893 "Firstname": "Element:Firstname",
1894 "Fname": "Element:Fname",
1895 "GuiButton": "Element:GuiButton",
1896 "GuiMenu": "Element:GuiMenu",
1897 "GuiMenuItem": "Element:GuiMenuItem",
1898 "ISSN": "Element:ISSN",
1899 "Issue-day": "Element:Issue-day",
1900 "Issue-months": "Element:Issue-months",
1901 "Issue-number": "Element:Issue-number",
1902 "KeyCap": "Element:KeyCap",
1903 "KeyCombo": "Element:KeyCombo",
1904 "Keyword": "Element:Keyword",
1905 "Literal": "Element:Literal",
1906 "MenuChoice": "Element:MenuChoice",
1907 "Month": "Element:Month",
1908 "Orgdiv": "Element:Orgdiv",
1909 "Orgname": "Element:Orgname",
1910 "Postcode": "Element:Postcode",
1911 "SS-Code": "Element:SS-Code",
1912 "SS-Title": "Element:SS-Title",
1913 "State": "Element:State",
1914 "Street": "Element:Street",
1915 "Surname": "Element:Surname",
1916 "Volume": "Element:Volume",
1917 "Year": "Element:Year",
1921 def revert_flexnames(document):
1922 if document.backend == "latex":
1923 flexlist = flex_insets
1925 flexlist = flex_elements
1927 rx = re.compile(r"^\\begin_inset Flex\s+(.+)$")
1930 i = find_token(document.body, "\\begin_inset Flex", i)
1933 m = rx.match(document.body[i])
1935 document.warning("Illegal flex inset: " + document.body[i])
1939 if style in flexlist:
1940 document.body[i] = "\\begin_inset Flex " + flexlist[style]
1944 def convert_mathdots(document):
1945 "Load mathdots automatically"
1946 i = find_token(document.header, "\\use_mhchem", 0)
1948 i = find_token(document.header, "\\use_esint", 0)
1950 document.warning("Malformed LyX document: Can't find \\use_mhchem.")
1952 j = find_token(document.preamble, "\\usepackage{mathdots}", 0)
1954 document.header.insert(i + 1, "\\use_mathdots 0")
1956 document.header.insert(i + 1, "\\use_mathdots 2")
1957 del document.preamble[j]
1960 def revert_mathdots(document):
1961 "Load mathdots if used in the document"
1963 mathdots = find_token(document.header, "\\use_mathdots", 0)
1965 document.warning("No \\use_mathdots line. Assuming auto.")
1967 val = get_value(document.header, "\\use_mathdots", mathdots)
1968 del document.header[mathdots]
1972 document.warning("Invalid \\use_mathdots value: " + val + ". Assuming auto.")
1973 # probably usedots has not been changed, but be safe.
1981 add_to_preamble(document, ["\\usepackage{mathdots}"])
1984 # so we are in the auto case. we want to load mathdots if \iddots is used.
1987 i = find_token(document.body, "\\begin_inset Formula", i)
1990 j = find_end_of_inset(document.body, i)
1993 "Malformed LyX document: Can't find end of Formula inset at line " + str(i)
1997 code = "\n".join(document.body[i:j])
1998 if code.find("\\iddots") != -1:
1999 add_to_preamble(document, ["\\@ifundefined{iddots}{\\usepackage{mathdots}}"])
2004 def convert_rule(document):
2005 "Convert \\lyxline to CommandInset line."
2009 "\\begin_inset CommandInset line",
2010 "LatexCommand rule",
2020 # if paragraphs are indented, we may have to unindent to get the
2021 # line to be full-width.
2022 indent = get_value(document.header, "\\paragraph_separation", 0)
2023 have_indent = indent == "indent"
2026 i = find_token(document.body, "\\lyxline", i)
2030 # we need to find out if this line follows other content
2031 # in its paragraph. find its layout....
2032 lastlay = find_token_backwards(document.body, "\\begin_layout", i)
2034 document.warning("Can't find layout for line at " + str(i))
2035 # do the best we can.
2036 document.body[i : i + 1] = inset
2040 # ...and look for other content before it.
2042 for line in document.body[lastlay + 1 : i]:
2043 # is it empty or a paragraph option?
2044 if not line or line[0] == "\\":
2050 document.body[i : i + 1] = inset
2052 # we need to unindent, lest the line be too long
2053 document.body.insert(lastlay + 1, "\\noindent")
2056 # so our line is in the middle of a paragraph
2057 # we need to add a new line, lest this line follow the
2058 # other content on that line and run off the side of the page
2059 document.body[i : i + 1] = inset
2060 document.body[i:i] = ["\\begin_inset Newline newline", "\\end_inset", ""]
2064 def revert_rule(document):
2065 "Revert line insets to Tex code"
2068 i = find_token(document.body, "\\begin_inset CommandInset line", i)
2072 j = find_token(document.body, "\\end_inset", i)
2074 document.warning("Malformed LyX document: Can't find end of line inset.")
2076 # determine the optional offset
2077 offset = get_quoted_value(document.body, "offset", i, j)
2079 offset = "[" + offset + "]"
2080 # determine the width
2081 width = get_quoted_value(document.body, "width", i, j, "100col%")
2082 width = latex_length(width)[1]
2083 # determine the height
2084 height = get_quoted_value(document.body, "height", i, j, "1pt")
2085 height = latex_length(height)[1]
2086 # output the \rule command
2087 subst = "\\rule[" + offset + "]{" + width + "}{" + height + "}"
2088 document.body[i : j + 1] = put_cmd_in_ert(subst)
2089 i += len(subst) - (j - i)
2092 def revert_diagram(document):
2093 "Add the feyn package if \\Diagram is used in math"
2096 i = find_token(document.body, "\\begin_inset Formula", i)
2099 j = find_end_of_inset(document.body, i)
2101 document.warning("Malformed LyX document: Can't find end of Formula inset.")
2103 lines = "\n".join(document.body[i:j])
2104 if lines.find("\\Diagram") == -1:
2107 add_to_preamble(document, ["\\usepackage{feyn}"])
2108 # only need to do it once!
2139 def convert_bibtex_clearpage(document):
2140 "insert a clear(double)page before bibliographystyle if bibtotoc option is used"
2142 if document.textclass not in chapters:
2145 i = find_token(document.header, "\\papersides", 0)
2148 document.warning("Malformed LyX document: Can't find papersides definition.")
2149 document.warning("Assuming single sided.")
2152 val = get_value(document.header, "\\papersides", i)
2157 if sides != 1 and sides != 2:
2158 document.warning("Invalid papersides value: " + val)
2159 document.warning("Assuming single sided.")
2164 j = find_token(document.body, "\\begin_inset CommandInset bibtex", j)
2168 k = find_end_of_inset(document.body, j)
2170 document.warning("Can't find end of Bibliography inset at line " + str(j))
2174 # only act if there is the option "bibtotoc"
2175 val = get_value(document.body, "options", j, k)
2177 document.warning("Can't find options for bibliography inset at line " + str(j))
2181 if val.find("bibtotoc") == -1:
2185 # so we want to insert a new page right before the paragraph that
2186 # this bibliography thing is in.
2187 lay = find_token_backwards(document.body, "\\begin_layout", j)
2190 "Can't find layout containing bibliography inset at line " + str(j)
2198 cmd = "cleardoublepage"
2200 "\\begin_layout Standard",
2201 "\\begin_inset Newpage " + cmd,
2208 document.body[lay:lay] = subst
2212 def revert_bibtex_clearpage(document):
2213 "remove clear(double)page before bibliographystyle if bibtotoc option is used"
2215 if document.textclass not in chapters:
2218 i = find_token(document.header, "\\papersides", 0)
2221 document.warning("Malformed LyX document: Can't find papersides definition.")
2222 document.warning("Assuming single sided.")
2225 val = get_value(document.header, "\\papersides", i)
2230 if sides != 1 and sides != 2:
2231 document.warning("Invalid papersides value: " + val)
2232 document.warning("Assuming single sided.")
2237 j = find_token(document.body, "\\begin_inset CommandInset bibtex", j)
2241 k = find_end_of_inset(document.body, j)
2243 document.warning("Can't find end of Bibliography inset at line " + str(j))
2247 # only act if there is the option "bibtotoc"
2248 val = get_value(document.body, "options", j, k)
2250 document.warning("Can't find options for bibliography inset at line " + str(j))
2254 if val.find("bibtotoc") == -1:
2258 # we had inserted \\clear[double]page right before the paragraph that
2259 # this bibliography thing is in. Remove this. The older format has the
2260 # respective command hardcoded.
2261 lay = find_token_backwards(document.body, "\\begin_layout", j)
2264 "Can't find layout containing bibliography inset at line " + str(j)
2268 # Find the layout before this.
2269 lay = find_token_backwards(document.body, "\\begin_layout", lay - 1)
2271 document.warning("Can't find layout before bibliography inset at line " + str(j))
2278 cmd = "cleardoublepage"
2281 document.body[lay] != "\\begin_layout Standard"
2282 or document.body[lay + 1] != "\\begin_inset Newpage " + cmd
2286 layend = find_end_of_layout(document.body, lay)
2289 "Can't find end of layout containg newpage inset at line " + str(layend)
2294 del document.body[lay : layend + 1]
2298 def check_passthru(document):
2299 tc = document.textclass
2300 ok = tc == "literate-article" or tc == "literate-book" or tc == "literate-report"
2302 mods = document.get_module_list()
2304 if mod == "sweave" or mod == "noweb":
2310 def convert_passthru(document):
2311 "http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg161298.html"
2312 if not check_passthru:
2315 rx = re.compile("\\\\begin_layout \\s*(\\w+)")
2317 for lay in ["Chunk", "Scrap"]:
2319 beg = find_token(document.body, "\\begin_layout " + lay, beg)
2322 end = find_end_of_layout(document.body, beg)
2324 document.warning("Can't find end of layout at line " + str(beg))
2328 # we are now going to replace newline insets within this layout
2329 # by new instances of this layout. so we have repeated layouts
2330 # instead of newlines.
2332 # if the paragraph has any customization, however, we do not want to
2333 # do the replacement.
2334 if document.body[beg + 1].startswith("\\"):
2340 ns = find_token(document.body, "\\begin_inset Newline newline", ns, end)
2343 ne = find_end_of_inset(document.body, ns)
2344 if ne == -1 or ne > end:
2345 document.warning("Can't find end of inset at line " + str(ne))
2348 if document.body[ne + 1] == "":
2350 subst = ["\\end_layout", "", "\\begin_layout " + lay]
2351 document.body[ns : ne + 1] = subst
2352 # now we need to adjust end, in particular, but might as well
2353 # do ns properly, too
2354 newlines = (ne - ns) - len(subst)
2358 # ok, we now want to find out if the next layout is the
2359 # same as this one. if so, we will insert an extra copy of it
2361 next = find_token(document.body, "\\begin_layout", end)
2363 m = rx.match(document.body[next])
2365 nextlay = m.group(1)
2367 subst = ["\\begin_layout " + lay, "", "\\end_layout", ""]
2368 document.body[next:next] = subst
2372 beg += 4 # for the extra layout
2375 def revert_passthru(document):
2376 "http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg161298.html"
2377 if not check_passthru:
2379 rx = re.compile("\\\\begin_layout \\s*(\\w+)")
2381 for lay in ["Chunk", "Scrap"]:
2383 beg = find_token(document.body, "\\begin_layout " + lay, beg)
2386 end = find_end_of_layout(document.body, beg)
2388 document.warning("Can't find end of layout at line " + str(beg))
2392 # we now want to find out if the next layout is the
2393 # same as this one. but we will need to do this over and
2396 next = find_token(document.body, "\\begin_layout", end)
2399 m = rx.match(document.body[next])
2402 nextlay = m.group(1)
2405 # so it is the same layout again. we now want to know if it is empty.
2406 # but first let's check and make sure there is no content between the
2407 # two layouts. i'm not sure if that can happen or not.
2408 for l in range(end + 1, next):
2409 if document.body[l] != "":
2410 document.warning("Found content between adjacent " + lay + " layouts!")
2412 nextend = find_end_of_layout(document.body, next)
2414 document.warning("Can't find end of layout at line " + str(next))
2417 for l in range(next + 1, nextend):
2418 if document.body[l] != "":
2422 # empty layouts just get removed
2423 # should we check if it's before yet another such layout?
2424 del document.body[next : nextend + 1]
2425 # and we do not want to check again. we know the next layout
2426 # should be another Chunk and should be left as is.
2429 # if it's not empty, then we want to insert a newline in place
2430 # of the layout switch
2431 subst = ["\\begin_inset Newline newline", "\\end_inset", ""]
2432 document.body[end : next + 1] = subst
2433 # and now we have to find the end of the new, larger layout
2434 newend = find_end_of_layout(document.body, beg)
2436 document.warning("Can't find end of new layout at line " + str(beg))
2442 def revert_multirowOffset(document):
2443 "Revert multirow cells with offset in tables to TeX-code"
2444 # this routine is the same as the revert_multirow routine except that
2445 # it checks additionally for the offset
2447 # first, let's find out if we need to do anything
2448 i = find_token(document.body, '<cell multirow="3" mroffset=', 0)
2452 add_to_preamble(document, ["\\usepackage{multirow}"])
2454 rgx = re.compile(r'mroffset="[^"]+?"')
2458 # find begin/end of table
2459 begin_table = find_token(document.body, "<lyxtabular version=", begin_table)
2460 if begin_table == -1:
2462 end_table = find_end_of(document.body, begin_table, "<lyxtabular", "</lyxtabular>")
2464 document.warning("Malformed LyX document: Could not find end of table.")
2467 # does this table have multirow?
2468 i = find_token(document.body, '<cell multirow="3"', begin_table, end_table)
2470 begin_table = end_table
2473 # store the number of rows and columns
2474 numrows = get_option_value(document.body[begin_table], "rows")
2475 numcols = get_option_value(document.body[begin_table], "columns")
2477 numrows = int(numrows)
2478 numcols = int(numcols)
2480 document.warning("Unable to determine rows and columns!")
2481 begin_table = end_table
2486 # collect info on rows and columns of this table.
2487 begin_row = begin_table
2488 for row in range(numrows):
2489 begin_row = find_token(document.body, "<row>", begin_row, end_table)
2491 document.warning("Can't find row " + str(row + 1))
2493 end_row = find_end_of(document.body, begin_row, "<row>", "</row>")
2495 document.warning("Can't find end of row " + str(row + 1))
2497 begin_cell = begin_row
2498 multirows.append([])
2499 for column in range(numcols):
2500 begin_cell = find_token(document.body, "<cell ", begin_cell, end_row)
2501 if begin_cell == -1:
2503 "Can't find column " + str(column + 1) + "in row " + str(row + 1)
2507 # this will fail if someone puts "</cell>" in a cell, but
2508 # that seems fairly unlikely.
2509 end_cell = find_end_of(document.body, begin_cell, "<cell", "</cell>")
2512 "Can't find end of column " + str(column + 1) + "in row " + str(row + 1)
2515 multirows[row].append([begin_cell, end_cell, 0])
2516 if document.body[begin_cell].find('multirow="3" mroffset=') != -1:
2517 multirows[row][column][2] = 3 # begin multirow
2518 mrstarts.append([row, column])
2519 elif document.body[begin_cell].find('multirow="4"') != -1:
2520 multirows[row][column][2] = 4 # in multirow
2521 begin_cell = end_cell
2523 # end of table info collection
2525 # work from the back to avoid messing up numbering
2531 col_width = get_option_value(document.body[begin_table + 2 + col], "width")
2532 # "0pt" means that no width is specified
2533 if not col_width or col_width == "0pt":
2535 # determine the number of cells that are part of the multirow
2537 for r in range(row + 1, numrows):
2538 if multirows[r][col][2] != 4:
2541 # take the opportunity to revert this line
2542 lineno = multirows[r][col][0]
2543 document.body[lineno] = (
2544 document.body[lineno]
2545 .replace(' multirow="4" ', " ")
2546 .replace('valignment="middle"', 'valignment="top"')
2547 .replace(' topline="true" ', " ")
2549 # remove bottom line of previous multirow-part cell
2550 lineno = multirows[r - 1][col][0]
2551 document.body[lineno] = document.body[lineno].replace(
2552 ' bottomline="true" ', " "
2554 # revert beginning cell
2555 bcell = multirows[row][col][0]
2556 ecell = multirows[row][col][1]
2557 offset = get_option_value(document.body[bcell], "mroffset")
2558 document.body[bcell] = (
2559 document.body[bcell]
2560 .replace(' multirow="3" ', " ")
2561 .replace('valignment="middle"', 'valignment="top"')
2563 # remove mroffset option
2564 document.body[bcell] = rgx.sub("", document.body[bcell])
2566 blay = find_token(document.body, "\\begin_layout", bcell, ecell)
2568 document.warning("Can't find layout for cell!")
2570 bend = find_end_of_layout(document.body, blay)
2572 document.warning("Can't find end of layout for cell!")
2574 # do the later one first, so as not to mess up the numbering
2575 # we are wrapping the whole cell in this ert
2576 # so before the end of the layout...
2577 document.body[bend:bend] = put_cmd_in_ert("}")
2578 # ...and after the beginning
2579 document.body[blay + 1 : blay + 1] = put_cmd_in_ert(
2580 "\\multirow{" + str(nummrs) + "}{" + col_width + "}[" + offset + "]{"
2583 # on to the next table
2584 begin_table = end_table
2587 def revert_script(document):
2588 "Convert subscript/superscript inset to TeX code"
2590 foundsubscript = False
2592 i = find_token(document.body, "\\begin_inset script", i)
2595 z = find_end_of_inset(document.body, i)
2597 document.warning("Malformed LyX document: Can't find end of script inset.")
2600 blay = find_token(document.body, "\\begin_layout", i, z)
2602 document.warning("Malformed LyX document: Can't find layout in script inset.")
2606 if check_token(document.body[i], "\\begin_inset script subscript"):
2607 subst = "\\textsubscript{"
2608 foundsubscript = True
2609 elif check_token(document.body[i], "\\begin_inset script superscript"):
2610 subst = "\\textsuperscript{"
2612 document.warning("Malformed LyX document: Unknown type of script inset.")
2615 bend = find_end_of_layout(document.body, blay)
2616 if bend == -1 or bend > z:
2618 "Malformed LyX document: Can't find end of layout in script inset."
2622 # remove the \end_layout \end_inset pair
2623 document.body[bend : z + 1] = put_cmd_in_ert("}")
2624 document.body[i : blay + 1] = put_cmd_in_ert(subst)
2626 # these classes provide a \textsubscript command:
2627 # FIXME: Would be nice if we could use the information of the .layout file here
2628 classes = ["memoir", "scrartcl", "scrbook", "scrlttr2", "scrreprt"]
2629 if foundsubscript and find_token_exact(classes, document.textclass, 0) == -1:
2630 add_to_preamble(document, ["\\usepackage{subscript}"])
2633 def convert_use_xetex(document):
2634 "convert \\use_xetex to \\use_non_tex_fonts"
2635 i = find_token(document.header, "\\use_xetex", 0)
2637 document.header.insert(-1, "\\use_non_tex_fonts 0")
2639 val = get_value(document.header, "\\use_xetex", 0)
2640 document.header[i] = "\\use_non_tex_fonts " + val
2643 def revert_use_xetex(document):
2644 "revert \\use_non_tex_fonts to \\use_xetex"
2646 i = find_token(document.header, "\\use_non_tex_fonts", 0)
2648 document.warning("Malformed document. No \\use_non_tex_fonts param!")
2651 val = get_value(document.header, "\\use_non_tex_fonts", 0)
2652 document.header[i] = "\\use_xetex " + val
2655 def revert_labeling(document):
2658 "scrarticle-beamer",
2664 if document.textclass in koma:
2668 i = find_token_exact(document.body, "\\begin_layout Labeling", i)
2671 document.body[i] = "\\begin_layout List"
2674 def revert_langpack(document):
2675 "revert \\language_package parameter"
2677 i = find_token(document.header, "\\language_package", 0)
2679 document.warning("Malformed document. No \\language_package param!")
2682 del document.header[i]
2685 def convert_langpack(document):
2686 "Add \\language_package parameter"
2687 i = find_token(document.header, r"\language", 0)
2689 document.warning("Malformed document. No \\language defined!")
2692 document.header.insert(i + 1, "\\language_package default")
2695 def revert_tabularwidth(document):
2698 i = find_token(document.body, "\\begin_inset Tabular", i)
2701 j = find_end_of_inset(document.body, i)
2703 document.warning("Unable to find end of Tabular inset at line " + str(i))
2707 features = find_token(document.body, "<features", i, j)
2709 document.warning("Can't find any features in Tabular inset at line " + str(i))
2712 if document.body[features].find('alignment="tabularwidth"') != -1:
2713 remove_option(document.body, features, "tabularwidth")
2716 def revert_html_css_as_file(document):
2717 if not del_token(document.header, "\\html_css_as_file", 0):
2718 document.warning("Malformed LyX document: Missing \\html_css_as_file.")
2725 supported_versions = ["2.0.0", "2.0"]
2733 [352, [convert_splitindex]],
2736 [355, [convert_strikeout]],
2738 [357, [convert_ulinelatex]],
2740 [359, [convert_nomencl_width]],
2750 [369, [convert_author_id]],
2752 [371, [convert_mhchem]],
2754 [373, [merge_gbrief]],
2757 [376, [convert_includeall]],
2760 [379, [convert_math_output]],
2770 [389, [convert_html_quotes]],
2774 [393, [convert_optarg]],
2775 [394, [convert_use_makebox]],
2778 [397, [remove_Nameref]],
2780 [399, [convert_mathdots]],
2781 [400, [convert_rule]],
2783 [402, [convert_bibtex_clearpage]],
2784 [403, [convert_flexnames]],
2785 [404, [convert_prettyref]],
2787 [406, [convert_passthru]],
2790 [409, [convert_use_xetex]],
2792 [411, [convert_langpack]],
2798 [412, [revert_html_css_as_file]],
2799 [411, [revert_tabularwidth]],
2800 [410, [revert_langpack]],
2801 [409, [revert_labeling]],
2802 [408, [revert_use_xetex]],
2803 [407, [revert_script]],
2804 [406, [revert_multirowOffset]],
2805 [405, [revert_passthru]],
2807 [403, [revert_refstyle]],
2808 [402, [revert_flexnames]],
2809 [401, [revert_bibtex_clearpage]],
2810 [400, [revert_diagram]],
2811 [399, [revert_rule]],
2812 [398, [revert_mathdots]],
2813 [397, [revert_mathrsfs]],
2815 [395, [revert_nameref]],
2816 [394, [revert_DIN_C_pagesizes]],
2817 [393, [revert_makebox]],
2818 [392, [revert_argument]],
2820 [390, [revert_align_decimal, revert_IEEEtran]],
2821 [389, [revert_output_sync]],
2822 [388, [revert_html_quotes]],
2823 [387, [revert_pagesizes]],
2824 [386, [revert_math_scale]],
2825 [385, [revert_lyx_version]],
2826 [384, [revert_shadedboxcolor]],
2827 [383, [revert_fontcolor]],
2828 [382, [revert_turkmen]],
2829 [381, [revert_notefontcolor]],
2830 [380, [revert_equalspacing_xymatrix]],
2831 [379, [revert_inset_preview]],
2832 [378, [revert_math_output]],
2834 [376, [revert_multirow]],
2835 [375, [revert_includeall]],
2836 [374, [revert_includeonly]],
2837 [373, [revert_html_options]],
2838 [372, [revert_gbrief]],
2839 [371, [revert_fontenc]],
2840 [370, [revert_mhchem]],
2841 [369, [revert_suppress_date]],
2842 [368, [revert_author_id]],
2843 [367, [revert_hspace_glue_lengths]],
2844 [366, [revert_percent_vspace_lengths, revert_percent_hspace_lengths]],
2845 [365, [revert_percent_skip_lengths]],
2846 [364, [revert_paragraph_indentation]],
2847 [363, [revert_branch_filename]],
2848 [362, [revert_longtable_align]],
2849 [361, [revert_applemac]],
2851 [359, [revert_nomencl_cwidth]],
2852 [358, [revert_nomencl_width]],
2853 [357, [revert_custom_processors]],
2854 [356, [revert_ulinelatex]],
2856 [354, [revert_strikeout]],
2857 [353, [revert_printindexall]],
2858 [352, [revert_subindex]],
2859 [351, [revert_splitindex]],
2860 [350, [revert_backgroundcolor]],
2861 [349, [revert_outputformat]],
2862 [348, [revert_xetex]],
2863 [347, [revert_phantom, revert_hphantom, revert_vphantom]],
2864 [346, [revert_tabularvalign]],
2865 [345, [revert_swiss]],
2869 if __name__ == "__main__":