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.1"""
24 # Uncomment only what you need to import, please.
26 from parser_tools import (
39 get_containing_layout,
46 # from parser_tools import find_token, find_end_of, find_tokens, \
47 # find_end_of_inset, find_end_of_layout, \
48 # is_in_inset, del_token, check_token
50 from lyx2lyx_tools import add_to_preamble, put_cmd_in_ert, get_ert, revert_language
52 # from lyx2lyx_tools import insert_to_preamble, \
53 # lyx2latex, latex_length, revert_flex_inset, \
54 # revert_font_attrs, hex2ratio, str2bool
56 ####################################################################
57 # Private helper functions
59 # def remove_option(lines, m, option):
60 #''' removes option from line m. returns whether we did anything '''
61 # l = lines[m].find(option)
64 # val = lines[m][l:].split('"')[1]
65 # lines[m] = lines[m][:l - 1] + lines[m][l+len(option + '="' + val + '"'):]
69 def revert_Argument_to_TeX_brace(document, line, endline, n, nmax, environment, opt):
71 Reverts an InsetArgument to TeX-code
73 revert_Argument_to_TeX_brace(document, LineOfBegin, LineOfEnd, StartArgument, EndArgument, isEnvironment, isOpt)
74 LineOfBegin is the line of the \\begin_layout or \\begin_inset statement
75 LineOfEnd is the line of the \\end_layout or \\end_inset statement, if "0" is given, the end of the file is used instead
76 StartArgument is the number of the first argument that needs to be converted
77 EndArgument is the number of the last argument that needs to be converted or the last defined one
78 isEnvironment must be true, if the layout is for a LaTeX environment
79 isOpt must be true, if the argument is an optional one
83 while lineArg != -1 and n < nmax + 1:
84 lineArg = find_token(document.body, "\\begin_inset Argument " + str(n), line)
85 if lineArg > endline and endline != 0:
88 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", lineArg)
89 # we have to assure that no other inset is in the Argument
90 beginInset = find_token(document.body, "\\begin_inset", beginPlain)
91 endInset = find_token(document.body, "\\end_inset", beginPlain)
94 while beginInset < endInset and beginInset != -1:
95 beginInset = find_token(document.body, "\\begin_inset", k)
96 endInset = find_token(document.body, "\\end_inset", l)
99 if environment == False:
101 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}{")
102 del document.body[lineArg : beginPlain + 1]
105 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("]")
106 document.body[lineArg : beginPlain + 1] = put_cmd_in_ert("[")
109 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}")
110 document.body[lineArg : beginPlain + 1] = put_cmd_in_ert("{")
116 def convert_TeX_brace_to_Argument(document, line, n, nmax, inset, environment, opt):
118 Converts TeX code for mandatory arguments to an InsetArgument
119 The conversion of TeX code for optional arguments must be done with another routine
120 !!! Be careful if the braces are different in your case as expected here:
121 - "}{" separates mandatory arguments of commands
122 - "}" + "{" separates mandatory arguments of commands
123 - "}" + " " + "{" separates mandatory arguments of commands
124 - { and } surround a mandatory argument of an environment
126 convert_TeX_brace_to_Argument(document, LineOfBeginLayout/Inset, StartArgument, EndArgument, isInset, isEnvironment, isOpt)
127 LineOfBeginLayout/Inset is the line of the \\begin_layout or \\begin_inset statement
128 StartArgument is the number of the first ERT that needs to be converted
129 EndArgument is the number of the last ERT that needs to be converted
130 isInset must be true, if braces inside an InsetLayout needs to be converted
131 isEnvironment must be true, if the layout is for a LaTeX environment
132 isOpt must be true, if the argument is an optional one
134 Todo: this routine can currently handle only one mandatory argument of environments
137 end_layout = find_end_of_layout(document.body, line)
142 lineERT = find_token(document.body, "\\begin_inset ERT", lineERT, end_layout)
145 if environment == False:
146 end_ERT = find_end_of_inset(document.body, lineERT)
148 document.warning("Can't find end of ERT!!")
150 # Note that this only checks for ][ or }{ at the beginning of a line
152 bracePair = find_token(document.body, "][", lineERT, end_ERT)
154 bracePair = find_token(document.body, "}{", lineERT, end_ERT)
156 end = find_token(document.body, "\\end_inset", bracePair)
157 document.body[lineERT : end_ERT + 1] = [
163 # in the case that n > 1 we have optional arguments before
164 # therefore detect them if any
166 # first check if there is an argument
167 lineArg = find_token(document.body, "\\begin_inset Argument", line)
168 if lineArg < lineERT and lineArg != -1:
169 # we have an argument, so now search backwards for its end
170 # we must now assure that we don't find other insets like e.g. a newline
171 endInsetArg = lineERT
172 endLayoutArg = endInsetArg
173 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
174 endInsetArg = endInsetArg - 1
175 endLayoutArg = endInsetArg
176 endInsetArg = find_token_backwards(
177 document.body, "\\end_inset", endInsetArg
179 endLayoutArg = find_token_backwards(
180 document.body, "\\end_layout", endLayoutArg
182 line = endInsetArg + 1
184 document.body[line + 1 : line + 1] = [
185 "\\begin_inset Argument " + str(n),
188 "\\begin_layout Plain Layout",
191 document.body[line + 4 : line + 4] = [
192 "\\begin_inset Argument " + str(n),
195 "\\begin_layout Plain Layout",
198 document.body[endn:endn] = [
199 "\\begin_inset Argument " + str(n),
202 "\\begin_layout Plain Layout",
208 # no brace pair found
209 # now check the case that we have "}" + "{" in two ERTs
211 endBrace = find_token(document.body, "]", lineERT, end_layout)
213 endBrace = find_token(document.body, "}", lineERT, end_layout)
214 if endBrace == lineERT + 5:
216 beginBrace = find_token(document.body, "[", endBrace, end_layout)
218 beginBrace = find_token(document.body, "{", endBrace, end_layout)
219 # assure that the ERTs are consecutive (11 or 12 depending if there is a space between the ERTs or not)
220 if beginBrace != -1 and (
221 beginBrace == endBrace + 11 or beginBrace == endBrace + 12
223 end = find_token(document.body, "\\end_inset", beginBrace)
224 document.body[lineERT : end + 1] = [
230 # in the case that n > 1 we have optional arguments before
231 # therefore detect them if any
233 # first check if there is an argument
234 lineArg = find_token(
235 document.body, "\\begin_inset Argument", line
237 if lineArg < lineERT and lineArg != -1:
238 # we have an argument, so now search backwards for its end
239 # we must now assure that we don't find other insets like e.g. a newline
240 endInsetArg = lineERT
241 endLayoutArg = endInsetArg
242 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
243 endInsetArg = endInsetArg - 1
244 endLayoutArg = endInsetArg
245 endInsetArg = find_token_backwards(
246 document.body, "\\end_inset", endInsetArg
248 endLayoutArg = find_token_backwards(
249 document.body, "\\end_layout", endLayoutArg
251 line = endInsetArg + 1
253 document.body[line + 1 : line + 1] = [
254 "\\begin_inset Argument " + str(n),
257 "\\begin_layout Plain Layout",
260 document.body[line + 4 : line + 4] = [
261 "\\begin_inset Argument " + str(n),
264 "\\begin_layout Plain Layout",
267 document.body[endn:endn] = [
268 "\\begin_inset Argument " + str(n),
271 "\\begin_layout Plain Layout",
275 # set the line where the next argument will be inserted
276 if beginBrace == endBrace + 11:
284 if environment == True:
285 # FIXME This version of the routine does not check for and pass over
286 # arguments before n. So it attempts to process the argument in the
287 # document, no matter what has been specified.
289 # The other branch does do that, but probably that code would be better
290 # in a single location: Skip all those arguments, then process the ones
292 end_ERT = find_end_of_inset(document.body, lineERT)
294 document.warning("Can't find end of ERT!!")
296 # Note that this only checks for [ or { at the beginning of a line
298 opening = find_token(document.body, "[", lineERT, end_ERT)
300 opening = find_token(document.body, "{", lineERT, end_ERT)
302 lineERT2 = find_token(document.body, "\\begin_inset ERT", end_ERT, end_layout)
304 # argument in a single ERT
305 # strip off the opening bracket
306 document.body[opening] = document.body[opening][1:]
307 ertcontlastline = end_ERT - 3
308 if (opt and document.body[ertcontlastline].endswith("]")) or document.body[
311 # strip off the closing bracket
312 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
313 end2 = find_token(document.body, "\\end_inset", ertcontlastline)
314 document.body[lineERT : lineERT + 1] = [
315 "\\begin_inset Argument " + str(n)
318 end_ERT2 = find_end_of_inset(document.body, lineERT2)
320 document.warning("Can't find end of second ERT!!")
323 closing = find_token(document.body, "]", lineERT2, end_ERT2)
325 closing = find_token(document.body, "}", lineERT2, end_ERT2)
326 if closing != -1: # assure that the "}" is in this ERT
327 end2 = find_token(document.body, "\\end_inset", closing)
328 document.body[lineERT2 : end2 + 1] = [
333 document.body[lineERT : end_ERT + 1] = [
334 "\\begin_inset Argument " + str(n),
337 "\\begin_layout Plain Layout",
341 document.warning("Unable to process argument!")
345 ###############################################################################
347 ### Conversion and reversion routines
349 ###############################################################################
352 def revert_visible_space(document):
353 "Revert InsetSpace visible into its ERT counterpart"
356 i = find_token(document.body, "\\begin_inset space \\textvisiblespace{}", i)
359 end = find_end_of_inset(document.body, i)
360 subst = put_cmd_in_ert("\\textvisiblespace{}")
361 document.body[i : end + 1] = subst
364 undertilde_commands = ["utilde"]
367 def convert_undertilde(document):
368 "Load undertilde automatically"
369 i = find_token(document.header, "\\use_mathdots", 0)
371 i = find_token(document.header, "\\use_mhchem", 0)
373 i = find_token(document.header, "\\use_esint", 0)
375 document.warning("Malformed LyX document: Can't find \\use_mathdots.")
377 j = find_token(document.preamble, "\\usepackage{undertilde}", 0)
379 # package was loaded in the preamble, convert this to header setting for round trip
380 document.header.insert(i + 1, "\\use_undertilde 2") # on
381 del document.preamble[j]
385 j = find_token(document.body, "\\begin_inset Formula", j)
388 k = find_end_of_inset(document.body, j)
391 "Malformed LyX document: Can't find end of Formula inset at line " + str(j)
395 code = "\n".join(document.body[j:k])
396 for c in undertilde_commands:
397 if code.find("\\%s" % c) != -1:
398 # at least one of the commands was found - need to switch package off
399 document.header.insert(i + 1, "\\use_undertilde 0") # off
402 # no command was found - set to auto (bug 9069)
403 document.header.insert(i + 1, "\\use_undertilde 1") # auto
406 def revert_undertilde(document):
407 "Load undertilde if used in the document"
408 regexp = re.compile(r"(\\use_undertilde)")
409 i = find_re(document.header, regexp, 0)
410 value = "1" # default is auto
412 value = get_value(document.header, "\\use_undertilde", i).split()[0]
413 del document.header[i]
414 if value == "2": # on
415 add_to_preamble(document, ["\\usepackage{undertilde}"])
416 elif value == "1": # auto
419 i = find_token(document.body, "\\begin_inset Formula", i)
422 j = find_end_of_inset(document.body, i)
425 "Malformed LyX document: Can't find end of Formula inset at line " + str(i)
429 code = "\n".join(document.body[i:j])
430 for c in undertilde_commands:
431 if code.find("\\%s" % c) != -1:
432 add_to_preamble(document, ["\\usepackage{undertilde}"])
437 def revert_negative_space(document):
438 "Revert InsetSpace negmedspace and negthickspace into their TeX-code counterparts"
443 i = find_token(document.body, "\\begin_inset space \\negmedspace{}", i)
445 j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
447 # load amsmath in the preamble if not already loaded if we are at the end of checking
449 i = find_token(document.header, "\\use_amsmath 2", 0)
453 ["\\@ifundefined{negthickspace}{\\usepackage{amsmath}}{}"],
458 end = find_end_of_inset(document.body, i)
459 subst = put_cmd_in_ert("\\negmedspace{}")
460 document.body[i : end + 1] = subst
461 j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
464 end = find_end_of_inset(document.body, j)
465 subst = put_cmd_in_ert("\\negthickspace{}")
466 document.body[j : end + 1] = subst
470 def revert_math_spaces(document):
471 "Revert formulas with protected custom space and protected hfills to TeX-code"
474 i = find_token(document.body, "\\begin_inset Formula", i)
477 j = document.body[i].find("\\hspace*")
479 end = find_end_of_inset(document.body, i)
480 subst = put_cmd_in_ert(document.body[i][21:])
481 document.body[i : end + 1] = subst
485 def convert_japanese_encodings(document):
486 "Rename the japanese encodings to names understood by platex"
487 jap_enc_dict = {"EUC-JP-pLaTeX": "euc", "JIS-pLaTeX": "jis", "SJIS-pLaTeX": "sjis"}
488 i = find_token(document.header, "\\inputencoding", 0)
491 val = get_value(document.header, "\\inputencoding", i)
492 if val in list(jap_enc_dict.keys()):
493 document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
496 def revert_japanese_encodings(document):
497 "Revert the japanese encodings name changes"
498 jap_enc_dict = {"euc": "EUC-JP-pLaTeX", "jis": "JIS-pLaTeX", "sjis": "SJIS-pLaTeX"}
499 i = find_token(document.header, "\\inputencoding", 0)
502 val = get_value(document.header, "\\inputencoding", i)
503 if val in list(jap_enc_dict.keys()):
504 document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
507 def convert_justification(document):
508 "Add the \\justification buffer param"
509 i = find_token(document.header, "\\suppress_date", 0)
511 i = find_token(document.header, "\\paperorientation", 0)
513 i = find_token(document.header, "\\use_indices", 0)
515 i = find_token(document.header, "\\use_bibtopic", 0)
517 document.warning("Malformed LyX document: Missing \\suppress_date.")
519 document.header.insert(i + 1, "\\justification true")
522 def revert_justification(document):
523 "Revert the \\justification buffer param"
524 if not del_token(document.header, "\\justification", 0):
525 document.warning("Malformed LyX document: Missing \\justification.")
528 def revert_australian(document):
529 "Set English language variants Australian and Newzealand to English"
531 if document.language == "australian" or document.language == "newzealand":
532 document.language = "english"
533 i = find_token(document.header, "\\language", 0)
535 document.header[i] = "\\language english"
538 j = find_token(document.body, "\\lang australian", j)
540 j = find_token(document.body, "\\lang newzealand", 0)
544 document.body[j] = document.body[j].replace(
545 "\\lang newzealand", "\\lang english"
548 document.body[j] = document.body[j].replace("\\lang australian", "\\lang english")
552 def convert_biblio_style(document):
553 "Add a sensible default for \\biblio_style based on the citation engine."
554 i = find_token(document.header, "\\cite_engine", 0)
556 engine = get_value(document.header, "\\cite_engine", i).split("_")[0]
557 style = {"basic": "plain", "natbib": "plainnat", "jurabib": "jurabib"}
558 document.header.insert(i + 1, "\\biblio_style " + style[engine])
561 def revert_biblio_style(document):
562 "BibTeX insets with default option use the style defined by \\biblio_style."
563 i = find_token(document.header, "\\biblio_style", 0)
565 document.warning("No \\biblio_style line. Nothing to do.")
568 default_style = get_value(document.header, "\\biblio_style", i)
569 del document.header[i]
571 # We are looking for bibtex insets having the default option
574 i = find_token(document.body, "\\begin_inset CommandInset bibtex", i)
577 j = find_end_of_inset(document.body, i)
580 "Malformed LyX document: Can't find end of bibtex inset at line " + str(i)
584 k = find_token(document.body, "options", i, j)
586 options = get_quoted_value(document.body, "options", k)
587 if "default" in options.split(","):
588 document.body[k] = 'options "%s"' % options.replace("default", default_style)
592 def handle_longtable_captions(document, forward):
595 begin_table = find_token(document.body, "<lyxtabular version=", begin_table)
596 if begin_table == -1:
598 end_table = find_end_of(document.body, begin_table, "<lyxtabular", "</lyxtabular>")
600 document.warning("Malformed LyX document: Could not find end of table.")
603 fline = find_token(document.body, "<features", begin_table, end_table)
605 document.warning("Can't find features for inset at line " + str(begin_table))
608 p = document.body[fline].find("islongtable")
613 numrows = get_option_value(document.body[begin_table], "rows")
615 numrows = int(numrows)
617 document.warning(document.body[begin_table])
618 document.warning("Unable to determine rows!")
619 begin_table = end_table
621 begin_row = begin_table
622 for row in range(numrows):
623 begin_row = find_token(document.body, "<row", begin_row, end_table)
625 document.warning("Can't find row " + str(row + 1))
627 end_row = find_end_of(document.body, begin_row, "<row", "</row>")
629 document.warning("Can't find end of row " + str(row + 1))
633 get_option_value(document.body[begin_row], "caption") == "true"
634 and get_option_value(document.body[begin_row], "endfirsthead") != "true"
635 and get_option_value(document.body[begin_row], "endhead") != "true"
636 and get_option_value(document.body[begin_row], "endfoot") != "true"
637 and get_option_value(document.body[begin_row], "endlastfoot") != "true"
639 document.body[begin_row] = set_option_value(
640 document.body[begin_row], "caption", 'true", endfirsthead="true'
642 elif get_option_value(document.body[begin_row], "caption") == "true":
643 if get_option_value(document.body[begin_row], "endhead") == "true":
644 document.body[begin_row] = set_option_value(
645 document.body[begin_row], "endhead", "false"
647 if get_option_value(document.body[begin_row], "endfoot") == "true":
648 document.body[begin_row] = set_option_value(
649 document.body[begin_row], "endfoot", "false"
651 if get_option_value(document.body[begin_row], "endlastfoot") == "true":
652 document.body[begin_row] = set_option_value(
653 document.body[begin_row], "endlastfoot", "false"
656 # since there could be a tabular inside this one, we
657 # cannot jump to end.
661 def convert_longtable_captions(document):
662 "Add a firsthead flag to caption rows"
663 handle_longtable_captions(document, True)
666 def revert_longtable_captions(document):
667 "remove head/foot flag from caption rows"
668 handle_longtable_captions(document, False)
671 def convert_use_packages(document):
672 "use_xxx yyy => use_package xxx yyy"
673 packages = ["amsmath", "esint", "mathdots", "mhchem", "undertilde"]
675 i = find_token(document.header, "\\use_%s" % p, 0)
677 value = get_value(document.header, "\\use_%s" % p, i)
678 document.header[i] = f"\\use_package {p} {value}"
681 def revert_use_packages(document):
682 "use_package xxx yyy => use_xxx yyy"
683 packages = ["amsmath", "esint", "mhchem", "mathdots", "undertilde"]
684 # the order is arbitrary for the use_package version, and not all packages need to be given.
685 # Ensure a complete list and correct order (important for older LyX versions and especially lyx2lyx)
686 # first loop: find line with first package
689 regexp = re.compile(r"(\\use_package\s+%s)" % p)
690 i = find_re(document.header, regexp, 0)
691 if i != -1 and (j < 0 or i < j):
693 # second loop: replace or insert packages in front of all existing ones
695 regexp = re.compile(r"(\\use_package\s+%s)" % p)
696 i = find_re(document.header, regexp, 0)
698 value = get_value(document.header, "\\use_package %s" % p, i).split()[1]
699 del document.header[i]
700 document.header.insert(j, f"\\use_{p} {value}")
702 document.header.insert(j, "\\use_%s 1" % p)
706 def convert_use_package(document, pkg, commands, oldauto):
707 # oldauto defines how the version we are converting from behaves:
708 # if it is true, the old version uses the package automatically.
709 # if it is false, the old version never uses the package.
710 i = find_token(document.header, "\\use_package")
712 document.warning("Malformed LyX document: Can't find \\use_package.")
714 packageline = "\\usepackage{%s}" % pkg
715 if del_complete_lines(
716 document.preamble, ["% Added by lyx2lyx", packageline]
717 ) or del_complete_lines(document.preamble, [packageline]):
718 # package was loaded in the preamble, convert this to header setting
719 document.header.insert(i + 1, "\\use_package " + pkg + " 2") # on
720 # If oldauto is true we have two options:
721 # We can either set the package to auto - this is correct for files in
722 # format 425 to 463, and may create a conflict for older files which use
723 # any command in commands with a different definition.
724 # Or we can look whether any command in commands is used, and set it to
725 # auto if not and to off if yes. This will not create a conflict, but will
726 # create uncompilable documents for files in format 425 to 463, which use
727 # any command in commands.
728 # We choose the first option since its error is less likely.
730 document.header.insert(i + 1, "\\use_package " + pkg + " 1") # auto
734 j = find_token(document.body, "\\begin_inset Formula", j)
737 k = find_end_of_inset(document.body, j)
740 "Malformed LyX document: Can't find end of Formula inset at line " + str(j)
744 code = "\n".join(document.body[j:k])
746 if code.find("\\%s" % c) != -1:
747 # at least one of the commands was found - need to switch package off
748 document.header.insert(i + 1, "\\use_package " + pkg + " 0") # off
751 # no command was found - set to auto (bug 9069)
752 document.header.insert(i + 1, "\\use_package " + pkg + " 1") # auto
755 def revert_use_package(document, pkg, commands, oldauto):
756 # oldauto defines how the version we are reverting to behaves:
757 # if it is true, the old version uses the package automatically.
758 # if it is false, the old version never uses the package.
759 regexp = re.compile(r"(\\use_package\s+%s)" % pkg)
760 i = find_re(document.header, regexp, 0)
761 value = "1" # default is auto
763 value = get_value(document.header, "\\use_package", i).split()[1]
764 del document.header[i]
765 if value == "2": # on
766 add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
767 elif value == "1" and not oldauto: # auto
770 i = find_token(document.body, "\\begin_inset Formula", i)
773 j = find_end_of_inset(document.body, i)
776 "Malformed LyX document: Can't find end of Formula inset at line " + str(i)
780 code = "\n".join(document.body[i:j])
782 if code.find("\\%s" % c) != -1:
783 add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
788 mathtools_commands = [
811 def convert_use_mathtools(document):
812 "insert use_package mathtools"
813 convert_use_package(document, "mathtools", mathtools_commands, False)
816 def revert_use_mathtools(document):
817 "remove use_package mathtools"
818 revert_use_package(document, "mathtools", mathtools_commands, False)
821 # commands provided by stmaryrd.sty but LyX uses other packages:
822 # boxdot lightning, bigtriangledown, bigtriangleup
823 stmaryrd_commands = [
861 "curlywedgedownarrow",
902 "trianglelefteqslant",
903 "trianglerighteqslant",
904 "ntrianglelefteqslant",
905 "ntrianglerighteqslant",
915 "leftrightarrowtriangle",
917 "rightarrowtriangle",
930 "Mapsfrom" "Longmapsto",
936 def convert_use_stmaryrd(document):
937 "insert use_package stmaryrd"
938 convert_use_package(document, "stmaryrd", stmaryrd_commands, False)
941 def revert_use_stmaryrd(document):
942 "remove use_package stmaryrd"
943 revert_use_package(document, "stmaryrd", stmaryrd_commands, False)
946 stackrel_commands = ["stackrel"]
949 def convert_use_stackrel(document):
950 "insert use_package stackrel"
951 convert_use_package(document, "stackrel", stackrel_commands, False)
954 def revert_use_stackrel(document):
955 "remove use_package stackrel"
956 revert_use_package(document, "stackrel", stackrel_commands, False)
959 def convert_cite_engine_type(document):
960 "Determine the \\cite_engine_type from the citation engine."
961 i = find_token(document.header, "\\cite_engine", 0)
964 engine = get_value(document.header, "\\cite_engine", i)
966 engine, type = engine.split("_")
968 type = {"basic": "numerical", "jurabib": "authoryear"}[engine]
969 document.header[i] = "\\cite_engine " + engine
970 document.header.insert(i + 1, "\\cite_engine_type " + type)
973 def revert_cite_engine_type(document):
974 "Natbib had the type appended with an underscore."
975 engine_type = "numerical"
976 i = find_token(document.header, "\\cite_engine_type", 0)
978 document.warning("No \\cite_engine_type line. Assuming numerical.")
980 engine_type = get_value(document.header, "\\cite_engine_type", i)
981 del document.header[i]
983 # We are looking for the natbib citation engine
984 i = find_token(document.header, "\\cite_engine natbib", 0)
987 document.header[i] = "\\cite_engine natbib_" + engine_type
990 def convert_cite_engine_type_default(document):
991 "Convert \\cite_engine_type to default for the basic citation engine."
992 i = find_token(document.header, "\\cite_engine basic", 0)
995 i = find_token(document.header, "\\cite_engine_type", 0)
998 document.header[i] = "\\cite_engine_type default"
1001 def revert_cite_engine_type_default(document):
1002 """Revert \\cite_engine_type default.
1004 Revert to numerical for the basic cite engine, otherwise to authoryear."""
1005 engine_type = "authoryear"
1006 i = find_token(document.header, "\\cite_engine_type default", 0)
1009 j = find_token(document.header, "\\cite_engine basic", 0)
1011 engine_type = "numerical"
1012 document.header[i] = "\\cite_engine_type " + engine_type
1015 cancel_commands = ["cancel", "bcancel", "xcancel", "cancelto"]
1018 # this is the same, as revert_use_cancel() except for the default
1019 def revert_cancel(document):
1020 "add cancel to the preamble if necessary"
1021 revert_use_package(document, "cancel", cancel_commands, False)
1024 def revert_verbatim(document, starred=False):
1025 "Revert verbatim environments completely to TeX-code."
1029 layout_name = "Verbatim"
1030 latex_name = "verbatim"
1032 layout_name = "Verbatim*"
1033 latex_name = "verbatim*"
1038 "\\begin_layout Plain Layout",
1041 "\\begin_layout Plain Layout",
1046 "end{%s}" % (latex_name),
1055 "\\begin_layout Standard",
1057 "\\begin_inset ERT",
1060 "\\begin_layout Plain Layout",
1064 "begin{%s}" % (latex_name),
1067 "\\begin_layout Plain Layout",
1072 i = find_token(document.body, "\\begin_layout %s" % (layout_name), i)
1075 j = find_end_of_layout(document.body, i)
1078 "Malformed LyX document: Can't find end of %s layout" % (layout_name)
1082 # delete all line breaks insets (there are no other insets)
1085 n = find_token(document.body, "\\begin_inset Newline newline", l, j)
1087 n = find_token(document.body, "\\begin_inset Newline linebreak", l, j)
1090 m = find_end_of_inset(document.body, n)
1091 del document.body[m : m + 1]
1092 document.body[n : n + 1] = [
1095 "\\begin_layout Plain Layout",
1098 # we deleted a line, so the end of the inset moved forward.
1099 # FIXME But we also added some lines, didn't we? I think this
1102 # consecutive verbatim environments need to be connected
1103 k = find_token(document.body, "\\begin_layout %s" % (layout_name), j)
1104 if k == j + 2 and consecutive == False:
1106 document.body[j : j + 1] = [
1109 "\\begin_layout Plain Layout",
1111 document.body[i : i + 1] = subst_begin
1113 if k == j + 2 and consecutive == True:
1114 document.body[j : j + 1] = [
1117 "\\begin_layout Plain Layout",
1119 del document.body[i : i + 1]
1121 if k != j + 2 and consecutive == True:
1122 document.body[j : j + 1] = subst_end
1123 # the next paragraph must not be indented
1124 # FIXME This seems to be causing problems, because of the
1125 # hardcoded use of 19. We should figure out exactly where
1126 # this needs to go by searching for the right tag.
1127 document.body[j + 19 : j + 19] = ["\\noindent"]
1128 del document.body[i : i + 1]
1132 document.body[j : j + 1] = subst_end
1133 # the next paragraph must not be indented
1134 # FIXME This seems to be causing problems, because of the
1135 # hardcoded use of 19. We should figure out exactly where
1136 # this needs to go by searching for the right tag.
1137 document.body[j + 19 : j + 19] = ["\\noindent"]
1138 document.body[i : i + 1] = subst_begin
1141 def revert_tipa(document):
1142 "Revert native TIPA insets to mathed or ERT."
1145 i = find_token(document.body, "\\begin_inset IPA", i)
1148 j = find_end_of_inset(document.body, i)
1150 document.warning("Malformed LyX document: Can't find end of IPA inset")
1154 n = find_token(document.body, "\\begin_layout", i, j)
1156 document.warning("Malformed LyX document: IPA inset has no embedded layout")
1159 m = find_end_of_layout(document.body, n)
1161 document.warning("Malformed LyX document: Can't find end of embedded layout")
1164 content = document.body[n + 1 : m]
1165 p = find_token(document.body, "\\begin_layout", m, j)
1166 if p != -1 or len(content) > 1:
1168 content = document.body[i + 1 : j]
1170 # IPA insets with multiple pars need to be wrapped by \begin{IPA}...\end{IPA}
1171 document.body[i : j + 1] = (
1172 ["\\end_layout", "", "\\begin_layout Standard"]
1173 + put_cmd_in_ert("\\begin{IPA}")
1176 + ["\\begin_layout Standard"]
1177 + put_cmd_in_ert("\\end{IPA}")
1179 add_to_preamble(document, ["\\usepackage{tipa,tipx}"])
1181 # single-par IPA insets can be reverted to mathed
1182 document.body[i : j + 1] = [
1183 "\\begin_inset Formula $\\text{\\textipa{" + content[0] + "}}$",
1189 def revert_cell_rotation(document):
1190 "Revert cell rotations to TeX-code"
1192 load_rotating = False
1196 # first, let's find out if we need to do anything
1197 i = find_token(document.body, "<cell ", i)
1200 j = document.body[i].find('rotate="')
1202 k = document.body[i].find('"', j + 8)
1203 value = document.body[i][j + 8 : k]
1205 rgx = re.compile(r' rotate="[^"]+?"')
1206 # remove rotate option
1207 document.body[i] = rgx.sub("", document.body[i])
1209 rgx = re.compile(r' rotate="[^"]+?"')
1210 document.body[i] = rgx.sub(' rotate="true"', document.body[i])
1212 rgx = re.compile(r' rotate="[^"]+?"')
1213 load_rotating = True
1214 # remove rotate option
1215 document.body[i] = rgx.sub("", document.body[i])
1217 document.body[i + 5 : i + 5] = put_cmd_in_ert("\\end{turn}")
1218 document.body[i + 4 : i + 4] = put_cmd_in_ert(
1219 "\\begin{turn}{" + value + "}"
1226 add_to_preamble(document, ["\\@ifundefined{turnbox}{\\usepackage{rotating}}{}"])
1229 def convert_cell_rotation(document):
1230 'Convert cell rotation statements from "true" to "90"'
1234 # first, let's find out if we need to do anything
1235 i = find_token(document.body, "<cell ", i)
1238 j = document.body[i].find('rotate="true"')
1240 rgx = re.compile(r'rotate="[^"]+?"')
1241 # convert "true" to "90"
1242 document.body[i] = rgx.sub('rotate="90"', document.body[i])
1247 def revert_table_rotation(document):
1248 "Revert table rotations to TeX-code"
1250 load_rotating = False
1254 # first, let's find out if we need to do anything
1255 i = find_token(document.body, "<features ", i)
1258 j = document.body[i].find('rotate="')
1260 end_table = find_token(document.body, "</lyxtabular>", j)
1261 k = document.body[i].find('"', j + 8)
1262 value = document.body[i][j + 8 : k]
1264 rgx = re.compile(r' rotate="[^"]+?"')
1265 # remove rotate option
1266 document.body[i] = rgx.sub("", document.body[i])
1268 rgx = re.compile(r'rotate="[^"]+?"')
1269 document.body[i] = rgx.sub('rotate="true"', document.body[i])
1271 rgx = re.compile(r' rotate="[^"]+?"')
1272 load_rotating = True
1273 # remove rotate option
1274 document.body[i] = rgx.sub("", document.body[i])
1276 document.body[end_table + 3 : end_table + 3] = put_cmd_in_ert("\\end{turn}")
1277 document.body[i - 2 : i - 2] = put_cmd_in_ert(
1278 "\\begin{turn}{" + value + "}"
1285 add_to_preamble(document, ["\\@ifundefined{turnbox}{\\usepackage{rotating}}{}"])
1288 def convert_table_rotation(document):
1289 'Convert table rotation statements from "true" to "90"'
1293 # first, let's find out if we need to do anything
1294 i = find_token(document.body, "<features ", i)
1297 j = document.body[i].find('rotate="true"')
1299 rgx = re.compile(r'rotate="[^"]+?"')
1300 # convert "true" to "90"
1301 document.body[i] = rgx.sub('rotate="90"', document.body[i])
1306 def convert_listoflistings(document):
1307 r"Convert ERT \lstlistoflistings to TOC lstlistoflistings inset"
1308 # We can support roundtrip because the command is so simple
1311 i = find_token(document.body, "\\begin_inset ERT", i)
1314 j = find_end_of_inset(document.body, i)
1316 document.warning("Malformed LyX document: Can't find end of ERT inset")
1319 ert = get_ert(document.body, i)
1320 if ert == "\\lstlistoflistings{}":
1321 document.body[i:j] = [
1322 "\\begin_inset CommandInset toc",
1323 "LatexCommand lstlistoflistings",
1331 def revert_listoflistings(document):
1332 "Convert TOC lstlistoflistings inset to ERT lstlistoflistings"
1335 i = find_token(document.body, "\\begin_inset CommandInset toc", i)
1338 if document.body[i + 1] == "LatexCommand lstlistoflistings":
1339 j = find_end_of_inset(document.body, i)
1341 document.warning("Malformed LyX document: Can't find end of TOC inset")
1344 subst = put_cmd_in_ert("\\lstlistoflistings{}")
1345 document.body[i : j + 1] = subst
1346 add_to_preamble(document, ["\\usepackage{listings}"])
1350 def convert_use_amssymb(document):
1351 "insert use_package amssymb"
1352 regexp = re.compile(r"(\\use_package\s+amsmath)")
1353 i = find_re(document.header, regexp, 0)
1355 document.warning("Malformed LyX document: Can't find \\use_package amsmath.")
1357 value = get_value(document.header, "\\use_package", i).split()[1]
1360 useamsmath = int(value)
1362 document.warning("Invalid \\use_package amsmath: " + value + ". Assuming auto.")
1364 j = find_token(document.preamble, "\\usepackage{amssymb}", 0)
1366 document.header.insert(i + 1, "\\use_package amssymb %d" % useamsmath)
1368 document.header.insert(i + 1, "\\use_package amssymb 2")
1369 del document.preamble[j]
1372 def revert_use_amssymb(document):
1373 "remove use_package amssymb"
1374 regexp1 = re.compile(r"(\\use_package\s+amsmath)")
1375 regexp2 = re.compile(r"(\\use_package\s+amssymb)")
1376 i = find_re(document.header, regexp1, 0)
1377 j = find_re(document.header, regexp2, 0)
1378 value1 = "1" # default is auto
1379 value2 = "1" # default is auto
1381 value1 = get_value(document.header, "\\use_package", i).split()[1]
1383 value2 = get_value(document.header, "\\use_package", j).split()[1]
1384 del document.header[j]
1385 if value1 != value2 and value2 == "2": # on
1386 add_to_preamble(document, ["\\usepackage{amssymb}"])
1389 def convert_use_cancel(document):
1390 "insert use_package cancel"
1391 convert_use_package(document, "cancel", cancel_commands, True)
1394 def revert_use_cancel(document):
1395 "remove use_package cancel"
1396 revert_use_package(document, "cancel", cancel_commands, True)
1399 def revert_ancientgreek(document):
1400 "Set the document language for ancientgreek to greek"
1402 if document.language == "ancientgreek":
1403 document.language = "greek"
1404 i = find_token(document.header, "\\language", 0)
1406 document.header[i] = "\\language greek"
1409 j = find_token(document.body, "\\lang ancientgreek", j)
1413 document.body[j] = document.body[j].replace("\\lang ancientgreek", "\\lang greek")
1417 def revert_languages(document):
1418 "Set the document language for new supported languages to English"
1421 polyglossia_languages = [
1435 babel_languages = ["kurmanji"]
1436 for lang in polyglossia_languages:
1437 revert_language(document, lang, "", lang)
1438 for lang in babel_languages:
1439 revert_language(document, lang, lang, "")
1442 def convert_armenian(document):
1443 "Use polyglossia and thus non-TeX fonts for Armenian"
1445 if document.language == "armenian":
1446 i = find_token(document.header, "\\use_non_tex_fonts", 0)
1448 document.header[i] = "\\use_non_tex_fonts true"
1451 def revert_armenian(document):
1452 "Use ArmTeX and thus TeX fonts for Armenian"
1454 if document.language == "armenian":
1455 i = find_token(document.header, "\\use_non_tex_fonts", 0)
1457 document.header[i] = "\\use_non_tex_fonts false"
1460 def revert_libertine(document):
1461 "Revert native libertine font definition to LaTeX"
1463 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1464 i = find_token(document.header, "\\font_roman libertine", 0)
1467 j = find_token(document.header, "\\font_osf true", 0)
1470 preamble = "\\usepackage"
1472 document.header[j] = "\\font_osf false"
1475 preamble += "[lining]"
1476 preamble += "{libertine-type1}"
1477 add_to_preamble(document, [preamble])
1478 document.header[i] = "\\font_roman default"
1481 def revert_txtt(document):
1482 "Revert native txtt font definition to LaTeX"
1484 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1485 i = find_token(document.header, "\\font_typewriter txtt", 0)
1487 preamble = "\\renewcommand{\\ttdefault}{txtt}"
1488 add_to_preamble(document, [preamble])
1489 document.header[i] = "\\font_typewriter default"
1492 def revert_mathdesign(document):
1493 "Revert native mathdesign font definition to LaTeX"
1495 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1496 mathdesign_dict = {"mdbch": "charter", "mdput": "utopia", "mdugm": "garamond"}
1497 i = find_token(document.header, "\\font_roman", 0)
1500 val = get_value(document.header, "\\font_roman", i)
1501 if val in list(mathdesign_dict.keys()):
1502 preamble = "\\usepackage[%s" % mathdesign_dict[val]
1504 j = find_token(document.header, "\\font_osf true", 0)
1507 document.header[j] = "\\font_osf false"
1508 l = find_token(document.header, "\\font_sc true", 0)
1511 document.header[l] = "\\font_sc false"
1513 preamble += ",expert"
1514 preamble += "]{mathdesign}"
1515 add_to_preamble(document, [preamble])
1516 document.header[i] = "\\font_roman default"
1519 def revert_texgyre(document):
1520 "Revert native TeXGyre font definition to LaTeX"
1522 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1533 i = find_token(document.header, "\\font_roman", 0)
1535 val = get_value(document.header, "\\font_roman", i)
1536 if val in texgyre_fonts:
1537 preamble = "\\usepackage{%s}" % val
1538 add_to_preamble(document, [preamble])
1539 document.header[i] = "\\font_roman default"
1540 i = find_token(document.header, "\\font_sans", 0)
1542 val = get_value(document.header, "\\font_sans", i)
1543 if val in texgyre_fonts:
1544 preamble = "\\usepackage{%s}" % val
1545 add_to_preamble(document, [preamble])
1546 document.header[i] = "\\font_sans default"
1547 i = find_token(document.header, "\\font_typewriter", 0)
1549 val = get_value(document.header, "\\font_typewriter", i)
1550 if val in texgyre_fonts:
1551 preamble = "\\usepackage{%s}" % val
1552 add_to_preamble(document, [preamble])
1553 document.header[i] = "\\font_typewriter default"
1556 def revert_ipadeco(document):
1557 "Revert IPA decorations to ERT"
1560 i = find_token(document.body, "\\begin_inset IPADeco", i)
1563 end = find_end_of_inset(document.body, i)
1565 document.warning("Can't find end of inset at line " + str(i))
1568 line = document.body[i]
1569 rx = re.compile(r"\\begin_inset IPADeco (.*)$")
1571 decotype = m.group(1)
1572 if decotype != "toptiebar" and decotype != "bottomtiebar":
1573 document.warning("Invalid IPADeco type: " + decotype)
1576 blay = find_token(document.body, "\\begin_layout Plain Layout", i, end)
1578 document.warning("Can't find layout for inset at line " + str(i))
1581 bend = find_end_of_layout(document.body, blay)
1584 "Malformed LyX document: Could not find end of IPADeco inset's layout."
1589 "\\begin_inset ERT",
1592 "\\begin_layout Plain Layout",
1604 "\\begin_inset ERT",
1607 "\\begin_layout Plain Layout",
1614 # do the later one first so as not to mess up the numbering
1615 document.body[bend : end + 1] = substj
1616 document.body[i : blay + 1] = substi
1617 i = end + len(substi) + len(substj) - (end - bend) - (blay - i) - 2
1618 add_to_preamble(document, "\\usepackage{tipa}")
1621 def revert_ipachar(document):
1622 "Revert \\IPAChar to ERT"
1625 while i < len(document.body):
1626 m = re.match(r"(.*)\\IPAChar \\(\w+\{\w+\})(.*)", document.body[i])
1630 ipachar = m.group(2)
1634 "\\begin_inset ERT",
1637 "\\begin_layout Standard",
1648 document.body[i : i + 1] = subst
1653 add_to_preamble(document, "\\usepackage{tone}")
1656 def revert_minionpro(document):
1657 "Revert native MinionPro font definition to LaTeX"
1659 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1660 i = find_token(document.header, "\\font_roman minionpro", 0)
1663 j = find_token(document.header, "\\font_osf true", 0)
1666 preamble = "\\usepackage"
1668 document.header[j] = "\\font_osf false"
1671 preamble += "{MinionPro}"
1672 add_to_preamble(document, [preamble])
1673 document.header[i] = "\\font_roman default"
1676 def revert_mathfonts(document):
1677 "Revert native math font definitions to LaTeX"
1679 i = find_token(document.header, "\\font_math", 0)
1682 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1683 val = get_value(document.header, "\\font_math", i)
1684 if val == "eulervm":
1685 add_to_preamble(document, "\\usepackage{eulervm}")
1686 elif val == "default":
1688 "lmodern": "\\renewcommand{\\rmdefault}{lmr}",
1689 "minionpro": "\\usepackage[onlytext,lf]{MinionPro}",
1690 "minionpro-osf": "\\usepackage[onlytext]{MinionPro}",
1691 "palatino": "\\renewcommand{\\rmdefault}{ppl}",
1692 "palatino-osf": "\\renewcommand{\\rmdefault}{pplj}",
1693 "times": "\\renewcommand{\\rmdefault}{ptm}",
1694 "utopia": "\\renewcommand{\\rmdefault}{futs}",
1695 "utopia-osf": "\\renewcommand{\\rmdefault}{futj}",
1697 j = find_token(document.header, "\\font_roman", 0)
1699 rm = get_value(document.header, "\\font_roman", j)
1700 k = find_token(document.header, "\\font_osf true", 0)
1703 if rm in list(mathfont_dict.keys()):
1704 add_to_preamble(document, mathfont_dict[rm])
1705 document.header[j] = "\\font_roman default"
1707 document.header[k] = "\\font_osf false"
1708 del document.header[i]
1711 def revert_mdnomath(document):
1712 "Revert mathdesign and fourier without math"
1714 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1716 "md-charter": "mdbch",
1717 "md-utopia": "mdput",
1718 "md-garamond": "mdugm",
1720 i = find_token(document.header, "\\font_roman", 0)
1723 val = get_value(document.header, "\\font_roman", i)
1724 if val in list(mathdesign_dict.keys()):
1725 j = find_token(document.header, "\\font_math", 0)
1727 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1728 mval = get_value(document.header, "\\font_math", j)
1729 if mval == "default":
1730 document.header[i] = "\\font_roman default"
1732 document, "\\renewcommand{\\rmdefault}{%s}" % mathdesign_dict[val]
1735 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1738 def convert_mathfonts(document):
1739 document.header.insert(-1, "\\font_math auto")
1742 def convert_mdnomath(document):
1743 "Change mathdesign font name"
1745 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1747 "mdbch": "md-charter",
1748 "mdput": "md-utopia",
1749 "mdugm": "md-garamond",
1751 i = find_token(document.header, "\\font_roman", 0)
1754 val = get_value(document.header, "\\font_roman", i)
1755 if val in list(mathdesign_dict.keys()):
1756 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1759 def revert_newtxmath(document):
1760 "Revert native newtxmath definitions to LaTeX"
1762 i = find_token(document.header, "\\font_math", 0)
1765 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1766 val = get_value(document.header, "\\font_math", i)
1768 "libertine-ntxm": "\\usepackage[libertine]{newtxmath}",
1769 "minion-ntxm": "\\usepackage[minion]{newtxmath}",
1770 "newtxmath": "\\usepackage{newtxmath}",
1772 if val in list(mathfont_dict.keys()):
1773 add_to_preamble(document, mathfont_dict[val])
1774 document.header[i] = "\\font_math auto"
1777 def revert_biolinum(document):
1778 "Revert native biolinum font definition to LaTeX"
1780 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1781 i = find_token(document.header, "\\font_sans biolinum", 0)
1784 j = find_token(document.header, "\\font_osf true", 0)
1787 preamble = "\\usepackage"
1790 preamble += "{biolinum-type1}"
1791 add_to_preamble(document, [preamble])
1792 document.header[i] = "\\font_sans default"
1795 def revert_uop(document):
1796 "Revert native URW Classico (Optima) font definition to LaTeX"
1798 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1799 i = find_token(document.header, "\\font_sans uop", 0)
1801 preamble = "\\renewcommand{\\sfdefault}{uop}"
1802 add_to_preamble(document, [preamble])
1803 document.header[i] = "\\font_sans default"
1806 def convert_latexargs(document):
1807 "Convert InsetArgument to new syntax"
1809 if find_token(document.body, "\\begin_inset Argument", 0) == -1:
1813 # A list of layouts (document classes) with only optional or no arguments.
1814 # These can be safely converted to the new syntax
1815 # (I took the liberty to add some of my personal layouts/modules here; JSP)
1900 "scrarticle-beamer",
1925 # A list of "safe" modules, same as above
1929 "beamer-resenumerate",
1932 "customHeadersFooters",
1935 "eqs-within-sections",
1936 "figs-within-sections",
1952 "tabs-within-sections",
1953 "theorems-ams-bytype",
1954 "theorems-ams-extended-bytype",
1955 "theorems-ams-extended",
1958 "theorems-chap-bytype",
1961 "theorems-sec-bytype",
1967 # Modules we need to take care of
1968 caveat_modules = ["initials"] # TODO: , "graphicboxes", "bicaption"]
1969 # information about the relevant styles in caveat_modules (number of opt and req args)
1970 # use this if we get more caveat_modules. For now, use hard coding (see below).
1971 # initials = [{'Layout' : 'Initial', 'opt' : 1, 'req' : 1}]
1972 # graphicboxes = { ... }
1974 # Is this a known safe layout?
1975 safe_layout = document.textclass in safe_layouts
1978 "Lyx2lyx knows nothing about textclass '%s'. "
1979 "Please check if short title insets have been converted correctly."
1980 % document.textclass
1982 # Do we use unsafe or unknown modules
1983 mods = document.get_module_list()
1984 unknown_modules = False
1985 used_caveat_modules = list()
1987 if mod in safe_modules:
1989 if mod in caveat_modules:
1990 used_caveat_modules.append(mod)
1992 unknown_modules = True
1994 "Lyx2lyx knows nothing about module '%s'. "
1995 "Please check if short title insets have been converted correctly." % mod
2000 i = find_token(document.body, "\\begin_inset Argument", i)
2004 if not safe_layout or unknown_modules:
2005 # We cannot do more here since we have no access to this layout.
2006 # InsetArgument itself will do the real work
2007 # (see InsetArgument::updateBuffer())
2008 document.body[i] = "\\begin_inset Argument 999"
2012 # Find containing paragraph layout
2013 parent = get_containing_layout(document.body, i)
2015 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2022 if len(used_caveat_modules) > 0:
2023 # We know for now that this must be the initials module with the Initial layout
2024 # If we get more such modules, we need some automating.
2025 if parent[0] == "Initial":
2026 # Layout has 1 opt and 1 req arg.
2027 # Count the actual arguments
2029 for p in range(parbeg, parend):
2030 if document.body[p] == "\\begin_inset Argument":
2035 # Collect all arguments in this paragraph
2037 for p in range(parbeg, parend):
2038 if document.body[p] == "\\begin_inset Argument":
2040 if allowed_opts != -1:
2041 # We have less arguments than opt + required.
2042 # required must take precedence.
2043 if argnr > allowed_opts and argnr < first_req:
2045 document.body[p] = "\\begin_inset Argument %d" % argnr
2049 def revert_latexargs(document):
2050 "Revert InsetArgument to old syntax"
2053 rx = re.compile(r"^\\begin_inset Argument (\d+)$")
2056 # Search for Argument insets
2057 i = find_token(document.body, "\\begin_inset Argument", i)
2060 m = rx.match(document.body[i])
2062 # No ID: inset already reverted
2065 # Find containing paragraph layout
2066 parent = get_containing_layout(document.body, i)
2068 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2073 # Do not set realparbeg to parent[3], since this does not work if we
2074 # have another inset (e.g. label or index) before the first argument
2075 # inset (this is the case in the user guide of LyX 2.0.8)
2077 # Collect all arguments in this paragraph
2079 for p in range(parbeg, parend):
2080 m = rx.match(document.body[p])
2083 # This is the first argument inset
2085 val = int(m.group(1))
2086 j = find_end_of_inset(document.body, p)
2087 # Revert to old syntax
2088 document.body[p] = "\\begin_inset Argument"
2090 document.warning("Malformed LyX document: Can't find end of Argument inset")
2093 args[val] = document.body[p : j + 1]
2095 realparend = realparend - len(document.body[p : j + 1])
2096 # Remove arg inset at this position
2097 del document.body[p : j + 1]
2101 # No argument inset found
2102 realparbeg = parent[3]
2103 # Now sort the arg insets
2105 for f in sorted(args):
2108 # Insert the sorted arg insets at paragraph begin
2109 document.body[realparbeg:realparbeg] = subst
2111 i = realparbeg + 1 + len(subst)
2114 def revert_IEEEtran(document):
2116 Reverts InsetArgument of
2119 Biography without photo
2122 if document.textclass != "IEEEtran":
2125 layouts = {"Page headings": False, "Biography without photo": True}
2127 for layout in list(layouts.keys()):
2130 i = find_token(document.body, "\\begin_layout " + layout, i)
2133 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, layouts[layout], False)
2138 i = find_token(document.body, "\\begin_inset Flex Paragraph Start", i)
2141 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
2146 i = find_token_exact(document.body, "\\begin_layout Biography", i)
2150 if document.body[i] == "\\begin_layout Biography without photo":
2154 # start with the second argument, therefore 2
2155 revert_Argument_to_TeX_brace(document, i, 0, 2, 2, True, False)
2159 def revert_IEEEtran_2(document):
2161 Reverts Flex Paragraph Start to TeX-code
2163 if document.textclass == "IEEEtran":
2166 begin = find_token(document.body, "\\begin_inset Flex Paragraph Start", begin)
2169 end1 = find_end_of_inset(document.body, begin)
2170 document.body[end1 - 2 : end1 + 1] = put_cmd_in_ert("}")
2171 document.body[begin : begin + 4] = put_cmd_in_ert("\\IEEEPARstart{")
2175 def convert_IEEEtran(document):
2180 Biography without photo
2183 if document.textclass != "IEEEtran":
2186 layouts = {"Page headings": False, "Biography without photo": True}
2188 for layout in list(layouts.keys()):
2191 i = find_token(document.body, "\\begin_layout " + layout, i)
2194 convert_TeX_brace_to_Argument(document, i, 1, 1, False, layouts[layout], False)
2199 i = find_token_exact(document.body, "\\begin_layout Biography", i)
2203 if document.body[i] == "\\begin_layout Biography without photo":
2207 # the argument we want to convert is the second one
2208 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, False)
2212 def revert_AASTeX(document):
2213 "Reverts InsetArgument of Altaffilation to TeX-code"
2214 if document.textclass == "aastex":
2217 i = find_token(document.body, "\\begin_layout Altaffilation", i)
2220 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
2224 def convert_AASTeX(document):
2225 "Converts ERT of Altaffilation to InsetArgument"
2226 if document.textclass == "aastex":
2229 i = find_token(document.body, "\\begin_layout Altaffilation", i)
2232 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
2236 def revert_AGUTeX(document):
2237 "Reverts InsetArgument of Author affiliation to TeX-code"
2238 if document.textclass == "agutex":
2241 i = find_token(document.body, "\\begin_layout Author affiliation", i)
2244 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
2248 def convert_AGUTeX(document):
2249 "Converts ERT of Author affiliation to InsetArgument"
2250 if document.textclass == "agutex":
2253 i = find_token(document.body, "\\begin_layout Author affiliation", i)
2256 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
2260 def revert_IJMP(document):
2261 "Reverts InsetArgument of MarkBoth to TeX-code"
2262 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
2265 i = find_token(document.body, "\\begin_layout MarkBoth", i)
2268 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
2272 def convert_IJMP(document):
2273 "Converts ERT of MarkBoth to InsetArgument"
2274 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
2277 i = find_token(document.body, "\\begin_layout MarkBoth", i)
2280 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
2284 def revert_SIGPLAN(document):
2285 "Reverts InsetArguments of SIGPLAN to TeX-code"
2286 if document.textclass == "sigplanconf":
2291 i = find_token(document.body, "\\begin_layout Conference", i)
2293 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
2296 j = find_token(document.body, "\\begin_layout Author", j)
2298 revert_Argument_to_TeX_brace(document, j, 0, 1, 2, False, False)
2300 if i == -1 and j == -1:
2304 def convert_SIGPLAN(document):
2305 "Converts ERT of SIGPLAN to InsetArgument"
2306 if document.textclass == "sigplanconf":
2311 i = find_token(document.body, "\\begin_layout Conference", i)
2313 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
2316 j = find_token(document.body, "\\begin_layout Author", j)
2318 convert_TeX_brace_to_Argument(document, j, 1, 2, False, False, False)
2320 if i == -1 and j == -1:
2324 def revert_SIGGRAPH(document):
2325 "Reverts InsetArgument of Flex CRcat to TeX-code"
2326 if document.textclass == "acmsiggraph":
2329 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
2332 revert_Argument_to_TeX_brace(document, i, 0, 1, 3, False, False)
2336 def convert_SIGGRAPH(document):
2337 "Converts ERT of Flex CRcat to InsetArgument"
2338 if document.textclass == "acmsiggraph":
2341 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
2344 convert_TeX_brace_to_Argument(document, i, 1, 3, True, False, False)
2348 def revert_EuropeCV(document):
2349 "Reverts InsetArguments of europeCV to TeX-code"
2350 if document.textclass == "europecv":
2357 i = find_token(document.body, "\\begin_layout Item", i)
2359 revert_Argument_to_TeX_brace(document, i, 0, 2, 2, False, False)
2362 j = find_token(document.body, "\\begin_layout BulletedItem", j)
2364 revert_Argument_to_TeX_brace(document, j, 0, 2, 2, False, False)
2367 k = find_token(document.body, "\\begin_layout Language", k)
2369 revert_Argument_to_TeX_brace(document, k, 0, 2, 6, False, False)
2372 m = find_token(document.body, "\\begin_layout LastLanguage", m)
2374 revert_Argument_to_TeX_brace(document, m, 0, 2, 6, False, False)
2376 if i == -1 and j == -1 and k == -1 and m == -1:
2380 def convert_EuropeCV(document):
2381 "Converts ERT of europeCV to InsetArgument"
2382 if document.textclass == "europecv":
2389 i = find_token(document.body, "\\begin_layout Item", i)
2391 convert_TeX_brace_to_Argument(document, i, 2, 2, False, False, False)
2394 j = find_token(document.body, "\\begin_layout BulletedItem", j)
2396 convert_TeX_brace_to_Argument(document, j, 2, 2, False, False, False)
2399 k = find_token(document.body, "\\begin_layout Language", k)
2401 convert_TeX_brace_to_Argument(document, k, 2, 6, False, False, False)
2404 m = find_token(document.body, "\\begin_layout LastLanguage", m)
2406 convert_TeX_brace_to_Argument(document, m, 2, 6, False, False, False)
2408 if i == -1 and j == -1 and k == -1 and m == -1:
2412 def revert_ModernCV(document):
2413 "Reverts InsetArguments of modernCV to TeX-code"
2414 if document.textclass == "moderncv":
2422 j = find_token(document.body, "\\begin_layout Entry", j)
2424 revert_Argument_to_TeX_brace(document, j, 0, 1, 5, False, False)
2427 k = find_token(document.body, "\\begin_layout Item", k)
2429 revert_Argument_to_TeX_brace(document, k, 0, 1, 1, False, False)
2432 m = find_token(document.body, "\\begin_layout ItemWithComment", m)
2434 revert_Argument_to_TeX_brace(document, m, 0, 1, 2, False, False)
2435 document.body[m] = document.body[m].replace(
2436 "\\begin_layout ItemWithComment", "\\begin_layout Language"
2440 o = find_token(document.body, "\\begin_layout DoubleItem", o)
2442 revert_Argument_to_TeX_brace(document, o, 0, 1, 3, False, False)
2443 document.body[o] = document.body[o].replace(
2444 "\\begin_layout DoubleItem", "\\begin_layout Computer"
2448 p = find_token(document.body, "\\begin_layout Social", p)
2450 revert_Argument_to_TeX_brace(document, p, 0, 1, 1, False, True)
2452 if j == -1 and k == -1 and m == -1 and o == -1 and p == -1:
2456 def revert_ModernCV_2(document):
2457 "Reverts the Flex:Column inset of modernCV to TeX-code"
2458 if document.textclass == "moderncv":
2462 flex = find_token(document.body, "\\begin_inset Flex Column", flex)
2465 flexEnd = find_end_of_inset(document.body, flex)
2466 wasOpt = revert_Argument_to_TeX_brace(document, flex, flexEnd, 1, 1, False, True)
2467 revert_Argument_to_TeX_brace(document, flex, 0, 2, 2, False, False)
2468 flexEnd = find_end_of_inset(document.body, flex)
2470 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn")
2472 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn{")
2473 document.body[flexEnd + 4 : flexEnd + 7] = put_cmd_in_ert("}")
2477 def revert_ModernCV_3(document):
2478 "Reverts the Column style of modernCV to TeX-code"
2479 if document.textclass == "moderncv":
2480 # revert the layouts
2481 revert_ModernCV(document)
2483 # get the position of the end of the last column inset
2484 LastFlexEnd = revert_ModernCV_2(document)
2486 p = find_token(document.body, "\\begin_layout Columns", p)
2489 pEnd = find_end_of_layout(document.body, p)
2490 document.body[p] = document.body[p].replace(
2491 "\\begin_layout Columns", "\\begin_layout Standard"
2493 if LastFlexEnd != -1:
2494 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\begin{cvcolumns}")
2495 document.body[LastFlexEnd + 24 : LastFlexEnd + 24] = put_cmd_in_ert(
2501 def revert_ModernCV_4(document):
2502 "Reverts the style Social to TeX-code"
2503 if document.textclass == "moderncv":
2504 # revert the layouts
2505 revert_ModernCV(document)
2508 p = find_token(document.body, "\\begin_layout Social", p)
2511 pEnd = find_end_of_layout(document.body, p)
2512 document.body[p] = document.body[p].replace(
2513 "\\begin_layout Social", "\\begin_layout Standard"
2515 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\social")
2516 hasOpt = find_token(document.body, "[", p + 9)
2518 document.body[p + 30 : p + 30] = put_cmd_in_ert("{")
2519 document.body[p + 41 : p + 41] = put_cmd_in_ert("}")
2521 document.body[p + 11 : p + 11] = put_cmd_in_ert("{")
2522 document.body[p + 21 : p + 21] = put_cmd_in_ert("}")
2526 def convert_ModernCV(document):
2527 "Converts ERT of modernCV to InsetArgument"
2528 if document.textclass == "moderncv":
2536 i = find_token(document.body, "\\begin_layout DoubleItem", i)
2538 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
2539 document.body[o] = document.body[o].replace(
2540 "\\begin_layout DoubleItem", "\\begin_layout DoubleListItem"
2544 j = find_token(document.body, "\\begin_layout Entry", j)
2546 convert_TeX_brace_to_Argument(document, j, 1, 5, False, False, False)
2549 k = find_token(document.body, "\\begin_layout Item", k)
2551 convert_TeX_brace_to_Argument(document, k, 1, 1, False, False, False)
2554 m = find_token(document.body, "\\begin_layout Language", m)
2556 convert_TeX_brace_to_Argument(document, m, 1, 2, False, False, False)
2558 if i == -1 and j == -1 and k == -1 and m == -1:
2562 def revert_Initials(document):
2563 "Reverts InsetArgument of Initial to TeX-code"
2566 i = find_token(document.body, "\\begin_layout Initial", i)
2569 # first arg (optional) and second arg (first mandatory) are supported in LyX 2.0.x
2570 revert_Argument_to_TeX_brace(document, i, 0, 3, 3, False, False)
2574 def convert_Initials(document):
2575 "Converts ERT of Initial to InsetArgument"
2578 i = find_token(document.body, "\\begin_layout Initial", i)
2581 convert_TeX_brace_to_Argument(document, i, 3, 3, False, False, False)
2585 def revert_literate(document):
2586 "Revert Literate document to old format"
2587 if del_token(document.header, "noweb", 0):
2588 document.textclass = "literate-" + document.textclass
2591 i = find_token(document.body, "\\begin_layout Chunk", i)
2594 document.body[i] = "\\begin_layout Scrap"
2598 def convert_literate(document):
2599 "Convert Literate document to new format"
2600 i = find_token(document.header, "\\textclass", 0)
2601 if (i != -1) and "literate-" in document.header[i]:
2602 document.textclass = document.header[i].replace("\\textclass literate-", "")
2603 j = find_token(document.header, "\\begin_modules", 0)
2605 document.header.insert(j + 1, "noweb")
2607 document.header.insert(i + 1, "\\end_modules")
2608 document.header.insert(i + 1, "noweb")
2609 document.header.insert(i + 1, "\\begin_modules")
2612 i = find_token(document.body, "\\begin_layout Scrap", i)
2615 document.body[i] = "\\begin_layout Chunk"
2619 def revert_itemargs(document):
2620 "Reverts \\item arguments to TeX-code"
2623 i = find_token(document.body, "\\begin_inset Argument item:", i)
2626 j = find_end_of_inset(document.body, i)
2627 # Find containing paragraph layout
2628 parent = get_containing_layout(document.body, i)
2630 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2634 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2635 endPlain = find_end_of_layout(document.body, beginPlain)
2636 content = document.body[beginPlain + 1 : endPlain]
2637 del document.body[i : j + 1]
2638 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2639 document.body[parbeg:parbeg] = subst
2643 def revert_garamondx_newtxmath(document):
2644 "Revert native garamond newtxmath definition to LaTeX"
2646 i = find_token(document.header, "\\font_math", 0)
2649 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2650 val = get_value(document.header, "\\font_math", i)
2651 if val == "garamondx-ntxm":
2652 add_to_preamble(document, "\\usepackage[garamondx]{newtxmath}")
2653 document.header[i] = "\\font_math auto"
2656 def revert_garamondx(document):
2657 "Revert native garamond font definition to LaTeX"
2659 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2660 i = find_token(document.header, "\\font_roman garamondx", 0)
2663 j = find_token(document.header, "\\font_osf true", 0)
2666 preamble = "\\usepackage"
2668 preamble += "[osfI]"
2669 preamble += "{garamondx}"
2670 add_to_preamble(document, [preamble])
2671 document.header[i] = "\\font_roman default"
2674 def convert_beamerargs(document):
2675 "Converts beamer arguments to new layout"
2677 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2678 if document.textclass not in beamer_classes:
2681 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2682 list_layouts = ["Itemize", "Enumerate", "Description"]
2683 rx = re.compile(r"^\\begin_inset Argument (\d+)$")
2687 i = find_token(document.body, "\\begin_inset Argument", i)
2690 # Find containing paragraph layout
2691 parent = get_containing_layout(document.body, i)
2693 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2698 layoutname = parent[0]
2699 for p in range(parbeg, parend):
2700 if layoutname in shifted_layouts:
2701 m = rx.match(document.body[p])
2703 argnr = int(m.group(1))
2705 document.body[p] = "\\begin_inset Argument %d" % argnr
2706 if layoutname == "AgainFrame":
2707 m = rx.match(document.body[p])
2709 document.body[p] = "\\begin_inset Argument 3"
2710 if document.body[p + 4] == "\\begin_inset ERT":
2711 if document.body[p + 9].startswith("<"):
2712 # This is an overlay specification
2714 document.body[p + 9] = document.body[p + 9][1:]
2715 if document.body[p + 9].endswith(">"):
2717 document.body[p + 9] = document.body[p + 9][:-1]
2719 document.body[p] = "\\begin_inset Argument 2"
2720 if layoutname in list_layouts:
2721 m = rx.match(document.body[p])
2723 if m.group(1) == "1":
2724 if document.body[p + 4] == "\\begin_inset ERT":
2725 if document.body[p + 9].startswith("<"):
2726 # This is an overlay specification
2728 document.body[p + 9] = document.body[p + 9][1:]
2729 if document.body[p + 9].endswith(">"):
2731 document.body[p + 9] = document.body[p + 9][:-1]
2732 elif document.body[p + 4].startswith("<"):
2733 # This is an overlay specification (without ERT)
2735 document.body[p + 4] = document.body[p + 4][1:]
2736 if document.body[p + 4].endswith(">"):
2738 document.body[p + 4] = document.body[p + 4][:-1]
2739 elif layoutname != "Itemize":
2741 document.body[p] = "\\begin_inset Argument 2"
2746 # Helper function for the frame conversion routines
2748 # FIXME: This method currently requires the arguments to be either
2749 # * In one (whole) ERT each: <ERT>[<arg1>]</ERT><ERT><arg2></ERT><ERT>[arg3]</ERT>
2750 # * Altogether in one whole ERT: <ERT>[<arg1>]<arg2>[arg3]</ERT>
2751 # If individual arguments mix ERT and non-ERT or are splitted
2752 # over several ERTs, the parsing fails.
2753 def convert_beamerframeargs(document, i, parbeg):
2756 if document.body[parbeg] != "\\begin_inset ERT":
2758 ertend = find_end_of_inset(document.body, parbeg)
2760 document.warning("Malformed LyX document: missing ERT \\end_inset")
2762 ertcont = parbeg + 5
2763 if document.body[ertcont].startswith("[<"):
2764 # This is a default overlay specification
2766 document.body[ertcont] = document.body[ertcont][2:]
2767 if document.body[ertcont].endswith(">]"):
2769 document.body[ertcont] = document.body[ertcont][:-2]
2770 elif document.body[ertcont].endswith("]"):
2772 tok = document.body[ertcont].find(">][")
2775 document.body[ertcont][:tok],
2781 "\\begin_inset Argument 3",
2784 "\\begin_layout Plain Layout",
2785 document.body[ertcont][tok + 3 : -1],
2787 document.body[ertcont : ertcont + 1] = subst
2789 # Convert to ArgInset
2790 document.body[parbeg] = "\\begin_inset Argument 2"
2791 elif document.body[ertcont].startswith("<"):
2792 # This is an overlay specification
2794 document.body[ertcont] = document.body[ertcont][1:]
2795 if document.body[ertcont].endswith(">"):
2797 document.body[ertcont] = document.body[ertcont][:-1]
2798 # Convert to ArgInset
2799 document.body[parbeg] = "\\begin_inset Argument 1"
2800 elif document.body[ertcont].endswith(">]"):
2802 tok = document.body[ertcont].find(">[<")
2804 document.body[ertcont : ertcont + 1] = [
2805 document.body[ertcont][:tok],
2811 "\\begin_inset Argument 2",
2814 "\\begin_layout Plain Layout",
2815 document.body[ertcont][tok + 3 : -2],
2817 # Convert to ArgInset
2818 document.body[parbeg] = "\\begin_inset Argument 1"
2820 elif document.body[ertcont].endswith("]"):
2822 tok = document.body[ertcont].find(">[<")
2825 tokk = document.body[ertcont].find(">][")
2827 document.body[ertcont : ertcont + 1] = [
2828 document.body[ertcont][:tok],
2834 "\\begin_inset Argument 2",
2837 "\\begin_layout Plain Layout",
2838 document.body[ertcont][tok + 3 : tokk],
2844 "\\begin_inset Argument 3",
2847 "\\begin_layout Plain Layout",
2848 document.body[ertcont][tokk + 3 : -1],
2852 tokk = document.body[ertcont].find(">[")
2854 document.body[ertcont : ertcont + 1] = [
2855 document.body[ertcont][:tokk],
2861 "\\begin_inset Argument 3",
2864 "\\begin_layout Plain Layout",
2865 document.body[ertcont][tokk + 2 : -1],
2868 # Convert to ArgInset
2869 document.body[parbeg] = "\\begin_inset Argument 1"
2870 elif document.body[ertcont].startswith("["):
2871 # This is an ERT option
2873 document.body[ertcont] = document.body[ertcont][1:]
2874 if document.body[ertcont].endswith("]"):
2876 document.body[ertcont] = document.body[ertcont][:-1]
2877 # Convert to ArgInset
2878 document.body[parbeg] = "\\begin_inset Argument 3"
2884 def convert_againframe_args(document):
2885 "Converts beamer AgainFrame to new layout"
2887 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2888 if document.textclass not in beamer_classes:
2893 i = find_token(document.body, "\\begin_layout AgainFrame", i)
2896 parent = get_containing_layout(document.body, i)
2898 document.warning("Wrong parent layout!")
2902 # Convert ERT arguments
2903 # FIXME: See restrictions in convert_beamerframeargs method
2904 ertend = convert_beamerframeargs(document, i, parbeg)
2910 def convert_corollary_args(document):
2911 "Converts beamer corrolary-style ERT arguments native InsetArgs"
2913 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2914 if document.textclass not in beamer_classes:
2917 corollary_layouts = [
2927 for lay in corollary_layouts:
2930 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2933 parent = get_containing_layout(document.body, i)
2935 document.warning("Wrong parent layout!")
2939 if document.body[parbeg] == "\\begin_inset ERT":
2940 ertcontfirstline = parbeg + 5
2941 # Find the last ERT in this paragraph (which might also be the first)
2942 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
2943 if lastertbeg == -1:
2944 document.warning("Last ERT not found!")
2946 lastertend = find_end_of_inset(document.body, lastertbeg)
2947 if lastertend == -1:
2948 document.warning("End of last ERT not found!")
2950 ertcontlastline = lastertend - 3
2951 if document.body[ertcontfirstline].startswith("<"):
2952 # This is an overlay specification
2954 document.body[ertcontfirstline] = document.body[ertcontfirstline][1:]
2955 if document.body[ertcontlastline].endswith(">"):
2957 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
2958 if ertcontfirstline < ertcontlastline:
2959 # Multiline ERT. Might contain TeX code. Embrace in ERT.
2960 document.body[ertcontlastline : ertcontlastline + 1] = [
2961 document.body[ertcontlastline],
2966 document.body[ertcontfirstline : ertcontfirstline + 1] = [
2972 "\\begin_inset Argument 1",
2975 "\\begin_layout Plain Layout",
2976 "\\begin_inset ERT",
2979 "\\begin_layout Plain Layout",
2980 document.body[ertcontfirstline],
2983 # Convert to ArgInset
2984 document.body[parbeg] = "\\begin_inset Argument 1"
2985 elif document.body[ertcontlastline].endswith("]"):
2987 tok = document.body[ertcontfirstline].find(">[")
2989 if ertcontfirstline < ertcontlastline:
2990 # Multiline ERT. Might contain TeX code. Embrace in ERT.
2991 document.body[ertcontlastline : ertcontlastline + 1] = [
2992 document.body[ertcontlastline],
2997 document.body[ertcontfirstline : ertcontfirstline + 1] = [
2998 document.body[ertcontfirstline][:tok],
3004 "\\begin_inset Argument 2",
3007 "\\begin_layout Plain Layout",
3008 "\\begin_inset ERT",
3011 "\\begin_layout Plain Layout",
3012 document.body[ertcontfirstline][tok + 2 : -1],
3015 document.body[ertcontfirstline : ertcontfirstline + 1] = [
3016 document.body[ertcontfirstline][:tok],
3022 "\\begin_inset Argument 2",
3025 "\\begin_layout Plain Layout",
3026 document.body[ertcontfirstline][tok + 2 : -1],
3028 # Convert to ArgInset
3029 document.body[parbeg] = "\\begin_inset Argument 1"
3032 elif document.body[ertcontlastline].startswith("["):
3033 if document.body[ertcontlastline].endswith("]"):
3034 # This is an ERT option
3036 document.body[ertcontlastline] = document.body[ertcontlastline][1:]
3038 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
3039 # Convert to ArgInset
3040 document.body[parbeg] = "\\begin_inset Argument 2"
3042 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, True)
3048 def convert_quote_args(document):
3049 "Converts beamer quote style ERT args to native InsetArgs"
3051 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3052 if document.textclass not in beamer_classes:
3055 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
3056 for lay in quote_layouts:
3059 i = find_token(document.body, "\\begin_layout " + lay, i)
3062 parent = get_containing_layout(document.body, i)
3064 document.warning("Wrong parent layout!")
3068 if document.body[parbeg] == "\\begin_inset ERT":
3069 if document.body[i + 6].startswith("<"):
3070 # This is an overlay specification
3072 document.body[i + 6] = document.body[i + 6][1:]
3073 if document.body[i + 6].endswith(">"):
3075 document.body[i + 6] = document.body[i + 6][:-1]
3076 # Convert to ArgInset
3077 document.body[i + 1] = "\\begin_inset Argument 1"
3081 def cleanup_beamerargs(document):
3082 "Clean up empty ERTs (conversion artefacts)"
3084 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3085 if document.textclass not in beamer_classes:
3090 i = find_token(document.body, "\\begin_inset Argument", i)
3093 j = find_end_of_inset(document.body, i)
3095 document.warning("Malformed LyX document: Can't find end of Argument inset")
3099 ertbeg = find_token(document.body, "\\begin_inset ERT", i, j)
3102 ertend = find_end_of_inset(document.body, ertbeg)
3104 document.warning("Malformed LyX document: Can't find end of ERT inset")
3106 stripped = [line for line in document.body[ertbeg : ertend + 1] if line.strip()]
3107 if len(stripped) == 5:
3108 # This is an empty ERT
3109 offset = len(document.body[ertbeg : ertend + 1])
3110 del document.body[ertbeg : ertend + 1]
3117 def revert_beamerargs(document):
3118 "Reverts beamer arguments to old layout"
3120 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3121 if document.textclass not in beamer_classes:
3125 list_layouts = ["Itemize", "Enumerate", "Description"]
3137 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
3138 corollary_layouts = [
3148 rx = re.compile(r"^\\begin_inset Argument (\S+)$")
3151 i = find_token(document.body, "\\begin_inset Argument", i)
3154 # Find containing paragraph layout
3155 parent = get_containing_layout(document.body, i)
3157 document.warning("Malformed LyX document: Can't find parent paragraph layout")
3162 realparbeg = parent[3]
3163 layoutname = parent[0]
3165 for p in range(parbeg, parend):
3169 if layoutname in headings:
3170 m = rx.match(document.body[p])
3174 # Find containing paragraph layout
3175 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3176 endPlain = find_end_of_layout(document.body, beginPlain)
3177 endInset = find_end_of_inset(document.body, p)
3178 argcontent = document.body[beginPlain + 1 : endPlain]
3180 realparend = realparend - len(document.body[p : endInset + 1])
3182 del document.body[p : endInset + 1]
3183 if layoutname == "FrameSubtitle":
3185 put_cmd_in_ert("\\" + layoutname.lower() + "<")
3187 + put_cmd_in_ert(">")
3189 elif layoutname == "NoteItem":
3191 put_cmd_in_ert("\\note<")
3193 + put_cmd_in_ert(">[item]")
3195 elif layoutname.endswith("*"):
3198 "\\lyxframeend\\" + layoutname.lower()[:-1] + "<"
3201 + put_cmd_in_ert(">*")
3205 put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower() + "<")
3207 + put_cmd_in_ert(">")
3209 secarg = find_token(
3210 document.body, "\\begin_inset Argument 2", parbeg, parend
3213 # Find containing paragraph layout
3214 beginPlain = find_token(
3215 document.body, "\\begin_layout Plain Layout", secarg
3217 endPlain = find_end_of_layout(document.body, beginPlain)
3218 endInset = find_end_of_inset(document.body, secarg)
3219 argcontent = document.body[beginPlain + 1 : endPlain]
3221 realparend = realparend - len(document.body[secarg : endInset + 1])
3222 del document.body[secarg : endInset + 1]
3223 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
3224 pre += put_cmd_in_ert("{")
3225 document.body[parbeg] = "\\begin_layout Standard"
3226 document.body[realparbeg:realparbeg] = pre
3227 pe = find_end_of_layout(document.body, parbeg)
3228 post = put_cmd_in_ert("}")
3229 document.body[pe:pe] = post
3230 realparend += len(pre) + len(post)
3231 if layoutname == "AgainFrame":
3232 m = rx.match(document.body[p])
3236 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3237 endPlain = find_end_of_layout(document.body, beginPlain)
3238 endInset = find_end_of_inset(document.body, p)
3239 content = document.body[beginPlain + 1 : endPlain]
3241 realparend = realparend - len(document.body[p : endInset + 1])
3243 del document.body[p : endInset + 1]
3244 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3245 document.body[realparbeg:realparbeg] = subst
3246 if layoutname == "Overprint":
3247 m = rx.match(document.body[p])
3251 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3252 endPlain = find_end_of_layout(document.body, beginPlain)
3253 endInset = find_end_of_inset(document.body, p)
3254 content = document.body[beginPlain + 1 : endPlain]
3256 realparend = realparend - len(document.body[p : endInset + 1])
3258 del document.body[p : endInset + 1]
3259 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3260 document.body[realparbeg:realparbeg] = subst
3261 if layoutname == "OverlayArea":
3262 m = rx.match(document.body[p])
3266 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3267 endPlain = find_end_of_layout(document.body, beginPlain)
3268 endInset = find_end_of_inset(document.body, p)
3269 content = document.body[beginPlain + 1 : endPlain]
3271 realparend = realparend - len(document.body[p : endInset + 1])
3273 del document.body[p : endInset + 1]
3274 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3275 document.body[realparbeg:realparbeg] = subst
3276 if layoutname in list_layouts:
3277 m = rx.match(document.body[p])
3281 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3282 endPlain = find_end_of_layout(document.body, beginPlain)
3283 endInset = find_end_of_inset(document.body, p)
3284 content = document.body[beginPlain + 1 : endPlain]
3285 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3286 realparend = realparend + len(subst) - len(content)
3287 document.body[beginPlain + 1 : endPlain] = subst
3288 elif argnr == "item:1":
3289 j = find_end_of_inset(document.body, i)
3290 # Find containing paragraph layout
3291 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
3292 endPlain = find_end_of_layout(document.body, beginPlain)
3293 content = document.body[beginPlain + 1 : endPlain]
3294 del document.body[i : j + 1]
3295 if layoutname == "Description":
3296 # Description only has one (overlay) item arg
3297 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3298 # This must be put after the first space (begin of decription body
3299 # in LyX's arkward description list syntax)
3300 # Try to find that place ...
3301 rxx = re.compile(r"^([^\\ ]+ )(.*)$")
3302 for q in range(parbeg, parend):
3303 m = rxx.match(document.body[q])
3305 # We found it. Now insert the ERT argument just there:
3306 document.body[q:q] = (
3307 [m.group(1), ""] + subst + ["", m.group(2)]
3311 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3312 document.body[realparbeg:realparbeg] = subst
3313 elif argnr == "item:2":
3314 j = find_end_of_inset(document.body, i)
3315 # Find containing paragraph layout
3316 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
3317 endPlain = find_end_of_layout(document.body, beginPlain)
3318 content = document.body[beginPlain + 1 : endPlain]
3319 del document.body[i : j + 1]
3320 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3321 document.body[realparbeg:realparbeg] = subst
3322 if layoutname in quote_layouts:
3323 m = rx.match(document.body[p])
3327 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3328 endPlain = find_end_of_layout(document.body, beginPlain)
3329 endInset = find_end_of_inset(document.body, p)
3330 content = document.body[beginPlain + 1 : endPlain]
3332 realparend = realparend - len(document.body[p : endInset + 1])
3334 del document.body[p : endInset + 1]
3335 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3336 document.body[realparbeg:realparbeg] = subst
3337 if layoutname in corollary_layouts:
3338 m = rx.match(document.body[p])
3342 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3343 endPlain = find_end_of_layout(document.body, beginPlain)
3344 endInset = find_end_of_inset(document.body, p)
3345 content = document.body[beginPlain + 1 : endPlain]
3347 realparend = realparend - len(document.body[p : endInset + 1])
3349 del document.body[p : endInset + 1]
3350 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3351 document.body[realparbeg:realparbeg] = subst
3356 def revert_beamerargs2(document):
3357 "Reverts beamer arguments to old layout, step 2"
3359 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3360 if document.textclass not in beamer_classes:
3364 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
3365 corollary_layouts = [
3375 rx = re.compile(r"^\\begin_inset Argument (\S+)$")
3378 i = find_token(document.body, "\\begin_inset Argument", i)
3381 # Find containing paragraph layout
3382 parent = get_containing_layout(document.body, i)
3384 document.warning("Malformed LyX document: Can't find parent paragraph layout")
3389 realparbeg = parent[3]
3390 layoutname = parent[0]
3392 for p in range(parbeg, parend):
3396 if layoutname in shifted_layouts:
3397 m = rx.match(document.body[p])
3401 document.body[p] = "\\begin_inset Argument 1"
3402 if layoutname in corollary_layouts:
3403 m = rx.match(document.body[p])
3407 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3408 endPlain = find_end_of_layout(document.body, beginPlain)
3409 endInset = find_end_of_inset(document.body, p)
3410 content = document.body[beginPlain + 1 : endPlain]
3412 realparend = realparend - len(document.body[p : endInset + 1])
3414 del document.body[p : endInset + 1]
3415 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3416 document.body[realparbeg:realparbeg] = subst
3417 if layoutname == "OverlayArea":
3418 m = rx.match(document.body[p])
3422 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3423 endPlain = find_end_of_layout(document.body, beginPlain)
3424 endInset = find_end_of_inset(document.body, p)
3425 content = document.body[beginPlain + 1 : endPlain]
3427 realparend = realparend - len(document.body[p : endInset + 1])
3429 del document.body[p : endInset + 1]
3430 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3431 document.body[realparbeg:realparbeg] = subst
3432 if layoutname == "AgainFrame":
3433 m = rx.match(document.body[p])
3437 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3438 endPlain = find_end_of_layout(document.body, beginPlain)
3439 endInset = find_end_of_inset(document.body, p)
3440 content = document.body[beginPlain + 1 : endPlain]
3442 realparend = realparend - len(document.body[p : endInset + 1])
3444 del document.body[p : endInset + 1]
3445 subst = put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3446 document.body[realparbeg:realparbeg] = subst
3450 def revert_beamerargs3(document):
3451 "Reverts beamer arguments to old layout, step 3"
3453 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3454 if document.textclass not in beamer_classes:
3457 rx = re.compile(r"^\\begin_inset Argument (\S+)$")
3460 i = find_token(document.body, "\\begin_inset Argument", i)
3463 # Find containing paragraph layout
3464 parent = get_containing_layout(document.body, i)
3466 document.warning("Malformed LyX document: Can't find parent paragraph layout")
3471 realparbeg = parent[3]
3472 layoutname = parent[0]
3474 for p in range(parbeg, parend):
3478 if layoutname == "AgainFrame":
3479 m = rx.match(document.body[p])
3483 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3484 endPlain = find_end_of_layout(document.body, beginPlain)
3485 endInset = find_end_of_inset(document.body, p)
3486 content = document.body[beginPlain + 1 : endPlain]
3488 realparend = realparend - len(document.body[p : endInset + 1])
3490 del document.body[p : endInset + 1]
3491 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3492 document.body[realparbeg:realparbeg] = subst
3496 def revert_beamerflex(document):
3497 "Reverts beamer Flex insets"
3499 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3500 if document.textclass not in beamer_classes:
3505 "Emphasize": "\\emph",
3507 "Uncover": "\\uncover",
3508 "Visible": "\\visible",
3509 "Invisible": "\\invisible",
3510 "Alternative": "\\alt",
3511 "Beamer_Note": "\\note",
3513 old_flexes = {"Alert": "\\alert", "Structure": "\\structure"}
3514 rx = re.compile(r"^\\begin_inset Flex (.+)$")
3518 i = find_token(document.body, "\\begin_inset Flex", i)
3521 m = rx.match(document.body[i])
3523 flextype = m.group(1)
3524 z = find_end_of_inset(document.body, i)
3526 document.warning("Can't find end of Flex " + flextype + " inset.")
3529 if flextype in new_flexes:
3530 pre = put_cmd_in_ert(new_flexes[flextype])
3531 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
3533 argend = find_end_of_inset(document.body, arg)
3535 document.warning("Can't find end of Argument!")
3538 # Find containing paragraph layout
3539 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3540 endPlain = find_end_of_layout(document.body, beginPlain)
3541 argcontent = document.body[beginPlain + 1 : endPlain]
3543 z = z - len(document.body[arg : argend + 1])
3545 del document.body[arg : argend + 1]
3546 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
3547 arg = find_token(document.body, "\\begin_inset Argument 2", i, z)
3549 argend = find_end_of_inset(document.body, arg)
3551 document.warning("Can't find end of Argument!")
3554 # Find containing paragraph layout
3555 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3556 endPlain = find_end_of_layout(document.body, beginPlain)
3557 argcontent = document.body[beginPlain + 1 : endPlain]
3559 z = z - len(document.body[arg : argend + 1])
3561 del document.body[arg : argend + 1]
3562 if flextype == "Alternative":
3563 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
3565 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
3566 pre += put_cmd_in_ert("{")
3567 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
3568 endPlain = find_end_of_layout(document.body, beginPlain)
3570 z = z - len(document.body[i : beginPlain + 1])
3572 document.body[i : beginPlain + 1] = pre
3573 post = put_cmd_in_ert("}")
3574 document.body[z - 2 : z + 1] = post
3575 elif flextype in old_flexes:
3576 pre = put_cmd_in_ert(old_flexes[flextype])
3577 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
3581 argend = find_end_of_inset(document.body, arg)
3583 document.warning("Can't find end of Argument!")
3586 # Find containing paragraph layout
3587 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3588 endPlain = find_end_of_layout(document.body, beginPlain)
3589 argcontent = document.body[beginPlain + 1 : endPlain]
3591 z = z - len(document.body[arg : argend + 1])
3593 del document.body[arg : argend + 1]
3594 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
3595 pre += put_cmd_in_ert("{")
3596 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
3597 endPlain = find_end_of_layout(document.body, beginPlain)
3599 z = z - len(document.body[i : beginPlain + 1])
3601 document.body[i : beginPlain + 1] = pre
3602 post = put_cmd_in_ert("}")
3603 document.body[z - 2 : z + 1] = post
3608 def revert_beamerblocks(document):
3609 "Reverts beamer block arguments to ERT"
3611 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3612 if document.textclass not in beamer_classes:
3615 blocks = ["Block", "ExampleBlock", "AlertBlock"]
3617 rx = re.compile(r"^\\begin_inset Argument (\S+)$")
3620 i = find_token(document.body, "\\begin_inset Argument", i)
3623 # Find containing paragraph layout
3624 parent = get_containing_layout(document.body, i)
3626 document.warning("Malformed LyX document: Can't find parent paragraph layout")
3631 realparbeg = parent[3]
3632 layoutname = parent[0]
3634 for p in range(parbeg, parend):
3638 if layoutname in blocks:
3639 m = rx.match(document.body[p])
3643 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3644 endPlain = find_end_of_layout(document.body, beginPlain)
3645 endInset = find_end_of_inset(document.body, p)
3646 content = document.body[beginPlain + 1 : endPlain]
3648 realparend = realparend - len(document.body[p : endInset + 1])
3650 del document.body[p : endInset + 1]
3651 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3652 document.body[realparbeg:realparbeg] = subst
3654 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3655 endPlain = find_end_of_layout(document.body, beginPlain)
3656 endInset = find_end_of_inset(document.body, p)
3657 content = document.body[beginPlain + 1 : endPlain]
3659 realparend = realparend - len(document.body[p : endInset + 1])
3661 del document.body[p : endInset + 1]
3662 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3663 document.body[realparbeg:realparbeg] = subst
3667 def convert_beamerblocks(document):
3668 "Converts beamer block ERT args to native InsetArgs"
3670 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3671 if document.textclass not in beamer_classes:
3674 blocks = ["Block", "ExampleBlock", "AlertBlock"]
3678 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
3681 parent = get_containing_layout(document.body, i)
3682 if parent == False or parent[1] != i:
3683 document.warning("Wrong parent layout!")
3690 # If the paragraph starts with a language switch, adjust parbeg
3692 len(document.body[parbeg]) == 0
3694 and document.body[parbeg + 1].startswith("\\lang")
3697 if document.body[parbeg] == "\\begin_inset ERT":
3698 ertcontfirstline = parbeg + 5
3702 # Find the last ERT in this paragraph used for arguments
3703 # (which might also be the first)
3704 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
3705 if lastertbeg == -1:
3706 document.warning("Last ERT not found!")
3708 lastertend = find_end_of_inset(document.body, lastertbeg)
3709 if lastertend == -1:
3710 document.warning("End of last ERT not found!")
3712 # Is this ERT really used for an argument?
3713 # Note: This will fail when non-argument ERTs actually use brackets
3715 regexp = re.compile(r".*[>\]\}]", re.IGNORECASE)
3716 cbracket = find_re(document.body, regexp, lastertbeg, lastertend)
3719 if lastertbeg == parbeg:
3722 if lastertbeg == -1 or lastertend == -1:
3724 ertcontlastline = lastertend - 3
3726 if document.body[ertcontfirstline].lstrip().startswith("<"):
3727 # This is an overlay specification
3729 document.body[ertcontfirstline] = document.body[
3732 if document.body[ertcontlastline].rstrip().endswith(">"):
3734 document.body[ertcontlastline] = document.body[
3737 # Convert to ArgInset
3738 document.body[parbeg] = "\\begin_inset Argument 1"
3739 elif document.body[ertcontlastline].rstrip().endswith("}"):
3741 document.body[ertcontlastline] = document.body[
3745 ertcontdivline = ertcontfirstline
3746 tok = document.body[ertcontdivline].find(">{")
3748 regexp = re.compile(r".*>\{", re.IGNORECASE)
3749 ertcontdivline = find_re(
3755 tok = document.body[ertcontdivline].find(">{")
3757 if ertcontfirstline < ertcontlastline:
3758 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3759 document.body[ertcontlastline : ertcontlastline + 1] = [
3760 document.body[ertcontlastline],
3765 if ertcontdivline == ertcontfirstline:
3767 ertcontdivline : ertcontdivline + 1
3769 document.body[ertcontdivline][:tok],
3779 "\\begin_inset Argument 2",
3782 "\\begin_layout Plain Layout",
3783 "\\begin_inset ERT",
3786 "\\begin_layout Plain Layout",
3787 document.body[ertcontdivline][tok + 2 :],
3791 ertcontdivline : ertcontdivline + 1
3793 document.body[ertcontdivline][:tok],
3799 "\\begin_inset Argument 2",
3802 "\\begin_layout Plain Layout",
3803 "\\begin_inset ERT",
3806 "\\begin_layout Plain Layout",
3807 document.body[ertcontdivline][tok + 2 :],
3810 document.body[ertcontdivline : ertcontdivline + 1] = [
3811 document.body[ertcontdivline][:tok],
3817 "\\begin_inset Argument 2",
3820 "\\begin_layout Plain Layout",
3821 document.body[ertcontdivline][tok + 2 :],
3824 # check if have delimiters in two different ERTs
3825 tok = document.body[ertcontdivline].find(">")
3827 regexp = re.compile(r".*>", re.IGNORECASE)
3828 ertcontdivline = find_re(
3834 tok = document.body[ertcontdivline].find(">")
3836 tokk = document.body[ertcontdivline].find("{")
3838 regexp = re.compile(r".*\{", re.IGNORECASE)
3839 ertcontdivlinetwo = find_re(
3845 tokk = document.body[ertcontdivlinetwo].find("{")
3847 if ertcontfirstline < ertcontlastline:
3848 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3850 ertcontlastline : ertcontlastline + 1
3852 document.body[ertcontlastline],
3858 ertcontdivline : ertcontdivlinetwo + 1
3860 document.body[ertcontdivline][:tok],
3870 "\\begin_inset Argument 2",
3873 "\\begin_layout Plain Layout",
3874 "\\begin_inset ERT",
3877 "\\begin_layout Plain Layout",
3878 document.body[ertcontdivlinetwo][
3884 ertcontdivline : ertcontdivlinetwo + 1
3886 document.body[ertcontdivline][:tok],
3892 "\\begin_inset Argument 2",
3895 "\\begin_layout Plain Layout",
3896 document.body[ertcontdivlinetwo][
3900 # Convert to ArgInset
3901 if ertcontfirstline < ertcontlastline:
3902 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3903 document.body[parbeg : parbeg + 1] = [
3904 "\\begin_inset Argument 1",
3907 "\\begin_layout Plain Layout",
3908 "\\begin_inset ERT",
3912 document.body[parbeg] = "\\begin_inset Argument 1"
3913 elif document.body[ertcontfirstline].lstrip().startswith("{"):
3914 # This is the block title
3915 if document.body[ertcontlastline].rstrip().endswith("}"):
3916 # strip off the braces
3917 document.body[ertcontfirstline] = document.body[
3920 document.body[ertcontlastline] = document.body[
3923 if ertcontfirstline < ertcontlastline:
3924 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3925 document.body[parend : parend + 1] = [
3926 document.body[parend],
3931 document.body[parbeg : parbeg + 1] = [
3932 "\\begin_inset Argument 2",
3935 "\\begin_layout Plain Layout",
3936 "\\begin_inset ERT",
3940 # Convert to ArgInset
3941 document.body[parbeg] = "\\begin_inset Argument 2"
3942 # the overlay argument can also follow the title, so ...
3943 elif document.body[ertcontlastline].rstrip().endswith(">"):
3945 document.body[ertcontfirstline] = document.body[
3949 document.body[ertcontlastline] = document.body[
3953 ertcontdivline = ertcontfirstline
3954 tok = document.body[ertcontdivline].find("}<")
3956 regexp = re.compile(r".*\}<", re.IGNORECASE)
3957 ertcontdivline = find_re(
3963 tok = document.body[ertcontdivline].find("}<")
3965 if ertcontfirstline < ertcontlastline:
3966 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3967 document.body[ertcontlastline : ertcontlastline + 1] = [
3968 document.body[ertcontlastline],
3973 if ertcontdivline == ertcontfirstline:
3975 ertcontdivline : ertcontdivline + 1
3977 document.body[ertcontdivline][:tok],
3983 "\\begin_inset Argument 1",
3986 "\\begin_layout Plain Layout",
3987 "\\begin_inset ERT",
3990 "\\begin_layout Plain Layout",
3991 document.body[ertcontdivline][tok + 2 :],
3995 ertcontdivline : ertcontdivline + 1
3997 document.body[ertcontdivline][:tok],
4007 "\\begin_inset Argument 1",
4010 "\\begin_layout Plain Layout",
4011 "\\begin_inset ERT",
4014 "\\begin_layout Plain Layout",
4015 document.body[ertcontdivline][tok + 2 :],
4018 document.body[ertcontdivline : ertcontdivline + 1] = [
4019 document.body[ertcontdivline][:tok],
4025 "\\begin_inset Argument 1",
4028 "\\begin_layout Plain Layout",
4029 document.body[ertcontdivline][tok + 2 :],
4032 # check if have delimiters in two different ERTs
4033 tok = document.body[ertcontdivline].find("}")
4035 regexp = re.compile(r".*\}", re.IGNORECASE)
4036 ertcontdivline = find_re(
4042 tok = document.body[ertcontdivline].find("}")
4044 tokk = document.body[ertcontdivline].find("<")
4046 regexp = re.compile(r".*<", re.IGNORECASE)
4047 ertcontdivlinetwo = find_re(
4053 tokk = document.body[ertcontdivlinetwo].find(
4057 if ertcontfirstline < ertcontlastline:
4058 # Multiline ERT. Might contain TeX code. Embrace in ERT.
4060 ertcontlastline : ertcontlastline
4063 document.body[ertcontlastline],
4069 ertcontdivline : ertcontdivlinetwo
4072 document.body[ertcontdivline][:tok],
4082 "\\begin_inset Argument 1",
4085 "\\begin_layout Plain Layout",
4086 "\\begin_inset ERT",
4089 "\\begin_layout Plain Layout",
4090 document.body[ertcontdivlinetwo][
4096 ertcontdivline : ertcontdivlinetwo
4099 document.body[ertcontdivline][:tok],
4105 "\\begin_inset Argument 1",
4108 "\\begin_layout Plain Layout",
4109 document.body[ertcontdivlinetwo][
4113 # Convert to ArgInset
4114 if ertcontfirstline < ertcontlastline:
4115 # Multiline ERT. Might contain TeX code. Embrace in ERT.
4116 document.body[parbeg : parbeg + 1] = [
4117 "\\begin_inset Argument 2",
4120 "\\begin_layout Plain Layout",
4121 "\\begin_inset ERT",
4125 document.body[parbeg] = "\\begin_inset Argument 2"
4126 elif count_pars_in_inset(document.body, ertcontfirstline) > 1:
4127 # Multipar ERT. Skip this.
4130 # ERT has contents after the closing bracket. We cannot convert this.
4131 # convert_TeX_brace_to_Argument cannot either.
4132 # convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, False)
4136 j = find_end_of_layout(document.body, i)
4138 document.warning("end of layout not found!")
4139 k = find_token(document.body, "\\begin_inset Argument", i, j)
4141 document.warning("InsetArgument not found!")
4143 l = find_end_of_inset(document.body, k)
4144 m = find_token(document.body, "\\begin_inset ERT", l, j)
4147 ertcontfirstline = m + 5
4152 def convert_overprint(document):
4153 "Convert old beamer overprint layouts to ERT"
4155 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4156 if document.textclass not in beamer_classes:
4161 i = find_token(document.body, "\\begin_layout Overprint", i)
4164 # Find end of sequence
4165 j = find_end_of_sequence(document.body, i)
4167 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
4171 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
4173 if document.body[j] == "\\end_deeper":
4175 ["", "\\begin_layout Standard"]
4176 + put_cmd_in_ert("\\end{overprint}")
4181 ["\\end_layout", "", "\\begin_layout Standard"]
4182 + put_cmd_in_ert("\\end{overprint}")
4185 endseq = endseq + len(esubst) - len(document.body[j:j])
4186 document.body[j:j] = esubst
4187 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
4189 argend = find_end_of_layout(document.body, argbeg)
4192 "Malformed LyX document. Cannot find end of Overprint argument!"
4196 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
4197 endPlain = find_end_of_layout(document.body, beginPlain)
4198 content = document.body[beginPlain + 1 : endPlain]
4200 endseq = endseq - len(document.body[argbeg : argend + 1])
4202 del document.body[argbeg : argend + 1]
4203 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4205 endseq = endseq - len(document.body[i:i])
4206 document.body[i:i] = subst + ["\\end_layout"]
4207 endseq += len(subst)
4209 for p in range(i, endseq):
4210 if document.body[p] == "\\begin_layout Overprint":
4211 document.body[p] = "\\begin_layout Standard"
4216 def revert_overprint(document):
4217 "Revert old beamer overprint layouts to ERT"
4219 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4220 if document.textclass not in beamer_classes:
4225 i = find_token(document.body, "\\begin_layout Overprint", i)
4228 # Find end of sequence
4229 j = find_end_of_sequence(document.body, i)
4231 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
4235 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
4236 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}")
4237 endseq = endseq + len(esubst) - len(document.body[j:j])
4238 if document.body[j] == "\\end_deeper":
4239 document.body[j:j] = [""] + esubst + ["", "\\end_layout"]
4241 document.body[j:j] = ["\\end_layout", ""] + esubst
4244 if document.body[r] == "\\begin_deeper":
4245 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
4247 document.body[r] = ""
4248 document.body[s] = ""
4252 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
4254 # Is this really our argument?
4255 nested = find_token(document.body, "\\begin_deeper", i, argbeg)
4257 argend = find_end_of_inset(document.body, argbeg)
4260 "Malformed LyX document. Cannot find end of Overprint argument!"
4264 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
4265 endPlain = find_end_of_layout(document.body, beginPlain)
4266 content = document.body[beginPlain + 1 : endPlain]
4268 endseq = endseq - len(document.body[argbeg:argend])
4270 del document.body[argbeg : argend + 1]
4271 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4273 endseq = endseq - len(document.body[i:i])
4274 document.body[i:i] = subst + ["\\end_layout"]
4275 endseq += len(subst)
4281 if document.body[p] == "\\begin_layout Overprint":
4282 q = find_end_of_layout(document.body, p)
4285 "Malformed LyX document. Cannot find end of Overprint layout!"
4289 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\onslide")
4290 argbeg = find_token(document.body, "\\begin_inset Argument item:1", p, q)
4292 argend = find_end_of_inset(document.body, argbeg)
4295 "Malformed LyX document. Cannot find end of Overprint item argument!"
4299 beginPlain = find_token(
4300 document.body, "\\begin_layout Plain Layout", argbeg
4302 endPlain = find_end_of_layout(document.body, beginPlain)
4303 content = document.body[beginPlain + 1 : endPlain]
4305 endseq = endseq - len(document.body[argbeg : argend + 1])
4307 del document.body[argbeg : argend + 1]
4308 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
4309 endseq = endseq - len(document.body[p : p + 1]) + len(subst)
4310 document.body[p : p + 1] = subst
4316 def revert_frametitle(document):
4317 "Reverts beamer frametitle layout to ERT"
4319 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4320 if document.textclass not in beamer_classes:
4323 rx = re.compile(r"^\\begin_inset Argument (\S+)$")
4326 i = find_token(document.body, "\\begin_layout FrameTitle", i)
4329 j = find_end_of_layout(document.body, i)
4331 document.warning("Malformed LyX document: Can't find end of FrameTitle layout")
4335 document.body[j:j] = put_cmd_in_ert("}") + document.body[j:j]
4336 endlay += len(put_cmd_in_ert("}"))
4337 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\frametitle")
4338 for p in range(i, j):
4341 m = rx.match(document.body[p])
4345 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4346 endPlain = find_end_of_layout(document.body, beginPlain)
4347 endInset = find_end_of_inset(document.body, p)
4348 content = document.body[beginPlain + 1 : endPlain]
4350 endlay = endlay - len(document.body[p : endInset + 1])
4352 del document.body[p : endInset + 1]
4353 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
4355 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4356 endPlain = find_end_of_layout(document.body, beginPlain)
4357 endInset = find_end_of_inset(document.body, p)
4358 content = document.body[beginPlain + 1 : endPlain]
4360 endlay = endlay - len(document.body[p : endInset + 1])
4362 del document.body[p : endInset + 1]
4363 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4365 subst += put_cmd_in_ert("{")
4366 document.body[i : i + 1] = subst
4370 def convert_epigraph(document):
4371 "Converts memoir epigraph to new syntax"
4373 if document.textclass != "memoir":
4378 i = find_token(document.body, "\\begin_layout Epigraph", i)
4381 j = find_end_of_layout(document.body, i)
4383 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
4388 ert = find_token(document.body, "\\begin_inset ERT", i, j)
4390 endInset = find_end_of_inset(document.body, ert)
4391 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", ert)
4392 endPlain = find_end_of_layout(document.body, beginPlain)
4393 ertcont = beginPlain + 2
4394 if document.body[ertcont] == "}{":
4396 # Convert to ArgInset
4397 endlay = endlay - 2 * len(document.body[j])
4399 "\\begin_inset Argument post:1",
4402 "\\begin_layout Plain Layout",
4404 endsubst = ["\\end_layout", "", "\\end_inset", "", document.body[j]]
4405 document.body[j : j + 1] = endsubst
4406 document.body[endInset + 1 : endInset + 1] = begsubst
4408 endlay += len(begsubst) + len(endsubst)
4409 endlay = endlay - len(document.body[ert : endInset + 1])
4410 del document.body[ert : endInset + 1]
4415 def revert_epigraph(document):
4416 "Reverts memoir epigraph argument to ERT"
4418 if document.textclass != "memoir":
4423 i = find_token(document.body, "\\begin_layout Epigraph", i)
4426 j = find_end_of_layout(document.body, i)
4428 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
4433 p = find_token(document.body, "\\begin_layout Argument post:1", i, j)
4435 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4436 endPlain = find_end_of_layout(document.body, beginPlain)
4437 endInset = find_end_of_inset(document.body, p)
4438 content = document.body[beginPlain + 1 : endPlain]
4440 endlay = endlay - len(document.body[p : endInset + 1])
4442 del document.body[p : endInset + 1]
4443 subst += put_cmd_in_ert("}{") + content
4445 subst += put_cmd_in_ert("}{")
4447 document.body[j:j] = subst + document.body[j:j]
4451 def convert_captioninsets(document):
4452 "Converts caption insets to new syntax"
4456 i = find_token(document.body, "\\begin_inset Caption", i)
4459 document.body[i] = "\\begin_inset Caption Standard"
4463 def revert_captioninsets(document):
4464 "Reverts caption insets to old syntax"
4468 i = find_token(document.body, "\\begin_inset Caption Standard", i)
4471 document.body[i] = "\\begin_inset Caption"
4475 def convert_captionlayouts(document):
4476 "Convert caption layouts to caption insets."
4479 "Captionabove": "Above",
4480 "Captionbelow": "Below",
4481 "FigCaption": "FigCaption",
4482 "Table_Caption": "Table",
4483 "CenteredCaption": "Centered",
4484 "Bicaption": "Bicaption",
4487 for captype in caption_dict.keys():
4490 i = find_token(document.body, "\\begin_layout " + captype, i)
4493 j = find_end_of_layout(document.body, i)
4495 document.warning("Malformed LyX document: Missing `\\end_layout'.")
4498 document.body[j:j] = ["\\end_layout", "", "\\end_inset", "", ""]
4499 document.body[i : i + 1] = [
4500 "\\begin_layout %s" % document.default_layout,
4501 "\\begin_inset Caption %s" % caption_dict[captype],
4503 "\\begin_layout %s" % document.default_layout,
4508 def revert_captionlayouts(document):
4509 "Revert caption insets to caption layouts."
4512 "Above": "Captionabove",
4513 "Below": "Captionbelow",
4514 "FigCaption": "FigCaption",
4515 "Table": "Table_Caption",
4516 "Centered": "CenteredCaption",
4517 "Bicaption": "Bicaption",
4521 rx = re.compile(r"^\\begin_inset Caption (\S+)$")
4523 i = find_token(document.body, "\\begin_inset Caption", i)
4527 m = rx.match(document.body[i])
4531 if val not in list(caption_dict.keys()):
4535 # We either need to delete the previous \begin_layout line, or we
4536 # need to end the previous layout if this inset is not in the first
4537 # position of the paragraph.
4538 layout_before = find_token_backwards(document.body, "\\begin_layout", i)
4539 if layout_before == -1:
4540 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
4542 layout_line = document.body[layout_before]
4543 del_layout_before = True
4544 l = layout_before + 1
4546 if document.body[l] != "":
4547 del_layout_before = False
4550 if del_layout_before:
4551 del document.body[layout_before:i]
4554 document.body[i:i] = ["\\end_layout", ""]
4557 # Find start of layout in the inset and end of inset
4558 j = find_token(document.body, "\\begin_layout", i)
4560 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
4562 k = find_end_of_inset(document.body, i)
4564 document.warning("Malformed LyX document: Missing `\\end_inset'.")
4567 # We either need to delete the following \end_layout line, or we need
4568 # to restart the old layout if this inset is not at the paragraph end.
4569 layout_after = find_token(document.body, "\\end_layout", k)
4570 if layout_after == -1:
4571 document.warning("Malformed LyX document: Missing `\\end_layout'.")
4573 del_layout_after = True
4575 while l < layout_after:
4576 if document.body[l] != "":
4577 del_layout_after = False
4580 if del_layout_after:
4581 del document.body[k + 1 : layout_after + 1]
4583 document.body[k + 1 : k + 1] = [layout_line, ""]
4585 # delete \begin_layout and \end_inset and replace \begin_inset with
4586 # "\begin_layout XXX". This works because we can only have one
4587 # paragraph in the caption inset: The old \end_layout will be recycled.
4588 del document.body[k]
4589 if document.body[k] == "":
4590 del document.body[k]
4591 del document.body[j]
4592 if document.body[j] == "":
4593 del document.body[j]
4594 document.body[i] = "\\begin_layout %s" % caption_dict[val]
4595 if document.body[i + 1] == "":
4596 del document.body[i + 1]
4600 def revert_fragileframe(document):
4601 "Reverts beamer FragileFrame layout to ERT"
4603 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4604 if document.textclass not in beamer_classes:
4609 i = find_token(document.body, "\\begin_layout FragileFrame", i)
4612 # Find end of sequence
4613 j = find_end_of_sequence(document.body, i)
4616 "Malformed LyX document. Cannot find end of FragileFrame sequence!"
4621 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{frame}")
4622 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{frame}")
4623 endseq = endseq + len(esubst) - len(document.body[j:j])
4624 if document.body[j] == "\\end_deeper":
4625 document.body[j:j] = [""] + esubst + ["", "\\end_layout"]
4627 document.body[j:j] = esubst
4628 for q in range(i, j):
4629 if document.body[q] == "\\begin_layout FragileFrame":
4630 document.body[q] = "\\begin_layout %s" % document.default_layout
4633 if document.body[r] == "\\begin_deeper":
4634 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
4636 document.body[r] = ""
4637 document.body[s] = ""
4641 for p in range(1, 5):
4642 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, j)
4645 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
4646 endPlain = find_end_of_layout(document.body, beginPlain)
4647 endInset = find_end_of_inset(document.body, arg)
4648 content = document.body[beginPlain + 1 : endPlain]
4650 j = j - len(document.body[arg : endInset + 1])
4652 del document.body[arg : endInset + 1]
4653 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
4655 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
4656 endPlain = find_end_of_layout(document.body, beginPlain)
4657 endInset = find_end_of_inset(document.body, arg)
4658 content = document.body[beginPlain + 1 : endPlain]
4660 j = j - len(document.body[arg : endInset + 1])
4662 del document.body[arg : endInset + 1]
4663 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
4665 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
4666 endPlain = find_end_of_layout(document.body, beginPlain)
4667 endInset = find_end_of_inset(document.body, arg)
4668 content = document.body[beginPlain + 1 : endPlain]
4670 j = j - len(document.body[arg : endInset + 1])
4672 del document.body[arg : endInset + 1]
4673 subst += put_cmd_in_ert("[fragile,") + content + put_cmd_in_ert("]")
4675 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
4676 endPlain = find_end_of_layout(document.body, beginPlain)
4677 endInset = find_end_of_inset(document.body, arg)
4678 content = document.body[beginPlain + 1 : endPlain]
4680 j = j - len(document.body[arg : endInset + 1])
4682 del document.body[arg : endInset + 1]
4683 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
4685 subst += put_cmd_in_ert("[fragile]")
4687 document.body[i : i + 1] = subst
4691 def revert_newframes(document):
4692 "Reverts beamer Frame and PlainFrame layouts to old forms"
4694 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4695 if document.textclass not in beamer_classes:
4699 "Frame": "BeginFrame",
4700 "PlainFrame": "BeginPlainFrame",
4703 rx = re.compile(r"^\\begin_layout (\S+)$")
4706 i = find_token(document.body, "\\begin_layout", i)
4710 m = rx.match(document.body[i])
4714 if val not in list(frame_dict.keys()):
4717 # Find end of sequence
4718 j = find_end_of_sequence(document.body, i)
4720 document.warning("Malformed LyX document. Cannot find end of Frame sequence!")
4724 subst = ["\\begin_layout %s" % frame_dict[val]]
4725 esubst = ["", "\\begin_layout EndFrame", "", "\\end_layout"]
4726 endseq = endseq + len(esubst) - len(document.body[j:j])
4727 if document.body[j] == "\\end_deeper":
4728 document.body[j:j] = esubst
4730 document.body[j + 1 : j + 1] = esubst
4731 for q in range(i, j):
4732 if document.body[q] == "\\begin_layout %s" % val:
4733 document.body[q] = "\\begin_layout %s" % document.default_layout
4736 if document.body[r] == "\\begin_deeper":
4737 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
4739 document.body[r] = ""
4740 document.body[s] = ""
4744 l = find_end_of_layout(document.body, i)
4745 for p in range(1, 5):
4746 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, l)
4749 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
4750 endPlain = find_end_of_layout(document.body, beginPlain)
4751 endInset = find_end_of_inset(document.body, arg)
4752 content = document.body[beginPlain + 1 : endPlain]
4754 l = l - len(document.body[arg : endInset + 1])
4756 del document.body[arg : endInset + 1]
4757 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
4759 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
4760 endPlain = find_end_of_layout(document.body, beginPlain)
4761 endInset = find_end_of_inset(document.body, arg)
4762 content = document.body[beginPlain + 1 : endPlain]
4764 l = l - len(document.body[arg : endInset + 1])
4766 del document.body[arg : endInset + 1]
4767 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
4769 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
4770 endPlain = find_end_of_layout(document.body, beginPlain)
4771 endInset = find_end_of_inset(document.body, arg)
4772 content = document.body[beginPlain + 1 : endPlain]
4774 l = l - len(document.body[arg : endInset + 1])
4776 del document.body[arg : endInset + 1]
4777 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4779 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
4780 endPlain = find_end_of_layout(document.body, beginPlain)
4781 endInset = find_end_of_inset(document.body, arg)
4782 content = document.body[beginPlain + 1 : endPlain]
4784 l = l - len(document.body[arg : endInset + 1])
4786 del document.body[arg : endInset + 1]
4789 document.body[i : i + 1] = subst
4793 # known encodings that do not change their names (same LyX and LaTeX names)
4827 def convert_encodings(document):
4828 "Use the LyX names of the encodings instead of the LaTeX names."
4829 LaTeX2LyX_enc_dict = {
4830 "8859-6": "iso8859-6",
4831 "8859-8": "iso8859-8",
4833 "euc": "euc-jp-platex",
4838 "iso88595": "iso8859-5",
4839 "iso-8859-7": "iso8859-7",
4841 "jis": "jis-platex",
4843 "l7xenc": "iso8859-13",
4844 "latin1": "iso8859-1",
4845 "latin2": "iso8859-2",
4846 "latin3": "iso8859-3",
4847 "latin4": "iso8859-4",
4848 "latin5": "iso8859-9",
4849 "latin9": "iso8859-15",
4850 "latin10": "iso8859-16",
4851 "SJIS": "shift-jis",
4852 "sjis": "shift-jis-platex",
4855 i = find_token(document.header, "\\inputencoding", 0)
4858 val = get_value(document.header, "\\inputencoding", i)
4859 if val in list(LaTeX2LyX_enc_dict.keys()):
4860 document.header[i] = "\\inputencoding %s" % LaTeX2LyX_enc_dict[val]
4861 elif val not in known_enc_tuple:
4862 document.warning("Ignoring unknown input encoding: `%s'" % val)
4865 def revert_encodings(document):
4866 """Revert to using the LaTeX names of the encodings instead of the LyX names.
4867 Also revert utf8-platex to sjis, the language default when using Japanese.
4869 LyX2LaTeX_enc_dict = {
4874 "euc-jp-platex": "euc",
4877 "iso8859-1": "latin1",
4878 "iso8859-2": "latin2",
4879 "iso8859-3": "latin3",
4880 "iso8859-4": "latin4",
4881 "iso8859-5": "iso88595",
4882 "iso8859-6": "8859-6",
4883 "iso8859-7": "iso-8859-7",
4884 "iso8859-8": "8859-8",
4885 "iso8859-9": "latin5",
4886 "iso8859-13": "l7xenc",
4887 "iso8859-15": "latin9",
4888 "iso8859-16": "latin10",
4890 "jis-platex": "jis",
4891 "shift-jis": "SJIS",
4892 "shift-jis-platex": "sjis",
4894 "utf8-platex": "sjis",
4896 i = find_token(document.header, "\\inputencoding", 0)
4899 val = get_value(document.header, "\\inputencoding", i)
4900 if val in list(LyX2LaTeX_enc_dict.keys()):
4901 document.header[i] = "\\inputencoding %s" % LyX2LaTeX_enc_dict[val]
4902 elif val not in known_enc_tuple:
4903 document.warning("Ignoring unknown input encoding: `%s'" % val)
4906 def revert_IEEEtran_3(document):
4908 Reverts Flex Insets to TeX-code
4910 if document.textclass == "IEEEtran":
4916 h = find_token(document.body, "\\begin_inset Flex Author Mark", h)
4918 endh = find_end_of_inset(document.body, h)
4919 document.body[endh - 2 : endh + 1] = put_cmd_in_ert("}")
4920 document.body[h : h + 4] = put_cmd_in_ert("\\IEEEauthorrefmark{")
4923 i = find_token(document.body, "\\begin_inset Flex Author Name", i)
4925 endi = find_end_of_inset(document.body, i)
4926 document.body[endi - 2 : endi + 1] = put_cmd_in_ert("}")
4927 document.body[i : i + 4] = put_cmd_in_ert("\\IEEEauthorblockN{")
4930 j = find_token(document.body, "\\begin_inset Flex Author Affiliation", j)
4932 endj = find_end_of_inset(document.body, j)
4933 document.body[endj - 2 : endj + 1] = put_cmd_in_ert("}")
4934 document.body[j : j + 4] = put_cmd_in_ert("\\IEEEauthorblockA{")
4936 if i == -1 and j == -1 and h == -1:
4940 def revert_kurier_fonts(document):
4941 "Revert kurier font definition to LaTeX"
4943 i = find_token(document.header, "\\font_math", 0)
4945 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4946 val = get_value(document.header, "\\font_math", i)
4947 if val == "kurier-math":
4950 "\\let\\Myrmdefault\\rmdefault\n"
4951 "\\usepackage[math]{kurier}\n"
4952 "\\renewcommand{\\rmdefault}{\\Myrmdefault}",
4954 document.header[i] = "\\font_math auto"
4956 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4957 kurier_fonts = ["kurier", "kurierc", "kurierl", "kurierlc"]
4958 k = find_token(document.header, "\\font_sans kurier", 0)
4960 sf = get_value(document.header, "\\font_sans", k)
4961 if sf in kurier_fonts:
4962 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4963 document.header[k] = "\\font_sans default"
4966 def revert_iwona_fonts(document):
4967 "Revert iwona font definition to LaTeX"
4969 i = find_token(document.header, "\\font_math", 0)
4971 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4972 val = get_value(document.header, "\\font_math", i)
4973 if val == "iwona-math":
4976 "\\let\\Myrmdefault\\rmdefault\n"
4977 "\\usepackage[math]{iwona}\n"
4978 "\\renewcommand{\\rmdefault}{\\Myrmdefault}",
4980 document.header[i] = "\\font_math auto"
4982 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4983 iwona_fonts = ["iwona", "iwonac", "iwonal", "iwonalc"]
4984 k = find_token(document.header, "\\font_sans iwona", 0)
4986 sf = get_value(document.header, "\\font_sans", k)
4987 if sf in iwona_fonts:
4988 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4989 document.header[k] = "\\font_sans default"
4992 def revert_new_libertines(document):
4993 "Revert new libertine font definition to LaTeX"
4995 if find_token(document.header, "\\use_non_tex_fonts true", 0) != -1:
4998 i = find_token(document.header, "\\font_typewriter libertine-mono", 0)
5000 preamble = "\\usepackage"
5001 sc = find_token(document.header, "\\font_tt_scale", 0)
5003 scval = get_value(document.header, "\\font_tt_scale", sc)
5005 preamble += "[scale=%f]" % (float(scval) / 100)
5006 document.header[sc] = "\\font_tt_scale 100"
5007 preamble += "{libertineMono-type1}"
5008 add_to_preamble(document, [preamble])
5009 document.header[i] = "\\font_typewriter default"
5011 k = find_token(document.header, "\\font_sans biolinum", 0)
5013 preamble = "\\usepackage"
5015 j = find_token(document.header, "\\font_osf true", 0)
5020 sc = find_token(document.header, "\\font_sf_scale", 0)
5022 scval = get_value(document.header, "\\font_sf_scale", sc)
5024 options += ",scale=%f" % (float(scval) / 100)
5025 document.header[sc] = "\\font_sf_scale 100"
5027 preamble += "[" + options + "]"
5028 preamble += "{biolinum-type1}"
5029 add_to_preamble(document, [preamble])
5030 document.header[k] = "\\font_sans default"
5033 def convert_lyxframes(document):
5034 "Converts old beamer frames to new style"
5036 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
5037 if document.textclass not in beamer_classes:
5040 framebeg = ["BeginFrame", "BeginPlainFrame"]
5055 for lay in framebeg:
5058 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
5061 parent = get_containing_layout(document.body, i)
5062 if parent == False or parent[1] != i:
5063 document.warning("Wrong parent layout!")
5066 frametype = parent[0]
5070 # Step I: Convert ERT arguments
5071 # FIXME: See restrictions in convert_beamerframeargs method
5072 ertend = convert_beamerframeargs(document, i, parbeg)
5075 # Step II: Now rename the layout and convert the title to an argument
5076 j = find_end_of_layout(document.body, i)
5077 document.body[j : j + 1] = [
5084 if lay == "BeginFrame":
5085 document.body[i] = "\\begin_layout Frame"
5087 document.body[i] = "\\begin_layout PlainFrame"
5088 document.body[ertend + 1 : ertend + 1] = [
5089 "\\begin_inset Argument 4",
5092 "\\begin_layout Plain Layout",
5094 # Step III: find real frame end
5097 inInset = get_containing_inset(document.body, i)
5099 fend = find_token(document.body, "\\begin_layout", jj)
5101 document.warning("Malformed LyX document: No real frame end!")
5103 val = get_value(document.body, "\\begin_layout", fend)
5104 if val not in frameend:
5107 # is this frame nested in an inset (e.g., Note)?
5108 if inInset != False:
5109 # if so, end the frame inside the inset
5110 if inInset[2] < fend:
5112 if val == frametype:
5113 document.body[fend:fend] = [
5116 "\\begin_layout Separator",
5120 # consider explicit EndFrames between two identical frame types
5121 elif val == "EndFrame":
5122 nextlayout = find_token(document.body, "\\begin_layout", fend + 1)
5125 and get_value(document.body, "\\begin_layout", nextlayout)
5128 document.body[fend:fend] = [
5131 "\\begin_layout Separator",
5136 document.body[fend:fend] = ["\\end_deeper"]
5138 document.body[fend:fend] = ["\\end_deeper"]
5139 document.body[j + 1 : j + 1] = ["", "\\begin_deeper"]
5144 def remove_endframes(document):
5145 "Remove deprecated beamer endframes"
5147 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
5148 if document.textclass not in beamer_classes:
5153 i = find_token_exact(document.body, "\\begin_layout EndFrame", i)
5156 j = find_end_of_layout(document.body, i)
5158 document.warning("Malformed LyX document: Missing \\end_layout to EndFrame")
5161 del document.body[i : j + 1]
5164 def revert_powerdot_flexes(document):
5165 "Reverts powerdot flex insets"
5167 if document.textclass != "powerdot":
5171 "Onslide": "\\onslide",
5172 "Onslide*": "\\onslide*",
5173 "Onslide+": "\\onslide+",
5175 rx = re.compile(r"^\\begin_inset Flex (.+)$")
5179 i = find_token(document.body, "\\begin_inset Flex", i)
5182 m = rx.match(document.body[i])
5184 flextype = m.group(1)
5185 z = find_end_of_inset(document.body, i)
5187 document.warning("Can't find end of Flex " + flextype + " inset.")
5190 if flextype in flexes:
5191 pre = put_cmd_in_ert(flexes[flextype])
5192 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
5194 argend = find_end_of_inset(document.body, arg)
5196 document.warning("Can't find end of Argument!")
5199 # Find containing paragraph layout
5200 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
5201 endPlain = find_end_of_layout(document.body, beginPlain)
5202 argcontent = document.body[beginPlain + 1 : endPlain]
5204 z = z - len(document.body[arg : argend + 1])
5206 del document.body[arg : argend + 1]
5207 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
5208 pre += put_cmd_in_ert("{")
5209 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
5210 endPlain = find_end_of_layout(document.body, beginPlain)
5212 z = z - len(document.body[i : beginPlain + 1])
5214 document.body[i : beginPlain + 1] = pre
5215 post = put_cmd_in_ert("}")
5216 document.body[z - 2 : z + 1] = post
5220 def revert_powerdot_pause(document):
5221 "Reverts powerdot pause layout to ERT"
5223 if document.textclass != "powerdot":
5228 i = find_token(document.body, "\\begin_layout Pause", i)
5231 j = find_end_of_layout(document.body, i)
5233 document.warning("Malformed LyX document: Can't find end of Pause layout")
5237 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\pause")
5238 for p in range(i, j):
5241 arg = find_token(document.body, "\\begin_inset Argument 1", i, j)
5243 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
5244 endPlain = find_end_of_layout(document.body, beginPlain)
5245 endInset = find_end_of_inset(document.body, p)
5246 content = document.body[beginPlain + 1 : endPlain]
5248 endlay = endlay - len(document.body[p : endInset + 1])
5250 del document.body[p : endInset + 1]
5251 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
5253 document.body[i : i + 1] = subst
5257 def revert_powerdot_itemargs(document):
5258 "Reverts powerdot item arguments to ERT"
5260 if document.textclass != "powerdot":
5264 list_layouts = ["Itemize", "ItemizeType1", "Enumerate", "EnumerateType1"]
5265 rx = re.compile(r"^\\begin_inset Argument (\S+)$")
5268 i = find_token(document.body, "\\begin_inset Argument", i)
5271 # Find containing paragraph layout
5272 parent = get_containing_layout(document.body, i)
5274 document.warning("Malformed LyX document: Can't find parent paragraph layout")
5279 realparbeg = parent[3]
5280 layoutname = parent[0]
5282 for p in range(parbeg, parend):
5286 if layoutname in list_layouts:
5287 m = rx.match(document.body[p])
5290 if argnr == "item:1":
5291 j = find_end_of_inset(document.body, i)
5292 # Find containing paragraph layout
5293 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
5294 endPlain = find_end_of_layout(document.body, beginPlain)
5295 content = document.body[beginPlain + 1 : endPlain]
5296 del document.body[i : j + 1]
5297 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
5298 document.body[realparbeg:realparbeg] = subst
5299 elif argnr == "item:2":
5300 j = find_end_of_inset(document.body, i)
5301 # Find containing paragraph layout
5302 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
5303 endPlain = find_end_of_layout(document.body, beginPlain)
5304 content = document.body[beginPlain + 1 : endPlain]
5305 del document.body[i : j + 1]
5306 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
5307 document.body[realparbeg:realparbeg] = subst
5312 def revert_powerdot_columns(document):
5313 "Reverts powerdot twocolumn to TeX-code"
5314 if document.textclass != "powerdot":
5317 rx = re.compile(r"^\\begin_inset Argument (\S+)$")
5320 i = find_token(document.body, "\\begin_layout Twocolumn", i)
5323 j = find_end_of_layout(document.body, i)
5325 document.warning("Malformed LyX document: Can't find end of Twocolumn layout")
5329 document.body[j:j] = put_cmd_in_ert("}") + document.body[j:j]
5330 endlay += len(put_cmd_in_ert("}"))
5331 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\twocolumn")
5332 for p in range(i, j):
5335 m = rx.match(document.body[p])
5339 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
5340 endPlain = find_end_of_layout(document.body, beginPlain)
5341 endInset = find_end_of_inset(document.body, p)
5342 content = document.body[beginPlain + 1 : endPlain]
5344 endlay = endlay - len(document.body[p : endInset + 1])
5346 del document.body[p : endInset + 1]
5347 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
5349 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
5350 endPlain = find_end_of_layout(document.body, beginPlain)
5351 endInset = find_end_of_inset(document.body, p)
5352 content = document.body[beginPlain + 1 : endPlain]
5354 endlay = endlay - len(document.body[p : endInset + 1])
5356 del document.body[p : endInset + 1]
5357 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
5359 subst += put_cmd_in_ert("{")
5360 document.body[i : i + 1] = subst
5364 def revert_mbox_fbox(document):
5365 "Convert revert mbox/fbox boxes to TeX-code"
5368 i = find_token(document.body, "\\begin_inset Box", i)
5371 j = find_token(document.body, "width", i)
5373 document.warning("Malformed LyX document: Can't find box width")
5375 width = get_value(document.body, "width", j)
5376 k = find_end_of_inset(document.body, j)
5378 document.warning("Malformed LyX document: Can't find end of box inset")
5381 BeginLayout = find_token(document.body, "\\begin_layout Plain Layout", j)
5382 EndLayout = find_end_of_layout(document.body, BeginLayout)
5383 # replace if width is ""
5385 document.body[EndLayout : k + 1] = put_cmd_in_ert("}")
5386 if document.body[i] == "\\begin_inset Box Frameless":
5387 document.body[i : BeginLayout + 1] = put_cmd_in_ert("\\mbox{")
5388 if document.body[i] == "\\begin_inset Box Boxed":
5389 document.body[i : BeginLayout + 1] = put_cmd_in_ert("\\fbox{")
5393 def revert_starred_caption(document):
5394 "Reverts unnumbered longtable caption insets"
5398 i = find_token(document.body, "\\begin_inset Caption LongTableNoNumber", i)
5401 # This is not equivalent, but since the caption inset is a full blown
5402 # text inset a true conversion to ERT is too difficult.
5403 document.body[i] = "\\begin_inset Caption Standard"
5407 def revert_forced_local_layout(document):
5410 i = find_token(document.header, "\\begin_forced_local_layout", i)
5416 "\\begin_forced_local_layout",
5417 "\\end_forced_local_layout",
5420 # this should not happen
5422 regexp = re.compile(r"\s*forcelocal", re.IGNORECASE)
5423 k = find_re(document.header, regexp, i, j)
5425 del document.header[k]
5427 k = find_re(document.header, regexp, i, j)
5428 k = find_token(document.header, "\\begin_local_layout", 0)
5430 document.header[i] = "\\begin_local_layout"
5431 document.header[j] = "\\end_local_layout"
5433 l = find_end_of(document.header, k, "\\begin_local_layout", "\\end_local_layout")
5435 # this should not happen
5437 lines = document.header[i + 1 : j]
5439 document.header[k + 1 : k + 1] = lines
5440 document.header[i:j] = []
5442 document.header[i:j] = []
5443 document.header[k + 1 : k + 1] = lines
5446 def revert_aa1(document):
5447 "Reverts InsetArguments of aa to TeX-code"
5448 if document.textclass == "aa":
5452 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
5454 revert_Argument_to_TeX_brace(document, i, 0, 1, 4, False, False)
5460 def revert_aa2(document):
5461 "Reverts InsetArguments of aa to TeX-code"
5462 if document.textclass == "aa":
5466 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
5468 document.body[i] = "\\begin_layout Abstract"
5474 def revert_tibetan(document):
5475 "Set the document language for Tibetan to English"
5477 revert_language(document, "tibetan", "", "tibetan")
5487 # The idea here is that we will have a sequence of chunk paragraphs.
5488 # We want to convert them to paragraphs in one or several chunk insets.
5489 # Individual chunks are terminated by the character @ on the last line.
5490 # This line will be discarded, and following lines are treated as new
5491 # chunks, which go into their own insets.
5492 # The first line of a chunk should look like: <<CONTENT>>=
5493 # We will discard the delimiters, and put the CONTENT into the
5494 # optional argument of the inset, if the CONTENT is non-empty.
5495 def convert_chunks(document):
5496 first_re = re.compile(r"<<(.*)>>=(.*)")
5499 # find start of a block of chunks
5500 i = find_token(document.body, "\\begin_layout Chunk", file_pos)
5506 chunk_started = False
5509 # process the one we just found
5510 j = find_end_of_layout(document.body, i)
5512 document.warning("Malformed LyX documents. Can't find end of Chunk layout!")
5513 # there is no point continuing, as we will run into the same error again.
5515 this_chunk = "".join(document.body[i + 1 : j])
5517 # there may be empty lines between chunks
5518 # we just skip them.
5519 if not chunk_started:
5520 if this_chunk != "":
5522 chunk_started = True
5525 contents.append(document.body[i + 1 : j])
5527 # look for potential chunk terminator
5528 # on the last line of the chunk paragraph
5529 if document.body[j - 1] == "@":
5532 # look for subsequent chunk paragraph
5533 i = find_token(document.body, "\\begin_layout", j)
5537 if get_value(document.body, "\\begin_layout", i) != "Chunk":
5540 file_pos = end = j + 1
5542 # The last chunk should simply have an "@" in it
5543 # or at least end with "@" (can happen if @ is
5544 # preceded by a newline)
5546 if len(contents) > 0:
5547 lastpar = "".join(contents[-1])
5548 if not lastpar.endswith("@"):
5549 document.warning("Unexpected chunk content: chunk not terminated by '@'!")
5550 if len(contents) == 0:
5551 # convert empty chunk layouts to Standard
5552 document.body[start] = "\\begin_layout Standard"
5556 # chunk par only contains "@". Just drop it.
5559 # chunk par contains more. Only drop the "@".
5562 # The first line should look like: <<CONTENT>>=
5563 # We want the CONTENT
5564 optarg = " ".join(contents[0])
5566 # We can already have real chunk content in
5567 # the first par (separated from the options by a newline).
5568 # We collect such stuff to re-insert it later.
5571 match = first_re.search(optarg)
5573 optarg = match.groups()[0]
5574 if match.groups()[1] != "":
5576 for c in contents[0]:
5577 if c.endswith(">>="):
5581 postoptstuff.append(c)
5582 # We have stripped everything. This can be deleted.
5585 newstuff = ["\\begin_layout Standard"]
5587 # Maintain paragraph parameters
5593 "\\start_of_appendix",
5594 "\\paragraph_spacing",
5596 "\\labelwidthstring",
5600 if document.body[parms].split(" ", 1)[0] not in par_params:
5602 newstuff.extend([document.body[parms]])
5607 "\\begin_inset Flex Chunk",
5610 "\\begin_layout Plain Layout",
5615 # If we have a non-empty optional argument, insert it.
5616 if match and optarg != "":
5619 "\\begin_inset Argument 1",
5622 "\\begin_layout Plain Layout",
5631 # Since we already opened a Plain layout, the first paragraph
5632 # does not need to do that.
5635 # we need to replace newlines with new layouts
5637 started_text = False
5638 for lno in range(0, len(postoptstuff)):
5639 if postoptstuff[lno].startswith("\\begin_inset Newline newline"):
5641 elif start_newline != -1:
5642 if postoptstuff[lno].startswith("\\end_inset"):
5643 # replace that bit, but only if we already have some text
5644 # and we're not at the end except for a blank line
5645 if started_text and (
5646 lno != len(postoptstuff) - 2 or postoptstuff[-1] != ""
5652 "\\begin_layout Plain Layout",
5659 newstuff.extend([postoptstuff[lno]])
5660 newstuff.append("\\end_layout")
5664 newstuff.extend(["", "\\begin_layout Plain Layout", ""])
5668 newstuff.append("\\end_layout")
5670 newstuff.extend(["", "\\end_inset", "", "\\end_layout", ""])
5672 document.body[start:end] = newstuff
5674 file_pos += len(newstuff) - (end - start)
5677 def revert_chunks(document):
5680 i = find_token(document.body, "\\begin_inset Flex Chunk", i)
5684 iend = find_end_of_inset(document.body, i)
5686 document.warning("Can't find end of Chunk!")
5690 # Look for optional argument
5692 ostart = find_token(document.body, "\\begin_inset Argument 1", i, iend)
5694 oend = find_end_of_inset(document.body, ostart)
5695 k = find_token(document.body, "\\begin_layout Plain Layout", ostart, oend)
5697 document.warning("Malformed LyX document: Can't find argument contents!")
5699 m = find_end_of_layout(document.body, k)
5700 optarg = "".join(document.body[k + 1 : m])
5702 # We now remove the optional argument, so we have something
5703 # uniform on which to work
5704 document.body[ostart : oend + 1] = []
5705 # iend is now invalid
5706 iend = find_end_of_inset(document.body, i)
5708 retval = get_containing_layout(document.body, i)
5710 document.warning("Can't find containing layout for Chunk!")
5713 (lname, lstart, lend, pstart) = retval
5714 # we now want to work through the various paragraphs, and collect their contents
5718 k = find_token(document.body, "\\begin_layout Plain Layout", k, lend)
5721 j = find_end_of_layout(document.body, k)
5723 document.warning("Can't find end of layout inside chunk!")
5725 parlist.append(document.body[k + 1 : j])
5727 # we now need to wrap all of these paragraphs in chunks
5729 newlines.extend(["\\begin_layout Chunk", "", "<<" + optarg + ">>=", "\\end_layout", ""])
5730 for stuff in parlist:
5731 newlines.extend(["\\begin_layout Chunk"] + stuff + ["\\end_layout", ""])
5732 newlines.extend(["\\begin_layout Chunk", "", "@", "\\end_layout", ""])
5733 # replace old content with new content
5734 document.body[lstart : lend + 1] = newlines
5735 i = lstart + len(newlines)
5742 supported_versions = ["2.1.0", "2.1"]
5745 [415, [convert_undertilde]],
5747 [417, [convert_japanese_encodings]],
5748 [418, [convert_justification]],
5750 [420, [convert_biblio_style]],
5751 [421, [convert_longtable_captions]],
5752 [422, [convert_use_packages]],
5753 [423, [convert_use_mathtools]],
5754 [424, [convert_cite_engine_type]],
5755 # No convert_cancel, since cancel will be loaded automatically
5756 # in format 425 without any possibility to switch it off.
5757 # This has been fixed in format 464.
5761 [428, [convert_cell_rotation]],
5762 [429, [convert_table_rotation]],
5763 [430, [convert_listoflistings]],
5764 [431, [convert_use_amssymb]],
5766 [433, [convert_armenian]],
5773 [440, [convert_mathfonts]],
5774 [441, [convert_mdnomath]],
5779 [446, [convert_latexargs]],
5794 [448, [convert_literate]],
5801 convert_againframe_args,
5802 convert_corollary_args,
5806 [452, [convert_beamerblocks]],
5807 [453, [convert_use_stmaryrd]],
5808 [454, [convert_overprint]],
5810 [456, [convert_epigraph]],
5811 [457, [convert_use_stackrel]],
5812 [458, [convert_captioninsets, convert_captionlayouts]],
5817 [463, [convert_encodings]],
5818 [464, [convert_use_cancel]],
5819 [465, [convert_lyxframes, remove_endframes]],
5825 [471, [convert_cite_engine_type_default]],
5828 [474, [convert_chunks, cleanup_beamerargs]],
5832 [473, [revert_chunks]],
5833 [472, [revert_tibetan]],
5834 [471, [revert_aa1, revert_aa2]],
5835 [470, [revert_cite_engine_type_default]],
5836 [469, [revert_forced_local_layout]],
5837 [468, [revert_starred_caption]],
5838 [467, [revert_mbox_fbox]],
5839 [466, [revert_iwona_fonts]],
5843 revert_powerdot_flexes,
5844 revert_powerdot_pause,
5845 revert_powerdot_itemargs,
5846 revert_powerdot_columns,
5850 [463, [revert_use_cancel]],
5851 [462, [revert_encodings]],
5852 [461, [revert_new_libertines]],
5853 [460, [revert_kurier_fonts]],
5854 [459, [revert_IEEEtran_3]],
5855 [458, [revert_fragileframe, revert_newframes]],
5856 [457, [revert_captioninsets, revert_captionlayouts]],
5857 [456, [revert_use_stackrel]],
5858 [455, [revert_epigraph]],
5859 [454, [revert_frametitle]],
5860 [453, [revert_overprint]],
5861 [452, [revert_use_stmaryrd]],
5862 [451, [revert_beamerblocks]],
5865 [revert_beamerargs, revert_beamerargs2, revert_beamerargs3, revert_beamerflex],
5867 [449, [revert_garamondx, revert_garamondx_newtxmath]],
5868 [448, [revert_itemargs]],
5869 [447, [revert_literate]],
5886 [445, [revert_latexargs]],
5887 [444, [revert_uop]],
5888 [443, [revert_biolinum]],
5890 [441, [revert_newtxmath]],
5891 [440, [revert_mdnomath]],
5892 [439, [revert_mathfonts]],
5893 [438, [revert_minionpro]],
5894 [437, [revert_ipadeco, revert_ipachar]],
5895 [436, [revert_texgyre]],
5896 [435, [revert_mathdesign]],
5897 [434, [revert_txtt]],
5898 [433, [revert_libertine]],
5899 [432, [revert_armenian]],
5900 [431, [revert_languages, revert_ancientgreek]],
5901 [430, [revert_use_amssymb]],
5902 [429, [revert_listoflistings]],
5903 [428, [revert_table_rotation]],
5904 [427, [revert_cell_rotation]],
5905 [426, [revert_tipa]],
5906 [425, [revert_verbatim]],
5907 [424, [revert_cancel]],
5908 [423, [revert_cite_engine_type]],
5909 [422, [revert_use_mathtools]],
5910 [421, [revert_use_packages]],
5911 [420, [revert_longtable_captions]],
5912 [419, [revert_biblio_style]],
5913 [418, [revert_australian]],
5914 [417, [revert_justification]],
5915 [416, [revert_japanese_encodings]],
5916 [415, [revert_negative_space, revert_math_spaces]],
5917 [414, [revert_undertilde]],
5918 [413, [revert_visible_space]],
5922 if __name__ == "__main__":