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
124 end_layout = find_end_of_layout(document.body, line)
129 lineERT = find_token(document.body, "\\begin_inset ERT", lineERT, end_layout)
132 if environment == False:
133 end_ERT = find_end_of_inset(document.body, lineERT)
135 document.warning("Can't find end of ERT!!")
137 # Note that this only checks for ][ or }{ at the beginning of a line
139 bracePair = find_token(document.body, "][", lineERT, end_ERT)
141 bracePair = find_token(document.body, "}{", lineERT, end_ERT)
143 end = find_token(document.body, "\\end_inset", bracePair)
144 document.body[lineERT : end_ERT + 1] = ["\\end_layout", "", "\\end_inset"]
146 # in the case that n > 1 we have optional arguments before
147 # therefore detect them if any
149 # first check if there is an argument
150 lineArg = find_token(document.body, "\\begin_inset Argument", line)
151 if lineArg < lineERT and lineArg != -1:
152 # we have an argument, so now search backwards for its end
153 # we must now assure that we don't find other insets like e.g. a newline
154 endInsetArg = lineERT
155 endLayoutArg = endInsetArg
156 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
157 endInsetArg = endInsetArg - 1
158 endLayoutArg = endInsetArg
159 endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
160 endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
161 line = endInsetArg + 1
163 document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
165 document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
167 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
172 # no brace pair found
173 # now check the case that we have "}" + "{" in two ERTs
175 endBrace = find_token(document.body, "]", lineERT, end_layout)
177 endBrace = find_token(document.body, "}", lineERT, end_layout)
178 if endBrace == lineERT + 5:
180 beginBrace = find_token(document.body, "[", endBrace, end_layout)
182 beginBrace = find_token(document.body, "{", endBrace, end_layout)
183 # assure that the ERTs are consecutive (11 or 12 depending if there is a space between the ERTs or not)
184 if beginBrace == endBrace + 11 or beginBrace == endBrace + 12:
185 end = find_token(document.body, "\\end_inset", beginBrace)
186 document.body[lineERT : end + 1] = ["\\end_layout", "", "\\end_inset"]
188 # in the case that n > 1 we have optional arguments before
189 # therefore detect them if any
191 # first check if there is an argument
192 lineArg = find_token(document.body, "\\begin_inset Argument", line)
193 if lineArg < lineERT and lineArg != -1:
194 # we have an argument, so now search backwards for its end
195 # we must now assure that we don't find other insets like e.g. a newline
196 endInsetArg = lineERT
197 endLayoutArg = endInsetArg
198 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
199 endInsetArg = endInsetArg - 1
200 endLayoutArg = endInsetArg
201 endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
202 endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
203 line = endInsetArg + 1
205 document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
207 document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
209 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
212 # set the line where the next argument will be inserted
213 if beginBrace == endBrace + 11:
221 if environment == True:
222 end_ERT = find_end_of_inset(document.body, lineERT)
224 document.warning("Can't find end of ERT!!")
226 # Note that this only checks for [ or { at the beginning of a line
228 opening = find_token(document.body, "[", lineERT, end_ERT)
230 opening = find_token(document.body, "{", lineERT, end_ERT)
232 document.body[lineERT : end_ERT + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
234 lineERT2 = find_token(document.body, "\\begin_inset ERT", end_ERT, end_layout)
236 end_ERT2 = find_end_of_inset(document.body, lineERT2)
238 document.warning("Can't find end of second ERT!!")
241 closing = find_token(document.body, "]", lineERT2, end_ERT2)
243 closing = find_token(document.body, "}", lineERT2, end_ERT2)
244 if closing != -1: # assure that the "}" is in this ERT
245 end2 = find_token(document.body, "\\end_inset", closing)
246 document.body[lineERT2 : end2 + 1] = ["\\end_layout", "", "\\end_inset"]
249 ###############################################################################
251 ### Conversion and reversion routines
253 ###############################################################################
255 def revert_visible_space(document):
256 "Revert InsetSpace visible into its ERT counterpart"
259 i = find_token(document.body, "\\begin_inset space \\textvisiblespace{}", i)
262 end = find_end_of_inset(document.body, i)
263 subst = put_cmd_in_ert("\\textvisiblespace{}")
264 document.body[i:end + 1] = subst
267 undertilde_commands = ["utilde"]
268 def convert_undertilde(document):
269 " Load undertilde automatically "
270 i = find_token(document.header, "\\use_mathdots" , 0)
272 i = find_token(document.header, "\\use_mhchem" , 0)
274 i = find_token(document.header, "\\use_esint" , 0)
276 document.warning("Malformed LyX document: Can't find \\use_mathdots.")
278 j = find_token(document.preamble, "\\usepackage{undertilde}", 0)
280 # package was loaded in the preamble, convert this to header setting for round trip
281 document.header.insert(i + 1, "\\use_undertilde 2") # on
282 del document.preamble[j]
286 j = find_token(document.body, '\\begin_inset Formula', j)
289 k = find_end_of_inset(document.body, j)
291 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(j))
294 code = "\n".join(document.body[j:k])
295 for c in undertilde_commands:
296 if code.find("\\%s" % c) != -1:
297 # at least one of the commands was found - need to switch package off
298 document.header.insert(i + 1, "\\use_undertilde 0") # off
301 # no command was found - set to auto (bug 9069)
302 document.header.insert(i + 1, "\\use_undertilde 1") # auto
306 def revert_undertilde(document):
307 " Load undertilde if used in the document "
308 regexp = re.compile(r'(\\use_undertilde)')
309 i = find_re(document.header, regexp, 0)
310 value = "1" # default is auto
312 value = get_value(document.header, "\\use_undertilde" , i).split()[0]
313 del document.header[i]
314 if value == "2": # on
315 add_to_preamble(document, ["\\usepackage{undertilde}"])
316 elif value == "1": # auto
319 i = find_token(document.body, '\\begin_inset Formula', i)
322 j = find_end_of_inset(document.body, i)
324 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
327 code = "\n".join(document.body[i:j])
328 for c in undertilde_commands:
329 if code.find("\\%s" % c) != -1:
330 add_to_preamble(document, ["\\usepackage{undertilde}"])
335 def revert_negative_space(document):
336 "Revert InsetSpace negmedspace and negthickspace into its TeX-code counterpart"
341 i = find_token(document.body, "\\begin_inset space \\negmedspace{}", i)
343 j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
345 # load amsmath in the preamble if not already loaded if we are at the end of checking
347 i = find_token(document.header, "\\use_amsmath 2", 0)
349 add_to_preamble(document, ["\\@ifundefined{negthickspace}{\\usepackage{amsmath}}"])
353 end = find_end_of_inset(document.body, i)
354 subst = put_cmd_in_ert("\\negmedspace{}")
355 document.body[i:end + 1] = subst
356 j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
359 end = find_end_of_inset(document.body, j)
360 subst = put_cmd_in_ert("\\negthickspace{}")
361 document.body[j:end + 1] = subst
365 def revert_math_spaces(document):
366 "Revert formulas with protected custom space and protected hfills to TeX-code"
369 i = find_token(document.body, "\\begin_inset Formula", i)
372 j = document.body[i].find("\\hspace*")
374 end = find_end_of_inset(document.body, i)
375 subst = put_cmd_in_ert(document.body[i][21:])
376 document.body[i:end + 1] = subst
380 def convert_japanese_encodings(document):
381 " Rename the japanese encodings to names understood by platex "
383 "EUC-JP-pLaTeX": "euc",
385 "SJIS-pLaTeX": "sjis"
387 i = find_token(document.header, "\\inputencoding" , 0)
390 val = get_value(document.header, "\\inputencoding", i)
391 if val in jap_enc_dict.keys():
392 document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
395 def revert_japanese_encodings(document):
396 " Revert the japanese encodings name changes "
398 "euc": "EUC-JP-pLaTeX",
400 "sjis": "SJIS-pLaTeX"
402 i = find_token(document.header, "\\inputencoding" , 0)
405 val = get_value(document.header, "\\inputencoding", i)
406 if val in jap_enc_dict.keys():
407 document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
410 def convert_justification(document):
411 " Add the \\justification buffer param"
412 i = find_token(document.header, "\\use_indices" , 0)
414 document.warning("Malformed LyX document: Missing \\use_indices.")
416 document.header.insert(i + 1, "\\justification true")
419 def revert_justification(document):
420 " Revert the \\justification buffer param"
421 if not del_token(document.header, '\\justification', 0):
422 document.warning("Malformed LyX document: Missing \\justification.")
425 def revert_australian(document):
426 "Set English language variants Australian and Newzealand to English"
428 if document.language == "australian" or document.language == "newzealand":
429 document.language = "english"
430 i = find_token(document.header, "\\language", 0)
432 document.header[i] = "\\language english"
435 j = find_token(document.body, "\\lang australian", j)
437 j = find_token(document.body, "\\lang newzealand", 0)
441 document.body[j] = document.body[j].replace("\\lang newzealand", "\\lang english")
443 document.body[j] = document.body[j].replace("\\lang australian", "\\lang english")
447 def convert_biblio_style(document):
448 "Add a sensible default for \\biblio_style based on the citation engine."
449 i = find_token(document.header, "\\cite_engine", 0)
451 engine = get_value(document.header, "\\cite_engine", i).split("_")[0]
452 style = {"basic": "plain", "natbib": "plainnat", "jurabib": "jurabib"}
453 document.header.insert(i + 1, "\\biblio_style " + style[engine])
456 def revert_biblio_style(document):
457 "BibTeX insets with default option use the style defined by \\biblio_style."
458 i = find_token(document.header, "\\biblio_style" , 0)
460 document.warning("No \\biblio_style line. Nothing to do.")
463 default_style = get_value(document.header, "\\biblio_style", i)
464 del document.header[i]
466 # We are looking for bibtex insets having the default option
469 i = find_token(document.body, "\\begin_inset CommandInset bibtex", i)
472 j = find_end_of_inset(document.body, i)
474 document.warning("Malformed LyX document: Can't find end of bibtex inset at line " + str(i))
477 k = find_token(document.body, "options", i, j)
479 options = get_quoted_value(document.body, "options", k)
480 if "default" in options.split(","):
481 document.body[k] = 'options "%s"' \
482 % options.replace("default", default_style)
486 def handle_longtable_captions(document, forward):
489 begin_table = find_token(document.body, '<lyxtabular version=', begin_table)
490 if begin_table == -1:
492 end_table = find_end_of(document.body, begin_table, '<lyxtabular', '</lyxtabular>')
494 document.warning("Malformed LyX document: Could not find end of table.")
497 fline = find_token(document.body, "<features", begin_table, end_table)
499 document.warning("Can't find features for inset at line " + str(begin_table))
502 p = document.body[fline].find("islongtable")
507 numrows = get_option_value(document.body[begin_table], "rows")
509 numrows = int(numrows)
511 document.warning(document.body[begin_table])
512 document.warning("Unable to determine rows!")
513 begin_table = end_table
515 begin_row = begin_table
516 for row in range(numrows):
517 begin_row = find_token(document.body, '<row', begin_row, end_table)
519 document.warning("Can't find row " + str(row + 1))
521 end_row = find_end_of(document.body, begin_row, '<row', '</row>')
523 document.warning("Can't find end of row " + str(row + 1))
526 if (get_option_value(document.body[begin_row], 'caption') == 'true' and
527 get_option_value(document.body[begin_row], 'endfirsthead') != 'true' and
528 get_option_value(document.body[begin_row], 'endhead') != 'true' and
529 get_option_value(document.body[begin_row], 'endfoot') != 'true' and
530 get_option_value(document.body[begin_row], 'endlastfoot') != 'true'):
531 document.body[begin_row] = set_option_value(document.body[begin_row], 'caption', 'true", endfirsthead="true')
532 elif get_option_value(document.body[begin_row], 'caption') == 'true':
533 if get_option_value(document.body[begin_row], 'endfirsthead') == 'true':
534 document.body[begin_row] = set_option_value(document.body[begin_row], 'endfirsthead', 'false')
535 if get_option_value(document.body[begin_row], 'endhead') == 'true':
536 document.body[begin_row] = set_option_value(document.body[begin_row], 'endhead', 'false')
537 if get_option_value(document.body[begin_row], 'endfoot') == 'true':
538 document.body[begin_row] = set_option_value(document.body[begin_row], 'endfoot', 'false')
539 if get_option_value(document.body[begin_row], 'endlastfoot') == 'true':
540 document.body[begin_row] = set_option_value(document.body[begin_row], 'endlastfoot', 'false')
542 # since there could be a tabular inside this one, we
543 # cannot jump to end.
547 def convert_longtable_captions(document):
548 "Add a firsthead flag to caption rows"
549 handle_longtable_captions(document, True)
552 def revert_longtable_captions(document):
553 "remove head/foot flag from caption rows"
554 handle_longtable_captions(document, False)
557 def convert_use_packages(document):
558 "use_xxx yyy => use_package xxx yyy"
559 packages = ["amsmath", "esint", "mathdots", "mhchem", "undertilde"]
561 i = find_token(document.header, "\\use_%s" % p, 0)
563 value = get_value(document.header, "\\use_%s" % p, i)
564 document.header[i] = "\\use_package %s %s" % (p, value)
567 def revert_use_packages(document):
568 "use_package xxx yyy => use_xxx yyy"
569 packages = ["amsmath", "esint", "mhchem", "mathdots", "undertilde"]
570 # the order is arbitrary for the use_package version, and not all packages need to be given.
571 # Ensure a complete list and correct order (important for older LyX versions and especially lyx2lyx)
572 # first loop: find line with first package
575 regexp = re.compile(r'(\\use_package\s+%s)' % p)
576 i = find_re(document.header, regexp, 0)
577 if i != -1 and (j < 0 or i < j):
579 # second loop: replace or insert packages in front of all existing ones
581 regexp = re.compile(r'(\\use_package\s+%s)' % p)
582 i = find_re(document.header, regexp, 0)
584 value = get_value(document.header, "\\use_package %s" % p, i).split()[1]
585 del document.header[i]
586 document.header.insert(j, "\\use_%s %s" % (p, value))
588 document.header.insert(j, "\\use_%s 1" % p)
592 def convert_use_package(document, pkg, commands, oldauto):
593 # oldauto defines how the version we are converting from behaves:
594 # if it is true, the old version uses the package automatically.
595 # if it is false, the old version never uses the package.
596 i = find_token(document.header, "\\use_package", 0)
598 document.warning("Malformed LyX document: Can't find \\use_package.")
600 j = find_token(document.preamble, "\\usepackage{" + pkg + "}", 0)
602 # package was loaded in the preamble, convert this to header setting for round trip
603 document.header.insert(i + 1, "\\use_package " + pkg + " 2") # on
604 del document.preamble[j]
605 # If oldauto is true we have two options:
606 # We can either set the package to auto - this is correct for files in
607 # format 425 to 463, and may create a conflict for older files which use
608 # any command in commands with a different definition.
609 # Or we can look whether any command in commands is used, and set it to
610 # auto if not and to off if yes. This will not create a conflict, but will
611 # create uncompilable documents for files in format 425 to 463, which use
612 # any command in commands.
613 # We choose the first option since its error is less likely.
615 document.header.insert(i + 1, "\\use_package " + pkg + " 1") # auto
619 j = find_token(document.body, '\\begin_inset Formula', j)
622 k = find_end_of_inset(document.body, j)
624 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(j))
627 code = "\n".join(document.body[j:k])
629 if code.find("\\%s" % c) != -1:
630 # at least one of the commands was found - need to switch package off
631 document.header.insert(i + 1, "\\use_package " + pkg + " 0") # off
634 # no command was found - set to auto (bug 9069)
635 document.header.insert(i + 1, "\\use_package " + pkg + " 1") # auto
638 def revert_use_package(document, pkg, commands, oldauto):
639 # oldauto defines how the version we are reverting to behaves:
640 # if it is true, the old version uses the package automatically.
641 # if it is false, the old version never uses the package.
642 regexp = re.compile(r'(\\use_package\s+%s)' % pkg)
643 i = find_re(document.header, regexp, 0)
644 value = "1" # default is auto
646 value = get_value(document.header, "\\use_package" , i).split()[1]
647 del document.header[i]
648 if value == "2": # on
649 add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
650 elif value == "1" and not oldauto: # auto
653 i = find_token(document.body, '\\begin_inset Formula', i)
656 j = find_end_of_inset(document.body, i)
658 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
661 code = "\n".join(document.body[i:j])
663 if code.find("\\%s" % c) != -1:
664 add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
669 mathtools_commands = ["mathclap", "mathllap", "mathrlap", \
670 "lgathered", "rgathered", "vcentcolon", "dblcolon", \
671 "coloneqq", "Coloneqq", "coloneq", "Coloneq", "eqqcolon", \
672 "Eqqcolon", "eqcolon", "Eqcolon", "colonapprox", \
673 "Colonapprox", "colonsim", "Colonsim"]
674 def convert_use_mathtools(document):
675 "insert use_package mathtools"
676 convert_use_package(document, "mathtools", mathtools_commands, False)
679 def revert_use_mathtools(document):
680 "remove use_package mathtools"
681 revert_use_package(document, "mathtools", mathtools_commands, False)
684 # commands provided by stmaryrd.sty but LyX uses other packages:
685 # boxdot lightning, bigtriangledown, bigtriangleup
686 stmaryrd_commands = ["shortleftarrow", "shortrightarrow", "shortuparrow", \
687 "shortdownarrow", "Yup", "Ydown", "Yleft", "Yright", \
688 "varcurlyvee", "varcurlywedge", "minuso", "baro", \
689 "sslash", "bbslash", "moo", "varotimes", "varoast", \
690 "varobar", "varodot", "varoslash", "varobslash", \
691 "varocircle", "varoplus", "varominus", "boxast", \
692 "boxbar", "boxslash", "boxbslash", "boxcircle", \
693 "boxbox", "boxempty", "merge", "vartimes", \
694 "fatsemi", "sswarrow", "ssearrow", "curlywedgeuparrow", \
695 "curlywedgedownarrow", "fatslash", "fatbslash", "lbag", \
696 "rbag", "varbigcirc", "leftrightarroweq", \
697 "curlyveedownarrow", "curlyveeuparrow", "nnwarrow", \
698 "nnearrow", "leftslice", "rightslice", "varolessthan", \
699 "varogreaterthan", "varovee", "varowedge", "talloblong", \
700 "interleave", "obar", "obslash", "olessthan", \
701 "ogreaterthan", "ovee", "owedge", "oblong", "inplus", \
702 "niplus", "nplus", "subsetplus", "supsetplus", \
703 "subsetpluseq", "supsetpluseq", "Lbag", "Rbag", \
704 "llbracket", "rrbracket", "llparenthesis", \
705 "rrparenthesis", "binampersand", "bindnasrepma", \
706 "trianglelefteqslant", "trianglerighteqslant", \
707 "ntrianglelefteqslant", "ntrianglerighteqslant", \
708 "llfloor", "rrfloor", "llceil", "rrceil", "arrownot", \
709 "Arrownot", "Mapstochar", "mapsfromchar", "Mapsfromchar", \
710 "leftrightarrowtriangle", "leftarrowtriangle", \
711 "rightarrowtriangle", \
712 "bigcurlyvee", "bigcurlywedge", "bigsqcap", "bigbox", \
713 "bigparallel", "biginterleave", "bignplus", \
714 "varcopyright", "longarrownot", "Longarrownot", \
715 "Mapsto", "mapsfrom", "Mapsfrom" "Longmapsto", \
716 "longmapsfrom", "Longmapsfrom"]
717 def convert_use_stmaryrd(document):
718 "insert use_package stmaryrd"
719 convert_use_package(document, "stmaryrd", stmaryrd_commands, False)
722 def revert_use_stmaryrd(document):
723 "remove use_package stmaryrd"
724 revert_use_package(document, "stmaryrd", stmaryrd_commands, False)
727 stackrel_commands = ["stackrel"]
728 def convert_use_stackrel(document):
729 "insert use_package stackrel"
730 convert_use_package(document, "stackrel", stackrel_commands, False)
733 def revert_use_stackrel(document):
734 "remove use_package stackrel"
735 revert_use_package(document, "stackrel", stackrel_commands, False)
738 def convert_cite_engine_type(document):
739 "Determine the \\cite_engine_type from the citation engine."
740 i = find_token(document.header, "\\cite_engine", 0)
743 engine = get_value(document.header, "\\cite_engine", i)
745 engine, type = engine.split("_")
747 type = {"basic": "numerical", "jurabib": "authoryear"}[engine]
748 document.header[i] = "\\cite_engine " + engine
749 document.header.insert(i + 1, "\\cite_engine_type " + type)
752 def revert_cite_engine_type(document):
753 "Natbib had the type appended with an underscore."
754 engine_type = "numerical"
755 i = find_token(document.header, "\\cite_engine_type" , 0)
757 document.warning("No \\cite_engine_type line. Assuming numerical.")
759 engine_type = get_value(document.header, "\\cite_engine_type", i)
760 del document.header[i]
762 # We are looking for the natbib citation engine
763 i = find_token(document.header, "\\cite_engine natbib", 0)
766 document.header[i] = "\\cite_engine natbib_" + engine_type
769 def convert_cite_engine_type_default(document):
770 "Convert \\cite_engine_type to default for the basic citation engine."
771 i = find_token(document.header, "\\cite_engine basic", 0)
774 i = find_token(document.header, "\\cite_engine_type" , 0)
777 document.header[i] = "\\cite_engine_type default"
780 def revert_cite_engine_type_default(document):
781 """Revert \\cite_engine_type default.
783 Revert to numerical for the basic cite engine, otherwise to authoryear."""
784 engine_type = "authoryear"
785 i = find_token(document.header, "\\cite_engine_type default" , 0)
788 j = find_token(document.header, "\\cite_engine basic", 0)
790 engine_type = "numerical"
791 document.header[i] = "\\cite_engine_type " + engine_type
794 cancel_commands = ["cancel", "bcancel", "xcancel", "cancelto"]
795 # this is the same, as revert_use_cancel() except for the default
796 def revert_cancel(document):
797 "add cancel to the preamble if necessary"
798 revert_use_package(document, "cancel", cancel_commands, False)
801 def revert_verbatim(document):
802 " Revert verbatim einvironments completely to TeX-code. "
805 subst_end = ['\end_layout', '', '\\begin_layout Plain Layout',
807 '\\begin_layout Plain Layout', '', '',
810 '\\end_layout', '', '\\end_inset',
811 '', '', '\\end_layout']
812 subst_begin = ['\\begin_layout Standard', '\\noindent',
813 '\\begin_inset ERT', 'status open', '',
814 '\\begin_layout Plain Layout', '', '', '\\backslash',
816 '\\end_layout', '', '\\begin_layout Plain Layout', '']
819 i = find_token(document.body, "\\begin_layout Verbatim", i)
822 j = find_end_of_layout(document.body, i)
824 document.warning("Malformed LyX document: Can't find end of Verbatim layout")
827 # delete all line breaks insets (there are no other insets)
830 n = find_token(document.body, "\\begin_inset Newline newline", l, j)
832 n = find_token(document.body, "\\begin_inset Newline linebreak", l, j)
835 m = find_end_of_inset(document.body, n)
836 del(document.body[m:m+1])
837 document.body[n:n+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
839 # we deleted a line, so the end of the inset moved forward.
841 # consecutive verbatim environments need to be connected
842 k = find_token(document.body, "\\begin_layout Verbatim", j)
843 if k == j + 2 and consecutive == False:
845 document.body[j:j+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
846 document.body[i:i+1] = subst_begin
848 if k == j + 2 and consecutive == True:
849 document.body[j:j+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
850 del(document.body[i:i+1])
852 if k != j + 2 and consecutive == True:
853 document.body[j:j+1] = subst_end
854 # the next paragraph must not be indented
855 document.body[j+19:j+19] = ['\\noindent']
856 del(document.body[i:i+1])
860 document.body[j:j+1] = subst_end
861 # the next paragraph must not be indented
862 document.body[j+19:j+19] = ['\\noindent']
863 document.body[i:i+1] = subst_begin
866 def revert_tipa(document):
867 " Revert native TIPA insets to mathed or ERT. "
870 i = find_token(document.body, "\\begin_inset IPA", i)
873 j = find_end_of_inset(document.body, i)
875 document.warning("Malformed LyX document: Can't find end of IPA inset")
879 n = find_token(document.body, "\\begin_layout", i, j)
881 document.warning("Malformed LyX document: IPA inset has no embedded layout")
884 m = find_end_of_layout(document.body, n)
886 document.warning("Malformed LyX document: Can't find end of embedded layout")
889 content = document.body[n+1:m]
890 p = find_token(document.body, "\\begin_layout", m, j)
891 if p != -1 or len(content) > 1:
893 content = document.body[i+1:j]
895 # IPA insets with multiple pars need to be wrapped by \begin{IPA}...\end{IPA}
896 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}")
897 add_to_preamble(document, ["\\usepackage{tipa,tipx}"])
899 # single-par IPA insets can be reverted to mathed
900 document.body[i:j+1] = ["\\begin_inset Formula $\\text{\\textipa{" + content[0] + "}}$", "\\end_inset"]
904 def revert_cell_rotation(document):
905 "Revert cell rotations to TeX-code"
907 load_rotating = False
911 # first, let's find out if we need to do anything
912 i = find_token(document.body, '<cell ', i)
915 j = document.body[i].find('rotate="')
917 k = document.body[i].find('"', j + 8)
918 value = document.body[i][j + 8 : k]
920 rgx = re.compile(r' rotate="[^"]+?"')
921 # remove rotate option
922 document.body[i] = rgx.sub('', document.body[i])
924 rgx = re.compile(r' rotate="[^"]+?"')
925 document.body[i] = rgx.sub(' rotate="true"', document.body[i])
927 rgx = re.compile(r' rotate="[^"]+?"')
929 # remove rotate option
930 document.body[i] = rgx.sub('', document.body[i])
932 document.body[i + 5 : i + 5] = \
933 put_cmd_in_ert("\\end{turn}")
934 document.body[i + 4 : i + 4] = \
935 put_cmd_in_ert("\\begin{turn}{" + value + "}")
941 add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"])
944 def convert_cell_rotation(document):
945 'Convert cell rotation statements from "true" to "90"'
949 # first, let's find out if we need to do anything
950 i = find_token(document.body, '<cell ', i)
953 j = document.body[i].find('rotate="true"')
955 rgx = re.compile(r'rotate="[^"]+?"')
956 # convert "true" to "90"
957 document.body[i] = rgx.sub('rotate="90"', document.body[i])
962 def revert_table_rotation(document):
963 "Revert table rotations to TeX-code"
965 load_rotating = False
969 # first, let's find out if we need to do anything
970 i = find_token(document.body, '<features ', i)
973 j = document.body[i].find('rotate="')
975 end_table = find_token(document.body, '</lyxtabular>', j)
976 k = document.body[i].find('"', j + 8)
977 value = document.body[i][j + 8 : k]
979 rgx = re.compile(r' rotate="[^"]+?"')
980 # remove rotate option
981 document.body[i] = rgx.sub('', document.body[i])
983 rgx = re.compile(r'rotate="[^"]+?"')
984 document.body[i] = rgx.sub('rotate="true"', document.body[i])
986 rgx = re.compile(r' rotate="[^"]+?"')
988 # remove rotate option
989 document.body[i] = rgx.sub('', document.body[i])
991 document.body[end_table + 3 : end_table + 3] = \
992 put_cmd_in_ert("\\end{turn}")
993 document.body[i - 2 : i - 2] = \
994 put_cmd_in_ert("\\begin{turn}{" + value + "}")
1000 add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"])
1003 def convert_table_rotation(document):
1004 'Convert table rotation statements from "true" to "90"'
1008 # first, let's find out if we need to do anything
1009 i = find_token(document.body, '<features ', i)
1012 j = document.body[i].find('rotate="true"')
1014 rgx = re.compile(r'rotate="[^"]+?"')
1015 # convert "true" to "90"
1016 document.body[i] = rgx.sub('rotate="90"', document.body[i])
1021 def convert_listoflistings(document):
1022 'Convert ERT \lstlistoflistings to TOC lstlistoflistings inset'
1023 # We can support roundtrip because the command is so simple
1026 i = find_token(document.body, "\\begin_inset ERT", i)
1029 j = find_end_of_inset(document.body, i)
1031 document.warning("Malformed LyX document: Can't find end of ERT inset")
1034 ert = get_ert(document.body, i)
1035 if ert == "\\lstlistoflistings{}":
1036 document.body[i:j] = ["\\begin_inset CommandInset toc", "LatexCommand lstlistoflistings", ""]
1042 def revert_listoflistings(document):
1043 'Convert TOC lstlistoflistings inset to ERT lstlistoflistings'
1046 i = find_token(document.body, "\\begin_inset CommandInset toc", i)
1049 if document.body[i+1] == "LatexCommand lstlistoflistings":
1050 j = find_end_of_inset(document.body, i)
1052 document.warning("Malformed LyX document: Can't find end of TOC inset")
1055 subst = put_cmd_in_ert("\\lstlistoflistings{}")
1056 document.body[i:j+1] = subst
1057 add_to_preamble(document, ["\\usepackage{listings}"])
1061 def convert_use_amssymb(document):
1062 "insert use_package amssymb"
1063 regexp = re.compile(r'(\\use_package\s+amsmath)')
1064 i = find_re(document.header, regexp, 0)
1066 document.warning("Malformed LyX document: Can't find \\use_package amsmath.")
1068 value = get_value(document.header, "\\use_package" , i).split()[1]
1071 useamsmath = int(value)
1073 document.warning("Invalid \\use_package amsmath: " + value + ". Assuming auto.")
1075 j = find_token(document.preamble, "\\usepackage{amssymb}", 0)
1077 document.header.insert(i + 1, "\\use_package amssymb %d" % useamsmath)
1079 document.header.insert(i + 1, "\\use_package amssymb 2")
1080 del document.preamble[j]
1083 def revert_use_amssymb(document):
1084 "remove use_package amssymb"
1085 regexp1 = re.compile(r'(\\use_package\s+amsmath)')
1086 regexp2 = re.compile(r'(\\use_package\s+amssymb)')
1087 i = find_re(document.header, regexp1, 0)
1088 j = find_re(document.header, regexp2, 0)
1089 value1 = "1" # default is auto
1090 value2 = "1" # default is auto
1092 value1 = get_value(document.header, "\\use_package" , i).split()[1]
1094 value2 = get_value(document.header, "\\use_package" , j).split()[1]
1095 del document.header[j]
1096 if value1 != value2 and value2 == "2": # on
1097 add_to_preamble(document, ["\\usepackage{amssymb}"])
1100 def convert_use_cancel(document):
1101 "insert use_package cancel"
1102 convert_use_package(document, "cancel", cancel_commands, True)
1105 def revert_use_cancel(document):
1106 "remove use_package cancel"
1107 revert_use_package(document, "cancel", cancel_commands, True)
1110 def revert_ancientgreek(document):
1111 "Set the document language for ancientgreek to greek"
1113 if document.language == "ancientgreek":
1114 document.language = "greek"
1115 i = find_token(document.header, "\\language", 0)
1117 document.header[i] = "\\language greek"
1120 j = find_token(document.body, "\\lang ancientgreek", j)
1124 document.body[j] = document.body[j].replace("\\lang ancientgreek", "\\lang greek")
1128 def revert_languages(document):
1129 "Set the document language for new supported languages to English"
1132 "coptic", "divehi", "hindi", "kurmanji", "lao", "marathi", "occitan", "sanskrit",
1133 "syriac", "tamil", "telugu", "urdu"
1135 for n in range(len(languages)):
1136 if document.language == languages[n]:
1137 document.language = "english"
1138 i = find_token(document.header, "\\language", 0)
1140 document.header[i] = "\\language english"
1142 while j < len(document.body):
1143 j = find_token(document.body, "\\lang " + languages[n], j)
1145 document.body[j] = document.body[j].replace("\\lang " + languages[n], "\\lang english")
1148 j = len(document.body)
1151 def convert_armenian(document):
1152 "Use polyglossia and thus non-TeX fonts for Armenian"
1154 if document.language == "armenian":
1155 i = find_token(document.header, "\\use_non_tex_fonts", 0)
1157 document.header[i] = "\\use_non_tex_fonts true"
1160 def revert_armenian(document):
1161 "Use ArmTeX and thus TeX fonts for Armenian"
1163 if document.language == "armenian":
1164 i = find_token(document.header, "\\use_non_tex_fonts", 0)
1166 document.header[i] = "\\use_non_tex_fonts false"
1169 def revert_libertine(document):
1170 " Revert native libertine font definition to LaTeX "
1172 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1173 i = find_token(document.header, "\\font_roman libertine", 0)
1176 j = find_token(document.header, "\\font_osf true", 0)
1179 preamble = "\\usepackage"
1181 document.header[j] = "\\font_osf false"
1184 preamble += "[lining]"
1185 preamble += "{libertine-type1}"
1186 add_to_preamble(document, [preamble])
1187 document.header[i] = "\\font_roman default"
1190 def revert_txtt(document):
1191 " Revert native txtt font definition to LaTeX "
1193 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1194 i = find_token(document.header, "\\font_typewriter txtt", 0)
1196 preamble = "\\renewcommand{\\ttdefault}{txtt}"
1197 add_to_preamble(document, [preamble])
1198 document.header[i] = "\\font_typewriter default"
1201 def revert_mathdesign(document):
1202 " Revert native mathdesign font definition to LaTeX "
1204 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1210 i = find_token(document.header, "\\font_roman", 0)
1213 val = get_value(document.header, "\\font_roman", i)
1214 if val in mathdesign_dict.keys():
1215 preamble = "\\usepackage[%s" % mathdesign_dict[val]
1217 j = find_token(document.header, "\\font_osf true", 0)
1220 document.header[j] = "\\font_osf false"
1221 l = find_token(document.header, "\\font_sc true", 0)
1224 document.header[l] = "\\font_sc false"
1226 preamble += ",expert"
1227 preamble += "]{mathdesign}"
1228 add_to_preamble(document, [preamble])
1229 document.header[i] = "\\font_roman default"
1232 def revert_texgyre(document):
1233 " Revert native TeXGyre font definition to LaTeX "
1235 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1236 texgyre_fonts = ["tgadventor", "tgbonum", "tgchorus", "tgcursor", \
1237 "tgheros", "tgpagella", "tgschola", "tgtermes"]
1238 i = find_token(document.header, "\\font_roman", 0)
1240 val = get_value(document.header, "\\font_roman", i)
1241 if val in texgyre_fonts:
1242 preamble = "\\usepackage{%s}" % val
1243 add_to_preamble(document, [preamble])
1244 document.header[i] = "\\font_roman default"
1245 i = find_token(document.header, "\\font_sans", 0)
1247 val = get_value(document.header, "\\font_sans", i)
1248 if val in texgyre_fonts:
1249 preamble = "\\usepackage{%s}" % val
1250 add_to_preamble(document, [preamble])
1251 document.header[i] = "\\font_sans default"
1252 i = find_token(document.header, "\\font_typewriter", 0)
1254 val = get_value(document.header, "\\font_typewriter", i)
1255 if val in texgyre_fonts:
1256 preamble = "\\usepackage{%s}" % val
1257 add_to_preamble(document, [preamble])
1258 document.header[i] = "\\font_typewriter default"
1261 def revert_ipadeco(document):
1262 " Revert IPA decorations to ERT "
1265 i = find_token(document.body, "\\begin_inset IPADeco", i)
1268 end = find_end_of_inset(document.body, i)
1270 document.warning("Can't find end of inset at line " + str(i))
1273 line = document.body[i]
1274 rx = re.compile(r'\\begin_inset IPADeco (.*)$')
1276 decotype = m.group(1)
1277 if decotype != "toptiebar" and decotype != "bottomtiebar":
1278 document.warning("Invalid IPADeco type: " + decotype)
1281 blay = find_token(document.body, "\\begin_layout Plain Layout", i, end)
1283 document.warning("Can't find layout for inset at line " + str(i))
1286 bend = find_end_of_layout(document.body, blay)
1288 document.warning("Malformed LyX document: Could not find end of IPADeco inset's layout.")
1291 substi = ["\\begin_inset ERT", "status collapsed", "",
1292 "\\begin_layout Plain Layout", "", "", "\\backslash",
1293 decotype + "{", "\\end_layout", "", "\\end_inset"]
1294 substj = ["\\size default", "", "\\begin_inset ERT", "status collapsed", "",
1295 "\\begin_layout Plain Layout", "", "}", "\\end_layout", "", "\\end_inset"]
1296 # do the later one first so as not to mess up the numbering
1297 document.body[bend:end + 1] = substj
1298 document.body[i:blay + 1] = substi
1299 i = end + len(substi) + len(substj) - (end - bend) - (blay - i) - 2
1300 add_to_preamble(document, "\\usepackage{tipa}")
1303 def revert_ipachar(document):
1304 ' Revert \\IPAChar to ERT '
1307 while i < len(document.body):
1308 m = re.match(r'(.*)\\IPAChar \\(\w+\{\w+\})(.*)', document.body[i])
1312 ipachar = m.group(2)
1315 '\\begin_inset ERT',
1316 'status collapsed', '',
1317 '\\begin_layout Standard',
1318 '', '', '\\backslash',
1323 document.body[i: i+1] = subst
1328 add_to_preamble(document, "\\usepackage{tone}")
1331 def revert_minionpro(document):
1332 " Revert native MinionPro font definition to LaTeX "
1334 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1335 i = find_token(document.header, "\\font_roman minionpro", 0)
1338 j = find_token(document.header, "\\font_osf true", 0)
1341 preamble = "\\usepackage"
1343 document.header[j] = "\\font_osf false"
1346 preamble += "{MinionPro}"
1347 add_to_preamble(document, [preamble])
1348 document.header[i] = "\\font_roman default"
1351 def revert_mathfonts(document):
1352 " Revert native math font definitions to LaTeX "
1354 i = find_token(document.header, "\\font_math", 0)
1357 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1358 val = get_value(document.header, "\\font_math", i)
1359 if val == "eulervm":
1360 add_to_preamble(document, "\\usepackage{eulervm}")
1361 elif val == "default":
1363 "lmodern": "\\renewcommand{\\rmdefault}{lmr}",
1364 "minionpro": "\\usepackage[onlytext,lf]{MinionPro}",
1365 "minionpro-osf": "\\usepackage[onlytext]{MinionPro}",
1366 "palatino": "\\renewcommand{\\rmdefault}{ppl}",
1367 "palatino-osf": "\\renewcommand{\\rmdefault}{pplj}",
1368 "times": "\\renewcommand{\\rmdefault}{ptm}",
1369 "utopia": "\\renewcommand{\\rmdefault}{futs}",
1370 "utopia-osf": "\\renewcommand{\\rmdefault}{futj}",
1372 j = find_token(document.header, "\\font_roman", 0)
1374 rm = get_value(document.header, "\\font_roman", j)
1375 k = find_token(document.header, "\\font_osf true", 0)
1378 if rm in mathfont_dict.keys():
1379 add_to_preamble(document, mathfont_dict[rm])
1380 document.header[j] = "\\font_roman default"
1382 document.header[k] = "\\font_osf false"
1383 del document.header[i]
1386 def revert_mdnomath(document):
1387 " Revert mathdesign and fourier without math "
1389 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1391 "md-charter": "mdbch",
1392 "md-utopia": "mdput",
1393 "md-garamond": "mdugm"
1395 i = find_token(document.header, "\\font_roman", 0)
1398 val = get_value(document.header, "\\font_roman", i)
1399 if val in mathdesign_dict.keys():
1400 j = find_token(document.header, "\\font_math", 0)
1402 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1403 mval = get_value(document.header, "\\font_math", j)
1404 if mval == "default":
1405 document.header[i] = "\\font_roman default"
1406 add_to_preamble(document, "\\renewcommand{\\rmdefault}{%s}" % mathdesign_dict[val])
1408 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1411 def convert_mdnomath(document):
1412 " Change mathdesign font name "
1414 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1416 "mdbch": "md-charter",
1417 "mdput": "md-utopia",
1418 "mdugm": "md-garamond"
1420 i = find_token(document.header, "\\font_roman", 0)
1423 val = get_value(document.header, "\\font_roman", i)
1424 if val in mathdesign_dict.keys():
1425 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1428 def revert_newtxmath(document):
1429 " Revert native newtxmath definitions to LaTeX "
1431 i = find_token(document.header, "\\font_math", 0)
1434 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1435 val = get_value(document.header, "\\font_math", i)
1437 "libertine-ntxm": "\\usepackage[libertine]{newtxmath}",
1438 "minion-ntxm": "\\usepackage[minion]{newtxmath}",
1439 "newtxmath": "\\usepackage{newtxmath}",
1441 if val in mathfont_dict.keys():
1442 add_to_preamble(document, mathfont_dict[val])
1443 document.header[i] = "\\font_math auto"
1446 def revert_biolinum(document):
1447 " Revert native biolinum font definition to LaTeX "
1449 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1450 i = find_token(document.header, "\\font_sans biolinum", 0)
1453 j = find_token(document.header, "\\font_osf true", 0)
1456 preamble = "\\usepackage"
1459 preamble += "{biolinum-type1}"
1460 add_to_preamble(document, [preamble])
1461 document.header[i] = "\\font_sans default"
1464 def revert_uop(document):
1465 " Revert native URW Classico (Optima) font definition to LaTeX "
1467 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1468 i = find_token(document.header, "\\font_sans uop", 0)
1470 preamble = "\\renewcommand{\\sfdefault}{uop}"
1471 add_to_preamble(document, [preamble])
1472 document.header[i] = "\\font_sans default"
1475 def convert_latexargs(document):
1476 " Convert InsetArgument to new syntax "
1478 if find_token(document.body, "\\begin_inset Argument", 0) == -1:
1482 # A list of layouts (document classes) with only optional or no arguments.
1483 # These can be safely converted to the new syntax
1484 # (I took the liberty to add some of my personal layouts/modules here; JSP)
1485 safe_layouts = ["aa", "aapaper", "aastex", "achemso", "acmsiggraph", "AEA",
1486 "agu-dtd", "agums", "agutex", "amsart", "amsbook", "apa",
1487 "arab-article", "armenian-article", "article-beamer", "article",
1488 "beamer", "book", "broadway", "chess", "cl2emult", "ctex-article",
1489 "ctex-book", "ctex-report", "dinbrief", "docbook-book", "docbook-chapter",
1490 "docbook", "docbook-section", "doublecol-new", "dtk", "ectaart", "egs",
1491 "elsarticle", "elsart", "entcs", "europecv", "extarticle", "extbook",
1492 "extletter", "extreport", "foils", "frletter", "g-brief2", "g-brief",
1493 "heb-article", "heb-letter", "hollywood", "IEEEtran", "ijmpc", "ijmpd",
1494 "iopart", "isprs", "jarticle", "jasatex", "jbook", "jgrga", "jreport",
1495 "jsarticle", "jsbeamer", "jsbook", "jss", "kluwer", "latex8", "letter", "lettre",
1496 "literate-article", "literate-book", "literate-report", "llncs", "ltugboat",
1497 "memoir", "moderncv", "mwart", "mwbk", "mwrep", "paper", "powerdot",
1498 "recipebook", "report", "revtex4", "revtex", "scrartcl", "scrarticle-beamer",
1499 "scrbook", "scrlettr", "scrlttr2", "scrreprt", "seminar", "siamltex",
1500 "sigplanconf", "simplecv", "singlecol", "singlecol-new", "slides", "spie",
1501 "svglobal3", "svglobal", "svjog", "svmono", "svmult", "svprobth", "tarticle",
1502 "tbook", "treport", "tufte-book", "tufte-handout"]
1503 # A list of "safe" modules, same as above
1504 safe_modules = ["biblatex", "beameraddons", "beamersession", "braille", "customHeadersFooters",
1505 "endnotes", "enumitem", "eqs-within-sections", "figs-within-sections", "fix-cm",
1506 "fixltx2e", "foottoend", "hanging", "jscharstyles", "knitr", "lilypond",
1507 "linguistics", "linguisticx", "logicalmkup", "minimalistic", "nomindex", "noweb",
1508 "pdfcomment", "sweave", "tabs-within-sections", "theorems-ams-bytype",
1509 "theorems-ams-extended-bytype", "theorems-ams-extended", "theorems-ams", "theorems-bytype",
1510 "theorems-chap-bytype", "theorems-chap", "theorems-named", "theorems-sec-bytype",
1511 "theorems-sec", "theorems-starred", "theorems-std", "todonotes"]
1512 # Modules we need to take care of
1513 caveat_modules = ["initials"]
1514 # information about the relevant styles in caveat_modules (number of opt and req args)
1515 # use this if we get more caveat_modules. For now, use hard coding (see below).
1516 # initials = [{'Layout' : 'Initial', 'opt' : 1, 'req' : 1}]
1518 # Is this a known safe layout?
1519 safe_layout = document.textclass in safe_layouts
1521 document.warning("Lyx2lyx knows nothing about textclass '%s'. "
1522 "Please check if short title insets have been converted correctly."
1523 % document.textclass)
1524 # Do we use unsafe or unknown modules
1525 mods = document.get_module_list()
1526 unknown_modules = False
1527 used_caveat_modules = list()
1529 if mod in safe_modules:
1531 if mod in caveat_modules:
1532 used_caveat_modules.append(mod)
1534 unknown_modules = True
1535 document.warning("Lyx2lyx knows nothing about module '%s'. "
1536 "Please check if short title insets have been converted correctly."
1541 i = find_token(document.body, "\\begin_inset Argument", i)
1545 if not safe_layout or unknown_modules:
1546 # We cannot do more here since we have no access to this layout.
1547 # InsetArgument itself will do the real work
1548 # (see InsetArgument::updateBuffer())
1549 document.body[i] = "\\begin_inset Argument 999"
1553 # Find containing paragraph layout
1554 parent = get_containing_layout(document.body, i)
1556 document.warning("Malformed LyX document: Can't find parent paragraph layout")
1563 if len(used_caveat_modules) > 0:
1564 # We know for now that this must be the initials module with the Initial layout
1565 # If we get more such modules, we need some automating.
1566 if parent[0] == "Initial":
1567 # Layout has 1 opt and 1 req arg.
1568 # Count the actual arguments
1570 for p in range(parbeg, parend):
1571 if document.body[p] == "\\begin_inset Argument":
1576 # Collect all arguments in this paragraph
1578 for p in range(parbeg, parend):
1579 if document.body[p] == "\\begin_inset Argument":
1581 if allowed_opts != -1:
1582 # We have less arguments than opt + required.
1583 # required must take precedence.
1584 if argnr > allowed_opts and argnr < first_req:
1586 document.body[p] = "\\begin_inset Argument %d" % argnr
1590 def revert_latexargs(document):
1591 " Revert InsetArgument to old syntax "
1594 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
1597 # Search for Argument insets
1598 i = find_token(document.body, "\\begin_inset Argument", i)
1601 m = rx.match(document.body[i])
1603 # No ID: inset already reverted
1606 # Find containing paragraph layout
1607 parent = get_containing_layout(document.body, i)
1609 document.warning("Malformed LyX document: Can't find parent paragraph layout")
1614 # Do not set realparbeg to parent[3], since this does not work if we
1615 # have another inset (e.g. label or index) before the first argument
1616 # inset (this is the case in the user guide of LyX 2.0.8)
1618 # Collect all arguments in this paragraph
1620 for p in range(parbeg, parend):
1621 m = rx.match(document.body[p])
1624 # This is the first argument inset
1626 val = int(m.group(1))
1627 j = find_end_of_inset(document.body, p)
1628 # Revert to old syntax
1629 document.body[p] = "\\begin_inset Argument"
1631 document.warning("Malformed LyX document: Can't find end of Argument inset")
1634 args[val] = document.body[p : j + 1]
1636 realparend = realparend - len(document.body[p : j + 1])
1637 # Remove arg inset at this position
1638 del document.body[p : j + 1]
1642 # No argument inset found
1643 realparbeg = parent[3]
1644 # Now sort the arg insets
1646 for f in sorted(args):
1649 # Insert the sorted arg insets at paragraph begin
1650 document.body[realparbeg : realparbeg] = subst
1652 i = realparbeg + 1 + len(subst)
1655 def revert_IEEEtran(document):
1657 Reverts InsetArgument of
1660 Biography without photo
1663 if document.textclass == "IEEEtran":
1670 i = find_token(document.body, "\\begin_layout Page headings", i)
1672 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1675 i2 = find_token(document.body, "\\begin_inset Flex Paragraph Start", i2)
1677 revert_Argument_to_TeX_brace(document, i2, 0, 1, 1, False, False)
1680 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1682 revert_Argument_to_TeX_brace(document, j, 0, 1, 1, True, False)
1685 k = find_token(document.body, "\\begin_layout Biography", k)
1686 kA = find_token(document.body, "\\begin_layout Biography without photo", k)
1687 if k == kA and k != -1:
1691 # start with the second argument, therefore 2
1692 revert_Argument_to_TeX_brace(document, k, 0, 2, 2, True, False)
1694 if i == -1 and i2 == -1 and j == -1 and k == -1:
1698 def revert_IEEEtran_2(document):
1700 Reverts Flex Paragraph Start to TeX-code
1702 if document.textclass == "IEEEtran":
1705 begin = find_token(document.body, "\\begin_inset Flex Paragraph Start", begin)
1708 end1 = find_end_of_inset(document.body, begin)
1709 document.body[end1 - 2 : end1 + 1] = put_cmd_in_ert("}")
1710 document.body[begin : begin + 4] = put_cmd_in_ert("\\IEEEPARstart{")
1714 def convert_IEEEtran(document):
1719 Biography without photo
1722 if document.textclass == "IEEEtran":
1728 i = find_token(document.body, "\\begin_layout Page headings", i)
1730 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1733 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1735 convert_TeX_brace_to_Argument(document, j, 1, 1, False, True, False)
1738 # assure that we don't handle Biography Biography without photo
1739 k = find_token(document.body, "\\begin_layout Biography", k)
1740 kA = find_token(document.body, "\\begin_layout Biography without photo", k - 1)
1741 if k == kA and k != -1:
1745 # the argument we want to convert is the second one
1746 convert_TeX_brace_to_Argument(document, k, 2, 2, False, True, False)
1748 if i == -1 and j == -1 and k == -1:
1752 def revert_AASTeX(document):
1753 " Reverts InsetArgument of Altaffilation to TeX-code "
1754 if document.textclass == "aastex":
1757 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1760 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1764 def convert_AASTeX(document):
1765 " Converts ERT of Altaffilation to InsetArgument "
1766 if document.textclass == "aastex":
1769 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1772 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1776 def revert_AGUTeX(document):
1777 " Reverts InsetArgument of Author affiliation to TeX-code "
1778 if document.textclass == "agutex":
1781 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1784 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1788 def convert_AGUTeX(document):
1789 " Converts ERT of Author affiliation to InsetArgument "
1790 if document.textclass == "agutex":
1793 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1796 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1800 def revert_IJMP(document):
1801 " Reverts InsetArgument of MarkBoth to TeX-code "
1802 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1805 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1808 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1812 def convert_IJMP(document):
1813 " Converts ERT of MarkBoth to InsetArgument "
1814 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1817 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1820 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1824 def revert_SIGPLAN(document):
1825 " Reverts InsetArguments of SIGPLAN to TeX-code "
1826 if document.textclass == "sigplanconf":
1831 i = find_token(document.body, "\\begin_layout Conference", i)
1833 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1836 j = find_token(document.body, "\\begin_layout Author", j)
1838 revert_Argument_to_TeX_brace(document, j, 0, 1, 2, False, False)
1840 if i == -1 and j == -1:
1844 def convert_SIGPLAN(document):
1845 " Converts ERT of SIGPLAN to InsetArgument "
1846 if document.textclass == "sigplanconf":
1851 i = find_token(document.body, "\\begin_layout Conference", i)
1853 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1856 j = find_token(document.body, "\\begin_layout Author", j)
1858 convert_TeX_brace_to_Argument(document, j, 1, 2, False, False, False)
1860 if i == -1 and j == -1:
1864 def revert_SIGGRAPH(document):
1865 " Reverts InsetArgument of Flex CRcat to TeX-code "
1866 if document.textclass == "acmsiggraph":
1869 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1872 revert_Argument_to_TeX_brace(document, i, 0, 1, 3, False, False)
1876 def convert_SIGGRAPH(document):
1877 " Converts ERT of Flex CRcat to InsetArgument "
1878 if document.textclass == "acmsiggraph":
1881 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1884 convert_TeX_brace_to_Argument(document, i, 1, 3, True, False, False)
1888 def revert_EuropeCV(document):
1889 " Reverts InsetArguments of europeCV to TeX-code "
1890 if document.textclass == "europecv":
1897 i = find_token(document.body, "\\begin_layout Item", i)
1899 revert_Argument_to_TeX_brace(document, i, 0, 2, 2, False, False)
1902 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1904 revert_Argument_to_TeX_brace(document, j, 0, 2, 2, False, False)
1907 k = find_token(document.body, "\\begin_layout Language", k)
1909 revert_Argument_to_TeX_brace(document, k, 0, 2, 6, False, False)
1912 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1914 revert_Argument_to_TeX_brace(document, m, 0, 2, 6, False, False)
1916 if i == -1 and j == -1 and k == -1 and m == -1:
1920 def convert_EuropeCV(document):
1921 " Converts ERT of europeCV to InsetArgument "
1922 if document.textclass == "europecv":
1929 i = find_token(document.body, "\\begin_layout Item", i)
1931 convert_TeX_brace_to_Argument(document, i, 2, 2, False, False, False)
1934 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1936 convert_TeX_brace_to_Argument(document, j, 2, 2, False, False, False)
1939 k = find_token(document.body, "\\begin_layout Language", k)
1941 convert_TeX_brace_to_Argument(document, k, 2, 6, False, False, False)
1944 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1946 convert_TeX_brace_to_Argument(document, m, 2, 6, False, False, False)
1948 if i == -1 and j == -1 and k == -1 and m == -1:
1952 def revert_ModernCV(document):
1953 " Reverts InsetArguments of modernCV to TeX-code "
1954 if document.textclass == "moderncv":
1962 j = find_token(document.body, "\\begin_layout Entry", j)
1964 revert_Argument_to_TeX_brace(document, j, 0, 1, 5, False, False)
1967 k = find_token(document.body, "\\begin_layout Item", k)
1969 revert_Argument_to_TeX_brace(document, k, 0, 1, 1, False, False)
1972 m = find_token(document.body, "\\begin_layout ItemWithComment", m)
1974 revert_Argument_to_TeX_brace(document, m, 0, 1, 2, False, False)
1975 document.body[m] = document.body[m].replace("\\begin_layout ItemWithComment", "\\begin_layout Language")
1978 o = find_token(document.body, "\\begin_layout DoubleItem", o)
1980 revert_Argument_to_TeX_brace(document, o, 0, 1, 3, False, False)
1981 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout Computer")
1984 p = find_token(document.body, "\\begin_layout Social", p)
1986 revert_Argument_to_TeX_brace(document, p, 0, 1, 1, False, True)
1988 if j == -1 and k == -1 and m == -1 and o == -1 and p == -1:
1992 def revert_ModernCV_2(document):
1993 " Reverts the Flex:Column inset of modernCV to TeX-code "
1994 if document.textclass == "moderncv":
1998 flex = find_token(document.body, "\\begin_inset Flex Column", flex)
2001 flexEnd = find_end_of_inset(document.body, flex)
2002 wasOpt = revert_Argument_to_TeX_brace(document, flex, flexEnd, 1, 1, False, True)
2003 revert_Argument_to_TeX_brace(document, flex, 0, 2, 2, False, False)
2004 flexEnd = find_end_of_inset(document.body, flex)
2006 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn")
2008 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn{")
2009 document.body[flexEnd + 4 : flexEnd + 7] = put_cmd_in_ert("}")
2013 def revert_ModernCV_3(document):
2014 " Reverts the Column style of modernCV to TeX-code "
2015 if document.textclass == "moderncv":
2016 # revert the layouts
2017 revert_ModernCV(document)
2019 # get the position of the end of the last column inset
2020 LastFlexEnd = revert_ModernCV_2(document)
2022 p = find_token(document.body, "\\begin_layout Columns", p)
2025 pEnd = find_end_of_layout(document.body, p)
2026 document.body[p] = document.body[p].replace("\\begin_layout Columns", "\\begin_layout Standard")
2027 if LastFlexEnd != -1:
2028 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\begin{cvcolumns}")
2029 document.body[LastFlexEnd + 24 : LastFlexEnd + 24] = put_cmd_in_ert("\\end{cvcolumns}")
2033 def revert_ModernCV_4(document):
2034 " Reverts the style Social to TeX-code "
2035 if document.textclass == "moderncv":
2036 # revert the layouts
2037 revert_ModernCV(document)
2040 p = find_token(document.body, "\\begin_layout Social", p)
2043 pEnd = find_end_of_layout(document.body, p)
2044 document.body[p] = document.body[p].replace("\\begin_layout Social", "\\begin_layout Standard")
2045 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\social")
2046 hasOpt = find_token(document.body, "[", p + 9)
2048 document.body[p + 30 : p + 30] = put_cmd_in_ert("{")
2049 document.body[p + 41 : p + 41] = put_cmd_in_ert("}")
2051 document.body[p + 11 : p + 11] = put_cmd_in_ert("{")
2052 document.body[p + 21 : p + 21] = put_cmd_in_ert("}")
2056 def convert_ModernCV(document):
2057 " Converts ERT of modernCV to InsetArgument "
2058 if document.textclass == "moderncv":
2066 i = find_token(document.body, "\\begin_layout DoubleItem", i)
2068 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
2069 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout DoubleListItem")
2072 j = find_token(document.body, "\\begin_layout Entry", j)
2074 convert_TeX_brace_to_Argument(document, j, 1, 5, False, False, False)
2077 k = find_token(document.body, "\\begin_layout Item", k)
2079 convert_TeX_brace_to_Argument(document, k, 1, 1, False, False, False)
2082 m = find_token(document.body, "\\begin_layout Language", m)
2084 convert_TeX_brace_to_Argument(document, m, 1, 2, False, False, False)
2086 if i == -1 and j == -1 and k == -1 and m == -1:
2090 def revert_Initials(document):
2091 " Reverts InsetArgument of Initial to TeX-code "
2094 i = find_token(document.body, "\\begin_layout Initial", i)
2097 # first arg (optional) and second arg (first mandatory) are supported in LyX 2.0.x
2098 revert_Argument_to_TeX_brace(document, i, 0, 3, 3, False, False)
2102 def convert_Initials(document):
2103 " Converts ERT of Initial to InsetArgument "
2106 i = find_token(document.body, "\\begin_layout Initial", i)
2109 convert_TeX_brace_to_Argument(document, i, 3, 3, False, False, False)
2113 def revert_literate(document):
2114 " Revert Literate document to old format "
2115 if del_token(document.header, "noweb", 0):
2116 document.textclass = "literate-" + document.textclass
2119 i = find_token(document.body, "\\begin_layout Chunk", i)
2122 document.body[i] = "\\begin_layout Scrap"
2126 def convert_literate(document):
2127 " Convert Literate document to new format"
2128 i = find_token(document.header, "\\textclass", 0)
2129 if (i != -1) and "literate-" in document.header[i]:
2130 document.textclass = document.header[i].replace("\\textclass literate-", "")
2131 j = find_token(document.header, "\\begin_modules", 0)
2133 document.header.insert(j + 1, "noweb")
2135 document.header.insert(i + 1, "\\end_modules")
2136 document.header.insert(i + 1, "noweb")
2137 document.header.insert(i + 1, "\\begin_modules")
2140 i = find_token(document.body, "\\begin_layout Scrap", i)
2143 document.body[i] = "\\begin_layout Chunk"
2147 def revert_itemargs(document):
2148 " Reverts \\item arguments to TeX-code "
2151 i = find_token(document.body, "\\begin_inset Argument item:", i)
2154 j = find_end_of_inset(document.body, i)
2155 # Find containing paragraph layout
2156 parent = get_containing_layout(document.body, i)
2158 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2162 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2163 endPlain = find_end_of_layout(document.body, beginPlain)
2164 content = document.body[beginPlain + 1 : endPlain]
2165 del document.body[i:j+1]
2166 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2167 document.body[parbeg : parbeg] = subst
2171 def revert_garamondx_newtxmath(document):
2172 " Revert native garamond newtxmath definition to LaTeX "
2174 i = find_token(document.header, "\\font_math", 0)
2177 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2178 val = get_value(document.header, "\\font_math", i)
2179 if val == "garamondx-ntxm":
2180 add_to_preamble(document, "\\usepackage[garamondx]{newtxmath}")
2181 document.header[i] = "\\font_math auto"
2184 def revert_garamondx(document):
2185 " Revert native garamond font definition to LaTeX "
2187 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2188 i = find_token(document.header, "\\font_roman garamondx", 0)
2191 j = find_token(document.header, "\\font_osf true", 0)
2194 preamble = "\\usepackage"
2196 preamble += "[osfI]"
2197 preamble += "{garamondx}"
2198 add_to_preamble(document, [preamble])
2199 document.header[i] = "\\font_roman default"
2202 def convert_beamerargs(document):
2203 " Converts beamer arguments to new layout "
2205 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2206 if document.textclass not in beamer_classes:
2209 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2210 list_layouts = ["Itemize", "Enumerate", "Description"]
2211 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
2215 i = find_token(document.body, "\\begin_inset Argument", i)
2218 # Find containing paragraph layout
2219 parent = get_containing_layout(document.body, i)
2221 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2226 layoutname = parent[0]
2227 for p in range(parbeg, parend):
2228 if layoutname in shifted_layouts:
2229 m = rx.match(document.body[p])
2231 argnr = int(m.group(1))
2233 document.body[p] = "\\begin_inset Argument %d" % argnr
2234 if layoutname == "AgainFrame":
2235 m = rx.match(document.body[p])
2237 document.body[p] = "\\begin_inset Argument 3"
2238 if document.body[p + 4] == "\\begin_inset ERT":
2239 if document.body[p + 9].startswith("<"):
2240 # This is an overlay specification
2242 document.body[p + 9] = document.body[p + 9][1:]
2243 if document.body[p + 9].endswith(">"):
2245 document.body[p + 9] = document.body[p + 9][:-1]
2247 document.body[p] = "\\begin_inset Argument 2"
2248 if layoutname in list_layouts:
2249 m = rx.match(document.body[p])
2251 if m.group(1) == "1":
2252 if document.body[p + 4] == "\\begin_inset ERT":
2253 if document.body[p + 9].startswith("<"):
2254 # This is an overlay specification
2256 document.body[p + 9] = document.body[p + 9][1:]
2257 if document.body[p + 9].endswith(">"):
2259 document.body[p + 9] = document.body[p + 9][:-1]
2260 elif document.body[p + 4].startswith("<"):
2261 # This is an overlay specification (without ERT)
2263 document.body[p + 4] = document.body[p + 4][1:]
2264 if document.body[p + 4].endswith(">"):
2266 document.body[p + 4] = document.body[p + 4][:-1]
2267 elif layoutname != "Itemize":
2269 document.body[p] = "\\begin_inset Argument 2"
2274 # Helper function for the frame conversion routines
2276 # FIXME: This method currently requires the arguments to be either
2277 # * In one (whole) ERT each: <ERT>[<arg1>]</ERT><ERT><arg2></ERT><ERT>[arg3]</ERT>
2278 # * Altogether in one whole ERT: <ERT>[<arg1>]<arg2>[arg3]</ERT>
2279 # If individual arguments mix ERT and non-ERT or are splitted
2280 # over several ERTs, the parsing fails.
2281 def convert_beamerframeargs(document, i, parbeg):
2284 if document.body[parbeg] != "\\begin_inset ERT":
2286 ertend = find_end_of_inset(document.body, parbeg)
2288 document.warning("Malformed LyX document: missing ERT \\end_inset")
2290 ertcont = parbeg + 5
2291 if document.body[ertcont].startswith("[<"):
2292 # This is a default overlay specification
2294 document.body[ertcont] = document.body[ertcont][2:]
2295 if document.body[ertcont].endswith(">]"):
2297 document.body[ertcont] = document.body[ertcont][:-2]
2298 elif document.body[ertcont].endswith("]"):
2300 tok = document.body[ertcont].find('>][')
2302 subst = [document.body[ertcont][:tok],
2303 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2304 'status collapsed', '', '\\begin_layout Plain Layout',
2305 document.body[ertcont][tok + 3:-1]]
2306 document.body[ertcont : ertcont + 1] = subst
2308 # Convert to ArgInset
2309 document.body[parbeg] = "\\begin_inset Argument 2"
2310 elif document.body[ertcont].startswith("<"):
2311 # This is an overlay specification
2313 document.body[ertcont] = document.body[ertcont][1:]
2314 if document.body[ertcont].endswith(">"):
2316 document.body[ertcont] = document.body[ertcont][:-1]
2317 # Convert to ArgInset
2318 document.body[parbeg] = "\\begin_inset Argument 1"
2319 elif document.body[ertcont].endswith(">]"):
2321 tok = document.body[ertcont].find('>[<')
2323 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2324 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2325 'status collapsed', '', '\\begin_layout Plain Layout',
2326 document.body[ertcont][tok + 3:-2]]
2327 # Convert to ArgInset
2328 document.body[parbeg] = "\\begin_inset Argument 1"
2330 elif document.body[ertcont].endswith("]"):
2332 tok = document.body[ertcont].find('>[<')
2335 tokk = document.body[ertcont].find('>][')
2337 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2338 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2339 'status collapsed', '', '\\begin_layout Plain Layout',
2340 document.body[ertcont][tok + 3:tokk],
2341 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2342 'status collapsed', '', '\\begin_layout Plain Layout',
2343 document.body[ertcont][tokk + 3:-1]]
2346 tokk = document.body[ertcont].find('>[')
2348 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tokk],
2349 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2350 'status collapsed', '', '\\begin_layout Plain Layout',
2351 document.body[ertcont][tokk + 2:-1]]
2353 # Convert to ArgInset
2354 document.body[parbeg] = "\\begin_inset Argument 1"
2355 elif document.body[ertcont].startswith("["):
2356 # This is an ERT option
2358 document.body[ertcont] = document.body[ertcont][1:]
2359 if document.body[ertcont].endswith("]"):
2361 document.body[ertcont] = document.body[ertcont][:-1]
2362 # Convert to ArgInset
2363 document.body[parbeg] = "\\begin_inset Argument 3"
2369 def convert_againframe_args(document):
2370 " Converts beamer AgainFrame to new layout "
2372 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2373 if document.textclass not in beamer_classes:
2378 i = find_token(document.body, "\\begin_layout AgainFrame", i)
2381 parent = get_containing_layout(document.body, i)
2383 document.warning("Wrong parent layout!")
2387 # Convert ERT arguments
2388 # FIXME: See restrictions in convert_beamerframeargs method
2389 ertend = convert_beamerframeargs(document, i, parbeg)
2395 def convert_corollary_args(document):
2396 " Converts beamer corrolary-style ERT arguments native InsetArgs "
2398 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2399 if document.textclass not in beamer_classes:
2402 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2403 for lay in corollary_layouts:
2406 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2409 parent = get_containing_layout(document.body, i)
2411 document.warning("Wrong parent layout!")
2415 if document.body[parbeg] == "\\begin_inset ERT":
2416 ertcont = parbeg + 5
2417 if document.body[ertcont].startswith("<"):
2418 # This is an overlay specification
2420 document.body[ertcont] = document.body[ertcont][1:]
2421 if document.body[ertcont].endswith(">"):
2423 document.body[ertcont] = document.body[ertcont][:-1]
2424 elif document.body[ertcont].endswith("]"):
2426 tok = document.body[ertcont].find('>[')
2428 subst = [document.body[ertcont][:tok],
2429 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2430 'status collapsed', '', '\\begin_layout Plain Layout',
2431 document.body[ertcont][tok + 2:-1]]
2432 document.body[ertcont : ertcont + 1] = subst
2433 # Convert to ArgInset
2434 document.body[parbeg] = "\\begin_inset Argument 1"
2437 elif document.body[ertcont].startswith("["):
2438 if document.body[ertcont].endswith("]"):
2439 # This is an ERT option
2441 document.body[ertcont] = document.body[ertcont][1:]
2443 document.body[ertcont] = document.body[ertcont][:-1]
2444 # Convert to ArgInset
2445 document.body[parbeg] = "\\begin_inset Argument 2"
2447 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, True)
2454 def convert_quote_args(document):
2455 " Converts beamer quote style ERT args to native InsetArgs "
2457 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2458 if document.textclass not in beamer_classes:
2461 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2462 for lay in quote_layouts:
2465 i = find_token(document.body, "\\begin_layout " + lay, i)
2468 parent = get_containing_layout(document.body, i)
2470 document.warning("Wrong parent layout!")
2474 if document.body[parbeg] == "\\begin_inset ERT":
2475 if document.body[i + 6].startswith("<"):
2476 # This is an overlay specification
2478 document.body[i + 6] = document.body[i + 6][1:]
2479 if document.body[i + 6].endswith(">"):
2481 document.body[i + 6] = document.body[i + 6][:-1]
2482 # Convert to ArgInset
2483 document.body[i + 1] = "\\begin_inset Argument 1"
2487 def revert_beamerargs(document):
2488 " Reverts beamer arguments to old layout "
2490 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2491 if document.textclass not in beamer_classes:
2495 list_layouts = ["Itemize", "Enumerate", "Description"]
2496 headings = ["Part", "Section", "Section*", "Subsection", "Subsection*",
2497 "Subsubsection", "Subsubsection*", "FrameSubtitle", "NoteItem"]
2498 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2499 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2500 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2503 i = find_token(document.body, "\\begin_inset Argument", i)
2506 # Find containing paragraph layout
2507 parent = get_containing_layout(document.body, i)
2509 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2514 realparbeg = parent[3]
2515 layoutname = parent[0]
2517 for p in range(parbeg, parend):
2521 if layoutname in headings:
2522 m = rx.match(document.body[p])
2526 # Find containing paragraph layout
2527 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2528 endPlain = find_end_of_layout(document.body, beginPlain)
2529 endInset = find_end_of_inset(document.body, p)
2530 argcontent = document.body[beginPlain + 1 : endPlain]
2532 realparend = realparend - len(document.body[p : endInset + 1])
2534 del document.body[p : endInset + 1]
2535 if layoutname == "FrameSubtitle":
2536 pre = put_cmd_in_ert("\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2537 elif layoutname == "NoteItem":
2538 pre = put_cmd_in_ert("\\note<") + argcontent + put_cmd_in_ert(">[item]")
2539 elif layoutname.endswith('*'):
2540 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower()[:-1] + "<") + argcontent + put_cmd_in_ert(">*")
2542 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2543 secarg = find_token(document.body, "\\begin_inset Argument 2", parbeg, parend)
2545 # Find containing paragraph layout
2546 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", secarg)
2547 endPlain = find_end_of_layout(document.body, beginPlain)
2548 endInset = find_end_of_inset(document.body, secarg)
2549 argcontent = document.body[beginPlain + 1 : endPlain]
2551 realparend = realparend - len(document.body[secarg : endInset + 1])
2552 del document.body[secarg : endInset + 1]
2553 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2554 pre += put_cmd_in_ert("{")
2555 document.body[parbeg] = "\\begin_layout Standard"
2556 document.body[realparbeg : realparbeg] = pre
2557 pe = find_end_of_layout(document.body, parbeg)
2558 post = put_cmd_in_ert("}")
2559 document.body[pe : pe] = post
2560 realparend += len(pre) + len(post)
2561 if layoutname == "AgainFrame":
2562 m = rx.match(document.body[p])
2566 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2567 endPlain = find_end_of_layout(document.body, beginPlain)
2568 endInset = find_end_of_inset(document.body, p)
2569 content = document.body[beginPlain + 1 : endPlain]
2571 realparend = realparend - len(document.body[p : endInset + 1])
2573 del document.body[p : endInset + 1]
2574 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2575 document.body[realparbeg : realparbeg] = subst
2576 if layoutname == "Overprint":
2577 m = rx.match(document.body[p])
2581 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2582 endPlain = find_end_of_layout(document.body, beginPlain)
2583 endInset = find_end_of_inset(document.body, p)
2584 content = document.body[beginPlain + 1 : endPlain]
2586 realparend = realparend - len(document.body[p : endInset + 1])
2588 del document.body[p : endInset + 1]
2589 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2590 document.body[realparbeg : realparbeg] = subst
2591 if layoutname == "OverlayArea":
2592 m = rx.match(document.body[p])
2596 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2597 endPlain = find_end_of_layout(document.body, beginPlain)
2598 endInset = find_end_of_inset(document.body, p)
2599 content = document.body[beginPlain + 1 : endPlain]
2601 realparend = realparend - len(document.body[p : endInset + 1])
2603 del document.body[p : endInset + 1]
2604 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2605 document.body[realparbeg : realparbeg] = subst
2606 if layoutname in list_layouts:
2607 m = rx.match(document.body[p])
2611 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2612 endPlain = find_end_of_layout(document.body, beginPlain)
2613 endInset = find_end_of_inset(document.body, p)
2614 content = document.body[beginPlain + 1 : endPlain]
2615 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2616 realparend = realparend + len(subst) - len(content)
2617 document.body[beginPlain + 1 : endPlain] = subst
2618 elif argnr == "item:1":
2619 j = find_end_of_inset(document.body, i)
2620 # Find containing paragraph layout
2621 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2622 endPlain = find_end_of_layout(document.body, beginPlain)
2623 content = document.body[beginPlain + 1 : endPlain]
2624 del document.body[i:j+1]
2625 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2626 document.body[realparbeg : realparbeg] = subst
2627 elif argnr == "item:2":
2628 j = find_end_of_inset(document.body, i)
2629 # Find containing paragraph layout
2630 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2631 endPlain = find_end_of_layout(document.body, beginPlain)
2632 content = document.body[beginPlain + 1 : endPlain]
2633 del document.body[i:j+1]
2634 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2635 document.body[realparbeg : realparbeg] = subst
2636 if layoutname in quote_layouts:
2637 m = rx.match(document.body[p])
2641 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2642 endPlain = find_end_of_layout(document.body, beginPlain)
2643 endInset = find_end_of_inset(document.body, p)
2644 content = document.body[beginPlain + 1 : endPlain]
2646 realparend = realparend - len(document.body[p : endInset + 1])
2648 del document.body[p : endInset + 1]
2649 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2650 document.body[realparbeg : realparbeg] = subst
2651 if layoutname in corollary_layouts:
2652 m = rx.match(document.body[p])
2656 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2657 endPlain = find_end_of_layout(document.body, beginPlain)
2658 endInset = find_end_of_inset(document.body, p)
2659 content = document.body[beginPlain + 1 : endPlain]
2661 realparend = realparend - len(document.body[p : endInset + 1])
2663 del document.body[p : endInset + 1]
2664 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2665 document.body[realparbeg : realparbeg] = subst
2670 def revert_beamerargs2(document):
2671 " Reverts beamer arguments to old layout, step 2 "
2673 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2674 if document.textclass not in beamer_classes:
2678 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2679 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2680 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2683 i = find_token(document.body, "\\begin_inset Argument", i)
2686 # Find containing paragraph layout
2687 parent = get_containing_layout(document.body, i)
2689 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2694 realparbeg = parent[3]
2695 layoutname = parent[0]
2697 for p in range(parbeg, parend):
2701 if layoutname in shifted_layouts:
2702 m = rx.match(document.body[p])
2706 document.body[p] = "\\begin_inset Argument 1"
2707 if layoutname in corollary_layouts:
2708 m = rx.match(document.body[p])
2712 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2713 endPlain = find_end_of_layout(document.body, beginPlain)
2714 endInset = find_end_of_inset(document.body, p)
2715 content = document.body[beginPlain + 1 : endPlain]
2717 realparend = realparend - len(document.body[p : endInset + 1])
2719 del document.body[p : endInset + 1]
2720 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2721 document.body[realparbeg : realparbeg] = subst
2722 if layoutname == "OverlayArea":
2723 m = rx.match(document.body[p])
2727 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2728 endPlain = find_end_of_layout(document.body, beginPlain)
2729 endInset = find_end_of_inset(document.body, p)
2730 content = document.body[beginPlain + 1 : endPlain]
2732 realparend = realparend - len(document.body[p : endInset + 1])
2734 del document.body[p : endInset + 1]
2735 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2736 document.body[realparbeg : realparbeg] = subst
2737 if layoutname == "AgainFrame":
2738 m = rx.match(document.body[p])
2742 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2743 endPlain = find_end_of_layout(document.body, beginPlain)
2744 endInset = find_end_of_inset(document.body, p)
2745 content = document.body[beginPlain + 1 : endPlain]
2747 realparend = realparend - len(document.body[p : endInset + 1])
2749 del document.body[p : endInset + 1]
2750 subst = put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
2751 document.body[realparbeg : realparbeg] = subst
2755 def revert_beamerargs3(document):
2756 " Reverts beamer arguments to old layout, step 3 "
2758 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2759 if document.textclass not in beamer_classes:
2762 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2765 i = find_token(document.body, "\\begin_inset Argument", i)
2768 # Find containing paragraph layout
2769 parent = get_containing_layout(document.body, i)
2771 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2776 realparbeg = parent[3]
2777 layoutname = parent[0]
2779 for p in range(parbeg, parend):
2783 if layoutname == "AgainFrame":
2784 m = rx.match(document.body[p])
2788 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2789 endPlain = find_end_of_layout(document.body, beginPlain)
2790 endInset = find_end_of_inset(document.body, p)
2791 content = document.body[beginPlain + 1 : endPlain]
2793 realparend = realparend - len(document.body[p : endInset + 1])
2795 del document.body[p : endInset + 1]
2796 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2797 document.body[realparbeg : realparbeg] = subst
2801 def revert_beamerflex(document):
2802 " Reverts beamer Flex insets "
2804 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2805 if document.textclass not in beamer_classes:
2808 new_flexes = {"Bold" : "\\textbf", "Emphasize" : "\\emph", "Only" : "\\only",
2809 "Uncover" : "\\uncover", "Visible" : "\\visible",
2810 "Invisible" : "\\invisible", "Alternative" : "\\alt",
2811 "Beamer_Note" : "\\note"}
2812 old_flexes = {"Alert" : "\\alert", "Structure" : "\\structure"}
2813 rx = re.compile(r'^\\begin_inset Flex (.+)$')
2817 i = find_token(document.body, "\\begin_inset Flex", i)
2820 m = rx.match(document.body[i])
2822 flextype = m.group(1)
2823 z = find_end_of_inset(document.body, i)
2825 document.warning("Can't find end of Flex " + flextype + " inset.")
2828 if flextype in new_flexes:
2829 pre = put_cmd_in_ert(new_flexes[flextype])
2830 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2832 argend = find_end_of_inset(document.body, arg)
2834 document.warning("Can't find end of Argument!")
2837 # Find containing paragraph layout
2838 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2839 endPlain = find_end_of_layout(document.body, beginPlain)
2840 argcontent = document.body[beginPlain + 1 : endPlain]
2842 z = z - len(document.body[arg : argend + 1])
2844 del document.body[arg : argend + 1]
2845 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2846 arg = find_token(document.body, "\\begin_inset Argument 2", i, z)
2848 argend = find_end_of_inset(document.body, arg)
2850 document.warning("Can't find end of Argument!")
2853 # Find containing paragraph layout
2854 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2855 endPlain = find_end_of_layout(document.body, beginPlain)
2856 argcontent = document.body[beginPlain + 1 : endPlain]
2858 z = z - len(document.body[arg : argend + 1])
2860 del document.body[arg : argend + 1]
2861 if flextype == "Alternative":
2862 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
2864 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2865 pre += put_cmd_in_ert("{")
2866 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2867 endPlain = find_end_of_layout(document.body, beginPlain)
2869 z = z - len(document.body[i : beginPlain + 1])
2871 document.body[i : beginPlain + 1] = pre
2872 post = put_cmd_in_ert("}")
2873 document.body[z - 2 : z + 1] = post
2874 elif flextype in old_flexes:
2875 pre = put_cmd_in_ert(old_flexes[flextype])
2876 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2880 argend = find_end_of_inset(document.body, arg)
2882 document.warning("Can't find end of Argument!")
2885 # Find containing paragraph layout
2886 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2887 endPlain = find_end_of_layout(document.body, beginPlain)
2888 argcontent = document.body[beginPlain + 1 : endPlain]
2890 z = z - len(document.body[arg : argend + 1])
2892 del document.body[arg : argend + 1]
2893 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2894 pre += put_cmd_in_ert("{")
2895 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2896 endPlain = find_end_of_layout(document.body, beginPlain)
2898 z = z - len(document.body[i : beginPlain + 1])
2900 document.body[i : beginPlain + 1] = pre
2901 post = put_cmd_in_ert("}")
2902 document.body[z - 2 : z + 1] = post
2907 def revert_beamerblocks(document):
2908 " Reverts beamer block arguments to ERT "
2910 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2911 if document.textclass not in beamer_classes:
2914 blocks = ["Block", "ExampleBlock", "AlertBlock"]
2916 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2919 i = find_token(document.body, "\\begin_inset Argument", i)
2922 # Find containing paragraph layout
2923 parent = get_containing_layout(document.body, i)
2925 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2930 realparbeg = parent[3]
2931 layoutname = parent[0]
2933 for p in range(parbeg, parend):
2937 if layoutname in blocks:
2938 m = rx.match(document.body[p])
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
2953 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2954 endPlain = find_end_of_layout(document.body, beginPlain)
2955 endInset = find_end_of_inset(document.body, p)
2956 content = document.body[beginPlain + 1 : endPlain]
2958 realparend = realparend - len(document.body[p : endInset + 1])
2960 del document.body[p : endInset + 1]
2961 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2962 document.body[realparbeg : realparbeg] = subst
2967 def convert_beamerblocks(document):
2968 " Converts beamer block ERT args to native InsetArgs "
2970 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2971 if document.textclass not in beamer_classes:
2974 blocks = ["Block", "ExampleBlock", "AlertBlock"]
2978 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2981 parent = get_containing_layout(document.body, i)
2982 if parent == False or parent[1] != i:
2983 document.warning("Wrong parent layout!")
2990 if document.body[parbeg] == "\\begin_inset ERT":
2991 ertcontfirstline = parbeg + 5
2992 # Find the last ERT in this paragraph (which might also be the first)
2993 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
2994 if lastertbeg == -1:
2995 document.warning("Last ERT not found!")
2997 lastertend = find_end_of_inset(document.body, lastertbeg)
2998 if lastertend == -1:
2999 document.warning("End of last ERT not found!")
3001 ertcontlastline = lastertend - 3
3003 if document.body[ertcontfirstline].lstrip().startswith("<"):
3004 # This is an overlay specification
3006 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3007 if document.body[ertcontlastline].rstrip().endswith(">"):
3009 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3010 # Convert to ArgInset
3011 document.body[parbeg] = "\\begin_inset Argument 1"
3012 elif document.body[ertcontlastline].rstrip().endswith("}"):
3014 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3016 ertcontdivline = ertcontfirstline
3017 tok = document.body[ertcontdivline].find('>{')
3019 regexp = re.compile(r'.*>\{', re.IGNORECASE)
3020 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, ertcontlastline)
3021 tok = document.body[ertcontdivline].find('>{')
3023 if ertcontfirstline < ertcontlastline:
3024 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3025 document.body[ertcontlastline : ertcontlastline + 1] = [
3026 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3027 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3028 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3029 'status collapsed', '', '\\begin_layout Plain Layout',
3030 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3031 document.body[ertcontdivline][tok + 2:]]
3033 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3034 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3035 'status collapsed', '', '\\begin_layout Plain Layout',
3036 document.body[ertcontdivline][tok + 2:]]
3037 # Convert to ArgInset
3038 document.body[parbeg] = "\\begin_inset Argument 1"
3039 elif document.body[ertcontfirstline].lstrip().startswith("{"):
3040 # This is the block title
3041 if document.body[ertcontlastline].rstrip().endswith("}"):
3042 # strip off the braces
3043 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3044 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3045 if ertcontfirstline < ertcontlastline:
3046 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3047 document.body[parend : parend + 1] = [
3048 document.body[parend], '\\end_layout', '', '\\end_inset']
3049 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3050 'status collapsed', '', '\\begin_layout Plain Layout',
3051 '\\begin_inset ERT', '']
3053 # Convert to ArgInset
3054 document.body[parbeg] = "\\begin_inset Argument 2"
3055 elif count_pars_in_inset(document.body, ertcontfirstline) > 1:
3056 # Multipar ERT. Skip this.
3059 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, False)
3062 j = find_end_of_layout(document.body, i)
3064 document.warning("end of layout not found!")
3065 k = find_token(document.body, "\\begin_inset Argument", i, j)
3067 document.warning("InsetArgument not found!")
3069 l = find_end_of_inset(document.body, k)
3070 m = find_token(document.body, "\\begin_inset ERT", l, j)
3073 ertcontfirstline = m + 5
3078 def convert_overprint(document):
3079 " Convert old beamer overprint layouts to ERT "
3081 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3082 if document.textclass not in beamer_classes:
3087 i = find_token(document.body, "\\begin_layout Overprint", i)
3090 # Find end of sequence
3091 j = find_end_of_sequence(document.body, i)
3093 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3097 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3099 if document.body[j] == "\\end_deeper":
3100 esubst = ["", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3102 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3103 endseq = endseq + len(esubst) - len(document.body[j : j])
3104 document.body[j : j] = esubst
3105 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3107 argend = find_end_of_layout(document.body, argbeg)
3109 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3112 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3113 endPlain = find_end_of_layout(document.body, beginPlain)
3114 content = document.body[beginPlain + 1 : endPlain]
3116 endseq = endseq - len(document.body[argbeg : argend + 1])
3118 del document.body[argbeg : argend + 1]
3119 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3121 endseq = endseq - len(document.body[i : i])
3122 document.body[i : i] = subst + ["\\end_layout"]
3123 endseq += len(subst)
3125 for p in range(i, endseq):
3126 if document.body[p] == "\\begin_layout Overprint":
3127 document.body[p] = "\\begin_layout Standard"
3132 def revert_overprint(document):
3133 " Revert old beamer overprint layouts to ERT "
3135 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3136 if document.textclass not in beamer_classes:
3141 i = find_token(document.body, "\\begin_layout Overprint", i)
3144 # Find end of sequence
3145 j = find_end_of_sequence(document.body, i)
3147 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3151 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3152 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}")
3153 endseq = endseq + len(esubst) - len(document.body[j : j])
3154 if document.body[j] == "\\end_deeper":
3155 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3157 document.body[j : j] = ["\\end_layout", ""] + esubst
3160 if document.body[r] == "\\begin_deeper":
3161 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3163 document.body[r] = ""
3164 document.body[s] = ""
3168 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3170 # Is this really our argument?
3171 nested = find_token(document.body, "\\begin_deeper", i, argbeg)
3173 argend = find_end_of_inset(document.body, argbeg)
3175 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3178 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3179 endPlain = find_end_of_layout(document.body, beginPlain)
3180 content = document.body[beginPlain + 1 : endPlain]
3182 endseq = endseq - len(document.body[argbeg : argend])
3184 del document.body[argbeg : argend + 1]
3185 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3187 endseq = endseq - len(document.body[i : i])
3188 document.body[i : i] = subst + ["\\end_layout"]
3189 endseq += len(subst)
3195 if document.body[p] == "\\begin_layout Overprint":
3196 q = find_end_of_layout(document.body, p)
3198 document.warning("Malformed LyX document. Cannot find end of Overprint layout!")
3201 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\onslide")
3202 argbeg = find_token(document.body, "\\begin_inset Argument item:1", p, q)
3204 argend = find_end_of_inset(document.body, argbeg)
3206 document.warning("Malformed LyX document. Cannot find end of Overprint item argument!")
3209 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3210 endPlain = find_end_of_layout(document.body, beginPlain)
3211 content = document.body[beginPlain + 1 : endPlain]
3213 endseq = endseq - len(document.body[argbeg : argend + 1])
3215 del document.body[argbeg : argend + 1]
3216 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3217 endseq = endseq - len(document.body[p : p + 1]) + len(subst)
3218 document.body[p : p + 1] = subst
3224 def revert_frametitle(document):
3225 " Reverts beamer frametitle layout to ERT "
3227 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3228 if document.textclass not in beamer_classes:
3231 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3234 i = find_token(document.body, "\\begin_layout FrameTitle", i)
3237 j = find_end_of_layout(document.body, i)
3239 document.warning("Malformed LyX document: Can't find end of FrameTitle layout")
3243 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
3244 endlay += len(put_cmd_in_ert("}"))
3245 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\frametitle")
3246 for p in range(i, j):
3249 m = rx.match(document.body[p])
3253 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3254 endPlain = find_end_of_layout(document.body, beginPlain)
3255 endInset = find_end_of_inset(document.body, p)
3256 content = document.body[beginPlain + 1 : endPlain]
3258 endlay = endlay - len(document.body[p : endInset + 1])
3260 del document.body[p : endInset + 1]
3261 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3263 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3264 endPlain = find_end_of_layout(document.body, beginPlain)
3265 endInset = find_end_of_inset(document.body, p)
3266 content = document.body[beginPlain + 1 : endPlain]
3268 endlay = endlay - len(document.body[p : endInset + 1])
3270 del document.body[p : endInset + 1]
3271 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3273 subst += put_cmd_in_ert("{")
3274 document.body[i : i + 1] = subst
3278 def convert_epigraph(document):
3279 " Converts memoir epigraph to new syntax "
3281 if document.textclass != "memoir":
3286 i = find_token(document.body, "\\begin_layout Epigraph", i)
3289 j = find_end_of_layout(document.body, i)
3291 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3296 ert = find_token(document.body, "\\begin_inset ERT", i, j)
3298 endInset = find_end_of_inset(document.body, ert)
3299 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", ert)
3300 endPlain = find_end_of_layout(document.body, beginPlain)
3301 ertcont = beginPlain + 2
3302 if document.body[ertcont] == "}{":
3304 # Convert to ArgInset
3305 endlay = endlay - 2 * len(document.body[j])
3306 begsubst = ['\\begin_inset Argument post:1', 'status collapsed', '',
3307 '\\begin_layout Plain Layout']
3308 endsubst = ['\\end_layout', '', '\\end_inset', '', document.body[j]]
3309 document.body[j : j + 1] = endsubst
3310 document.body[endInset + 1 : endInset + 1] = begsubst
3312 endlay += len(begsubst) + len(endsubst)
3313 endlay = endlay - len(document.body[ert : endInset + 1])
3314 del document.body[ert : endInset + 1]
3319 def revert_epigraph(document):
3320 " Reverts memoir epigraph argument to ERT "
3322 if document.textclass != "memoir":
3327 i = find_token(document.body, "\\begin_layout Epigraph", i)
3330 j = find_end_of_layout(document.body, i)
3332 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3337 p = find_token(document.body, "\\begin_layout Argument post:1", i, j)
3339 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3340 endPlain = find_end_of_layout(document.body, beginPlain)
3341 endInset = find_end_of_inset(document.body, p)
3342 content = document.body[beginPlain + 1 : endPlain]
3344 endlay = endlay - len(document.body[p : endInset + 1])
3346 del document.body[p : endInset + 1]
3347 subst += put_cmd_in_ert("}{") + content
3349 subst += put_cmd_in_ert("}{")
3351 document.body[j : j] = subst + document.body[j : j]
3355 def convert_captioninsets(document):
3356 " Converts caption insets to new syntax "
3360 i = find_token(document.body, "\\begin_inset Caption", i)
3363 document.body[i] = "\\begin_inset Caption Standard"
3367 def revert_captioninsets(document):
3368 " Reverts caption insets to old syntax "
3372 i = find_token(document.body, "\\begin_inset Caption Standard", i)
3375 document.body[i] = "\\begin_inset Caption"
3379 def convert_captionlayouts(document):
3380 " Convert caption layouts to caption insets. "
3383 "Captionabove": "Above",
3384 "Captionbelow": "Below",
3385 "FigCaption" : "FigCaption",
3386 "Table_Caption" : "Table",
3387 "CenteredCaption" : "Centered",
3388 "Bicaption" : "Bicaption",
3393 i = find_token(document.body, "\\begin_layout", i)
3396 val = get_value(document.body, "\\begin_layout", i)
3397 if val in caption_dict.keys():
3398 j = find_end_of_layout(document.body, i)
3400 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3403 document.body[j:j] = ["\\end_layout", "", "\\end_inset", "", ""]
3404 document.body[i:i+1] = ["\\begin_layout %s" % document.default_layout,
3405 "\\begin_inset Caption %s" % caption_dict[val], "",
3406 "\\begin_layout %s" % document.default_layout]
3410 def revert_captionlayouts(document):
3411 " Revert caption insets to caption layouts. "
3414 "Above" : "Captionabove",
3415 "Below" : "Captionbelow",
3416 "FigCaption" : "FigCaption",
3417 "Table" : "Table_Caption",
3418 "Centered" : "CenteredCaption",
3419 "Bicaption" : "Bicaption",
3423 rx = re.compile(r'^\\begin_inset Caption (\S+)$')
3425 i = find_token(document.body, "\\begin_inset Caption", i)
3429 m = rx.match(document.body[i])
3433 if val not in caption_dict.keys():
3437 # We either need to delete the previous \begin_layout line, or we
3438 # need to end the previous layout if this inset is not in the first
3439 # position of the paragraph.
3440 layout_before = find_token_backwards(document.body, "\\begin_layout", i)
3441 if layout_before == -1:
3442 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3444 layout_line = document.body[layout_before]
3445 del_layout_before = True
3446 l = layout_before + 1
3448 if document.body[l] != "":
3449 del_layout_before = False
3452 if del_layout_before:
3453 del document.body[layout_before:i]
3456 document.body[i:i] = ["\\end_layout", ""]
3459 # Find start of layout in the inset and end of inset
3460 j = find_token(document.body, "\\begin_layout", i)
3462 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3464 k = find_end_of_inset(document.body, i)
3466 document.warning("Malformed LyX document: Missing `\\end_inset'.")
3469 # We either need to delete the following \end_layout line, or we need
3470 # to restart the old layout if this inset is not at the paragraph end.
3471 layout_after = find_token(document.body, "\\end_layout", k)
3472 if layout_after == -1:
3473 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3475 del_layout_after = True
3477 while l < layout_after:
3478 if document.body[l] != "":
3479 del_layout_after = False
3482 if del_layout_after:
3483 del document.body[k+1:layout_after+1]
3485 document.body[k+1:k+1] = [layout_line, ""]
3487 # delete \begin_layout and \end_inset and replace \begin_inset with
3488 # "\begin_layout XXX". This works because we can only have one
3489 # paragraph in the caption inset: The old \end_layout will be recycled.
3490 del document.body[k]
3491 if document.body[k] == "":
3492 del document.body[k]
3493 del document.body[j]
3494 if document.body[j] == "":
3495 del document.body[j]
3496 document.body[i] = "\\begin_layout %s" % caption_dict[val]
3497 if document.body[i+1] == "":
3498 del document.body[i+1]
3502 def revert_fragileframe(document):
3503 " Reverts beamer FragileFrame layout to ERT "
3505 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3506 if document.textclass not in beamer_classes:
3511 i = find_token(document.body, "\\begin_layout FragileFrame", i)
3514 # Find end of sequence
3515 j = find_end_of_sequence(document.body, i)
3517 document.warning("Malformed LyX document. Cannot find end of FragileFrame sequence!")
3521 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{frame}")
3522 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{frame}")
3523 endseq = endseq + len(esubst) - len(document.body[j : j])
3524 if document.body[j] == "\\end_deeper":
3525 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3527 document.body[j : j] = esubst
3528 for q in range(i, j):
3529 if document.body[q] == "\\begin_layout FragileFrame":
3530 document.body[q] = "\\begin_layout %s" % document.default_layout
3533 if document.body[r] == "\\begin_deeper":
3534 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3536 document.body[r] = ""
3537 document.body[s] = ""
3541 for p in range(1, 5):
3542 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, j)
3545 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3546 endPlain = find_end_of_layout(document.body, beginPlain)
3547 endInset = find_end_of_inset(document.body, arg)
3548 content = document.body[beginPlain + 1 : endPlain]
3550 j = j - len(document.body[arg : endInset + 1])
3552 del document.body[arg : endInset + 1]
3553 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3555 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3556 endPlain = find_end_of_layout(document.body, beginPlain)
3557 endInset = find_end_of_inset(document.body, arg)
3558 content = document.body[beginPlain + 1 : endPlain]
3560 j = j - len(document.body[arg : endInset + 1])
3562 del document.body[arg : endInset + 1]
3563 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3565 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3566 endPlain = find_end_of_layout(document.body, beginPlain)
3567 endInset = find_end_of_inset(document.body, arg)
3568 content = document.body[beginPlain + 1 : endPlain]
3570 j = j - len(document.body[arg : endInset + 1])
3572 del document.body[arg : endInset + 1]
3573 subst += put_cmd_in_ert("[fragile,") + content + put_cmd_in_ert("]")
3575 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3576 endPlain = find_end_of_layout(document.body, beginPlain)
3577 endInset = find_end_of_inset(document.body, arg)
3578 content = document.body[beginPlain + 1 : endPlain]
3580 j = j - len(document.body[arg : endInset + 1])
3582 del document.body[arg : endInset + 1]
3583 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3585 subst += put_cmd_in_ert("[fragile]")
3587 document.body[i : i + 1] = subst
3591 def revert_newframes(document):
3592 " Reverts beamer Frame and PlainFrame layouts to old forms "
3594 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3595 if document.textclass not in beamer_classes:
3599 "Frame" : "BeginFrame",
3600 "PlainFrame" : "BeginPlainFrame",
3603 rx = re.compile(r'^\\begin_layout (\S+)$')
3606 i = find_token(document.body, "\\begin_layout", i)
3610 m = rx.match(document.body[i])
3614 if val not in frame_dict.keys():
3617 # Find end of sequence
3618 j = find_end_of_sequence(document.body, i)
3620 document.warning("Malformed LyX document. Cannot find end of Frame sequence!")
3624 subst = ["\\begin_layout %s" % frame_dict[val]]
3625 esubst = ["\\begin_layout EndFrame", "", "\\end_layout"]
3626 endseq = endseq + len(esubst) - len(document.body[j : j])
3627 if document.body[j] == "\\end_deeper":
3628 document.body[j : j] = [""] + esubst
3630 document.body[j : j] = esubst
3631 for q in range(i, j):
3632 if document.body[q] == "\\begin_layout %s" % val:
3633 document.body[q] = "\\begin_layout %s" % document.default_layout
3636 if document.body[r] == "\\begin_deeper":
3637 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3639 document.body[r] = ""
3640 document.body[s] = ""
3644 l = find_end_of_layout(document.body, i)
3645 for p in range(1, 5):
3646 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, l)
3649 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3650 endPlain = find_end_of_layout(document.body, beginPlain)
3651 endInset = find_end_of_inset(document.body, arg)
3652 content = document.body[beginPlain + 1 : endPlain]
3654 l = l - len(document.body[arg : endInset + 1])
3656 del document.body[arg : endInset + 1]
3657 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3659 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3660 endPlain = find_end_of_layout(document.body, beginPlain)
3661 endInset = find_end_of_inset(document.body, arg)
3662 content = document.body[beginPlain + 1 : endPlain]
3664 l = l - len(document.body[arg : endInset + 1])
3666 del document.body[arg : endInset + 1]
3667 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3669 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3670 endPlain = find_end_of_layout(document.body, beginPlain)
3671 endInset = find_end_of_inset(document.body, arg)
3672 content = document.body[beginPlain + 1 : endPlain]
3674 l = l - len(document.body[arg : endInset + 1])
3676 del document.body[arg : endInset + 1]
3677 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3679 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3680 endPlain = find_end_of_layout(document.body, beginPlain)
3681 endInset = find_end_of_inset(document.body, arg)
3682 content = document.body[beginPlain + 1 : endPlain]
3684 l = l - len(document.body[arg : endInset + 1])
3686 del document.body[arg : endInset + 1]
3689 document.body[i : i + 1] = subst
3692 # known encodings that do not change their names (same LyX and LaTeX names)
3693 known_enc_tuple = ("auto", "default", "ansinew", "applemac", "armscii8", "ascii",
3694 "cp437", "cp437de", "cp850", "cp852", "cp855", "cp858", "cp862", "cp865", "cp866",
3695 "cp1250", "cp1251", "cp1252", "cp1255", "cp1256", "cp1257", "koi8-r", "koi8-u",
3696 "pt154", "pt254", "tis620-0", "utf8", "utf8x", "utf8-plain")
3698 def convert_encodings(document):
3699 "Use the LyX names of the encodings instead of the LaTeX names."
3700 LaTeX2LyX_enc_dict = {
3701 "8859-6": "iso8859-6",
3702 "8859-8": "iso8859-8",
3704 "euc": "euc-jp-platex",
3709 "iso88595": "iso8859-5",
3710 "iso-8859-7": "iso8859-7",
3712 "jis": "jis-platex",
3714 "l7xenc": "iso8859-13",
3715 "latin1": "iso8859-1",
3716 "latin2": "iso8859-2",
3717 "latin3": "iso8859-3",
3718 "latin4": "iso8859-4",
3719 "latin5": "iso8859-9",
3720 "latin9": "iso8859-15",
3721 "latin10": "iso8859-16",
3722 "SJIS": "shift-jis",
3723 "sjis": "shift-jis-platex",
3726 i = find_token(document.header, "\\inputencoding" , 0)
3729 val = get_value(document.header, "\\inputencoding", i)
3730 if val in LaTeX2LyX_enc_dict.keys():
3731 document.header[i] = "\\inputencoding %s" % LaTeX2LyX_enc_dict[val]
3732 elif val not in known_enc_tuple:
3733 document.warning("Ignoring unknown input encoding: `%s'" % val)
3736 def revert_encodings(document):
3737 """Revert to using the LaTeX names of the encodings instead of the LyX names.
3738 Also revert utf8-platex to sjis, the language default when using Japanese.
3740 LyX2LaTeX_enc_dict = {
3745 "euc-jp-platex": "euc",
3748 "iso8859-1": "latin1",
3749 "iso8859-2": "latin2",
3750 "iso8859-3": "latin3",
3751 "iso8859-4": "latin4",
3752 "iso8859-5": "iso88595",
3753 "iso8859-6": "8859-6",
3754 "iso8859-7": "iso-8859-7",
3755 "iso8859-8": "8859-8",
3756 "iso8859-9": "latin5",
3757 "iso8859-13": "l7xenc",
3758 "iso8859-15": "latin9",
3759 "iso8859-16": "latin10",
3761 "jis-platex": "jis",
3762 "shift-jis": "SJIS",
3763 "shift-jis-platex": "sjis",
3765 "utf8-platex": "sjis"
3767 i = find_token(document.header, "\\inputencoding" , 0)
3770 val = get_value(document.header, "\\inputencoding", i)
3771 if val in LyX2LaTeX_enc_dict.keys():
3772 document.header[i] = "\\inputencoding %s" % LyX2LaTeX_enc_dict[val]
3773 elif val not in known_enc_tuple:
3774 document.warning("Ignoring unknown input encoding: `%s'" % val)
3777 def revert_IEEEtran_3(document):
3779 Reverts Flex Insets to TeX-code
3781 if document.textclass == "IEEEtran":
3787 h = find_token(document.body, "\\begin_inset Flex Author Mark", h)
3789 endh = find_end_of_inset(document.body, h)
3790 document.body[endh - 2 : endh + 1] = put_cmd_in_ert("}")
3791 document.body[h : h + 4] = put_cmd_in_ert("\\IEEEauthorrefmark{")
3794 i = find_token(document.body, "\\begin_inset Flex Author Name", i)
3796 endi = find_end_of_inset(document.body, i)
3797 document.body[endi - 2 : endi + 1] = put_cmd_in_ert("}")
3798 document.body[i : i + 4] = put_cmd_in_ert("\\IEEEauthorblockN{")
3801 j = find_token(document.body, "\\begin_inset Flex Author Affiliation", j)
3803 endj = find_end_of_inset(document.body, j)
3804 document.body[endj - 2 : endj + 1] = put_cmd_in_ert("}")
3805 document.body[j : j + 4] = put_cmd_in_ert("\\IEEEauthorblockA{")
3807 if i == -1 and j == -1 and h == -1:
3811 def revert_kurier_fonts(document):
3812 " Revert kurier font definition to LaTeX "
3814 i = find_token(document.header, "\\font_math", 0)
3816 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
3817 val = get_value(document.header, "\\font_math", i)
3818 if val == "kurier-math":
3819 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
3820 "\\usepackage[math]{kurier}\n" \
3821 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
3822 document.header[i] = "\\font_math auto"
3824 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
3825 kurier_fonts = ["kurier", "kurierc", "kurierl", "kurierlc"]
3826 k = find_token(document.header, "\\font_sans kurier", 0)
3828 sf = get_value(document.header, "\\font_sans", k)
3829 if sf in kurier_fonts:
3830 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
3831 document.header[k] = "\\font_sans default"
3833 def revert_iwona_fonts(document):
3834 " Revert iwona font definition to LaTeX "
3836 i = find_token(document.header, "\\font_math", 0)
3838 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
3839 val = get_value(document.header, "\\font_math", i)
3840 if val == "iwona-math":
3841 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
3842 "\\usepackage[math]{iwona}\n" \
3843 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
3844 document.header[i] = "\\font_math auto"
3846 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
3847 iwona_fonts = ["iwona", "iwonac", "iwonal", "iwonalc"]
3848 k = find_token(document.header, "\\font_sans iwona", 0)
3850 sf = get_value(document.header, "\\font_sans", k)
3851 if sf in iwona_fonts:
3852 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
3853 document.header[k] = "\\font_sans default"
3856 def revert_new_libertines(document):
3857 " Revert new libertine font definition to LaTeX "
3859 if find_token(document.header, "\\use_non_tex_fonts true", 0) != -1:
3862 i = find_token(document.header, "\\font_typewriter libertine-mono", 0)
3864 preamble = "\\usepackage"
3865 sc = find_token(document.header, "\\font_tt_scale", 0)
3867 scval = get_value(document.header, "\\font_tt_scale", sc)
3869 preamble += "[scale=%f]" % (float(scval) / 100)
3870 document.header[sc] = "\\font_tt_scale 100"
3871 preamble += "{libertineMono-type1}"
3872 add_to_preamble(document, [preamble])
3873 document.header[i] = "\\font_typewriter default"
3875 k = find_token(document.header, "\\font_sans biolinum", 0)
3877 preamble = "\\usepackage"
3879 j = find_token(document.header, "\\font_osf true", 0)
3884 sc = find_token(document.header, "\\font_sf_scale", 0)
3886 scval = get_value(document.header, "\\font_sf_scale", sc)
3888 options += ",scale=%f" % (float(scval) / 100)
3889 document.header[sc] = "\\font_sf_scale 100"
3891 preamble += "[" + options +"]"
3892 preamble += "{biolinum-type1}"
3893 add_to_preamble(document, [preamble])
3894 document.header[k] = "\\font_sans default"
3897 def convert_lyxframes(document):
3898 " Converts old beamer frames to new style "
3900 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3901 if document.textclass not in beamer_classes:
3904 framebeg = ["BeginFrame", "BeginPlainFrame"]
3905 frameend = ["Frame", "PlainFrame", "EndFrame", "BeginFrame", "BeginPlainFrame", "AgainFrame",
3906 "Section", "Section*", "Subsection", "Subsection*", "Subsubsection", "Subsubsection*"]
3907 for lay in framebeg:
3910 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
3913 parent = get_containing_layout(document.body, i)
3914 if parent == False or parent[1] != i:
3915 document.warning("Wrong parent layout!")
3918 frametype = parent[0]
3922 # Step I: Convert ERT arguments
3923 # FIXME: See restrictions in convert_beamerframeargs method
3924 ertend = convert_beamerframeargs(document, i, parbeg)
3927 # Step II: Now rename the layout and convert the title to an argument
3928 j = find_end_of_layout(document.body, i)
3929 document.body[j : j + 1] = ['\\end_layout', '', '\\end_inset', '', '\\end_layout']
3930 if lay == "BeginFrame":
3931 document.body[i] = "\\begin_layout Frame"
3933 document.body[i] = "\\begin_layout PlainFrame"
3934 document.body[ertend + 1 : ertend + 1] = ['\\begin_inset Argument 4',
3935 'status open', '', '\\begin_layout Plain Layout']
3936 # Step III: find real frame end
3940 fend = find_token(document.body, "\\begin_layout", jj)
3942 document.warning("Malformed LyX document: No real frame end!")
3944 val = get_value(document.body, "\\begin_layout", fend)
3945 if val not in frameend:
3948 old = document.body[fend]
3949 if val == frametype:
3950 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
3951 # consider explicit EndFrames between two identical frame types
3952 elif val == "EndFrame":
3953 nextlayout = find_token(document.body, "\\begin_layout", fend + 1)
3954 if nextlayout != -1 and get_value(document.body, "\\begin_layout", nextlayout) == frametype:
3955 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
3957 document.body[fend : fend] = ['\\end_deeper']
3959 document.body[fend : fend] = ['\\end_deeper']
3960 document.body[j + 1 : j + 1] = ['', '\\begin_deeper']
3965 def remove_endframes(document):
3966 " Remove deprecated beamer endframes "
3968 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3969 if document.textclass not in beamer_classes:
3974 i = find_token_exact(document.body, "\\begin_layout EndFrame", i)
3977 j = find_end_of_layout(document.body, i)
3979 document.warning("Malformed LyX document: Missing \\end_layout to EndFrame")
3982 del document.body[i : j + 1]
3985 def revert_powerdot_flexes(document):
3986 " Reverts powerdot flex insets "
3988 if document.textclass != "powerdot":
3991 flexes = {"Onslide" : "\\onslide",
3992 "Onslide*" : "\\onslide*",
3993 "Onslide+" : "\\onslide+"}
3994 rx = re.compile(r'^\\begin_inset Flex (.+)$')
3998 i = find_token(document.body, "\\begin_inset Flex", i)
4001 m = rx.match(document.body[i])
4003 flextype = m.group(1)
4004 z = find_end_of_inset(document.body, i)
4006 document.warning("Can't find end of Flex " + flextype + " inset.")
4009 if flextype in flexes:
4010 pre = put_cmd_in_ert(flexes[flextype])
4011 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
4013 argend = find_end_of_inset(document.body, arg)
4015 document.warning("Can't find end of Argument!")
4018 # Find containing paragraph layout
4019 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
4020 endPlain = find_end_of_layout(document.body, beginPlain)
4021 argcontent = document.body[beginPlain + 1 : endPlain]
4023 z = z - len(document.body[arg : argend + 1])
4025 del document.body[arg : argend + 1]
4026 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
4027 pre += put_cmd_in_ert("{")
4028 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4029 endPlain = find_end_of_layout(document.body, beginPlain)
4031 z = z - len(document.body[i : beginPlain + 1])
4033 document.body[i : beginPlain + 1] = pre
4034 post = put_cmd_in_ert("}")
4035 document.body[z - 2 : z + 1] = post
4039 def revert_powerdot_pause(document):
4040 " Reverts powerdot pause layout to ERT "
4042 if document.textclass != "powerdot":
4047 i = find_token(document.body, "\\begin_layout Pause", i)
4050 j = find_end_of_layout(document.body, i)
4052 document.warning("Malformed LyX document: Can't find end of Pause layout")
4056 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\pause")
4057 for p in range(i, j):
4060 arg = find_token(document.body, "\\begin_inset Argument 1", i, j)
4062 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4063 endPlain = find_end_of_layout(document.body, beginPlain)
4064 endInset = find_end_of_inset(document.body, p)
4065 content = document.body[beginPlain + 1 : endPlain]
4067 endlay = endlay - len(document.body[p : endInset + 1])
4069 del document.body[p : endInset + 1]
4070 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4072 document.body[i : i + 1] = subst
4076 def revert_powerdot_itemargs(document):
4077 " Reverts powerdot item arguments to ERT "
4079 if document.textclass != "powerdot":
4083 list_layouts = ["Itemize", "ItemizeType1", "Enumerate", "EnumerateType1"]
4084 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4087 i = find_token(document.body, "\\begin_inset Argument", i)
4090 # Find containing paragraph layout
4091 parent = get_containing_layout(document.body, i)
4093 document.warning("Malformed LyX document: Can't find parent paragraph layout")
4098 realparbeg = parent[3]
4099 layoutname = parent[0]
4101 for p in range(parbeg, parend):
4105 if layoutname in list_layouts:
4106 m = rx.match(document.body[p])
4109 if argnr == "item:1":
4110 j = find_end_of_inset(document.body, i)
4111 # Find containing paragraph layout
4112 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4113 endPlain = find_end_of_layout(document.body, beginPlain)
4114 content = document.body[beginPlain + 1 : endPlain]
4115 del document.body[i:j+1]
4116 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4117 document.body[realparbeg : realparbeg] = subst
4118 elif argnr == "item:2":
4119 j = find_end_of_inset(document.body, i)
4120 # Find containing paragraph layout
4121 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4122 endPlain = find_end_of_layout(document.body, beginPlain)
4123 content = document.body[beginPlain + 1 : endPlain]
4124 del document.body[i:j+1]
4125 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
4126 document.body[realparbeg : realparbeg] = subst
4131 def revert_powerdot_columns(document):
4132 " Reverts powerdot twocolumn to TeX-code "
4133 if document.textclass != "powerdot":
4136 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4139 i = find_token(document.body, "\\begin_layout Twocolumn", i)
4142 j = find_end_of_layout(document.body, i)
4144 document.warning("Malformed LyX document: Can't find end of Twocolumn layout")
4148 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
4149 endlay += len(put_cmd_in_ert("}"))
4150 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\twocolumn")
4151 for p in range(i, j):
4154 m = rx.match(document.body[p])
4158 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4159 endPlain = find_end_of_layout(document.body, beginPlain)
4160 endInset = find_end_of_inset(document.body, p)
4161 content = document.body[beginPlain + 1 : endPlain]
4163 endlay = endlay - len(document.body[p : endInset + 1])
4165 del document.body[p : endInset + 1]
4166 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4168 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4169 endPlain = find_end_of_layout(document.body, beginPlain)
4170 endInset = find_end_of_inset(document.body, p)
4171 content = document.body[beginPlain + 1 : endPlain]
4173 endlay = endlay - len(document.body[p : endInset + 1])
4175 del document.body[p : endInset + 1]
4176 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
4178 subst += put_cmd_in_ert("{")
4179 document.body[i : i + 1] = subst
4183 def revert_mbox_fbox(document):
4184 'Convert revert mbox/fbox boxes to TeX-code'
4187 i = find_token(document.body, "\\begin_inset Box", i)
4190 j = find_token(document.body, "width", i)
4192 document.warning("Malformed LyX document: Can't find box width")
4194 width = get_value(document.body, "width", j)
4195 k = find_end_of_inset(document.body, j)
4197 document.warning("Malformed LyX document: Can't find end of box inset")
4200 BeginLayout = find_token(document.body, "\\begin_layout Plain Layout", j)
4201 EndLayout = find_token(document.body, "\\end_layout", BeginLayout)
4202 # replace if width is ""
4204 document.body[EndLayout:k + 1] = put_cmd_in_ert("}")
4205 if document.body[i] == "\\begin_inset Box Frameless":
4206 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\mbox{")
4207 if document.body[i] == "\\begin_inset Box Boxed":
4208 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\fbox{")
4212 def revert_starred_caption(document):
4213 " Reverts unnumbered longtable caption insets "
4217 i = find_token(document.body, "\\begin_inset Caption LongTableNoNumber", i)
4220 # This is not equivalent, but since the caption inset is a full blown
4221 # text inset a true conversion to ERT is too difficult.
4222 document.body[i] = "\\begin_inset Caption Standard"
4226 def revert_forced_local_layout(document):
4229 i = find_token(document.header, "\\begin_forced_local_layout", i)
4232 j = find_end_of(document.header, i, "\\begin_forced_local_layout", "\\end_forced_local_layout")
4234 # this should not happen
4236 regexp = re.compile(r'\s*forcelocal', re.IGNORECASE)
4237 k = find_re(document.header, regexp, i, j)
4239 del document.header[k]
4241 k = find_re(document.header, regexp, i, j)
4242 k = find_token(document.header, "\\begin_local_layout", 0)
4244 document.header[i] = "\\begin_local_layout"
4245 document.header[j] = "\\end_local_layout"
4247 l = find_end_of(document.header, k, "\\begin_local_layout", "\\end_local_layout")
4249 # this should not happen
4251 lines = document.header[i+1 : j]
4253 document.header[k+1 : k+1] = lines
4254 document.header[i : j ] = []
4256 document.header[i : j ] = []
4257 document.header[k+1 : k+1] = lines
4260 def revert_aa1(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 revert_Argument_to_TeX_brace(document, i, 0, 1, 4, False, False)
4274 def revert_aa2(document):
4275 " Reverts InsetArguments of aa to TeX-code "
4276 if document.textclass == "aa":
4280 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4282 document.body[i] = "\\begin_layout Abstract"
4288 def revert_tibetan(document):
4289 "Set the document language for Tibetan to English"
4291 if document.language == "tibetan":
4292 document.language = "english"
4293 i = find_token(document.header, "\\language", 0)
4295 document.header[i] = "\\language english"
4297 while j < len(document.body):
4298 j = find_token(document.body, "\\lang tibetan", j)
4300 document.body[j] = document.body[j].replace("\\lang tibetan", "\\lang english")
4303 j = len(document.body)
4312 # The idea here is that we will have a sequence of chunk paragraphs.
4313 # We want to convert them to paragraphs in one or several chunk insets.
4314 # Individual chunks are terminated by the character @ on the last line.
4315 # This line will be discarded, and following lines are treated as new
4316 # chunks, which go into their own insets.
4317 # The first line of a chunk should look like: <<CONTENT>>=
4318 # We will discard the delimiters, and put the CONTENT into the
4319 # optional argument of the inset, if the CONTENT is non-empty.
4320 def convert_chunks(document):
4321 first_re = re.compile(r'<<(.*)>>=(.*)')
4324 # find start of a block of chunks
4325 i = find_token(document.body, "\\begin_layout Chunk", file_pos)
4331 chunk_started = False
4334 # process the one we just found
4335 j = find_end_of_layout(document.body, i)
4337 document.warning("Malformed LyX documents. Can't find end of Chunk layout!")
4338 # there is no point continuing, as we will run into the same error again.
4340 this_chunk = "".join(document.body[i + 1:j])
4342 # there may be empty lines between chunks
4343 # we just skip them.
4344 if not chunk_started:
4345 if this_chunk != "":
4347 chunk_started = True
4350 contents.append(document.body[i + 1:j])
4352 # look for potential chunk terminator
4353 # on the last line of the chunk paragraph
4354 if document.body[j - 1] == "@":
4357 # look for subsequent chunk paragraph
4358 i = find_token(document.body, "\\begin_layout", j)
4362 if get_value(document.body, "\\begin_layout", i) != "Chunk":
4365 file_pos = end = j + 1
4367 # The last chunk should simply have an "@" in it
4368 # or at least end with "@" (can happen if @ is
4369 # preceded by a newline)
4370 lastpar = ''.join(contents[-1])
4371 if not lastpar.endswith("@"):
4372 document.warning("Unexpected chunk content: chunk not terminated by '@'!")
4376 # chunk par only contains "@". Just drop it.
4379 # chunk par contains more. Only drop the "@".
4382 # The first line should look like: <<CONTENT>>=
4383 # We want the CONTENT
4384 optarg = ' '.join(contents[0])
4386 # We can already have real chunk content in
4387 # the first par (separated from the options by a newline).
4388 # We collect such stuff to re-insert it later.
4391 match = first_re.search(optarg)
4393 optarg = match.groups()[0]
4394 if match.groups()[1] != "":
4396 for c in contents[0]:
4397 if c.endswith(">>="):
4401 postoptstuff.append(c)
4402 # We have stripped everything. This can be deleted.
4405 newstuff = ['\\begin_layout Standard',
4406 '\\begin_inset Flex Chunk',
4408 '\\begin_layout Plain Layout', '']
4410 # If we have a non-empty optional argument, insert it.
4411 if match and optarg != "":
4413 ['\\begin_inset Argument 1',
4415 '\\begin_layout Plain Layout',
4420 # Since we already opened a Plain layout, the first paragraph
4421 # does not need to do that.
4424 newstuff.extend(postoptstuff)
4425 newstuff.append('\\end_layout')
4429 newstuff.extend(['', '\\begin_layout Plain Layout', ''])
4433 newstuff.append('\\end_layout')
4435 newstuff.extend(['', '\\end_inset', '', '\\end_layout', ''])
4437 document.body[start:end] = newstuff
4439 file_pos += len(newstuff) - (end - start)
4442 def revert_chunks(document):
4445 i = find_token(document.body, "\\begin_inset Flex Chunk", i)
4449 iend = find_end_of_inset(document.body, i)
4451 document.warning("Can't find end of Chunk!")
4455 # Look for optional argument
4457 ostart = find_token(document.body, "\\begin_inset Argument 1", i, iend)
4459 oend = find_end_of_inset(document.body, ostart)
4460 k = find_token(document.body, "\\begin_layout Plain Layout", ostart, oend)
4462 document.warning("Malformed LyX document: Can't find argument contents!")
4464 m = find_end_of_layout(document.body, k)
4465 optarg = "".join(document.body[k+1:m])
4468 # We now remove the optional argument, so we have something
4469 # uniform on which to work
4470 document.body[ostart : oend + 1] = []
4471 # iend is now invalid
4472 iend = find_end_of_inset(document.body, i)
4474 retval = get_containing_layout(document.body, i)
4476 document.warning("Can't find containing layout for Chunk!")
4479 (lname, lstart, lend, pstart) = retval
4480 # we now want to work through the various paragraphs, and collect their contents
4484 k = find_token(document.body, "\\begin_layout Plain Layout", k, lend)
4487 j = find_end_of_layout(document.body, k)
4489 document.warning("Can't find end of layout inside chunk!")
4491 parlist.append(document.body[k+1:j])
4493 # we now need to wrap all of these paragraphs in chunks
4496 newlines.extend(["\\begin_layout Chunk", "", "<<" + optarg + ">>=", "\\end_layout", ""])
4497 for stuff in parlist:
4498 newlines.extend(["\\begin_layout Chunk"] + stuff + ["\\end_layout", ""])
4499 newlines.extend(["\\begin_layout Chunk", "", "@", "\\end_layout", ""])
4500 # replace old content with new content
4501 document.body[lstart : lend + 1] = newlines
4502 i = lstart + len(newlines)
4509 supported_versions = ["2.1.0","2.1"]
4512 [415, [convert_undertilde]],
4514 [417, [convert_japanese_encodings]],
4515 [418, [convert_justification]],
4517 [420, [convert_biblio_style]],
4518 [421, [convert_longtable_captions]],
4519 [422, [convert_use_packages]],
4520 [423, [convert_use_mathtools]],
4521 [424, [convert_cite_engine_type]],
4522 # No convert_cancel, since cancel will be loaded automatically
4523 # in format 425 without any possibility to switch it off.
4524 # This has been fixed in format 464.
4528 [428, [convert_cell_rotation]],
4529 [429, [convert_table_rotation]],
4530 [430, [convert_listoflistings]],
4531 [431, [convert_use_amssymb]],
4533 [433, [convert_armenian]],
4541 [441, [convert_mdnomath]],
4546 [446, [convert_latexargs]],
4547 [447, [convert_IEEEtran, convert_AASTeX, convert_AGUTeX, convert_IJMP, convert_SIGPLAN, convert_SIGGRAPH, convert_EuropeCV, convert_Initials, convert_ModernCV]],
4548 [448, [convert_literate]],
4551 [451, [convert_beamerargs, convert_againframe_args, convert_corollary_args, convert_quote_args]],
4552 [452, [convert_beamerblocks]],
4553 [453, [convert_use_stmaryrd]],
4554 [454, [convert_overprint]],
4556 [456, [convert_epigraph]],
4557 [457, [convert_use_stackrel]],
4558 [458, [convert_captioninsets, convert_captionlayouts]],
4563 [463, [convert_encodings]],
4564 [464, [convert_use_cancel]],
4565 [465, [convert_lyxframes, remove_endframes]],
4571 [471, [convert_cite_engine_type_default]],
4574 [474, [convert_chunks]],
4578 [473, [revert_chunks]],
4579 [472, [revert_tibetan]],
4580 [471, [revert_aa1,revert_aa2]],
4581 [470, [revert_cite_engine_type_default]],
4582 [469, [revert_forced_local_layout]],
4583 [468, [revert_starred_caption]],
4584 [467, [revert_mbox_fbox]],
4585 [466, [revert_iwona_fonts]],
4586 [465, [revert_powerdot_flexes, revert_powerdot_pause, revert_powerdot_itemargs, revert_powerdot_columns]],
4588 [463, [revert_use_cancel]],
4589 [462, [revert_encodings]],
4590 [461, [revert_new_libertines]],
4591 [460, [revert_kurier_fonts]],
4592 [459, [revert_IEEEtran_3]],
4593 [458, [revert_fragileframe, revert_newframes]],
4594 [457, [revert_captioninsets, revert_captionlayouts]],
4595 [456, [revert_use_stackrel]],
4596 [455, [revert_epigraph]],
4597 [454, [revert_frametitle]],
4598 [453, [revert_overprint]],
4599 [452, [revert_use_stmaryrd]],
4600 [451, [revert_beamerblocks]],
4601 [450, [revert_beamerargs, revert_beamerargs2, revert_beamerargs3, revert_beamerflex]],
4602 [449, [revert_garamondx, revert_garamondx_newtxmath]],
4603 [448, [revert_itemargs]],
4604 [447, [revert_literate]],
4605 [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]],
4606 [445, [revert_latexargs]],
4607 [444, [revert_uop]],
4608 [443, [revert_biolinum]],
4610 [441, [revert_newtxmath]],
4611 [440, [revert_mdnomath]],
4612 [439, [revert_mathfonts]],
4613 [438, [revert_minionpro]],
4614 [437, [revert_ipadeco, revert_ipachar]],
4615 [436, [revert_texgyre]],
4616 [435, [revert_mathdesign]],
4617 [434, [revert_txtt]],
4618 [433, [revert_libertine]],
4619 [432, [revert_armenian]],
4620 [431, [revert_languages, revert_ancientgreek]],
4621 [430, [revert_use_amssymb]],
4622 [429, [revert_listoflistings]],
4623 [428, [revert_table_rotation]],
4624 [427, [revert_cell_rotation]],
4625 [426, [revert_tipa]],
4626 [425, [revert_verbatim]],
4627 [424, [revert_cancel]],
4628 [423, [revert_cite_engine_type]],
4629 [422, [revert_use_mathtools]],
4630 [421, [revert_use_packages]],
4631 [420, [revert_longtable_captions]],
4632 [419, [revert_biblio_style]],
4633 [418, [revert_australian]],
4634 [417, [revert_justification]],
4635 [416, [revert_japanese_encodings]],
4636 [415, [revert_negative_space, revert_math_spaces]],
4637 [414, [revert_undertilde]],
4638 [413, [revert_visible_space]]
4642 if __name__ == "__main__":