1 # -*- coding: utf-8 -*-
2 # This file is part of lyx2lyx
3 # -*- coding: utf-8 -*-
4 # Copyright (C) 2011 The LyX team
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 """ Convert files to the file format generated by LyX 2.1"""
26 # Uncomment only what you need to import, please.
28 from parser_tools import count_pars_in_inset, del_token, find_token, find_token_exact, \
29 find_token_backwards, find_end_of, find_end_of_inset, find_end_of_layout, \
30 find_end_of_sequence, find_re, get_option_value, get_containing_layout, \
31 get_value, get_quoted_value, set_option_value
33 #from parser_tools import find_token, find_end_of, find_tokens, \
34 #find_end_of_inset, find_end_of_layout, \
35 #is_in_inset, del_token, check_token
37 from lyx2lyx_tools import add_to_preamble, put_cmd_in_ert, get_ert
39 #from lyx2lyx_tools import insert_to_preamble, \
40 # lyx2latex, latex_length, revert_flex_inset, \
41 # revert_font_attrs, hex2ratio, str2bool
43 ####################################################################
44 # Private helper functions
46 #def remove_option(lines, m, option):
47 #''' removes option from line m. returns whether we did anything '''
48 #l = lines[m].find(option)
51 #val = lines[m][l:].split('"')[1]
52 #lines[m] = lines[m][:l - 1] + lines[m][l+len(option + '="' + val + '"'):]
56 def revert_Argument_to_TeX_brace(document, line, endline, n, nmax, environment, opt):
58 Reverts an InsetArgument to TeX-code
60 revert_Argument_to_TeX_brace(document, LineOfBegin, LineOfEnd, StartArgument, EndArgument, isEnvironment, isOpt)
61 LineOfBegin is the line of the \begin_layout or \begin_inset statement
62 LineOfEnd is the line of the \end_layout or \end_inset statement, if "0" is given, the end of the file is used instead
63 StartArgument is the number of the first argument that needs to be converted
64 EndArgument is the number of the last argument that needs to be converted or the last defined one
65 isEnvironment must be true, if the layout is for a LaTeX environment
66 isOpt must be true, if the argument is an optional one
70 while lineArg != -1 and n < nmax + 1:
71 lineArg = find_token(document.body, "\\begin_inset Argument " + str(n), line)
72 if lineArg > endline and endline != 0:
75 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", lineArg)
76 # we have to assure that no other inset is in the Argument
77 beginInset = find_token(document.body, "\\begin_inset", beginPlain)
78 endInset = find_token(document.body, "\\end_inset", beginPlain)
81 while beginInset < endInset and beginInset != -1:
82 beginInset = find_token(document.body, "\\begin_inset", k)
83 endInset = find_token(document.body, "\\end_inset", l)
86 if environment == False:
88 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}{")
89 del(document.body[lineArg : beginPlain + 1])
92 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("]")
93 document.body[lineArg : beginPlain + 1] = put_cmd_in_ert("[")
96 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}")
97 document.body[lineArg : beginPlain + 1] = put_cmd_in_ert("{")
103 def convert_TeX_brace_to_Argument(document, line, n, nmax, inset, environment, opt):
105 Converts TeX code for mandatory arguments to an InsetArgument
106 The conversion of TeX code for optional arguments must be done with another routine
107 !!! Be careful if the braces are different in your case as expected here:
108 - "}{" separates mandatory arguments of commands
109 - "}" + "{" separates mandatory arguments of commands
110 - "}" + " " + "{" separates mandatory arguments of commands
111 - { and } surround a mandatory argument of an environment
113 convert_TeX_brace_to_Argument(document, LineOfBeginLayout/Inset, StartArgument, EndArgument, isInset, isEnvironment, isOpt)
114 LineOfBeginLayout/Inset is the line of the \begin_layout or \begin_inset statement
115 StartArgument is the number of the first ERT that needs to be converted
116 EndArgument is the number of the last ERT that needs to be converted
117 isInset must be true, if braces inside an InsetLayout needs to be converted
118 isEnvironment must be true, if the layout is for a LaTeX environment
119 isOpt must be true, if the argument is an optional one
121 Todo: this routine can currently handle only one mandatory argument of environments
126 while lineERT != -1 and n < nmax + 1:
127 lineERT = find_token(document.body, "\\begin_inset ERT", lineERT)
128 if environment == False and lineERT != -1:
131 bracePair = find_token(document.body, "][", lineERT)
133 bracePair = find_token(document.body, "}{", lineERT)
134 # assure that the "}{" is in this ERT
135 if bracePair == lineERT + 5:
136 end = find_token(document.body, "\\end_inset", bracePair)
137 document.body[lineERT : end + 1] = ["\\end_layout", "", "\\end_inset"]
139 # in the case that n > 1 we have optional arguments before
140 # therefore detect them if any
142 # first check if there is an argument
143 lineArg = find_token(document.body, "\\begin_inset Argument", line)
144 if lineArg < lineERT and lineArg != -1:
145 # we have an argument, so now search backwards for its end
146 # we must now assure that we don't find other insets like e.g. a newline
147 endInsetArg = lineERT
148 endLayoutArg = endInsetArg
149 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
150 endInsetArg = endInsetArg - 1
151 endLayoutArg = endInsetArg
152 endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
153 endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
154 line = endInsetArg + 1
156 document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
158 document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
160 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
164 # now check the case that we have "}" + "{" in two ERTs
168 endBrace = find_token(document.body, "]", lineERT)
170 endBrace = find_token(document.body, "}", lineERT)
171 if endBrace == lineERT + 5:
174 beginBrace = find_token(document.body, "[", endBrace)
176 beginBrace = find_token(document.body, "{", endBrace)
177 # assure that the ERTs are consecutive (11 or 12 depending if there is a space between the ERTs or not)
178 if beginBrace == endBrace + 11 or beginBrace == endBrace + 12:
179 end = find_token(document.body, "\\end_inset", beginBrace)
180 document.body[lineERT : end + 1] = ["\\end_layout", "", "\\end_inset"]
182 # in the case that n > 1 we have optional arguments before
183 # therefore detect them if any
185 # first check if there is an argument
186 lineArg = find_token(document.body, "\\begin_inset Argument", line)
187 if lineArg < lineERT and lineArg != -1:
188 # we have an argument, so now search backwards for its end
189 # we must now assure that we don't find other insets like e.g. a newline
190 endInsetArg = lineERT
191 endLayoutArg = endInsetArg
192 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
193 endInsetArg = endInsetArg - 1
194 endLayoutArg = endInsetArg
195 endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
196 endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
197 line = endInsetArg + 1
199 document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
201 document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
203 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
206 # set the line where the next argument will be inserted
207 if beginBrace == endBrace + 11:
215 if environment == True and lineERT != -1:
218 opening = find_token(document.body, "[", lineERT)
220 opening = find_token(document.body, "{", lineERT)
221 if opening == lineERT + 5: # assure that the "{" is in this ERT
222 end = find_token(document.body, "\\end_inset", opening)
223 document.body[lineERT : end + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
225 lineERT2 = find_token(document.body, "\\begin_inset ERT", lineERT)
228 closing = find_token(document.body, "]", lineERT)
230 closing = find_token(document.body, "}", lineERT2)
231 if closing == lineERT2 + 5: # assure that the "}" is in this ERT
232 end2 = find_token(document.body, "\\end_inset", closing)
233 document.body[lineERT2 : end2 + 1] = ["\\end_layout", "", "\\end_inset"]
238 ###############################################################################
240 ### Conversion and reversion routines
242 ###############################################################################
244 def revert_visible_space(document):
245 "Revert InsetSpace visible into its ERT counterpart"
248 i = find_token(document.body, "\\begin_inset space \\textvisiblespace{}", i)
251 end = find_end_of_inset(document.body, i)
252 subst = put_cmd_in_ert("\\textvisiblespace{}")
253 document.body[i:end + 1] = subst
256 undertilde_commands = ["utilde"]
257 def convert_undertilde(document):
258 " Load undertilde automatically "
259 i = find_token(document.header, "\\use_mathdots" , 0)
261 i = find_token(document.header, "\\use_mhchem" , 0)
263 i = find_token(document.header, "\\use_esint" , 0)
265 document.warning("Malformed LyX document: Can't find \\use_mathdots.")
267 j = find_token(document.preamble, "\\usepackage{undertilde}", 0)
269 # package was loaded in the preamble, convert this to header setting for round trip
270 document.header.insert(i + 1, "\\use_undertilde 2") # on
271 del document.preamble[j]
275 j = find_token(document.body, '\\begin_inset Formula', j)
278 k = find_end_of_inset(document.body, j)
280 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(j))
283 code = "\n".join(document.body[j:k])
284 for c in undertilde_commands:
285 if code.find("\\%s" % c) != -1:
286 # at least one of the commands was found - need to switch package off
287 document.header.insert(i + 1, "\\use_undertilde 0") # off
290 # no command was found - set to auto (bug 9069)
291 document.header.insert(i + 1, "\\use_undertilde 1") # auto
295 def revert_undertilde(document):
296 " Load undertilde if used in the document "
297 regexp = re.compile(r'(\\use_undertilde)')
298 i = find_re(document.header, regexp, 0)
299 value = "1" # default is auto
301 value = get_value(document.header, "\\use_undertilde" , i).split()[0]
302 del document.header[i]
303 if value == "2": # on
304 add_to_preamble(document, ["\\usepackage{undertilde}"])
305 elif value == "1": # auto
308 i = find_token(document.body, '\\begin_inset Formula', i)
311 j = find_end_of_inset(document.body, i)
313 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
316 code = "\n".join(document.body[i:j])
317 for c in undertilde_commands:
318 if code.find("\\%s" % c) != -1:
319 add_to_preamble(document, ["\\usepackage{undertilde}"])
324 def revert_negative_space(document):
325 "Revert InsetSpace negmedspace and negthickspace into its TeX-code counterpart"
330 i = find_token(document.body, "\\begin_inset space \\negmedspace{}", i)
332 j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
334 # load amsmath in the preamble if not already loaded if we are at the end of checking
336 i = find_token(document.header, "\\use_amsmath 2", 0)
338 add_to_preamble(document, ["\\@ifundefined{negthickspace}{\\usepackage{amsmath}}"])
342 end = find_end_of_inset(document.body, i)
343 subst = put_cmd_in_ert("\\negmedspace{}")
344 document.body[i:end + 1] = subst
345 j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
348 end = find_end_of_inset(document.body, j)
349 subst = put_cmd_in_ert("\\negthickspace{}")
350 document.body[j:end + 1] = subst
354 def revert_math_spaces(document):
355 "Revert formulas with protected custom space and protected hfills to TeX-code"
358 i = find_token(document.body, "\\begin_inset Formula", i)
361 j = document.body[i].find("\\hspace*")
363 end = find_end_of_inset(document.body, i)
364 subst = put_cmd_in_ert(document.body[i][21:])
365 document.body[i:end + 1] = subst
369 def convert_japanese_encodings(document):
370 " Rename the japanese encodings to names understood by platex "
372 "EUC-JP-pLaTeX": "euc",
374 "SJIS-pLaTeX": "sjis"
376 i = find_token(document.header, "\\inputencoding" , 0)
379 val = get_value(document.header, "\\inputencoding", i)
380 if val in jap_enc_dict.keys():
381 document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
384 def revert_japanese_encodings(document):
385 " Revert the japanese encodings name changes "
387 "euc": "EUC-JP-pLaTeX",
389 "sjis": "SJIS-pLaTeX"
391 i = find_token(document.header, "\\inputencoding" , 0)
394 val = get_value(document.header, "\\inputencoding", i)
395 if val in jap_enc_dict.keys():
396 document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
399 def convert_justification(document):
400 " Add the \\justification buffer param"
401 i = find_token(document.header, "\\use_indices" , 0)
403 document.warning("Malformed LyX document: Missing \\use_indices.")
405 document.header.insert(i + 1, "\\justification true")
408 def revert_justification(document):
409 " Revert the \\justification buffer param"
410 if not del_token(document.header, '\\justification', 0):
411 document.warning("Malformed LyX document: Missing \\justification.")
414 def revert_australian(document):
415 "Set English language variants Australian and Newzealand to English"
417 if document.language == "australian" or document.language == "newzealand":
418 document.language = "english"
419 i = find_token(document.header, "\\language", 0)
421 document.header[i] = "\\language english"
424 j = find_token(document.body, "\\lang australian", j)
426 j = find_token(document.body, "\\lang newzealand", 0)
430 document.body[j] = document.body[j].replace("\\lang newzealand", "\\lang english")
432 document.body[j] = document.body[j].replace("\\lang australian", "\\lang english")
436 def convert_biblio_style(document):
437 "Add a sensible default for \\biblio_style based on the citation engine."
438 i = find_token(document.header, "\\cite_engine", 0)
440 engine = get_value(document.header, "\\cite_engine", i).split("_")[0]
441 style = {"basic": "plain", "natbib": "plainnat", "jurabib": "jurabib"}
442 document.header.insert(i + 1, "\\biblio_style " + style[engine])
445 def revert_biblio_style(document):
446 "BibTeX insets with default option use the style defined by \\biblio_style."
447 i = find_token(document.header, "\\biblio_style" , 0)
449 document.warning("No \\biblio_style line. Nothing to do.")
452 default_style = get_value(document.header, "\\biblio_style", i)
453 del document.header[i]
455 # We are looking for bibtex insets having the default option
458 i = find_token(document.body, "\\begin_inset CommandInset bibtex", i)
461 j = find_end_of_inset(document.body, i)
463 document.warning("Malformed LyX document: Can't find end of bibtex inset at line " + str(i))
466 k = find_token(document.body, "options", i, j)
468 options = get_quoted_value(document.body, "options", k)
469 if "default" in options.split(","):
470 document.body[k] = 'options "%s"' \
471 % options.replace("default", default_style)
475 def handle_longtable_captions(document, forward):
478 begin_table = find_token(document.body, '<lyxtabular version=', begin_table)
479 if begin_table == -1:
481 end_table = find_end_of(document.body, begin_table, '<lyxtabular', '</lyxtabular>')
483 document.warning("Malformed LyX document: Could not find end of table.")
486 fline = find_token(document.body, "<features", begin_table, end_table)
488 document.warning("Can't find features for inset at line " + str(begin_table))
491 p = document.body[fline].find("islongtable")
496 numrows = get_option_value(document.body[begin_table], "rows")
498 numrows = int(numrows)
500 document.warning(document.body[begin_table])
501 document.warning("Unable to determine rows!")
502 begin_table = end_table
504 begin_row = begin_table
505 for row in range(numrows):
506 begin_row = find_token(document.body, '<row', begin_row, end_table)
508 document.warning("Can't find row " + str(row + 1))
510 end_row = find_end_of(document.body, begin_row, '<row', '</row>')
512 document.warning("Can't find end of row " + str(row + 1))
515 if (get_option_value(document.body[begin_row], 'caption') == 'true' and
516 get_option_value(document.body[begin_row], 'endfirsthead') != 'true' and
517 get_option_value(document.body[begin_row], 'endhead') != 'true' and
518 get_option_value(document.body[begin_row], 'endfoot') != 'true' and
519 get_option_value(document.body[begin_row], 'endlastfoot') != 'true'):
520 document.body[begin_row] = set_option_value(document.body[begin_row], 'caption', 'true", endfirsthead="true')
521 elif get_option_value(document.body[begin_row], 'caption') == 'true':
522 if get_option_value(document.body[begin_row], 'endfirsthead') == 'true':
523 document.body[begin_row] = set_option_value(document.body[begin_row], 'endfirsthead', 'false')
524 if get_option_value(document.body[begin_row], 'endhead') == 'true':
525 document.body[begin_row] = set_option_value(document.body[begin_row], 'endhead', 'false')
526 if get_option_value(document.body[begin_row], 'endfoot') == 'true':
527 document.body[begin_row] = set_option_value(document.body[begin_row], 'endfoot', 'false')
528 if get_option_value(document.body[begin_row], 'endlastfoot') == 'true':
529 document.body[begin_row] = set_option_value(document.body[begin_row], 'endlastfoot', 'false')
531 # since there could be a tabular inside this one, we
532 # cannot jump to end.
536 def convert_longtable_captions(document):
537 "Add a firsthead flag to caption rows"
538 handle_longtable_captions(document, True)
541 def revert_longtable_captions(document):
542 "remove head/foot flag from caption rows"
543 handle_longtable_captions(document, False)
546 def convert_use_packages(document):
547 "use_xxx yyy => use_package xxx yyy"
548 packages = ["amsmath", "esint", "mathdots", "mhchem", "undertilde"]
550 i = find_token(document.header, "\\use_%s" % p, 0)
552 value = get_value(document.header, "\\use_%s" % p, i)
553 document.header[i] = "\\use_package %s %s" % (p, value)
556 def revert_use_packages(document):
557 "use_package xxx yyy => use_xxx yyy"
558 packages = ["amsmath", "esint", "mhchem", "mathdots", "undertilde"]
559 # the order is arbitrary for the use_package version, and not all packages need to be given.
560 # Ensure a complete list and correct order (important for older LyX versions and especially lyx2lyx)
561 # first loop: find line with first package
564 regexp = re.compile(r'(\\use_package\s+%s)' % p)
565 i = find_re(document.header, regexp, 0)
566 if i != -1 and (j < 0 or i < j):
568 # second loop: replace or insert packages in front of all existing ones
570 regexp = re.compile(r'(\\use_package\s+%s)' % p)
571 i = find_re(document.header, regexp, 0)
573 value = get_value(document.header, "\\use_package %s" % p, i).split()[1]
574 del document.header[i]
575 document.header.insert(j, "\\use_%s %s" % (p, value))
577 document.header.insert(j, "\\use_%s 1" % p)
581 def convert_use_package(document, pkg, commands, oldauto):
582 # oldauto defines how the version we are converting from behaves:
583 # if it is true, the old version uses the package automatically.
584 # if it is false, the old version never uses the package.
585 i = find_token(document.header, "\\use_package", 0)
587 document.warning("Malformed LyX document: Can't find \\use_package.")
589 j = find_token(document.preamble, "\\usepackage{" + pkg + "}", 0)
591 # package was loaded in the preamble, convert this to header setting for round trip
592 document.header.insert(i + 1, "\\use_package " + pkg + " 2") # on
593 del document.preamble[j]
594 # If oldauto is true we have two options:
595 # We can either set the package to auto - this is correct for files in
596 # format 425 to 463, and may create a conflict for older files which use
597 # any command in commands with a different definition.
598 # Or we can look whether any command in commands is used, and set it to
599 # auto if not and to off if yes. This will not create a conflict, but will
600 # create uncompilable documents for files in format 425 to 463, which use
601 # any command in commands.
602 # We choose the first option since its error is less likely.
604 document.header.insert(i + 1, "\\use_package " + pkg + " 1") # auto
608 j = find_token(document.body, '\\begin_inset Formula', j)
611 k = find_end_of_inset(document.body, j)
613 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(j))
616 code = "\n".join(document.body[j:k])
618 if code.find("\\%s" % c) != -1:
619 # at least one of the commands was found - need to switch package off
620 document.header.insert(i + 1, "\\use_package " + pkg + " 0") # off
623 # no command was found - set to auto (bug 9069)
624 document.header.insert(i + 1, "\\use_package " + pkg + " 1") # auto
627 def revert_use_package(document, pkg, commands, oldauto):
628 # oldauto defines how the version we are reverting to behaves:
629 # if it is true, the old version uses the package automatically.
630 # if it is false, the old version never uses the package.
631 regexp = re.compile(r'(\\use_package\s+%s)' % pkg)
632 i = find_re(document.header, regexp, 0)
633 value = "1" # default is auto
635 value = get_value(document.header, "\\use_package" , i).split()[1]
636 del document.header[i]
637 if value == "2": # on
638 add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
639 elif value == "1" and not oldauto: # auto
642 i = find_token(document.body, '\\begin_inset Formula', i)
645 j = find_end_of_inset(document.body, i)
647 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
650 code = "\n".join(document.body[i:j])
652 if code.find("\\%s" % c) != -1:
653 add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
658 mathtools_commands = ["mathclap", "mathllap", "mathrlap", \
659 "lgathered", "rgathered", "vcentcolon", "dblcolon", \
660 "coloneqq", "Coloneqq", "coloneq", "Coloneq", "eqqcolon", \
661 "Eqqcolon", "eqcolon", "Eqcolon", "colonapprox", \
662 "Colonapprox", "colonsim", "Colonsim"]
663 def convert_use_mathtools(document):
664 "insert use_package mathtools"
665 convert_use_package(document, "mathtools", mathtools_commands, False)
668 def revert_use_mathtools(document):
669 "remove use_package mathtools"
670 revert_use_package(document, "mathtools", mathtools_commands, False)
673 # commands provided by stmaryrd.sty but LyX uses other packages:
674 # boxdot lightning, bigtriangledown, bigtriangleup
675 stmaryrd_commands = ["shortleftarrow", "shortrightarrow", "shortuparrow", \
676 "shortdownarrow", "Yup", "Ydown", "Yleft", "Yright", \
677 "varcurlyvee", "varcurlywedge", "minuso", "baro", \
678 "sslash", "bbslash", "moo", "varotimes", "varoast", \
679 "varobar", "varodot", "varoslash", "varobslash", \
680 "varocircle", "varoplus", "varominus", "boxast", \
681 "boxbar", "boxslash", "boxbslash", "boxcircle", \
682 "boxbox", "boxempty", "merge", "vartimes", \
683 "fatsemi", "sswarrow", "ssearrow", "curlywedgeuparrow", \
684 "curlywedgedownarrow", "fatslash", "fatbslash", "lbag", \
685 "rbag", "varbigcirc", "leftrightarroweq", \
686 "curlyveedownarrow", "curlyveeuparrow", "nnwarrow", \
687 "nnearrow", "leftslice", "rightslice", "varolessthan", \
688 "varogreaterthan", "varovee", "varowedge", "talloblong", \
689 "interleave", "obar", "obslash", "olessthan", \
690 "ogreaterthan", "ovee", "owedge", "oblong", "inplus", \
691 "niplus", "nplus", "subsetplus", "supsetplus", \
692 "subsetpluseq", "supsetpluseq", "Lbag", "Rbag", \
693 "llbracket", "rrbracket", "llparenthesis", \
694 "rrparenthesis", "binampersand", "bindnasrepma", \
695 "trianglelefteqslant", "trianglerighteqslant", \
696 "ntrianglelefteqslant", "ntrianglerighteqslant", \
697 "llfloor", "rrfloor", "llceil", "rrceil", "arrownot", \
698 "Arrownot", "Mapstochar", "mapsfromchar", "Mapsfromchar", \
699 "leftrightarrowtriangle", "leftarrowtriangle", \
700 "rightarrowtriangle", \
701 "bigcurlyvee", "bigcurlywedge", "bigsqcap", "bigbox", \
702 "bigparallel", "biginterleave", "bignplus", \
703 "varcopyright", "longarrownot", "Longarrownot", \
704 "Mapsto", "mapsfrom", "Mapsfrom" "Longmapsto", \
705 "longmapsfrom", "Longmapsfrom"]
706 def convert_use_stmaryrd(document):
707 "insert use_package stmaryrd"
708 convert_use_package(document, "stmaryrd", stmaryrd_commands, False)
711 def revert_use_stmaryrd(document):
712 "remove use_package stmaryrd"
713 revert_use_package(document, "stmaryrd", stmaryrd_commands, False)
716 stackrel_commands = ["stackrel"]
717 def convert_use_stackrel(document):
718 "insert use_package stackrel"
719 convert_use_package(document, "stackrel", stackrel_commands, False)
722 def revert_use_stackrel(document):
723 "remove use_package stackrel"
724 revert_use_package(document, "stackrel", stackrel_commands, False)
727 def convert_cite_engine_type(document):
728 "Determine the \\cite_engine_type from the citation engine."
729 i = find_token(document.header, "\\cite_engine", 0)
732 engine = get_value(document.header, "\\cite_engine", i)
734 engine, type = engine.split("_")
736 type = {"basic": "numerical", "jurabib": "authoryear"}[engine]
737 document.header[i] = "\\cite_engine " + engine
738 document.header.insert(i + 1, "\\cite_engine_type " + type)
741 def revert_cite_engine_type(document):
742 "Natbib had the type appended with an underscore."
743 engine_type = "numerical"
744 i = find_token(document.header, "\\cite_engine_type" , 0)
746 document.warning("No \\cite_engine_type line. Assuming numerical.")
748 engine_type = get_value(document.header, "\\cite_engine_type", i)
749 del document.header[i]
751 # We are looking for the natbib citation engine
752 i = find_token(document.header, "\\cite_engine natbib", 0)
755 document.header[i] = "\\cite_engine natbib_" + engine_type
758 def convert_cite_engine_type_default(document):
759 "Convert \\cite_engine_type to default for the basic citation engine."
760 i = find_token(document.header, "\\cite_engine basic", 0)
763 i = find_token(document.header, "\\cite_engine_type" , 0)
766 document.header[i] = "\\cite_engine_type default"
769 def revert_cite_engine_type_default(document):
770 """Revert \\cite_engine_type default.
772 Revert to numerical for the basic cite engine, otherwise to authoryear."""
773 engine_type = "authoryear"
774 i = find_token(document.header, "\\cite_engine_type default" , 0)
777 j = find_token(document.header, "\\cite_engine basic", 0)
779 engine_type = "numerical"
780 document.header[i] = "\\cite_engine_type " + engine_type
783 cancel_commands = ["cancel", "bcancel", "xcancel", "cancelto"]
784 # this is the same, as revert_use_cancel() except for the default
785 def revert_cancel(document):
786 "add cancel to the preamble if necessary"
787 revert_use_package(document, "cancel", cancel_commands, False)
790 def revert_verbatim(document):
791 " Revert verbatim einvironments completely to TeX-code. "
794 subst_end = ['\end_layout', '', '\\begin_layout Plain Layout',
796 '\\begin_layout Plain Layout', '', '',
799 '\\end_layout', '', '\\end_inset',
800 '', '', '\\end_layout']
801 subst_begin = ['\\begin_layout Standard', '\\noindent',
802 '\\begin_inset ERT', 'status open', '',
803 '\\begin_layout Plain Layout', '', '', '\\backslash',
805 '\\end_layout', '', '\\begin_layout Plain Layout', '']
808 i = find_token(document.body, "\\begin_layout Verbatim", i)
811 j = find_end_of_layout(document.body, i)
813 document.warning("Malformed LyX document: Can't find end of Verbatim layout")
816 # delete all line breaks insets (there are no other insets)
819 n = find_token(document.body, "\\begin_inset Newline newline", l, j)
821 n = find_token(document.body, "\\begin_inset Newline linebreak", l, j)
824 m = find_end_of_inset(document.body, n)
825 del(document.body[m:m+1])
826 document.body[n:n+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
828 # we deleted a line, so the end of the inset moved forward.
830 # consecutive verbatim environments need to be connected
831 k = find_token(document.body, "\\begin_layout Verbatim", j)
832 if k == j + 2 and consecutive == False:
834 document.body[j:j+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
835 document.body[i:i+1] = subst_begin
837 if k == j + 2 and consecutive == True:
838 document.body[j:j+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
839 del(document.body[i:i+1])
841 if k != j + 2 and consecutive == True:
842 document.body[j:j+1] = subst_end
843 # the next paragraph must not be indented
844 document.body[j+19:j+19] = ['\\noindent']
845 del(document.body[i:i+1])
849 document.body[j:j+1] = subst_end
850 # the next paragraph must not be indented
851 document.body[j+19:j+19] = ['\\noindent']
852 document.body[i:i+1] = subst_begin
855 def revert_tipa(document):
856 " Revert native TIPA insets to mathed or ERT. "
859 i = find_token(document.body, "\\begin_inset IPA", i)
862 j = find_end_of_inset(document.body, i)
864 document.warning("Malformed LyX document: Can't find end of IPA inset")
868 n = find_token(document.body, "\\begin_layout", i, j)
870 document.warning("Malformed LyX document: IPA inset has no embedded layout")
873 m = find_end_of_layout(document.body, n)
875 document.warning("Malformed LyX document: Can't find end of embedded layout")
878 content = document.body[n+1:m]
879 p = find_token(document.body, "\\begin_layout", m, j)
880 if p != -1 or len(content) > 1:
882 content = document.body[i+1:j]
884 # IPA insets with multiple pars need to be wrapped by \begin{IPA}...\end{IPA}
885 document.body[i:j+1] = ['\\end_layout', '', '\\begin_layout Standard'] + put_cmd_in_ert("\\begin{IPA}") + ['\\end_layout'] + content + ['\\begin_layout Standard'] + put_cmd_in_ert("\\end{IPA}")
886 add_to_preamble(document, ["\\usepackage{tipa,tipx}"])
888 # single-par IPA insets can be reverted to mathed
889 document.body[i:j+1] = ["\\begin_inset Formula $\\text{\\textipa{" + content[0] + "}}$", "\\end_inset"]
893 def revert_cell_rotation(document):
894 "Revert cell rotations to TeX-code"
896 load_rotating = False
900 # first, let's find out if we need to do anything
901 i = find_token(document.body, '<cell ', i)
904 j = document.body[i].find('rotate="')
906 k = document.body[i].find('"', j + 8)
907 value = document.body[i][j + 8 : k]
909 rgx = re.compile(r' rotate="[^"]+?"')
910 # remove rotate option
911 document.body[i] = rgx.sub('', document.body[i])
913 rgx = re.compile(r' rotate="[^"]+?"')
914 document.body[i] = rgx.sub('rotate="true"', document.body[i])
916 rgx = re.compile(r' rotate="[^"]+?"')
918 # remove rotate option
919 document.body[i] = rgx.sub('', document.body[i])
921 document.body[i + 5 : i + 5] = \
922 put_cmd_in_ert("\\end{turn}")
923 document.body[i + 4 : i + 4] = \
924 put_cmd_in_ert("\\begin{turn}{" + value + "}")
930 add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"])
933 def convert_cell_rotation(document):
934 'Convert cell rotation statements from "true" to "90"'
938 # first, let's find out if we need to do anything
939 i = find_token(document.body, '<cell ', i)
942 j = document.body[i].find('rotate="true"')
944 rgx = re.compile(r'rotate="[^"]+?"')
945 # convert "true" to "90"
946 document.body[i] = rgx.sub('rotate="90"', document.body[i])
951 def revert_table_rotation(document):
952 "Revert table rotations to TeX-code"
954 load_rotating = False
958 # first, let's find out if we need to do anything
959 i = find_token(document.body, '<features ', i)
962 j = document.body[i].find('rotate="')
964 end_table = find_token(document.body, '</lyxtabular>', j)
965 k = document.body[i].find('"', j + 8)
966 value = document.body[i][j + 8 : k]
968 rgx = re.compile(r' rotate="[^"]+?"')
969 # remove rotate option
970 document.body[i] = rgx.sub('', document.body[i])
972 rgx = re.compile(r'rotate="[^"]+?"')
973 document.body[i] = rgx.sub('rotate="true"', document.body[i])
975 rgx = re.compile(r' rotate="[^"]+?"')
977 # remove rotate option
978 document.body[i] = rgx.sub('', document.body[i])
980 document.body[end_table + 3 : end_table + 3] = \
981 put_cmd_in_ert("\\end{turn}")
982 document.body[i - 2 : i - 2] = \
983 put_cmd_in_ert("\\begin{turn}{" + value + "}")
989 add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"])
992 def convert_table_rotation(document):
993 'Convert table rotation statements from "true" to "90"'
997 # first, let's find out if we need to do anything
998 i = find_token(document.body, '<features ', i)
1001 j = document.body[i].find('rotate="true"')
1003 rgx = re.compile(r'rotate="[^"]+?"')
1004 # convert "true" to "90"
1005 document.body[i] = rgx.sub('rotate="90"', document.body[i])
1010 def convert_listoflistings(document):
1011 'Convert ERT \lstlistoflistings to TOC lstlistoflistings inset'
1012 # We can support roundtrip because the command is so simple
1015 i = find_token(document.body, "\\begin_inset ERT", i)
1018 j = find_end_of_inset(document.body, i)
1020 document.warning("Malformed LyX document: Can't find end of ERT inset")
1023 ert = get_ert(document.body, i)
1024 if ert == "\\lstlistoflistings{}":
1025 document.body[i:j] = ["\\begin_inset CommandInset toc", "LatexCommand lstlistoflistings", ""]
1031 def revert_listoflistings(document):
1032 'Convert TOC lstlistoflistings inset to ERT lstlistoflistings'
1035 i = find_token(document.body, "\\begin_inset CommandInset toc", i)
1038 if document.body[i+1] == "LatexCommand lstlistoflistings":
1039 j = find_end_of_inset(document.body, i)
1041 document.warning("Malformed LyX document: Can't find end of TOC inset")
1044 subst = put_cmd_in_ert("\\lstlistoflistings{}")
1045 document.body[i:j+1] = subst
1046 add_to_preamble(document, ["\\usepackage{listings}"])
1050 def convert_use_amssymb(document):
1051 "insert use_package amssymb"
1052 regexp = re.compile(r'(\\use_package\s+amsmath)')
1053 i = find_re(document.header, regexp, 0)
1055 document.warning("Malformed LyX document: Can't find \\use_package amsmath.")
1057 value = get_value(document.header, "\\use_package" , i).split()[1]
1060 useamsmath = int(value)
1062 document.warning("Invalid \\use_package amsmath: " + value + ". Assuming auto.")
1064 j = find_token(document.preamble, "\\usepackage{amssymb}", 0)
1066 document.header.insert(i + 1, "\\use_package amssymb %d" % useamsmath)
1068 document.header.insert(i + 1, "\\use_package amssymb 2")
1069 del document.preamble[j]
1072 def revert_use_amssymb(document):
1073 "remove use_package amssymb"
1074 regexp1 = re.compile(r'(\\use_package\s+amsmath)')
1075 regexp2 = re.compile(r'(\\use_package\s+amssymb)')
1076 i = find_re(document.header, regexp1, 0)
1077 j = find_re(document.header, regexp2, 0)
1078 value1 = "1" # default is auto
1079 value2 = "1" # default is auto
1081 value1 = get_value(document.header, "\\use_package" , i).split()[1]
1083 value2 = get_value(document.header, "\\use_package" , j).split()[1]
1084 del document.header[j]
1085 if value1 != value2 and value2 == "2": # on
1086 add_to_preamble(document, ["\\usepackage{amssymb}"])
1089 def convert_use_cancel(document):
1090 "insert use_package cancel"
1091 convert_use_package(document, "cancel", cancel_commands, True)
1094 def revert_use_cancel(document):
1095 "remove use_package cancel"
1096 revert_use_package(document, "cancel", cancel_commands, True)
1099 def revert_ancientgreek(document):
1100 "Set the document language for ancientgreek to greek"
1102 if document.language == "ancientgreek":
1103 document.language = "greek"
1104 i = find_token(document.header, "\\language", 0)
1106 document.header[i] = "\\language greek"
1109 j = find_token(document.body, "\\lang ancientgreek", j)
1113 document.body[j] = document.body[j].replace("\\lang ancientgreek", "\\lang greek")
1117 def revert_languages(document):
1118 "Set the document language for new supported languages to English"
1121 "coptic", "divehi", "hindi", "kurmanji", "lao", "marathi", "occitan", "sanskrit",
1122 "syriac", "tamil", "telugu", "urdu"
1124 for n in range(len(languages)):
1125 if document.language == languages[n]:
1126 document.language = "english"
1127 i = find_token(document.header, "\\language", 0)
1129 document.header[i] = "\\language english"
1131 while j < len(document.body):
1132 j = find_token(document.body, "\\lang " + languages[n], j)
1134 document.body[j] = document.body[j].replace("\\lang " + languages[n], "\\lang english")
1137 j = len(document.body)
1140 def convert_armenian(document):
1141 "Use polyglossia and thus non-TeX fonts for Armenian"
1143 if document.language == "armenian":
1144 i = find_token(document.header, "\\use_non_tex_fonts", 0)
1146 document.header[i] = "\\use_non_tex_fonts true"
1149 def revert_armenian(document):
1150 "Use ArmTeX and thus TeX fonts for Armenian"
1152 if document.language == "armenian":
1153 i = find_token(document.header, "\\use_non_tex_fonts", 0)
1155 document.header[i] = "\\use_non_tex_fonts false"
1158 def revert_libertine(document):
1159 " Revert native libertine font definition to LaTeX "
1161 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1162 i = find_token(document.header, "\\font_roman libertine", 0)
1165 j = find_token(document.header, "\\font_osf true", 0)
1168 preamble = "\\usepackage"
1170 document.header[j] = "\\font_osf false"
1173 preamble += "[lining]"
1174 preamble += "{libertine-type1}"
1175 add_to_preamble(document, [preamble])
1176 document.header[i] = "\\font_roman default"
1179 def revert_txtt(document):
1180 " Revert native txtt font definition to LaTeX "
1182 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1183 i = find_token(document.header, "\\font_typewriter txtt", 0)
1185 preamble = "\\renewcommand{\\ttdefault}{txtt}"
1186 add_to_preamble(document, [preamble])
1187 document.header[i] = "\\font_typewriter default"
1190 def revert_mathdesign(document):
1191 " Revert native mathdesign font definition to LaTeX "
1193 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1199 i = find_token(document.header, "\\font_roman", 0)
1202 val = get_value(document.header, "\\font_roman", i)
1203 if val in mathdesign_dict.keys():
1204 preamble = "\\usepackage[%s" % mathdesign_dict[val]
1206 j = find_token(document.header, "\\font_osf true", 0)
1209 document.header[j] = "\\font_osf false"
1210 l = find_token(document.header, "\\font_sc true", 0)
1213 document.header[l] = "\\font_sc false"
1215 preamble += ",expert"
1216 preamble += "]{mathdesign}"
1217 add_to_preamble(document, [preamble])
1218 document.header[i] = "\\font_roman default"
1221 def revert_texgyre(document):
1222 " Revert native TeXGyre font definition to LaTeX "
1224 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1225 texgyre_fonts = ["tgadventor", "tgbonum", "tgchorus", "tgcursor", \
1226 "tgheros", "tgpagella", "tgschola", "tgtermes"]
1227 i = find_token(document.header, "\\font_roman", 0)
1229 val = get_value(document.header, "\\font_roman", i)
1230 if val in texgyre_fonts:
1231 preamble = "\\usepackage{%s}" % val
1232 add_to_preamble(document, [preamble])
1233 document.header[i] = "\\font_roman default"
1234 i = find_token(document.header, "\\font_sans", 0)
1236 val = get_value(document.header, "\\font_sans", i)
1237 if val in texgyre_fonts:
1238 preamble = "\\usepackage{%s}" % val
1239 add_to_preamble(document, [preamble])
1240 document.header[i] = "\\font_sans default"
1241 i = find_token(document.header, "\\font_typewriter", 0)
1243 val = get_value(document.header, "\\font_typewriter", i)
1244 if val in texgyre_fonts:
1245 preamble = "\\usepackage{%s}" % val
1246 add_to_preamble(document, [preamble])
1247 document.header[i] = "\\font_typewriter default"
1250 def revert_ipadeco(document):
1251 " Revert IPA decorations to ERT "
1254 i = find_token(document.body, "\\begin_inset IPADeco", i)
1257 end = find_end_of_inset(document.body, i)
1259 document.warning("Can't find end of inset at line " + str(i))
1262 line = document.body[i]
1263 rx = re.compile(r'\\begin_inset IPADeco (.*)$')
1265 decotype = m.group(1)
1266 if decotype != "toptiebar" and decotype != "bottomtiebar":
1267 document.warning("Invalid IPADeco type: " + decotype)
1270 blay = find_token(document.body, "\\begin_layout Plain Layout", i, end)
1272 document.warning("Can't find layout for inset at line " + str(i))
1275 bend = find_end_of_layout(document.body, blay)
1277 document.warning("Malformed LyX document: Could not find end of IPADeco inset's layout.")
1280 substi = ["\\begin_inset ERT", "status collapsed", "",
1281 "\\begin_layout Plain Layout", "", "", "\\backslash",
1282 decotype + "{", "\\end_layout", "", "\\end_inset"]
1283 substj = ["\\size default", "", "\\begin_inset ERT", "status collapsed", "",
1284 "\\begin_layout Plain Layout", "", "}", "\\end_layout", "", "\\end_inset"]
1285 # do the later one first so as not to mess up the numbering
1286 document.body[bend:end + 1] = substj
1287 document.body[i:blay + 1] = substi
1288 i = end + len(substi) + len(substj) - (end - bend) - (blay - i) - 2
1289 add_to_preamble(document, "\\usepackage{tipa}")
1292 def revert_ipachar(document):
1293 ' Revert \\IPAChar to ERT '
1296 while i < len(document.body):
1297 m = re.match(r'(.*)\\IPAChar \\(\w+\{\w+\})(.*)', document.body[i])
1301 ipachar = m.group(2)
1304 '\\begin_inset ERT',
1305 'status collapsed', '',
1306 '\\begin_layout Standard',
1307 '', '', '\\backslash',
1312 document.body[i: i+1] = subst
1317 add_to_preamble(document, "\\usepackage{tone}")
1320 def revert_minionpro(document):
1321 " Revert native MinionPro font definition to LaTeX "
1323 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1324 i = find_token(document.header, "\\font_roman minionpro", 0)
1327 j = find_token(document.header, "\\font_osf true", 0)
1330 preamble = "\\usepackage"
1332 document.header[j] = "\\font_osf false"
1335 preamble += "{MinionPro}"
1336 add_to_preamble(document, [preamble])
1337 document.header[i] = "\\font_roman default"
1340 def revert_mathfonts(document):
1341 " Revert native math font definitions to LaTeX "
1343 i = find_token(document.header, "\\font_math", 0)
1346 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1347 val = get_value(document.header, "\\font_math", i)
1348 if val == "eulervm":
1349 add_to_preamble(document, "\\usepackage{eulervm}")
1350 elif val == "default":
1352 "lmodern": "\\renewcommand{\\rmdefault}{lmr}",
1353 "minionpro": "\\usepackage[onlytext,lf]{MinionPro}",
1354 "minionpro-osf": "\\usepackage[onlytext]{MinionPro}",
1355 "palatino": "\\renewcommand{\\rmdefault}{ppl}",
1356 "palatino-osf": "\\renewcommand{\\rmdefault}{pplj}",
1357 "times": "\\renewcommand{\\rmdefault}{ptm}",
1358 "utopia": "\\renewcommand{\\rmdefault}{futs}",
1359 "utopia-osf": "\\renewcommand{\\rmdefault}{futj}",
1361 j = find_token(document.header, "\\font_roman", 0)
1363 rm = get_value(document.header, "\\font_roman", j)
1364 k = find_token(document.header, "\\font_osf true", 0)
1367 if rm in mathfont_dict.keys():
1368 add_to_preamble(document, mathfont_dict[rm])
1369 document.header[j] = "\\font_roman default"
1371 document.header[k] = "\\font_osf false"
1372 del document.header[i]
1375 def revert_mdnomath(document):
1376 " Revert mathdesign and fourier without math "
1378 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1380 "md-charter": "mdbch",
1381 "md-utopia": "mdput",
1382 "md-garamond": "mdugm"
1384 i = find_token(document.header, "\\font_roman", 0)
1387 val = get_value(document.header, "\\font_roman", i)
1388 if val in mathdesign_dict.keys():
1389 j = find_token(document.header, "\\font_math", 0)
1391 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1392 mval = get_value(document.header, "\\font_math", j)
1393 if mval == "default":
1394 document.header[i] = "\\font_roman default"
1395 add_to_preamble(document, "\\renewcommand{\\rmdefault}{%s}" % mathdesign_dict[val])
1397 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1400 def convert_mdnomath(document):
1401 " Change mathdesign font name "
1403 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1405 "mdbch": "md-charter",
1406 "mdput": "md-utopia",
1407 "mdugm": "md-garamond"
1409 i = find_token(document.header, "\\font_roman", 0)
1412 val = get_value(document.header, "\\font_roman", i)
1413 if val in mathdesign_dict.keys():
1414 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1417 def revert_newtxmath(document):
1418 " Revert native newtxmath definitions to LaTeX "
1420 i = find_token(document.header, "\\font_math", 0)
1423 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1424 val = get_value(document.header, "\\font_math", i)
1426 "libertine-ntxm": "\\usepackage[libertine]{newtxmath}",
1427 "minion-ntxm": "\\usepackage[minion]{newtxmath}",
1428 "newtxmath": "\\usepackage{newtxmath}",
1430 if val in mathfont_dict.keys():
1431 add_to_preamble(document, mathfont_dict[val])
1432 document.header[i] = "\\font_math auto"
1435 def revert_biolinum(document):
1436 " Revert native biolinum font definition to LaTeX "
1438 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1439 i = find_token(document.header, "\\font_sans biolinum", 0)
1442 j = find_token(document.header, "\\font_osf true", 0)
1445 preamble = "\\usepackage"
1448 preamble += "{biolinum-type1}"
1449 add_to_preamble(document, [preamble])
1450 document.header[i] = "\\font_sans default"
1453 def revert_uop(document):
1454 " Revert native URW Classico (Optima) font definition to LaTeX "
1456 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1457 i = find_token(document.header, "\\font_sans uop", 0)
1459 preamble = "\\renewcommand{\\sfdefault}{uop}"
1460 add_to_preamble(document, [preamble])
1461 document.header[i] = "\\font_sans default"
1464 def convert_latexargs(document):
1465 " Convert InsetArgument to new syntax "
1467 if find_token(document.body, "\\begin_inset Argument", 0) == -1:
1471 # A list of layouts (document classes) with only optional or no arguments.
1472 # These can be safely converted to the new syntax
1473 # (I took the liberty to add some of my personal layouts/modules here; JSP)
1474 safe_layouts = ["aa", "aapaper", "aastex", "achemso", "acmsiggraph", "AEA",
1475 "agu-dtd", "agums", "agutex", "amsart", "amsbook", "apa",
1476 "arab-article", "armenian-article", "article-beamer", "article",
1477 "beamer", "book", "broadway", "chess", "cl2emult", "ctex-article",
1478 "ctex-book", "ctex-report", "dinbrief", "docbook-book", "docbook-chapter",
1479 "docbook", "docbook-section", "doublecol-new", "dtk", "ectaart", "egs",
1480 "elsarticle", "elsart", "entcs", "europecv", "extarticle", "extbook",
1481 "extletter", "extreport", "foils", "frletter", "g-brief2", "g-brief",
1482 "heb-article", "heb-letter", "hollywood", "IEEEtran", "ijmpc", "ijmpd",
1483 "iopart", "isprs", "jarticle", "jasatex", "jbook", "jgrga", "jreport",
1484 "jsarticle", "jsbeamer", "jsbook", "jss", "kluwer", "latex8", "letter", "lettre",
1485 "literate-article", "literate-book", "literate-report", "llncs", "ltugboat",
1486 "memoir", "moderncv", "mwart", "mwbk", "mwrep", "paper", "powerdot",
1487 "recipebook", "report", "revtex4", "revtex", "scrartcl", "scrarticle-beamer",
1488 "scrbook", "scrlettr", "scrlttr2", "scrreprt", "seminar", "siamltex",
1489 "sigplanconf", "simplecv", "singlecol", "singlecol-new", "slides", "spie",
1490 "svglobal3", "svglobal", "svjog", "svmono", "svmult", "svprobth", "tarticle",
1491 "tbook", "treport", "tufte-book", "tufte-handout"]
1492 # A list of "safe" modules, same as above
1493 safe_modules = ["biblatex", "beameraddons", "beamersession", "braille", "customHeadersFooters",
1494 "endnotes", "enumitem", "eqs-within-sections", "figs-within-sections", "fix-cm",
1495 "fixltx2e", "foottoend", "hanging", "jscharstyles", "knitr", "lilypond",
1496 "linguistics", "linguisticx", "logicalmkup", "minimalistic", "nomindex", "noweb",
1497 "pdfcomment", "sweave", "tabs-within-sections", "theorems-ams-bytype",
1498 "theorems-ams-extended-bytype", "theorems-ams-extended", "theorems-ams", "theorems-bytype",
1499 "theorems-chap-bytype", "theorems-chap", "theorems-named", "theorems-sec-bytype",
1500 "theorems-sec", "theorems-starred", "theorems-std", "todonotes"]
1501 # Modules we need to take care of
1502 caveat_modules = ["initials"]
1503 # information about the relevant styles in caveat_modules (number of opt and req args)
1504 # use this if we get more caveat_modules. For now, use hard coding (see below).
1505 # initials = [{'Layout' : 'Initial', 'opt' : 1, 'req' : 1}]
1507 # Is this a known safe layout?
1508 safe_layout = document.textclass in safe_layouts
1510 document.warning("Lyx2lyx knows nothing about textclass '%s'. "
1511 "Please check if short title insets have been converted correctly."
1512 % document.textclass)
1513 # Do we use unsafe or unknown modules
1514 mods = document.get_module_list()
1515 unknown_modules = False
1516 used_caveat_modules = list()
1518 if mod in safe_modules:
1520 if mod in caveat_modules:
1521 used_caveat_modules.append(mod)
1523 unknown_modules = True
1524 document.warning("Lyx2lyx knows nothing about module '%s'. "
1525 "Please check if short title insets have been converted correctly."
1530 i = find_token(document.body, "\\begin_inset Argument", i)
1534 if not safe_layout or unknown_modules:
1535 # We cannot do more here since we have no access to this layout.
1536 # InsetArgument itself will do the real work
1537 # (see InsetArgument::updateBuffer())
1538 document.body[i] = "\\begin_inset Argument 999"
1542 # Find containing paragraph layout
1543 parent = get_containing_layout(document.body, i)
1545 document.warning("Malformed LyX document: Can't find parent paragraph layout")
1552 if len(used_caveat_modules) > 0:
1553 # We know for now that this must be the initials module with the Initial layout
1554 # If we get more such modules, we need some automating.
1555 if parent[0] == "Initial":
1556 # Layout has 1 opt and 1 req arg.
1557 # Count the actual arguments
1559 for p in range(parbeg, parend):
1560 if document.body[p] == "\\begin_inset Argument":
1565 # Collect all arguments in this paragraph
1567 for p in range(parbeg, parend):
1568 if document.body[p] == "\\begin_inset Argument":
1570 if allowed_opts != -1:
1571 # We have less arguments than opt + required.
1572 # required must take precedence.
1573 if argnr > allowed_opts and argnr < first_req:
1575 document.body[p] = "\\begin_inset Argument %d" % argnr
1579 def revert_latexargs(document):
1580 " Revert InsetArgument to old syntax "
1583 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
1586 # Search for Argument insets
1587 i = find_token(document.body, "\\begin_inset Argument", i)
1590 m = rx.match(document.body[i])
1592 # No ID: inset already reverted
1595 # Find containing paragraph layout
1596 parent = get_containing_layout(document.body, i)
1598 document.warning("Malformed LyX document: Can't find parent paragraph layout")
1603 # Do not set realparbeg to parent[3], since this does not work if we
1604 # have another inset (e.g. label or index) before the first argument
1605 # inset (this is the case in the user guide of LyX 2.0.8)
1607 # Collect all arguments in this paragraph
1609 for p in range(parbeg, parend):
1610 m = rx.match(document.body[p])
1613 # This is the first argument inset
1615 val = int(m.group(1))
1616 j = find_end_of_inset(document.body, p)
1617 # Revert to old syntax
1618 document.body[p] = "\\begin_inset Argument"
1620 document.warning("Malformed LyX document: Can't find end of Argument inset")
1623 args[val] = document.body[p : j + 1]
1625 realparend = realparend - len(document.body[p : j + 1])
1626 # Remove arg inset at this position
1627 del document.body[p : j + 1]
1631 # No argument inset found
1632 realparbeg = parent[3]
1633 # Now sort the arg insets
1635 for f in sorted(args):
1638 # Insert the sorted arg insets at paragraph begin
1639 document.body[realparbeg : realparbeg] = subst
1641 i = realparbeg + 1 + len(subst)
1644 def revert_IEEEtran(document):
1646 Reverts InsetArgument of
1649 Biography without photo
1652 if document.textclass == "IEEEtran":
1659 i = find_token(document.body, "\\begin_layout Page headings", i)
1661 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1664 i2 = find_token(document.body, "\\begin_inset Flex Paragraph Start", i2)
1666 revert_Argument_to_TeX_brace(document, i2, 0, 1, 1, False, False)
1669 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1671 revert_Argument_to_TeX_brace(document, j, 0, 1, 1, True, False)
1674 k = find_token(document.body, "\\begin_layout Biography", k)
1675 kA = find_token(document.body, "\\begin_layout Biography without photo", k)
1676 if k == kA and k != -1:
1680 # start with the second argument, therefore 2
1681 revert_Argument_to_TeX_brace(document, k, 0, 2, 2, True, False)
1683 if i == -1 and i2 == -1 and j == -1 and k == -1:
1687 def revert_IEEEtran_2(document):
1689 Reverts Flex Paragraph Start to TeX-code
1691 if document.textclass == "IEEEtran":
1694 begin = find_token(document.body, "\\begin_inset Flex Paragraph Start", begin)
1697 end1 = find_end_of_inset(document.body, begin)
1698 document.body[end1 - 2 : end1 + 1] = put_cmd_in_ert("}")
1699 document.body[begin : begin + 4] = put_cmd_in_ert("\\IEEEPARstart{")
1703 def convert_IEEEtran(document):
1708 Biography without photo
1711 if document.textclass == "IEEEtran":
1717 i = find_token(document.body, "\\begin_layout Page headings", i)
1719 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1722 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1724 convert_TeX_brace_to_Argument(document, j, 1, 1, False, True, False)
1727 # assure that we don't handle Biography Biography without photo
1728 k = find_token(document.body, "\\begin_layout Biography", k)
1729 kA = find_token(document.body, "\\begin_layout Biography without photo", k - 1)
1730 if k == kA and k != -1:
1734 # the argument we want to convert is the second one
1735 convert_TeX_brace_to_Argument(document, k, 2, 2, False, True, False)
1737 if i == -1 and j == -1 and k == -1:
1741 def revert_AASTeX(document):
1742 " Reverts InsetArgument of Altaffilation to TeX-code "
1743 if document.textclass == "aastex":
1746 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1749 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1753 def convert_AASTeX(document):
1754 " Converts ERT of Altaffilation to InsetArgument "
1755 if document.textclass == "aastex":
1758 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1761 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1765 def revert_AGUTeX(document):
1766 " Reverts InsetArgument of Author affiliation to TeX-code "
1767 if document.textclass == "agutex":
1770 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1773 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1777 def convert_AGUTeX(document):
1778 " Converts ERT of Author affiliation to InsetArgument "
1779 if document.textclass == "agutex":
1782 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1785 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1789 def revert_IJMP(document):
1790 " Reverts InsetArgument of MarkBoth to TeX-code "
1791 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1794 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1797 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1801 def convert_IJMP(document):
1802 " Converts ERT of MarkBoth to InsetArgument "
1803 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1806 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1809 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1813 def revert_SIGPLAN(document):
1814 " Reverts InsetArguments of SIGPLAN to TeX-code "
1815 if document.textclass == "sigplanconf":
1820 i = find_token(document.body, "\\begin_layout Conference", i)
1822 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1825 j = find_token(document.body, "\\begin_layout Author", j)
1827 revert_Argument_to_TeX_brace(document, j, 0, 1, 2, False, False)
1829 if i == -1 and j == -1:
1833 def convert_SIGPLAN(document):
1834 " Converts ERT of SIGPLAN to InsetArgument "
1835 if document.textclass == "sigplanconf":
1840 i = find_token(document.body, "\\begin_layout Conference", i)
1842 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1845 j = find_token(document.body, "\\begin_layout Author", j)
1847 convert_TeX_brace_to_Argument(document, j, 1, 2, False, False, False)
1849 if i == -1 and j == -1:
1853 def revert_SIGGRAPH(document):
1854 " Reverts InsetArgument of Flex CRcat to TeX-code "
1855 if document.textclass == "acmsiggraph":
1858 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1861 revert_Argument_to_TeX_brace(document, i, 0, 1, 3, False, False)
1865 def convert_SIGGRAPH(document):
1866 " Converts ERT of Flex CRcat to InsetArgument "
1867 if document.textclass == "acmsiggraph":
1870 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1873 convert_TeX_brace_to_Argument(document, i, 1, 3, True, False, False)
1877 def revert_EuropeCV(document):
1878 " Reverts InsetArguments of europeCV to TeX-code "
1879 if document.textclass == "europecv":
1886 i = find_token(document.body, "\\begin_layout Item", i)
1888 revert_Argument_to_TeX_brace(document, i, 0, 2, 2, False, False)
1891 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1893 revert_Argument_to_TeX_brace(document, j, 0, 2, 2, False, False)
1896 k = find_token(document.body, "\\begin_layout Language", k)
1898 revert_Argument_to_TeX_brace(document, k, 0, 2, 6, False, False)
1901 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1903 revert_Argument_to_TeX_brace(document, m, 0, 2, 6, False, False)
1905 if i == -1 and j == -1 and k == -1 and m == -1:
1909 def convert_EuropeCV(document):
1910 " Converts ERT of europeCV to InsetArgument "
1911 if document.textclass == "europecv":
1918 i = find_token(document.body, "\\begin_layout Item", i)
1920 convert_TeX_brace_to_Argument(document, i, 2, 2, False, False, False)
1923 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1925 convert_TeX_brace_to_Argument(document, j, 2, 2, False, False, False)
1928 k = find_token(document.body, "\\begin_layout Language", k)
1930 convert_TeX_brace_to_Argument(document, k, 2, 6, False, False, False)
1933 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1935 convert_TeX_brace_to_Argument(document, m, 2, 6, False, False, False)
1937 if i == -1 and j == -1 and k == -1 and m == -1:
1941 def revert_ModernCV(document):
1942 " Reverts InsetArguments of modernCV to TeX-code "
1943 if document.textclass == "moderncv":
1951 j = find_token(document.body, "\\begin_layout Entry", j)
1953 revert_Argument_to_TeX_brace(document, j, 0, 1, 5, False, False)
1956 k = find_token(document.body, "\\begin_layout Item", k)
1958 revert_Argument_to_TeX_brace(document, k, 0, 1, 1, False, False)
1961 m = find_token(document.body, "\\begin_layout ItemWithComment", m)
1963 revert_Argument_to_TeX_brace(document, m, 0, 1, 2, False, False)
1964 document.body[m] = document.body[m].replace("\\begin_layout ItemWithComment", "\\begin_layout Language")
1967 o = find_token(document.body, "\\begin_layout DoubleItem", o)
1969 revert_Argument_to_TeX_brace(document, o, 0, 1, 3, False, False)
1970 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout Computer")
1973 p = find_token(document.body, "\\begin_layout Social", p)
1975 revert_Argument_to_TeX_brace(document, p, 0, 1, 1, False, True)
1977 if j == -1 and k == -1 and m == -1 and o == -1 and p == -1:
1981 def revert_ModernCV_2(document):
1982 " Reverts the Flex:Column inset of modernCV to TeX-code "
1983 if document.textclass == "moderncv":
1987 flex = find_token(document.body, "\\begin_inset Flex Column", flex)
1990 flexEnd = find_end_of_inset(document.body, flex)
1991 wasOpt = revert_Argument_to_TeX_brace(document, flex, flexEnd, 1, 1, False, True)
1992 revert_Argument_to_TeX_brace(document, flex, 0, 2, 2, False, False)
1993 flexEnd = find_end_of_inset(document.body, flex)
1995 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn")
1997 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn{")
1998 document.body[flexEnd + 4 : flexEnd + 7] = put_cmd_in_ert("}")
2002 def revert_ModernCV_3(document):
2003 " Reverts the Column style of modernCV to TeX-code "
2004 if document.textclass == "moderncv":
2005 # revert the layouts
2006 revert_ModernCV(document)
2008 # get the position of the end of the last column inset
2009 LastFlexEnd = revert_ModernCV_2(document)
2011 p = find_token(document.body, "\\begin_layout Columns", p)
2014 pEnd = find_end_of_layout(document.body, p)
2015 document.body[p] = document.body[p].replace("\\begin_layout Columns", "\\begin_layout Standard")
2016 if LastFlexEnd != -1:
2017 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\begin{cvcolumns}")
2018 document.body[LastFlexEnd + 24 : LastFlexEnd + 24] = put_cmd_in_ert("\\end{cvcolumns}")
2022 def revert_ModernCV_4(document):
2023 " Reverts the style Social to TeX-code "
2024 if document.textclass == "moderncv":
2025 # revert the layouts
2026 revert_ModernCV(document)
2029 p = find_token(document.body, "\\begin_layout Social", p)
2032 pEnd = find_end_of_layout(document.body, p)
2033 document.body[p] = document.body[p].replace("\\begin_layout Social", "\\begin_layout Standard")
2034 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\social")
2035 hasOpt = find_token(document.body, "[", p + 9)
2037 document.body[p + 30 : p + 30] = put_cmd_in_ert("{")
2038 document.body[p + 41 : p + 41] = put_cmd_in_ert("}")
2040 document.body[p + 11 : p + 11] = put_cmd_in_ert("{")
2041 document.body[p + 21 : p + 21] = put_cmd_in_ert("}")
2045 def convert_ModernCV(document):
2046 " Converts ERT of modernCV to InsetArgument "
2047 if document.textclass == "moderncv":
2055 i = find_token(document.body, "\\begin_layout DoubleItem", i)
2057 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
2058 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout DoubleListItem")
2061 j = find_token(document.body, "\\begin_layout Entry", j)
2063 convert_TeX_brace_to_Argument(document, j, 1, 5, False, False, False)
2066 k = find_token(document.body, "\\begin_layout Item", k)
2068 convert_TeX_brace_to_Argument(document, k, 1, 1, False, False, False)
2071 m = find_token(document.body, "\\begin_layout Language", m)
2073 convert_TeX_brace_to_Argument(document, m, 1, 2, False, False, False)
2075 if i == -1 and j == -1 and k == -1 and m == -1:
2079 def revert_Initials(document):
2080 " Reverts InsetArgument of Initial to TeX-code "
2083 i = find_token(document.body, "\\begin_layout Initial", i)
2086 # first arg (optional) and second arg (first mandatory) are supported in LyX 2.0.x
2087 revert_Argument_to_TeX_brace(document, i, 0, 3, 3, False, False)
2091 def convert_Initials(document):
2092 " Converts ERT of Initial to InsetArgument "
2095 i = find_token(document.body, "\\begin_layout Initial", i)
2098 convert_TeX_brace_to_Argument(document, i, 3, 3, False, False, False)
2102 def revert_literate(document):
2103 " Revert Literate document to old format "
2104 if del_token(document.header, "noweb", 0):
2105 document.textclass = "literate-" + document.textclass
2108 i = find_token(document.body, "\\begin_layout Chunk", i)
2111 document.body[i] = "\\begin_layout Scrap"
2115 def convert_literate(document):
2116 " Convert Literate document to new format"
2117 i = find_token(document.header, "\\textclass", 0)
2118 if (i != -1) and "literate-" in document.header[i]:
2119 document.textclass = document.header[i].replace("\\textclass literate-", "")
2120 j = find_token(document.header, "\\begin_modules", 0)
2122 document.header.insert(j + 1, "noweb")
2124 document.header.insert(i + 1, "\\end_modules")
2125 document.header.insert(i + 1, "noweb")
2126 document.header.insert(i + 1, "\\begin_modules")
2129 i = find_token(document.body, "\\begin_layout Scrap", i)
2132 document.body[i] = "\\begin_layout Chunk"
2136 def revert_itemargs(document):
2137 " Reverts \\item arguments to TeX-code "
2140 i = find_token(document.body, "\\begin_inset Argument item:", i)
2143 j = find_end_of_inset(document.body, i)
2144 # Find containing paragraph layout
2145 parent = get_containing_layout(document.body, i)
2147 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2151 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2152 endPlain = find_end_of_layout(document.body, beginPlain)
2153 content = document.body[beginPlain + 1 : endPlain]
2154 del document.body[i:j+1]
2155 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2156 document.body[parbeg : parbeg] = subst
2160 def revert_garamondx_newtxmath(document):
2161 " Revert native garamond newtxmath definition to LaTeX "
2163 i = find_token(document.header, "\\font_math", 0)
2166 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2167 val = get_value(document.header, "\\font_math", i)
2168 if val == "garamondx-ntxm":
2169 add_to_preamble(document, "\\usepackage[garamondx]{newtxmath}")
2170 document.header[i] = "\\font_math auto"
2173 def revert_garamondx(document):
2174 " Revert native garamond font definition to LaTeX "
2176 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2177 i = find_token(document.header, "\\font_roman garamondx", 0)
2180 j = find_token(document.header, "\\font_osf true", 0)
2183 preamble = "\\usepackage"
2185 preamble += "[osfI]"
2186 preamble += "{garamondx}"
2187 add_to_preamble(document, [preamble])
2188 document.header[i] = "\\font_roman default"
2191 def convert_beamerargs(document):
2192 " Converts beamer arguments to new layout "
2194 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2195 if document.textclass not in beamer_classes:
2198 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2199 list_layouts = ["Itemize", "Enumerate", "Description"]
2200 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
2204 i = find_token(document.body, "\\begin_inset Argument", i)
2207 # Find containing paragraph layout
2208 parent = get_containing_layout(document.body, i)
2210 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2215 layoutname = parent[0]
2216 for p in range(parbeg, parend):
2217 if layoutname in shifted_layouts:
2218 m = rx.match(document.body[p])
2220 argnr = int(m.group(1))
2222 document.body[p] = "\\begin_inset Argument %d" % argnr
2223 if layoutname == "AgainFrame":
2224 m = rx.match(document.body[p])
2226 document.body[p] = "\\begin_inset Argument 3"
2227 if document.body[p + 4] == "\\begin_inset ERT":
2228 if document.body[p + 9].startswith("<"):
2229 # This is an overlay specification
2231 document.body[p + 9] = document.body[p + 9][1:]
2232 if document.body[p + 9].endswith(">"):
2234 document.body[p + 9] = document.body[p + 9][:-1]
2236 document.body[p] = "\\begin_inset Argument 2"
2237 if layoutname in list_layouts:
2238 m = rx.match(document.body[p])
2240 if m.group(1) == "1":
2241 if document.body[p + 4] == "\\begin_inset ERT":
2242 if document.body[p + 9].startswith("<"):
2243 # This is an overlay specification
2245 document.body[p + 9] = document.body[p + 9][1:]
2246 if document.body[p + 9].endswith(">"):
2248 document.body[p + 9] = document.body[p + 9][:-1]
2249 elif document.body[p + 4].startswith("<"):
2250 # This is an overlay specification (without ERT)
2252 document.body[p + 4] = document.body[p + 4][1:]
2253 if document.body[p + 4].endswith(">"):
2255 document.body[p + 4] = document.body[p + 4][:-1]
2256 elif layoutname != "Itemize":
2258 document.body[p] = "\\begin_inset Argument 2"
2263 # Helper function for the frame conversion routines
2265 # FIXME: This method currently requires the arguments to be either
2266 # * In one (whole) ERT each: <ERT>[<arg1>]</ERT><ERT><arg2></ERT><ERT>[arg3]</ERT>
2267 # * Altogether in one whole ERT: <ERT>[<arg1>]<arg2>[arg3]</ERT>
2268 # If individual arguments mix ERT and non-ERT or are splitted
2269 # over several ERTs, the parsing fails.
2270 def convert_beamerframeargs(document, i, parbeg):
2273 if document.body[parbeg] != "\\begin_inset ERT":
2275 ertend = find_end_of_inset(document.body, parbeg)
2277 document.warning("Malformed LyX document: missing ERT \\end_inset")
2279 ertcont = parbeg + 5
2280 if document.body[ertcont].startswith("[<"):
2281 # This is a default overlay specification
2283 document.body[ertcont] = document.body[ertcont][2:]
2284 if document.body[ertcont].endswith(">]"):
2286 document.body[ertcont] = document.body[ertcont][:-2]
2287 elif document.body[ertcont].endswith("]"):
2289 tok = document.body[ertcont].find('>][')
2291 subst = [document.body[ertcont][:tok],
2292 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2293 'status collapsed', '', '\\begin_layout Plain Layout',
2294 document.body[ertcont][tok + 3:-1]]
2295 document.body[ertcont : ertcont + 1] = subst
2297 # Convert to ArgInset
2298 document.body[parbeg] = "\\begin_inset Argument 2"
2299 elif document.body[ertcont].startswith("<"):
2300 # This is an overlay specification
2302 document.body[ertcont] = document.body[ertcont][1:]
2303 if document.body[ertcont].endswith(">"):
2305 document.body[ertcont] = document.body[ertcont][:-1]
2306 # Convert to ArgInset
2307 document.body[parbeg] = "\\begin_inset Argument 1"
2308 elif document.body[ertcont].endswith(">]"):
2310 tok = document.body[ertcont].find('>[<')
2312 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2313 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2314 'status collapsed', '', '\\begin_layout Plain Layout',
2315 document.body[ertcont][tok + 3:-2]]
2316 # Convert to ArgInset
2317 document.body[parbeg] = "\\begin_inset Argument 1"
2319 elif document.body[ertcont].endswith("]"):
2321 tok = document.body[ertcont].find('>[<')
2324 tokk = document.body[ertcont].find('>][')
2326 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2327 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2328 'status collapsed', '', '\\begin_layout Plain Layout',
2329 document.body[ertcont][tok + 3:tokk],
2330 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2331 'status collapsed', '', '\\begin_layout Plain Layout',
2332 document.body[ertcont][tokk + 3:-1]]
2335 tokk = document.body[ertcont].find('>[')
2337 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tokk],
2338 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2339 'status collapsed', '', '\\begin_layout Plain Layout',
2340 document.body[ertcont][tokk + 2:-1]]
2342 # Convert to ArgInset
2343 document.body[parbeg] = "\\begin_inset Argument 1"
2344 elif document.body[ertcont].startswith("["):
2345 # This is an ERT option
2347 document.body[ertcont] = document.body[ertcont][1:]
2348 if document.body[ertcont].endswith("]"):
2350 document.body[ertcont] = document.body[ertcont][:-1]
2351 # Convert to ArgInset
2352 document.body[parbeg] = "\\begin_inset Argument 3"
2358 def convert_againframe_args(document):
2359 " Converts beamer AgainFrame to new layout "
2361 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2362 if document.textclass not in beamer_classes:
2367 i = find_token(document.body, "\\begin_layout AgainFrame", i)
2370 parent = get_containing_layout(document.body, i)
2372 document.warning("Wrong parent layout!")
2376 # Convert ERT arguments
2377 # FIXME: See restrictions in convert_beamerframeargs method
2378 ertend = convert_beamerframeargs(document, i, parbeg)
2384 def convert_corollary_args(document):
2385 " Converts beamer corrolary-style ERT arguments native InsetArgs "
2387 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2388 if document.textclass not in beamer_classes:
2391 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2392 for lay in corollary_layouts:
2395 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2398 parent = get_containing_layout(document.body, i)
2400 document.warning("Wrong parent layout!")
2404 if document.body[parbeg] == "\\begin_inset ERT":
2405 ertcont = parbeg + 5
2406 if document.body[ertcont].startswith("<"):
2407 # This is an overlay specification
2409 document.body[ertcont] = document.body[ertcont][1:]
2410 if document.body[ertcont].endswith(">"):
2412 document.body[ertcont] = document.body[ertcont][:-1]
2413 elif document.body[ertcont].endswith("]"):
2415 tok = document.body[ertcont].find('>[')
2417 subst = [document.body[ertcont][:tok],
2418 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2419 'status collapsed', '', '\\begin_layout Plain Layout',
2420 document.body[ertcont][tok + 2:-1]]
2421 document.body[ertcont : ertcont + 1] = subst
2422 # Convert to ArgInset
2423 document.body[parbeg] = "\\begin_inset Argument 1"
2426 elif document.body[ertcont].startswith("["):
2427 if document.body[ertcont].endswith("]"):
2428 # This is an ERT option
2430 document.body[ertcont] = document.body[ertcont][1:]
2432 document.body[ertcont] = document.body[ertcont][:-1]
2433 # Convert to ArgInset
2434 document.body[parbeg] = "\\begin_inset Argument 2"
2436 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, True)
2443 def convert_quote_args(document):
2444 " Converts beamer quote style ERT args to native InsetArgs "
2446 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2447 if document.textclass not in beamer_classes:
2450 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2451 for lay in quote_layouts:
2454 i = find_token(document.body, "\\begin_layout " + lay, i)
2457 parent = get_containing_layout(document.body, i)
2459 document.warning("Wrong parent layout!")
2463 if document.body[parbeg] == "\\begin_inset ERT":
2464 if document.body[i + 6].startswith("<"):
2465 # This is an overlay specification
2467 document.body[i + 6] = document.body[i + 6][1:]
2468 if document.body[i + 6].endswith(">"):
2470 document.body[i + 6] = document.body[i + 6][:-1]
2471 # Convert to ArgInset
2472 document.body[i + 1] = "\\begin_inset Argument 1"
2476 def revert_beamerargs(document):
2477 " Reverts beamer arguments to old layout "
2479 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2480 if document.textclass not in beamer_classes:
2484 list_layouts = ["Itemize", "Enumerate", "Description"]
2485 headings = ["Part", "Section", "Section*", "Subsection", "Subsection*",
2486 "Subsubsection", "Subsubsection*", "FrameSubtitle", "NoteItem"]
2487 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2488 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2489 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2492 i = find_token(document.body, "\\begin_inset Argument", i)
2495 # Find containing paragraph layout
2496 parent = get_containing_layout(document.body, i)
2498 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2503 realparbeg = parent[3]
2504 layoutname = parent[0]
2506 for p in range(parbeg, parend):
2510 if layoutname in headings:
2511 m = rx.match(document.body[p])
2515 # Find containing paragraph layout
2516 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2517 endPlain = find_end_of_layout(document.body, beginPlain)
2518 endInset = find_end_of_inset(document.body, p)
2519 argcontent = document.body[beginPlain + 1 : endPlain]
2521 realparend = realparend - len(document.body[p : endInset + 1])
2523 del document.body[p : endInset + 1]
2524 if layoutname == "FrameSubtitle":
2525 pre = put_cmd_in_ert("\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2526 elif layoutname == "NoteItem":
2527 pre = put_cmd_in_ert("\\note<") + argcontent + put_cmd_in_ert(">[item]")
2528 elif layoutname.endswith('*'):
2529 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower()[:-1] + "<") + argcontent + put_cmd_in_ert(">*")
2531 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2532 secarg = find_token(document.body, "\\begin_inset Argument 2", parbeg, parend)
2534 # Find containing paragraph layout
2535 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", secarg)
2536 endPlain = find_end_of_layout(document.body, beginPlain)
2537 endInset = find_end_of_inset(document.body, secarg)
2538 argcontent = document.body[beginPlain + 1 : endPlain]
2540 realparend = realparend - len(document.body[secarg : endInset + 1])
2541 del document.body[secarg : endInset + 1]
2542 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2543 pre += put_cmd_in_ert("{")
2544 document.body[parbeg] = "\\begin_layout Standard"
2545 document.body[realparbeg : realparbeg] = pre
2546 pe = find_end_of_layout(document.body, parbeg)
2547 post = put_cmd_in_ert("}")
2548 document.body[pe : pe] = post
2549 realparend += len(pre) + len(post)
2550 if layoutname == "AgainFrame":
2551 m = rx.match(document.body[p])
2555 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2556 endPlain = find_end_of_layout(document.body, beginPlain)
2557 endInset = find_end_of_inset(document.body, p)
2558 content = document.body[beginPlain + 1 : endPlain]
2560 realparend = realparend - len(document.body[p : endInset + 1])
2562 del document.body[p : endInset + 1]
2563 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2564 document.body[realparbeg : realparbeg] = subst
2565 if layoutname == "Overprint":
2566 m = rx.match(document.body[p])
2570 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2571 endPlain = find_end_of_layout(document.body, beginPlain)
2572 endInset = find_end_of_inset(document.body, p)
2573 content = document.body[beginPlain + 1 : endPlain]
2575 realparend = realparend - len(document.body[p : endInset + 1])
2577 del document.body[p : endInset + 1]
2578 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2579 document.body[realparbeg : realparbeg] = subst
2580 if layoutname == "OverlayArea":
2581 m = rx.match(document.body[p])
2585 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2586 endPlain = find_end_of_layout(document.body, beginPlain)
2587 endInset = find_end_of_inset(document.body, p)
2588 content = document.body[beginPlain + 1 : endPlain]
2590 realparend = realparend - len(document.body[p : endInset + 1])
2592 del document.body[p : endInset + 1]
2593 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2594 document.body[realparbeg : realparbeg] = subst
2595 if layoutname in list_layouts:
2596 m = rx.match(document.body[p])
2600 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2601 endPlain = find_end_of_layout(document.body, beginPlain)
2602 endInset = find_end_of_inset(document.body, p)
2603 content = document.body[beginPlain + 1 : endPlain]
2604 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2605 realparend = realparend + len(subst) - len(content)
2606 document.body[beginPlain + 1 : endPlain] = subst
2607 elif argnr == "item:1":
2608 j = find_end_of_inset(document.body, i)
2609 # Find containing paragraph layout
2610 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2611 endPlain = find_end_of_layout(document.body, beginPlain)
2612 content = document.body[beginPlain + 1 : endPlain]
2613 del document.body[i:j+1]
2614 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2615 document.body[realparbeg : realparbeg] = subst
2616 elif argnr == "item:2":
2617 j = find_end_of_inset(document.body, i)
2618 # Find containing paragraph layout
2619 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2620 endPlain = find_end_of_layout(document.body, beginPlain)
2621 content = document.body[beginPlain + 1 : endPlain]
2622 del document.body[i:j+1]
2623 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2624 document.body[realparbeg : realparbeg] = subst
2625 if layoutname in quote_layouts:
2626 m = rx.match(document.body[p])
2630 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2631 endPlain = find_end_of_layout(document.body, beginPlain)
2632 endInset = find_end_of_inset(document.body, p)
2633 content = document.body[beginPlain + 1 : endPlain]
2635 realparend = realparend - len(document.body[p : endInset + 1])
2637 del document.body[p : endInset + 1]
2638 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2639 document.body[realparbeg : realparbeg] = subst
2640 if layoutname in corollary_layouts:
2641 m = rx.match(document.body[p])
2645 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2646 endPlain = find_end_of_layout(document.body, beginPlain)
2647 endInset = find_end_of_inset(document.body, p)
2648 content = document.body[beginPlain + 1 : endPlain]
2650 realparend = realparend - len(document.body[p : endInset + 1])
2652 del document.body[p : endInset + 1]
2653 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2654 document.body[realparbeg : realparbeg] = subst
2659 def revert_beamerargs2(document):
2660 " Reverts beamer arguments to old layout, step 2 "
2662 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2663 if document.textclass not in beamer_classes:
2667 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2668 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2669 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2672 i = find_token(document.body, "\\begin_inset Argument", i)
2675 # Find containing paragraph layout
2676 parent = get_containing_layout(document.body, i)
2678 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2683 realparbeg = parent[3]
2684 layoutname = parent[0]
2686 for p in range(parbeg, parend):
2690 if layoutname in shifted_layouts:
2691 m = rx.match(document.body[p])
2695 document.body[p] = "\\begin_inset Argument 1"
2696 if layoutname in corollary_layouts:
2697 m = rx.match(document.body[p])
2701 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2702 endPlain = find_end_of_layout(document.body, beginPlain)
2703 endInset = find_end_of_inset(document.body, p)
2704 content = document.body[beginPlain + 1 : endPlain]
2706 realparend = realparend - len(document.body[p : endInset + 1])
2708 del document.body[p : endInset + 1]
2709 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2710 document.body[realparbeg : realparbeg] = subst
2711 if layoutname == "OverlayArea":
2712 m = rx.match(document.body[p])
2716 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2717 endPlain = find_end_of_layout(document.body, beginPlain)
2718 endInset = find_end_of_inset(document.body, p)
2719 content = document.body[beginPlain + 1 : endPlain]
2721 realparend = realparend - len(document.body[p : endInset + 1])
2723 del document.body[p : endInset + 1]
2724 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2725 document.body[realparbeg : realparbeg] = subst
2726 if layoutname == "AgainFrame":
2727 m = rx.match(document.body[p])
2731 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2732 endPlain = find_end_of_layout(document.body, beginPlain)
2733 endInset = find_end_of_inset(document.body, p)
2734 content = document.body[beginPlain + 1 : endPlain]
2736 realparend = realparend - len(document.body[p : endInset + 1])
2738 del document.body[p : endInset + 1]
2739 subst = put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
2740 document.body[realparbeg : realparbeg] = subst
2744 def revert_beamerargs3(document):
2745 " Reverts beamer arguments to old layout, step 3 "
2747 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2748 if document.textclass not in beamer_classes:
2751 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2754 i = find_token(document.body, "\\begin_inset Argument", i)
2757 # Find containing paragraph layout
2758 parent = get_containing_layout(document.body, i)
2760 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2765 realparbeg = parent[3]
2766 layoutname = parent[0]
2768 for p in range(parbeg, parend):
2772 if layoutname == "AgainFrame":
2773 m = rx.match(document.body[p])
2777 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2778 endPlain = find_end_of_layout(document.body, beginPlain)
2779 endInset = find_end_of_inset(document.body, p)
2780 content = document.body[beginPlain + 1 : endPlain]
2782 realparend = realparend - len(document.body[p : endInset + 1])
2784 del document.body[p : endInset + 1]
2785 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2786 document.body[realparbeg : realparbeg] = subst
2790 def revert_beamerflex(document):
2791 " Reverts beamer Flex insets "
2793 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2794 if document.textclass not in beamer_classes:
2797 new_flexes = {"Bold" : "\\textbf", "Emphasize" : "\\emph", "Only" : "\\only",
2798 "Uncover" : "\\uncover", "Visible" : "\\visible",
2799 "Invisible" : "\\invisible", "Alternative" : "\\alt",
2800 "Beamer_Note" : "\\note"}
2801 old_flexes = {"Alert" : "\\alert", "Structure" : "\\structure"}
2802 rx = re.compile(r'^\\begin_inset Flex (.+)$')
2806 i = find_token(document.body, "\\begin_inset Flex", i)
2809 m = rx.match(document.body[i])
2811 flextype = m.group(1)
2812 z = find_end_of_inset(document.body, i)
2814 document.warning("Can't find end of Flex " + flextype + " inset.")
2817 if flextype in new_flexes:
2818 pre = put_cmd_in_ert(new_flexes[flextype])
2819 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2821 argend = find_end_of_inset(document.body, arg)
2823 document.warning("Can't find end of Argument!")
2826 # Find containing paragraph layout
2827 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2828 endPlain = find_end_of_layout(document.body, beginPlain)
2829 argcontent = document.body[beginPlain + 1 : endPlain]
2831 z = z - len(document.body[arg : argend + 1])
2833 del document.body[arg : argend + 1]
2834 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2835 arg = find_token(document.body, "\\begin_inset Argument 2", i, z)
2837 argend = find_end_of_inset(document.body, arg)
2839 document.warning("Can't find end of Argument!")
2842 # Find containing paragraph layout
2843 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2844 endPlain = find_end_of_layout(document.body, beginPlain)
2845 argcontent = document.body[beginPlain + 1 : endPlain]
2847 z = z - len(document.body[arg : argend + 1])
2849 del document.body[arg : argend + 1]
2850 if flextype == "Alternative":
2851 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
2853 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2854 pre += put_cmd_in_ert("{")
2855 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2856 endPlain = find_end_of_layout(document.body, beginPlain)
2858 z = z - len(document.body[i : beginPlain + 1])
2860 document.body[i : beginPlain + 1] = pre
2861 post = put_cmd_in_ert("}")
2862 document.body[z - 2 : z + 1] = post
2863 elif flextype in old_flexes:
2864 pre = put_cmd_in_ert(old_flexes[flextype])
2865 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2869 argend = find_end_of_inset(document.body, arg)
2871 document.warning("Can't find end of Argument!")
2874 # Find containing paragraph layout
2875 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2876 endPlain = find_end_of_layout(document.body, beginPlain)
2877 argcontent = document.body[beginPlain + 1 : endPlain]
2879 z = z - len(document.body[arg : argend + 1])
2881 del document.body[arg : argend + 1]
2882 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2883 pre += put_cmd_in_ert("{")
2884 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2885 endPlain = find_end_of_layout(document.body, beginPlain)
2887 z = z - len(document.body[i : beginPlain + 1])
2889 document.body[i : beginPlain + 1] = pre
2890 post = put_cmd_in_ert("}")
2891 document.body[z - 2 : z + 1] = post
2896 def revert_beamerblocks(document):
2897 " Reverts beamer block arguments to ERT "
2899 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2900 if document.textclass not in beamer_classes:
2903 blocks = ["Block", "ExampleBlock", "AlertBlock"]
2905 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2908 i = find_token(document.body, "\\begin_inset Argument", i)
2911 # Find containing paragraph layout
2912 parent = get_containing_layout(document.body, i)
2914 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2919 realparbeg = parent[3]
2920 layoutname = parent[0]
2922 for p in range(parbeg, parend):
2926 if layoutname in blocks:
2927 m = rx.match(document.body[p])
2931 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2932 endPlain = find_end_of_layout(document.body, beginPlain)
2933 endInset = find_end_of_inset(document.body, p)
2934 content = document.body[beginPlain + 1 : endPlain]
2936 realparend = realparend - len(document.body[p : endInset + 1])
2938 del document.body[p : endInset + 1]
2939 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2940 document.body[realparbeg : realparbeg] = subst
2942 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2943 endPlain = find_end_of_layout(document.body, beginPlain)
2944 endInset = find_end_of_inset(document.body, p)
2945 content = document.body[beginPlain + 1 : endPlain]
2947 realparend = realparend - len(document.body[p : endInset + 1])
2949 del document.body[p : endInset + 1]
2950 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2951 document.body[realparbeg : realparbeg] = subst
2956 def convert_beamerblocks(document):
2957 " Converts beamer block ERT args to native InsetArgs "
2959 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2960 if document.textclass not in beamer_classes:
2963 blocks = ["Block", "ExampleBlock", "AlertBlock"]
2967 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2970 parent = get_containing_layout(document.body, i)
2971 if parent == False or parent[1] != i:
2972 document.warning("Wrong parent layout!")
2979 if document.body[parbeg] == "\\begin_inset ERT":
2980 ertcontfirstline = parbeg + 5
2981 # Find the last ERT in this paragraph (which might also be the first)
2982 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
2983 if lastertbeg == -1:
2984 document.warning("Last ERT not found!")
2986 lastertend = find_end_of_inset(document.body, lastertbeg)
2987 if lastertend == -1:
2988 document.warning("End of last ERT not found!")
2990 ertcontlastline = lastertend - 3
2992 if document.body[ertcontfirstline].startswith("<"):
2993 # This is an overlay specification
2995 document.body[ertcontfirstline] = document.body[ertcontfirstline][1:]
2996 if document.body[ertcontlastline].endswith(">"):
2998 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
2999 # Convert to ArgInset
3000 document.body[parbeg] = "\\begin_inset Argument 1"
3001 elif document.body[ertcontlastline].endswith("}"):
3003 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
3005 ertcontdivline = ertcontfirstline
3006 tok = document.body[ertcontdivline].find('>{')
3008 regexp = re.compile(r'.*>\{', re.IGNORECASE)
3009 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, ertcontlastline)
3010 tok = document.body[ertcontdivline].find('>{')
3012 if ertcontfirstline < ertcontlastline:
3013 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3014 document.body[ertcontlastline : ertcontlastline + 1] = [
3015 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3016 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3017 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3018 'status collapsed', '', '\\begin_layout Plain Layout',
3019 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3020 document.body[ertcontdivline][tok + 2:]]
3022 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3023 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3024 'status collapsed', '', '\\begin_layout Plain Layout',
3025 document.body[ertcontdivline][tok + 2:]]
3026 # Convert to ArgInset
3027 document.body[parbeg] = "\\begin_inset Argument 1"
3028 elif document.body[ertcontfirstline].startswith("{"):
3029 # This is the block title
3030 if document.body[ertcontlastline].endswith("}"):
3031 # strip off the braces
3032 document.body[ertcontfirstline] = document.body[ertcontfirstline][1:]
3033 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
3034 if ertcontfirstline < ertcontlastline:
3035 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3036 document.body[parend : parend + 1] = [
3037 document.body[parend], '\\end_layout', '', '\\end_inset']
3038 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3039 'status collapsed', '', '\\begin_layout Plain Layout',
3040 '\\begin_inset ERT', '']
3042 # Convert to ArgInset
3043 document.body[parbeg] = "\\begin_inset Argument 2"
3044 elif count_pars_in_inset(document.body, ertcontfirstline) > 1:
3045 # Multipar ERT. Skip this.
3048 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, False)
3051 j = find_end_of_layout(document.body, i)
3053 document.warning("end of layout not found!")
3054 k = find_token(document.body, "\\begin_inset Argument", i, j)
3056 document.warning("InsetArgument not found!")
3058 l = find_end_of_inset(document.body, k)
3059 m = find_token(document.body, "\\begin_inset ERT", l, j)
3062 ertcontfirstline = m + 5
3067 def convert_overprint(document):
3068 " Convert old beamer overprint layouts to ERT "
3070 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3071 if document.textclass not in beamer_classes:
3076 i = find_token(document.body, "\\begin_layout Overprint", i)
3079 # Find end of sequence
3080 j = find_end_of_sequence(document.body, i)
3082 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3086 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3088 if document.body[j] == "\\end_deeper":
3089 esubst = ["", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3091 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3092 endseq = endseq + len(esubst) - len(document.body[j : j])
3093 document.body[j : j] = esubst
3094 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3096 argend = find_end_of_layout(document.body, argbeg)
3098 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3101 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3102 endPlain = find_end_of_layout(document.body, beginPlain)
3103 content = document.body[beginPlain + 1 : endPlain]
3105 endseq = endseq - len(document.body[argbeg : argend + 1])
3107 del document.body[argbeg : argend + 1]
3108 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3110 endseq = endseq - len(document.body[i : i])
3111 document.body[i : i] = subst + ["\\end_layout"]
3112 endseq += len(subst)
3114 for p in range(i, endseq):
3115 if document.body[p] == "\\begin_layout Overprint":
3116 document.body[p] = "\\begin_layout Standard"
3121 def revert_overprint(document):
3122 " Revert old beamer overprint layouts to ERT "
3124 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3125 if document.textclass not in beamer_classes:
3130 i = find_token(document.body, "\\begin_layout Overprint", i)
3133 # Find end of sequence
3134 j = find_end_of_sequence(document.body, i)
3136 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3140 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3141 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}")
3142 endseq = endseq + len(esubst) - len(document.body[j : j])
3143 if document.body[j] == "\\end_deeper":
3144 document.body[j : j] = ["\\end_deeper", ""] + esubst
3146 document.body[j : j] = esubst
3149 if document.body[r] == "\\begin_deeper":
3150 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3152 document.body[r] = ""
3153 document.body[s] = ""
3157 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3159 argend = find_end_of_inset(document.body, argbeg)
3161 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3164 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3165 endPlain = find_end_of_layout(document.body, beginPlain)
3166 content = document.body[beginPlain + 1 : endPlain]
3168 endseq = endseq - len(document.body[argbeg : argend])
3170 del document.body[argbeg : argend + 1]
3171 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3173 endseq = endseq - len(document.body[i : i])
3174 document.body[i : i] = subst + ["\\end_layout"]
3175 endseq += len(subst)
3181 if document.body[p] == "\\begin_layout Overprint":
3182 q = find_end_of_layout(document.body, p)
3184 document.warning("Malformed LyX document. Cannot find end of Overprint layout!")
3187 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\onslide")
3188 argbeg = find_token(document.body, "\\begin_inset Argument item:1", p, q)
3190 argend = find_end_of_inset(document.body, argbeg)
3192 document.warning("Malformed LyX document. Cannot find end of Overprint item argument!")
3195 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3196 endPlain = find_end_of_layout(document.body, beginPlain)
3197 content = document.body[beginPlain + 1 : endPlain]
3199 endseq = endseq - len(document.body[argbeg : argend + 1])
3201 del document.body[argbeg : argend + 1]
3202 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3203 endseq = endseq - len(document.body[p : p + 1]) + len(subst)
3204 document.body[p : p + 1] = subst
3210 def revert_frametitle(document):
3211 " Reverts beamer frametitle layout to ERT "
3213 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3214 if document.textclass not in beamer_classes:
3217 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3220 i = find_token(document.body, "\\begin_layout FrameTitle", i)
3223 j = find_end_of_layout(document.body, i)
3225 document.warning("Malformed LyX document: Can't find end of FrameTitle layout")
3229 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
3230 endlay += len(put_cmd_in_ert("}"))
3231 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\frametitle")
3232 for p in range(i, j):
3235 m = rx.match(document.body[p])
3239 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3240 endPlain = find_end_of_layout(document.body, beginPlain)
3241 endInset = find_end_of_inset(document.body, p)
3242 content = document.body[beginPlain + 1 : endPlain]
3244 endlay = endlay - len(document.body[p : endInset + 1])
3246 del document.body[p : endInset + 1]
3247 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3249 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3250 endPlain = find_end_of_layout(document.body, beginPlain)
3251 endInset = find_end_of_inset(document.body, p)
3252 content = document.body[beginPlain + 1 : endPlain]
3254 endlay = endlay - len(document.body[p : endInset + 1])
3256 del document.body[p : endInset + 1]
3257 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3259 subst += put_cmd_in_ert("{")
3260 document.body[i : i + 1] = subst
3264 def convert_epigraph(document):
3265 " Converts memoir epigraph to new syntax "
3267 if document.textclass != "memoir":
3272 i = find_token(document.body, "\\begin_layout Epigraph", i)
3275 j = find_end_of_layout(document.body, i)
3277 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3282 ert = find_token(document.body, "\\begin_inset ERT", i, j)
3284 endInset = find_end_of_inset(document.body, ert)
3285 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", ert)
3286 endPlain = find_end_of_layout(document.body, beginPlain)
3287 ertcont = beginPlain + 2
3288 if document.body[ertcont] == "}{":
3290 # Convert to ArgInset
3291 endlay = endlay - 2 * len(document.body[j])
3292 begsubst = ['\\begin_inset Argument post:1', 'status collapsed', '',
3293 '\\begin_layout Plain Layout']
3294 endsubst = ['\\end_layout', '', '\\end_inset', '', document.body[j]]
3295 document.body[j : j + 1] = endsubst
3296 document.body[endInset + 1 : endInset + 1] = begsubst
3298 endlay += len(begsubst) + len(endsubst)
3299 endlay = endlay - len(document.body[ert : endInset + 1])
3300 del document.body[ert : endInset + 1]
3305 def revert_epigraph(document):
3306 " Reverts memoir epigraph argument to ERT "
3308 if document.textclass != "memoir":
3313 i = find_token(document.body, "\\begin_layout Epigraph", i)
3316 j = find_end_of_layout(document.body, i)
3318 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3323 p = find_token(document.body, "\\begin_layout Argument post:1", i, j)
3325 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3326 endPlain = find_end_of_layout(document.body, beginPlain)
3327 endInset = find_end_of_inset(document.body, p)
3328 content = document.body[beginPlain + 1 : endPlain]
3330 endlay = endlay - len(document.body[p : endInset + 1])
3332 del document.body[p : endInset + 1]
3333 subst += put_cmd_in_ert("}{") + content
3335 subst += put_cmd_in_ert("}{")
3337 document.body[j : j] = subst + document.body[j : j]
3341 def convert_captioninsets(document):
3342 " Converts caption insets to new syntax "
3346 i = find_token(document.body, "\\begin_inset Caption", i)
3349 document.body[i] = "\\begin_inset Caption Standard"
3353 def revert_captioninsets(document):
3354 " Reverts caption insets to old syntax "
3358 i = find_token(document.body, "\\begin_inset Caption Standard", i)
3361 document.body[i] = "\\begin_inset Caption"
3365 def convert_captionlayouts(document):
3366 " Convert caption layouts to caption insets. "
3369 "Captionabove": "Above",
3370 "Captionbelow": "Below",
3371 "FigCaption" : "FigCaption",
3372 "Table_Caption" : "Table",
3373 "CenteredCaption" : "Centered",
3374 "Bicaption" : "Bicaption",
3379 i = find_token(document.body, "\\begin_layout", i)
3382 val = get_value(document.body, "\\begin_layout", i)
3383 if val in caption_dict.keys():
3384 j = find_end_of_layout(document.body, i)
3386 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3389 document.body[j:j] = ["\\end_layout", "", "\\end_inset", "", ""]
3390 document.body[i:i+1] = ["\\begin_layout %s" % document.default_layout,
3391 "\\begin_inset Caption %s" % caption_dict[val], "",
3392 "\\begin_layout %s" % document.default_layout]
3396 def revert_captionlayouts(document):
3397 " Revert caption insets to caption layouts. "
3400 "Above" : "Captionabove",
3401 "Below" : "Captionbelow",
3402 "FigCaption" : "FigCaption",
3403 "Table" : "Table_Caption",
3404 "Centered" : "CenteredCaption",
3405 "Bicaption" : "Bicaption",
3409 rx = re.compile(r'^\\begin_inset Caption (\S+)$')
3411 i = find_token(document.body, "\\begin_inset Caption", i)
3415 m = rx.match(document.body[i])
3419 if val not in caption_dict.keys():
3423 # We either need to delete the previous \begin_layout line, or we
3424 # need to end the previous layout if this inset is not in the first
3425 # position of the paragraph.
3426 layout_before = find_token_backwards(document.body, "\\begin_layout", i)
3427 if layout_before == -1:
3428 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3430 layout_line = document.body[layout_before]
3431 del_layout_before = True
3432 l = layout_before + 1
3434 if document.body[l] != "":
3435 del_layout_before = False
3438 if del_layout_before:
3439 del document.body[layout_before:i]
3442 document.body[i:i] = ["\\end_layout", ""]
3445 # Find start of layout in the inset and end of inset
3446 j = find_token(document.body, "\\begin_layout", i)
3448 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3450 k = find_end_of_inset(document.body, i)
3452 document.warning("Malformed LyX document: Missing `\\end_inset'.")
3455 # We either need to delete the following \end_layout line, or we need
3456 # to restart the old layout if this inset is not at the paragraph end.
3457 layout_after = find_token(document.body, "\\end_layout", k)
3458 if layout_after == -1:
3459 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3461 del_layout_after = True
3463 while l < layout_after:
3464 if document.body[l] != "":
3465 del_layout_after = False
3468 if del_layout_after:
3469 del document.body[k+1:layout_after+1]
3471 document.body[k+1:k+1] = [layout_line, ""]
3473 # delete \begin_layout and \end_inset and replace \begin_inset with
3474 # "\begin_layout XXX". This works because we can only have one
3475 # paragraph in the caption inset: The old \end_layout will be recycled.
3476 del document.body[k]
3477 if document.body[k] == "":
3478 del document.body[k]
3479 del document.body[j]
3480 if document.body[j] == "":
3481 del document.body[j]
3482 document.body[i] = "\\begin_layout %s" % caption_dict[val]
3483 if document.body[i+1] == "":
3484 del document.body[i+1]
3488 def revert_fragileframe(document):
3489 " Reverts beamer FragileFrame layout to ERT "
3491 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3492 if document.textclass not in beamer_classes:
3497 i = find_token(document.body, "\\begin_layout FragileFrame", i)
3500 # Find end of sequence
3501 j = find_end_of_sequence(document.body, i)
3503 document.warning("Malformed LyX document. Cannot find end of FragileFrame sequence!")
3507 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{frame}")
3508 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{frame}")
3509 endseq = endseq + len(esubst) - len(document.body[j : j])
3510 if document.body[j] == "\\end_deeper":
3511 document.body[j : j] = ["\\end_deeper", ""] + esubst
3513 document.body[j : j] = esubst
3514 for q in range(i, j):
3515 if document.body[q] == "\\begin_layout FragileFrame":
3516 document.body[q] = "\\begin_layout %s" % document.default_layout
3519 if document.body[r] == "\\begin_deeper":
3520 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3522 document.body[r] = ""
3523 document.body[s] = ""
3527 for p in range(1, 5):
3528 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, j)
3531 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3532 endPlain = find_end_of_layout(document.body, beginPlain)
3533 endInset = find_end_of_inset(document.body, arg)
3534 content = document.body[beginPlain + 1 : endPlain]
3536 j = j - len(document.body[arg : endInset + 1])
3538 del document.body[arg : endInset + 1]
3539 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3541 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3542 endPlain = find_end_of_layout(document.body, beginPlain)
3543 endInset = find_end_of_inset(document.body, arg)
3544 content = document.body[beginPlain + 1 : endPlain]
3546 j = j - len(document.body[arg : endInset + 1])
3548 del document.body[arg : endInset + 1]
3549 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3551 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3552 endPlain = find_end_of_layout(document.body, beginPlain)
3553 endInset = find_end_of_inset(document.body, arg)
3554 content = document.body[beginPlain + 1 : endPlain]
3556 j = j - len(document.body[arg : endInset + 1])
3558 del document.body[arg : endInset + 1]
3559 subst += put_cmd_in_ert("[fragile,") + content + put_cmd_in_ert("]")
3561 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3562 endPlain = find_end_of_layout(document.body, beginPlain)
3563 endInset = find_end_of_inset(document.body, arg)
3564 content = document.body[beginPlain + 1 : endPlain]
3566 j = j - len(document.body[arg : endInset + 1])
3568 del document.body[arg : endInset + 1]
3569 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3571 subst += put_cmd_in_ert("[fragile]")
3573 document.body[i : i + 1] = subst
3577 def revert_newframes(document):
3578 " Reverts beamer Frame and PlainFrame layouts to old forms "
3580 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3581 if document.textclass not in beamer_classes:
3585 "Frame" : "BeginFrame",
3586 "PlainFrame" : "BeginPlainFrame",
3589 rx = re.compile(r'^\\begin_layout (\S+)$')
3592 i = find_token(document.body, "\\begin_layout", i)
3596 m = rx.match(document.body[i])
3600 if val not in frame_dict.keys():
3603 # Find end of sequence
3604 j = find_end_of_sequence(document.body, i)
3606 document.warning("Malformed LyX document. Cannot find end of Frame sequence!")
3610 subst = ["\\begin_layout %s" % frame_dict[val]]
3611 esubst = ["\\end_layout", "", "\\begin_layout EndFrame", "", "\\end_layout"]
3612 endseq = endseq + len(esubst) - len(document.body[j : j])
3613 if document.body[j] == "\\end_deeper":
3614 document.body[j : j] = ["\\end_deeper", ""] + esubst
3616 document.body[j : j] = esubst
3617 for q in range(i, j):
3618 if document.body[q] == "\\begin_layout %s" % val:
3619 document.body[q] = "\\begin_layout %s" % document.default_layout
3622 if document.body[r] == "\\begin_deeper":
3623 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3625 document.body[r] = ""
3626 document.body[s] = ""
3630 l = find_end_of_layout(document.body, i)
3631 for p in range(1, 5):
3632 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, l)
3635 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3636 endPlain = find_end_of_layout(document.body, beginPlain)
3637 endInset = find_end_of_inset(document.body, arg)
3638 content = document.body[beginPlain + 1 : endPlain]
3640 l = l - len(document.body[arg : endInset + 1])
3642 del document.body[arg : endInset + 1]
3643 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3645 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3646 endPlain = find_end_of_layout(document.body, beginPlain)
3647 endInset = find_end_of_inset(document.body, arg)
3648 content = document.body[beginPlain + 1 : endPlain]
3650 l = l - len(document.body[arg : endInset + 1])
3652 del document.body[arg : endInset + 1]
3653 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3655 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3656 endPlain = find_end_of_layout(document.body, beginPlain)
3657 endInset = find_end_of_inset(document.body, arg)
3658 content = document.body[beginPlain + 1 : endPlain]
3660 l = l - len(document.body[arg : endInset + 1])
3662 del document.body[arg : endInset + 1]
3663 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3665 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3666 endPlain = find_end_of_layout(document.body, beginPlain)
3667 endInset = find_end_of_inset(document.body, arg)
3668 content = document.body[beginPlain + 1 : endPlain]
3670 l = l - len(document.body[arg : endInset + 1])
3672 del document.body[arg : endInset + 1]
3675 document.body[i : i + 1] = subst
3678 # known encodings that do not change their names (same LyX and LaTeX names)
3679 known_enc_tuple = ("auto", "default", "ansinew", "applemac", "armscii8", "ascii",
3680 "cp437", "cp437de", "cp850", "cp852", "cp855", "cp858", "cp862", "cp865", "cp866",
3681 "cp1250", "cp1251", "cp1252", "cp1255", "cp1256", "cp1257", "koi8-r", "koi8-u",
3682 "pt154", "pt254", "tis620-0", "utf8", "utf8x", "utf8-plain")
3684 def convert_encodings(document):
3685 "Use the LyX names of the encodings instead of the LaTeX names."
3686 LaTeX2LyX_enc_dict = {
3687 "8859-6": "iso8859-6",
3688 "8859-8": "iso8859-8",
3690 "euc": "euc-jp-platex",
3695 "iso88595": "iso8859-5",
3696 "iso-8859-7": "iso8859-7",
3698 "jis": "jis-platex",
3700 "l7xenc": "iso8859-13",
3701 "latin1": "iso8859-1",
3702 "latin2": "iso8859-2",
3703 "latin3": "iso8859-3",
3704 "latin4": "iso8859-4",
3705 "latin5": "iso8859-9",
3706 "latin9": "iso8859-15",
3707 "latin10": "iso8859-16",
3708 "SJIS": "shift-jis",
3709 "sjis": "shift-jis-platex",
3712 i = find_token(document.header, "\\inputencoding" , 0)
3715 val = get_value(document.header, "\\inputencoding", i)
3716 if val in LaTeX2LyX_enc_dict.keys():
3717 document.header[i] = "\\inputencoding %s" % LaTeX2LyX_enc_dict[val]
3718 elif val not in known_enc_tuple:
3719 document.warning("Ignoring unknown input encoding: `%s'" % val)
3722 def revert_encodings(document):
3723 """Revert to using the LaTeX names of the encodings instead of the LyX names.
3724 Also revert utf8-platex to sjis, the language default when using Japanese.
3726 LyX2LaTeX_enc_dict = {
3731 "euc-jp-platex": "euc",
3734 "iso8859-1": "latin1",
3735 "iso8859-2": "latin2",
3736 "iso8859-3": "latin3",
3737 "iso8859-4": "latin4",
3738 "iso8859-5": "iso88595",
3739 "iso8859-6": "8859-6",
3740 "iso8859-7": "iso-8859-7",
3741 "iso8859-8": "8859-8",
3742 "iso8859-9": "latin5",
3743 "iso8859-13": "l7xenc",
3744 "iso8859-15": "latin9",
3745 "iso8859-16": "latin10",
3747 "jis-platex": "jis",
3748 "shift-jis": "SJIS",
3749 "shift-jis-platex": "sjis",
3751 "utf8-platex": "sjis"
3753 i = find_token(document.header, "\\inputencoding" , 0)
3756 val = get_value(document.header, "\\inputencoding", i)
3757 if val in LyX2LaTeX_enc_dict.keys():
3758 document.header[i] = "\\inputencoding %s" % LyX2LaTeX_enc_dict[val]
3759 elif val not in known_enc_tuple:
3760 document.warning("Ignoring unknown input encoding: `%s'" % val)
3763 def revert_IEEEtran_3(document):
3765 Reverts Flex Insets to TeX-code
3767 if document.textclass == "IEEEtran":
3773 h = find_token(document.body, "\\begin_inset Flex Author Mark", h)
3775 endh = find_end_of_inset(document.body, h)
3776 document.body[endh - 2 : endh + 1] = put_cmd_in_ert("}")
3777 document.body[h : h + 4] = put_cmd_in_ert("\\IEEEauthorrefmark{")
3780 i = find_token(document.body, "\\begin_inset Flex Author Name", i)
3782 endi = find_end_of_inset(document.body, i)
3783 document.body[endi - 2 : endi + 1] = put_cmd_in_ert("}")
3784 document.body[i : i + 4] = put_cmd_in_ert("\\IEEEauthorblockN{")
3787 j = find_token(document.body, "\\begin_inset Flex Author Affiliation", j)
3789 endj = find_end_of_inset(document.body, j)
3790 document.body[endj - 2 : endj + 1] = put_cmd_in_ert("}")
3791 document.body[j : j + 4] = put_cmd_in_ert("\\IEEEauthorblockA{")
3793 if i == -1 and j == -1 and h == -1:
3797 def revert_kurier_fonts(document):
3798 " Revert kurier font definition to LaTeX "
3800 i = find_token(document.header, "\\font_math", 0)
3802 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
3803 val = get_value(document.header, "\\font_math", i)
3804 if val == "kurier-math":
3805 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
3806 "\\usepackage[math]{kurier}\n" \
3807 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
3808 document.header[i] = "\\font_math auto"
3810 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
3811 kurier_fonts = ["kurier", "kurierc", "kurierl", "kurierlc"]
3812 k = find_token(document.header, "\\font_sans kurier", 0)
3814 sf = get_value(document.header, "\\font_sans", k)
3815 if sf in kurier_fonts:
3816 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
3817 document.header[k] = "\\font_sans default"
3819 def revert_iwona_fonts(document):
3820 " Revert iwona font definition to LaTeX "
3822 i = find_token(document.header, "\\font_math", 0)
3824 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
3825 val = get_value(document.header, "\\font_math", i)
3826 if val == "iwona-math":
3827 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
3828 "\\usepackage[math]{iwona}\n" \
3829 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
3830 document.header[i] = "\\font_math auto"
3832 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
3833 iwona_fonts = ["iwona", "iwonac", "iwonal", "iwonalc"]
3834 k = find_token(document.header, "\\font_sans iwona", 0)
3836 sf = get_value(document.header, "\\font_sans", k)
3837 if sf in iwona_fonts:
3838 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
3839 document.header[k] = "\\font_sans default"
3842 def revert_new_libertines(document):
3843 " Revert new libertine font definition to LaTeX "
3845 if find_token(document.header, "\\use_non_tex_fonts true", 0) != -1:
3848 i = find_token(document.header, "\\font_typewriter libertine-mono", 0)
3850 preamble = "\\usepackage"
3851 sc = find_token(document.header, "\\font_tt_scale", 0)
3853 scval = get_value(document.header, "\\font_tt_scale", sc)
3855 preamble += "[scale=%f]" % (float(scval) / 100)
3856 document.header[sc] = "\\font_tt_scale 100"
3857 preamble += "{libertineMono-type1}"
3858 add_to_preamble(document, [preamble])
3859 document.header[i] = "\\font_typewriter default"
3861 k = find_token(document.header, "\\font_sans biolinum", 0)
3863 preamble = "\\usepackage"
3865 j = find_token(document.header, "\\font_osf true", 0)
3870 sc = find_token(document.header, "\\font_sf_scale", 0)
3872 scval = get_value(document.header, "\\font_sf_scale", sc)
3874 options += ",scale=%f" % (float(scval) / 100)
3875 document.header[sc] = "\\font_sf_scale 100"
3877 preamble += "[" + options +"]"
3878 preamble += "{biolinum-type1}"
3879 add_to_preamble(document, [preamble])
3880 document.header[k] = "\\font_sans default"
3883 def convert_lyxframes(document):
3884 " Converts old beamer frames to new style "
3886 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3887 if document.textclass not in beamer_classes:
3890 framebeg = ["BeginFrame", "BeginPlainFrame"]
3891 frameend = ["Frame", "PlainFrame", "EndFrame", "BeginFrame", "BeginPlainFrame", "AgainFrame",
3892 "Section", "Section*", "Subsection", "Subsection*", "Subsubsection", "Subsubsection*"]
3893 for lay in framebeg:
3896 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
3899 parent = get_containing_layout(document.body, i)
3900 if parent == False or parent[1] != i:
3901 document.warning("Wrong parent layout!")
3904 frametype = parent[0]
3908 # Step I: Convert ERT arguments
3909 # FIXME: See restrictions in convert_beamerframeargs method
3910 ertend = convert_beamerframeargs(document, i, parbeg)
3913 # Step II: Now rename the layout and convert the title to an argument
3914 j = find_end_of_layout(document.body, i)
3915 document.body[j : j + 1] = ['\\end_layout', '', '\\end_inset', '', '\\end_layout']
3916 if lay == "BeginFrame":
3917 document.body[i] = "\\begin_layout Frame"
3919 document.body[i] = "\\begin_layout PlainFrame"
3920 document.body[ertend + 1 : ertend + 1] = ['\\begin_inset Argument 4',
3921 'status open', '', '\\begin_layout Plain Layout']
3922 # Step III: find real frame end
3926 fend = find_token(document.body, "\\begin_layout", jj)
3928 document.warning("Malformed LyX document: No real frame end!")
3930 val = get_value(document.body, "\\begin_layout", fend)
3931 if val not in frameend:
3934 old = document.body[fend]
3935 if val == frametype:
3936 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
3937 # consider explicit EndFrames between two identical frame types
3938 elif val == "EndFrame":
3939 nextlayout = find_token(document.body, "\\begin_layout", fend + 1)
3940 if nextlayout != -1 and get_value(document.body, "\\begin_layout", nextlayout) == frametype:
3941 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
3943 document.body[fend : fend] = ['\\end_deeper']
3945 document.body[fend : fend] = ['\\end_deeper']
3946 document.body[j + 1 : j + 1] = ['', '\\begin_deeper']
3951 def remove_endframes(document):
3952 " Remove deprecated beamer endframes "
3954 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3955 if document.textclass not in beamer_classes:
3960 i = find_token_exact(document.body, "\\begin_layout EndFrame", i)
3963 j = find_end_of_layout(document.body, i)
3965 document.warning("Malformed LyX document: Missing \\end_layout to EndFrame")
3968 del document.body[i : j + 1]
3971 def revert_powerdot_flexes(document):
3972 " Reverts powerdot flex insets "
3974 if document.textclass != "powerdot":
3977 flexes = {"Onslide" : "\\onslide",
3978 "Onslide*" : "\\onslide*",
3979 "Onslide+" : "\\onslide+"}
3980 rx = re.compile(r'^\\begin_inset Flex (.+)$')
3984 i = find_token(document.body, "\\begin_inset Flex", i)
3987 m = rx.match(document.body[i])
3989 flextype = m.group(1)
3990 z = find_end_of_inset(document.body, i)
3992 document.warning("Can't find end of Flex " + flextype + " inset.")
3995 if flextype in flexes:
3996 pre = put_cmd_in_ert(flexes[flextype])
3997 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
3999 argend = find_end_of_inset(document.body, arg)
4001 document.warning("Can't find end of Argument!")
4004 # Find containing paragraph layout
4005 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
4006 endPlain = find_end_of_layout(document.body, beginPlain)
4007 argcontent = document.body[beginPlain + 1 : endPlain]
4009 z = z - len(document.body[arg : argend + 1])
4011 del document.body[arg : argend + 1]
4012 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
4013 pre += put_cmd_in_ert("{")
4014 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4015 endPlain = find_end_of_layout(document.body, beginPlain)
4017 z = z - len(document.body[i : beginPlain + 1])
4019 document.body[i : beginPlain + 1] = pre
4020 post = put_cmd_in_ert("}")
4021 document.body[z - 2 : z + 1] = post
4025 def revert_powerdot_pause(document):
4026 " Reverts powerdot pause layout to ERT "
4028 if document.textclass != "powerdot":
4033 i = find_token(document.body, "\\begin_layout Pause", i)
4036 j = find_end_of_layout(document.body, i)
4038 document.warning("Malformed LyX document: Can't find end of Pause layout")
4042 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\pause")
4043 for p in range(i, j):
4046 arg = find_token(document.body, "\\begin_inset Argument 1", i, j)
4048 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4049 endPlain = find_end_of_layout(document.body, beginPlain)
4050 endInset = find_end_of_inset(document.body, p)
4051 content = document.body[beginPlain + 1 : endPlain]
4053 endlay = endlay - len(document.body[p : endInset + 1])
4055 del document.body[p : endInset + 1]
4056 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4058 document.body[i : i + 1] = subst
4062 def revert_powerdot_itemargs(document):
4063 " Reverts powerdot item arguments to ERT "
4065 if document.textclass != "powerdot":
4069 list_layouts = ["Itemize", "ItemizeType1", "Enumerate", "EnumerateType1"]
4070 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4073 i = find_token(document.body, "\\begin_inset Argument", i)
4076 # Find containing paragraph layout
4077 parent = get_containing_layout(document.body, i)
4079 document.warning("Malformed LyX document: Can't find parent paragraph layout")
4084 realparbeg = parent[3]
4085 layoutname = parent[0]
4087 for p in range(parbeg, parend):
4091 if layoutname in list_layouts:
4092 m = rx.match(document.body[p])
4095 if argnr == "item:1":
4096 j = find_end_of_inset(document.body, i)
4097 # Find containing paragraph layout
4098 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4099 endPlain = find_end_of_layout(document.body, beginPlain)
4100 content = document.body[beginPlain + 1 : endPlain]
4101 del document.body[i:j+1]
4102 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4103 document.body[realparbeg : realparbeg] = subst
4104 elif argnr == "item:2":
4105 j = find_end_of_inset(document.body, i)
4106 # Find containing paragraph layout
4107 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4108 endPlain = find_end_of_layout(document.body, beginPlain)
4109 content = document.body[beginPlain + 1 : endPlain]
4110 del document.body[i:j+1]
4111 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
4112 document.body[realparbeg : realparbeg] = subst
4117 def revert_powerdot_columns(document):
4118 " Reverts powerdot twocolumn to TeX-code "
4119 if document.textclass != "powerdot":
4122 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4125 i = find_token(document.body, "\\begin_layout Twocolumn", i)
4128 j = find_end_of_layout(document.body, i)
4130 document.warning("Malformed LyX document: Can't find end of Twocolumn layout")
4134 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
4135 endlay += len(put_cmd_in_ert("}"))
4136 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\twocolumn")
4137 for p in range(i, j):
4140 m = rx.match(document.body[p])
4144 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4145 endPlain = find_end_of_layout(document.body, beginPlain)
4146 endInset = find_end_of_inset(document.body, p)
4147 content = document.body[beginPlain + 1 : endPlain]
4149 endlay = endlay - len(document.body[p : endInset + 1])
4151 del document.body[p : endInset + 1]
4152 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4154 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4155 endPlain = find_end_of_layout(document.body, beginPlain)
4156 endInset = find_end_of_inset(document.body, p)
4157 content = document.body[beginPlain + 1 : endPlain]
4159 endlay = endlay - len(document.body[p : endInset + 1])
4161 del document.body[p : endInset + 1]
4162 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
4164 subst += put_cmd_in_ert("{")
4165 document.body[i : i + 1] = subst
4169 def revert_mbox_fbox(document):
4170 'Convert revert mbox/fbox boxes to TeX-code'
4173 i = find_token(document.body, "\\begin_inset Box", i)
4176 j = find_token(document.body, "width", i)
4178 document.warning("Malformed LyX document: Can't find box width")
4180 width = get_value(document.body, "width", j)
4181 k = find_end_of_inset(document.body, j)
4183 document.warning("Malformed LyX document: Can't find end of box inset")
4186 BeginLayout = find_token(document.body, "\\begin_layout Plain Layout", j)
4187 EndLayout = find_token(document.body, "\\end_layout", BeginLayout)
4188 # replace if width is ""
4190 document.body[EndLayout:k + 1] = put_cmd_in_ert("}")
4191 if document.body[i] == "\\begin_inset Box Frameless":
4192 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\mbox{")
4193 if document.body[i] == "\\begin_inset Box Boxed":
4194 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\fbox{")
4198 def revert_starred_caption(document):
4199 " Reverts unnumbered longtable caption insets "
4203 i = find_token(document.body, "\\begin_inset Caption LongTableNoNumber", i)
4206 # This is not equivalent, but since the caption inset is a full blown
4207 # text inset a true conversion to ERT is too difficult.
4208 document.body[i] = "\\begin_inset Caption Standard"
4212 def revert_forced_local_layout(document):
4215 i = find_token(document.header, "\\begin_forced_local_layout", i)
4218 j = find_end_of(document.header, i, "\\begin_forced_local_layout", "\\end_forced_local_layout")
4220 # this should not happen
4222 regexp = re.compile(r'\s*forcelocal', re.IGNORECASE)
4223 k = find_re(document.header, regexp, i, j)
4225 del document.header[k]
4227 k = find_re(document.header, regexp, i, j)
4228 k = find_token(document.header, "\\begin_local_layout", 0)
4230 document.header[i] = "\\begin_local_layout"
4231 document.header[j] = "\\end_local_layout"
4233 l = find_end_of(document.header, k, "\\begin_local_layout", "\\end_local_layout")
4235 # this should not happen
4237 lines = document.header[i+1 : j]
4239 document.header[k+1 : k+1] = lines
4240 document.header[i : j ] = []
4242 document.header[i : j ] = []
4243 document.header[k+1 : k+1] = lines
4246 def revert_aa1(document):
4247 " Reverts InsetArguments of aa to TeX-code "
4248 if document.textclass == "aa":
4252 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4254 revert_Argument_to_TeX_brace(document, i, 0, 1, 4, False, False)
4260 def revert_aa2(document):
4261 " Reverts InsetArguments of aa to TeX-code "
4262 if document.textclass == "aa":
4266 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4268 document.body[i] = "\\begin_layout Abstract"
4274 def revert_tibetan(document):
4275 "Set the document language for Tibetan to English"
4277 if document.language == "tibetan":
4278 document.language = "english"
4279 i = find_token(document.header, "\\language", 0)
4281 document.header[i] = "\\language english"
4283 while j < len(document.body):
4284 j = find_token(document.body, "\\lang tibetan", j)
4286 document.body[j] = document.body[j].replace("\\lang tibetan", "\\lang english")
4289 j = len(document.body)
4298 # The idea here is that we will have a sequence of chunk paragraphs.
4299 # We want to convert them to paragraphs in one or several chunk insets.
4300 # Individual chunks are terminated by the character @ on the last line.
4301 # This line will be discarded, and following lines are treated as new
4302 # chunks, which go into their own insets.
4303 # The first line of a chunk should look like: <<CONTENT>>=
4304 # We will discard the delimiters, and put the CONTENT into the
4305 # optional argument of the inset, if the CONTENT is non-empty.
4306 def convert_chunks(document):
4307 first_re = re.compile(r'<<(.*)>>=(.*)')
4310 # find start of a block of chunks
4311 i = find_token(document.body, "\\begin_layout Chunk", file_pos)
4317 chunk_started = False
4320 # process the one we just found
4321 j = find_end_of_layout(document.body, i)
4323 document.warning("Malformed LyX documents. Can't find end of Chunk layout!")
4324 # there is no point continuing, as we will run into the same error again.
4326 this_chunk = "".join(document.body[i + 1:j])
4328 # there may be empty lines between chunks
4329 # we just skip them.
4330 if not chunk_started:
4331 if this_chunk != "":
4333 chunk_started = True
4336 contents.append(document.body[i + 1:j])
4338 # look for potential chunk terminator
4339 # on the last line of the chunk paragraph
4340 if document.body[j - 1] == "@":
4343 # look for subsequent chunk paragraph
4344 i = find_token(document.body, "\\begin_layout", j)
4348 if get_value(document.body, "\\begin_layout", i) != "Chunk":
4351 file_pos = end = j + 1
4353 # The last chunk should simply have an "@" in it
4354 # or at least end with "@" (can happen if @ is
4355 # preceded by a newline)
4356 lastpar = ''.join(contents[-1])
4357 if not lastpar.endswith("@"):
4358 document.warning("Unexpected chunk content: chunk not terminated by '@'!")
4362 # chunk par only contains "@". Just drop it.
4365 # chunk par contains more. Only drop the "@".
4368 # The first line should look like: <<CONTENT>>=
4369 # We want the CONTENT
4370 optarg = ' '.join(contents[0])
4372 # We can already have real chunk content in
4373 # the first par (separated from the options by a newline).
4374 # We collect such stuff to re-insert it later.
4377 match = first_re.search(optarg)
4379 optarg = match.groups()[0]
4380 if match.groups()[1] != "":
4382 for c in contents[0]:
4383 if c.endswith(">>="):
4387 postoptstuff.append(c)
4388 # We have stripped everything. This can be deleted.
4391 newstuff = ['\\begin_layout Standard',
4392 '\\begin_inset Flex Chunk',
4394 '\\begin_layout Plain Layout', '']
4396 # If we have a non-empty optional argument, insert it.
4397 if match and optarg != "":
4399 ['\\begin_inset Argument 1',
4401 '\\begin_layout Plain Layout',
4406 # Since we already opened a Plain layout, the first paragraph
4407 # does not need to do that.
4410 newstuff.extend(postoptstuff)
4411 newstuff.append('\\end_layout')
4415 newstuff.extend(['', '\\begin_layout Plain Layout', ''])
4419 newstuff.append('\\end_layout')
4421 newstuff.extend(['', '\\end_inset', '', '\\end_layout', ''])
4423 document.body[start:end] = newstuff
4425 file_pos += len(newstuff) - (end - start)
4428 def revert_chunks(document):
4431 i = find_token(document.body, "\\begin_inset Flex Chunk", i)
4435 iend = find_end_of_inset(document.body, i)
4437 document.warning("Can't find end of Chunk!")
4441 # Look for optional argument
4443 ostart = find_token(document.body, "\\begin_inset Argument 1", i, iend)
4445 oend = find_end_of_inset(document.body, ostart)
4446 k = find_token(document.body, "\\begin_layout Plain Layout", ostart, oend)
4448 document.warning("Malformed LyX document: Can't find argument contents!")
4450 m = find_end_of_layout(document.body, k)
4451 optarg = "".join(document.body[k+1:m])
4454 # We now remove the optional argument, so we have something
4455 # uniform on which to work
4456 document.body[ostart : oend + 1] = []
4457 # iend is now invalid
4458 iend = find_end_of_inset(document.body, i)
4460 retval = get_containing_layout(document.body, i)
4462 document.warning("Can't find containing layout for Chunk!")
4465 (lname, lstart, lend, pstart) = retval
4466 # we now want to work through the various paragraphs, and collect their contents
4470 k = find_token(document.body, "\\begin_layout Plain Layout", k, lend)
4473 j = find_end_of_layout(document.body, k)
4475 document.warning("Can't find end of layout inside chunk!")
4477 parlist.append(document.body[k+1:j])
4479 # we now need to wrap all of these paragraphs in chunks
4482 newlines.extend(["\\begin_layout Chunk", "", "<<" + optarg + ">>=", "\\end_layout", ""])
4483 for stuff in parlist:
4484 newlines.extend(["\\begin_layout Chunk"] + stuff + ["\\end_layout", ""])
4485 newlines.extend(["\\begin_layout Chunk", "", "@", "\\end_layout", ""])
4486 # replace old content with new content
4487 document.body[lstart : lend + 1] = newlines
4488 i = lstart + len(newlines)
4495 supported_versions = ["2.1.0","2.1"]
4498 [415, [convert_undertilde]],
4500 [417, [convert_japanese_encodings]],
4501 [418, [convert_justification]],
4503 [420, [convert_biblio_style]],
4504 [421, [convert_longtable_captions]],
4505 [422, [convert_use_packages]],
4506 [423, [convert_use_mathtools]],
4507 [424, [convert_cite_engine_type]],
4508 # No convert_cancel, since cancel will be loaded automatically
4509 # in format 425 without any possibility to switch it off.
4510 # This has been fixed in format 464.
4514 [428, [convert_cell_rotation]],
4515 [429, [convert_table_rotation]],
4516 [430, [convert_listoflistings]],
4517 [431, [convert_use_amssymb]],
4519 [433, [convert_armenian]],
4527 [441, [convert_mdnomath]],
4532 [446, [convert_latexargs]],
4533 [447, [convert_IEEEtran, convert_AASTeX, convert_AGUTeX, convert_IJMP, convert_SIGPLAN, convert_SIGGRAPH, convert_EuropeCV, convert_Initials, convert_ModernCV]],
4534 [448, [convert_literate]],
4537 [451, [convert_beamerargs, convert_againframe_args, convert_corollary_args, convert_quote_args]],
4538 [452, [convert_beamerblocks]],
4539 [453, [convert_use_stmaryrd]],
4540 [454, [convert_overprint]],
4542 [456, [convert_epigraph]],
4543 [457, [convert_use_stackrel]],
4544 [458, [convert_captioninsets, convert_captionlayouts]],
4549 [463, [convert_encodings]],
4550 [464, [convert_use_cancel]],
4551 [465, [convert_lyxframes, remove_endframes]],
4557 [471, [convert_cite_engine_type_default]],
4560 [474, [convert_chunks]],
4564 [473, [revert_chunks]],
4565 [472, [revert_tibetan]],
4566 [471, [revert_aa1,revert_aa2]],
4567 [470, [revert_cite_engine_type_default]],
4568 [469, [revert_forced_local_layout]],
4569 [468, [revert_starred_caption]],
4570 [467, [revert_mbox_fbox]],
4571 [466, [revert_iwona_fonts]],
4572 [465, [revert_powerdot_flexes, revert_powerdot_pause, revert_powerdot_itemargs, revert_powerdot_columns]],
4574 [463, [revert_use_cancel]],
4575 [462, [revert_encodings]],
4576 [461, [revert_new_libertines]],
4577 [460, [revert_kurier_fonts]],
4578 [459, [revert_IEEEtran_3]],
4579 [458, [revert_fragileframe, revert_newframes]],
4580 [457, [revert_captioninsets, revert_captionlayouts]],
4581 [456, [revert_use_stackrel]],
4582 [455, [revert_epigraph]],
4583 [454, [revert_frametitle]],
4584 [453, [revert_overprint]],
4585 [452, [revert_use_stmaryrd]],
4586 [451, [revert_beamerblocks]],
4587 [450, [revert_beamerargs, revert_beamerargs2, revert_beamerargs3, revert_beamerflex]],
4588 [449, [revert_garamondx, revert_garamondx_newtxmath]],
4589 [448, [revert_itemargs]],
4590 [447, [revert_literate]],
4591 [446, [revert_IEEEtran, revert_IEEEtran_2, revert_AASTeX, revert_AGUTeX, revert_IJMP, revert_SIGPLAN, revert_SIGGRAPH, revert_EuropeCV, revert_Initials, revert_ModernCV_3, revert_ModernCV_4]],
4592 [445, [revert_latexargs]],
4593 [444, [revert_uop]],
4594 [443, [revert_biolinum]],
4596 [441, [revert_newtxmath]],
4597 [440, [revert_mdnomath]],
4598 [439, [revert_mathfonts]],
4599 [438, [revert_minionpro]],
4600 [437, [revert_ipadeco, revert_ipachar]],
4601 [436, [revert_texgyre]],
4602 [435, [revert_mathdesign]],
4603 [434, [revert_txtt]],
4604 [433, [revert_libertine]],
4605 [432, [revert_armenian]],
4606 [431, [revert_languages, revert_ancientgreek]],
4607 [430, [revert_use_amssymb]],
4608 [429, [revert_listoflistings]],
4609 [428, [revert_table_rotation]],
4610 [427, [revert_cell_rotation]],
4611 [426, [revert_tipa]],
4612 [425, [revert_verbatim]],
4613 [424, [revert_cancel]],
4614 [423, [revert_cite_engine_type]],
4615 [422, [revert_use_mathtools]],
4616 [421, [revert_use_packages]],
4617 [420, [revert_longtable_captions]],
4618 [419, [revert_biblio_style]],
4619 [418, [revert_australian]],
4620 [417, [revert_justification]],
4621 [416, [revert_japanese_encodings]],
4622 [415, [revert_negative_space, revert_math_spaces]],
4623 [414, [revert_undertilde]],
4624 [413, [revert_visible_space]]
4628 if __name__ == "__main__":