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 = ["\\end_layout", "", "\\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] = ["\\end_deeper", ""] + esubst
3157 document.body[j : j] = 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 argend = find_end_of_inset(document.body, argbeg)
3172 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3175 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3176 endPlain = find_end_of_layout(document.body, beginPlain)
3177 content = document.body[beginPlain + 1 : endPlain]
3179 endseq = endseq - len(document.body[argbeg : argend])
3181 del document.body[argbeg : argend + 1]
3182 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3184 endseq = endseq - len(document.body[i : i])
3185 document.body[i : i] = subst + ["\\end_layout"]
3186 endseq += len(subst)
3192 if document.body[p] == "\\begin_layout Overprint":
3193 q = find_end_of_layout(document.body, p)
3195 document.warning("Malformed LyX document. Cannot find end of Overprint layout!")
3198 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\onslide")
3199 argbeg = find_token(document.body, "\\begin_inset Argument item:1", p, q)
3201 argend = find_end_of_inset(document.body, argbeg)
3203 document.warning("Malformed LyX document. Cannot find end of Overprint item argument!")
3206 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3207 endPlain = find_end_of_layout(document.body, beginPlain)
3208 content = document.body[beginPlain + 1 : endPlain]
3210 endseq = endseq - len(document.body[argbeg : argend + 1])
3212 del document.body[argbeg : argend + 1]
3213 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3214 endseq = endseq - len(document.body[p : p + 1]) + len(subst)
3215 document.body[p : p + 1] = subst
3221 def revert_frametitle(document):
3222 " Reverts beamer frametitle layout to ERT "
3224 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3225 if document.textclass not in beamer_classes:
3228 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3231 i = find_token(document.body, "\\begin_layout FrameTitle", i)
3234 j = find_end_of_layout(document.body, i)
3236 document.warning("Malformed LyX document: Can't find end of FrameTitle layout")
3240 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
3241 endlay += len(put_cmd_in_ert("}"))
3242 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\frametitle")
3243 for p in range(i, j):
3246 m = rx.match(document.body[p])
3250 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3251 endPlain = find_end_of_layout(document.body, beginPlain)
3252 endInset = find_end_of_inset(document.body, p)
3253 content = document.body[beginPlain + 1 : endPlain]
3255 endlay = endlay - len(document.body[p : endInset + 1])
3257 del document.body[p : endInset + 1]
3258 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3260 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3261 endPlain = find_end_of_layout(document.body, beginPlain)
3262 endInset = find_end_of_inset(document.body, p)
3263 content = document.body[beginPlain + 1 : endPlain]
3265 endlay = endlay - len(document.body[p : endInset + 1])
3267 del document.body[p : endInset + 1]
3268 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3270 subst += put_cmd_in_ert("{")
3271 document.body[i : i + 1] = subst
3275 def convert_epigraph(document):
3276 " Converts memoir epigraph to new syntax "
3278 if document.textclass != "memoir":
3283 i = find_token(document.body, "\\begin_layout Epigraph", i)
3286 j = find_end_of_layout(document.body, i)
3288 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3293 ert = find_token(document.body, "\\begin_inset ERT", i, j)
3295 endInset = find_end_of_inset(document.body, ert)
3296 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", ert)
3297 endPlain = find_end_of_layout(document.body, beginPlain)
3298 ertcont = beginPlain + 2
3299 if document.body[ertcont] == "}{":
3301 # Convert to ArgInset
3302 endlay = endlay - 2 * len(document.body[j])
3303 begsubst = ['\\begin_inset Argument post:1', 'status collapsed', '',
3304 '\\begin_layout Plain Layout']
3305 endsubst = ['\\end_layout', '', '\\end_inset', '', document.body[j]]
3306 document.body[j : j + 1] = endsubst
3307 document.body[endInset + 1 : endInset + 1] = begsubst
3309 endlay += len(begsubst) + len(endsubst)
3310 endlay = endlay - len(document.body[ert : endInset + 1])
3311 del document.body[ert : endInset + 1]
3316 def revert_epigraph(document):
3317 " Reverts memoir epigraph argument to ERT "
3319 if document.textclass != "memoir":
3324 i = find_token(document.body, "\\begin_layout Epigraph", i)
3327 j = find_end_of_layout(document.body, i)
3329 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3334 p = find_token(document.body, "\\begin_layout Argument post:1", i, j)
3336 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3337 endPlain = find_end_of_layout(document.body, beginPlain)
3338 endInset = find_end_of_inset(document.body, p)
3339 content = document.body[beginPlain + 1 : endPlain]
3341 endlay = endlay - len(document.body[p : endInset + 1])
3343 del document.body[p : endInset + 1]
3344 subst += put_cmd_in_ert("}{") + content
3346 subst += put_cmd_in_ert("}{")
3348 document.body[j : j] = subst + document.body[j : j]
3352 def convert_captioninsets(document):
3353 " Converts caption insets to new syntax "
3357 i = find_token(document.body, "\\begin_inset Caption", i)
3360 document.body[i] = "\\begin_inset Caption Standard"
3364 def revert_captioninsets(document):
3365 " Reverts caption insets to old syntax "
3369 i = find_token(document.body, "\\begin_inset Caption Standard", i)
3372 document.body[i] = "\\begin_inset Caption"
3376 def convert_captionlayouts(document):
3377 " Convert caption layouts to caption insets. "
3380 "Captionabove": "Above",
3381 "Captionbelow": "Below",
3382 "FigCaption" : "FigCaption",
3383 "Table_Caption" : "Table",
3384 "CenteredCaption" : "Centered",
3385 "Bicaption" : "Bicaption",
3390 i = find_token(document.body, "\\begin_layout", i)
3393 val = get_value(document.body, "\\begin_layout", i)
3394 if val in caption_dict.keys():
3395 j = find_end_of_layout(document.body, i)
3397 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3400 document.body[j:j] = ["\\end_layout", "", "\\end_inset", "", ""]
3401 document.body[i:i+1] = ["\\begin_layout %s" % document.default_layout,
3402 "\\begin_inset Caption %s" % caption_dict[val], "",
3403 "\\begin_layout %s" % document.default_layout]
3407 def revert_captionlayouts(document):
3408 " Revert caption insets to caption layouts. "
3411 "Above" : "Captionabove",
3412 "Below" : "Captionbelow",
3413 "FigCaption" : "FigCaption",
3414 "Table" : "Table_Caption",
3415 "Centered" : "CenteredCaption",
3416 "Bicaption" : "Bicaption",
3420 rx = re.compile(r'^\\begin_inset Caption (\S+)$')
3422 i = find_token(document.body, "\\begin_inset Caption", i)
3426 m = rx.match(document.body[i])
3430 if val not in caption_dict.keys():
3434 # We either need to delete the previous \begin_layout line, or we
3435 # need to end the previous layout if this inset is not in the first
3436 # position of the paragraph.
3437 layout_before = find_token_backwards(document.body, "\\begin_layout", i)
3438 if layout_before == -1:
3439 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3441 layout_line = document.body[layout_before]
3442 del_layout_before = True
3443 l = layout_before + 1
3445 if document.body[l] != "":
3446 del_layout_before = False
3449 if del_layout_before:
3450 del document.body[layout_before:i]
3453 document.body[i:i] = ["\\end_layout", ""]
3456 # Find start of layout in the inset and end of inset
3457 j = find_token(document.body, "\\begin_layout", i)
3459 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3461 k = find_end_of_inset(document.body, i)
3463 document.warning("Malformed LyX document: Missing `\\end_inset'.")
3466 # We either need to delete the following \end_layout line, or we need
3467 # to restart the old layout if this inset is not at the paragraph end.
3468 layout_after = find_token(document.body, "\\end_layout", k)
3469 if layout_after == -1:
3470 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3472 del_layout_after = True
3474 while l < layout_after:
3475 if document.body[l] != "":
3476 del_layout_after = False
3479 if del_layout_after:
3480 del document.body[k+1:layout_after+1]
3482 document.body[k+1:k+1] = [layout_line, ""]
3484 # delete \begin_layout and \end_inset and replace \begin_inset with
3485 # "\begin_layout XXX". This works because we can only have one
3486 # paragraph in the caption inset: The old \end_layout will be recycled.
3487 del document.body[k]
3488 if document.body[k] == "":
3489 del document.body[k]
3490 del document.body[j]
3491 if document.body[j] == "":
3492 del document.body[j]
3493 document.body[i] = "\\begin_layout %s" % caption_dict[val]
3494 if document.body[i+1] == "":
3495 del document.body[i+1]
3499 def revert_fragileframe(document):
3500 " Reverts beamer FragileFrame layout to ERT "
3502 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3503 if document.textclass not in beamer_classes:
3508 i = find_token(document.body, "\\begin_layout FragileFrame", i)
3511 # Find end of sequence
3512 j = find_end_of_sequence(document.body, i)
3514 document.warning("Malformed LyX document. Cannot find end of FragileFrame sequence!")
3518 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{frame}")
3519 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{frame}")
3520 endseq = endseq + len(esubst) - len(document.body[j : j])
3521 if document.body[j] == "\\end_deeper":
3522 document.body[j : j] = ["\\end_deeper", ""] + esubst
3524 document.body[j : j] = esubst
3525 for q in range(i, j):
3526 if document.body[q] == "\\begin_layout FragileFrame":
3527 document.body[q] = "\\begin_layout %s" % document.default_layout
3530 if document.body[r] == "\\begin_deeper":
3531 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3533 document.body[r] = ""
3534 document.body[s] = ""
3538 for p in range(1, 5):
3539 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, j)
3542 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3543 endPlain = find_end_of_layout(document.body, beginPlain)
3544 endInset = find_end_of_inset(document.body, arg)
3545 content = document.body[beginPlain + 1 : endPlain]
3547 j = j - len(document.body[arg : endInset + 1])
3549 del document.body[arg : endInset + 1]
3550 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3552 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3553 endPlain = find_end_of_layout(document.body, beginPlain)
3554 endInset = find_end_of_inset(document.body, arg)
3555 content = document.body[beginPlain + 1 : endPlain]
3557 j = j - len(document.body[arg : endInset + 1])
3559 del document.body[arg : endInset + 1]
3560 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3562 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3563 endPlain = find_end_of_layout(document.body, beginPlain)
3564 endInset = find_end_of_inset(document.body, arg)
3565 content = document.body[beginPlain + 1 : endPlain]
3567 j = j - len(document.body[arg : endInset + 1])
3569 del document.body[arg : endInset + 1]
3570 subst += put_cmd_in_ert("[fragile,") + content + put_cmd_in_ert("]")
3572 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3573 endPlain = find_end_of_layout(document.body, beginPlain)
3574 endInset = find_end_of_inset(document.body, arg)
3575 content = document.body[beginPlain + 1 : endPlain]
3577 j = j - len(document.body[arg : endInset + 1])
3579 del document.body[arg : endInset + 1]
3580 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3582 subst += put_cmd_in_ert("[fragile]")
3584 document.body[i : i + 1] = subst
3588 def revert_newframes(document):
3589 " Reverts beamer Frame and PlainFrame layouts to old forms "
3591 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3592 if document.textclass not in beamer_classes:
3596 "Frame" : "BeginFrame",
3597 "PlainFrame" : "BeginPlainFrame",
3600 rx = re.compile(r'^\\begin_layout (\S+)$')
3603 i = find_token(document.body, "\\begin_layout", i)
3607 m = rx.match(document.body[i])
3611 if val not in frame_dict.keys():
3614 # Find end of sequence
3615 j = find_end_of_sequence(document.body, i)
3617 document.warning("Malformed LyX document. Cannot find end of Frame sequence!")
3621 subst = ["\\begin_layout %s" % frame_dict[val]]
3622 esubst = ["\\end_layout", "", "\\begin_layout EndFrame", "", "\\end_layout"]
3623 endseq = endseq + len(esubst) - len(document.body[j : j])
3624 if document.body[j] == "\\end_deeper":
3625 document.body[j : j] = ["\\end_deeper", ""] + esubst
3627 document.body[j : j] = esubst
3628 for q in range(i, j):
3629 if document.body[q] == "\\begin_layout %s" % val:
3630 document.body[q] = "\\begin_layout %s" % document.default_layout
3633 if document.body[r] == "\\begin_deeper":
3634 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3636 document.body[r] = ""
3637 document.body[s] = ""
3641 l = find_end_of_layout(document.body, i)
3642 for p in range(1, 5):
3643 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, l)
3646 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3647 endPlain = find_end_of_layout(document.body, beginPlain)
3648 endInset = find_end_of_inset(document.body, arg)
3649 content = document.body[beginPlain + 1 : endPlain]
3651 l = l - len(document.body[arg : endInset + 1])
3653 del document.body[arg : endInset + 1]
3654 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3656 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3657 endPlain = find_end_of_layout(document.body, beginPlain)
3658 endInset = find_end_of_inset(document.body, arg)
3659 content = document.body[beginPlain + 1 : endPlain]
3661 l = l - len(document.body[arg : endInset + 1])
3663 del document.body[arg : endInset + 1]
3664 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3666 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3667 endPlain = find_end_of_layout(document.body, beginPlain)
3668 endInset = find_end_of_inset(document.body, arg)
3669 content = document.body[beginPlain + 1 : endPlain]
3671 l = l - len(document.body[arg : endInset + 1])
3673 del document.body[arg : endInset + 1]
3674 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3676 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3677 endPlain = find_end_of_layout(document.body, beginPlain)
3678 endInset = find_end_of_inset(document.body, arg)
3679 content = document.body[beginPlain + 1 : endPlain]
3681 l = l - len(document.body[arg : endInset + 1])
3683 del document.body[arg : endInset + 1]
3686 document.body[i : i + 1] = subst
3689 # known encodings that do not change their names (same LyX and LaTeX names)
3690 known_enc_tuple = ("auto", "default", "ansinew", "applemac", "armscii8", "ascii",
3691 "cp437", "cp437de", "cp850", "cp852", "cp855", "cp858", "cp862", "cp865", "cp866",
3692 "cp1250", "cp1251", "cp1252", "cp1255", "cp1256", "cp1257", "koi8-r", "koi8-u",
3693 "pt154", "pt254", "tis620-0", "utf8", "utf8x", "utf8-plain")
3695 def convert_encodings(document):
3696 "Use the LyX names of the encodings instead of the LaTeX names."
3697 LaTeX2LyX_enc_dict = {
3698 "8859-6": "iso8859-6",
3699 "8859-8": "iso8859-8",
3701 "euc": "euc-jp-platex",
3706 "iso88595": "iso8859-5",
3707 "iso-8859-7": "iso8859-7",
3709 "jis": "jis-platex",
3711 "l7xenc": "iso8859-13",
3712 "latin1": "iso8859-1",
3713 "latin2": "iso8859-2",
3714 "latin3": "iso8859-3",
3715 "latin4": "iso8859-4",
3716 "latin5": "iso8859-9",
3717 "latin9": "iso8859-15",
3718 "latin10": "iso8859-16",
3719 "SJIS": "shift-jis",
3720 "sjis": "shift-jis-platex",
3723 i = find_token(document.header, "\\inputencoding" , 0)
3726 val = get_value(document.header, "\\inputencoding", i)
3727 if val in LaTeX2LyX_enc_dict.keys():
3728 document.header[i] = "\\inputencoding %s" % LaTeX2LyX_enc_dict[val]
3729 elif val not in known_enc_tuple:
3730 document.warning("Ignoring unknown input encoding: `%s'" % val)
3733 def revert_encodings(document):
3734 """Revert to using the LaTeX names of the encodings instead of the LyX names.
3735 Also revert utf8-platex to sjis, the language default when using Japanese.
3737 LyX2LaTeX_enc_dict = {
3742 "euc-jp-platex": "euc",
3745 "iso8859-1": "latin1",
3746 "iso8859-2": "latin2",
3747 "iso8859-3": "latin3",
3748 "iso8859-4": "latin4",
3749 "iso8859-5": "iso88595",
3750 "iso8859-6": "8859-6",
3751 "iso8859-7": "iso-8859-7",
3752 "iso8859-8": "8859-8",
3753 "iso8859-9": "latin5",
3754 "iso8859-13": "l7xenc",
3755 "iso8859-15": "latin9",
3756 "iso8859-16": "latin10",
3758 "jis-platex": "jis",
3759 "shift-jis": "SJIS",
3760 "shift-jis-platex": "sjis",
3762 "utf8-platex": "sjis"
3764 i = find_token(document.header, "\\inputencoding" , 0)
3767 val = get_value(document.header, "\\inputencoding", i)
3768 if val in LyX2LaTeX_enc_dict.keys():
3769 document.header[i] = "\\inputencoding %s" % LyX2LaTeX_enc_dict[val]
3770 elif val not in known_enc_tuple:
3771 document.warning("Ignoring unknown input encoding: `%s'" % val)
3774 def revert_IEEEtran_3(document):
3776 Reverts Flex Insets to TeX-code
3778 if document.textclass == "IEEEtran":
3784 h = find_token(document.body, "\\begin_inset Flex Author Mark", h)
3786 endh = find_end_of_inset(document.body, h)
3787 document.body[endh - 2 : endh + 1] = put_cmd_in_ert("}")
3788 document.body[h : h + 4] = put_cmd_in_ert("\\IEEEauthorrefmark{")
3791 i = find_token(document.body, "\\begin_inset Flex Author Name", i)
3793 endi = find_end_of_inset(document.body, i)
3794 document.body[endi - 2 : endi + 1] = put_cmd_in_ert("}")
3795 document.body[i : i + 4] = put_cmd_in_ert("\\IEEEauthorblockN{")
3798 j = find_token(document.body, "\\begin_inset Flex Author Affiliation", j)
3800 endj = find_end_of_inset(document.body, j)
3801 document.body[endj - 2 : endj + 1] = put_cmd_in_ert("}")
3802 document.body[j : j + 4] = put_cmd_in_ert("\\IEEEauthorblockA{")
3804 if i == -1 and j == -1 and h == -1:
3808 def revert_kurier_fonts(document):
3809 " Revert kurier font definition to LaTeX "
3811 i = find_token(document.header, "\\font_math", 0)
3813 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
3814 val = get_value(document.header, "\\font_math", i)
3815 if val == "kurier-math":
3816 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
3817 "\\usepackage[math]{kurier}\n" \
3818 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
3819 document.header[i] = "\\font_math auto"
3821 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
3822 kurier_fonts = ["kurier", "kurierc", "kurierl", "kurierlc"]
3823 k = find_token(document.header, "\\font_sans kurier", 0)
3825 sf = get_value(document.header, "\\font_sans", k)
3826 if sf in kurier_fonts:
3827 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
3828 document.header[k] = "\\font_sans default"
3830 def revert_iwona_fonts(document):
3831 " Revert iwona font definition to LaTeX "
3833 i = find_token(document.header, "\\font_math", 0)
3835 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
3836 val = get_value(document.header, "\\font_math", i)
3837 if val == "iwona-math":
3838 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
3839 "\\usepackage[math]{iwona}\n" \
3840 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
3841 document.header[i] = "\\font_math auto"
3843 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
3844 iwona_fonts = ["iwona", "iwonac", "iwonal", "iwonalc"]
3845 k = find_token(document.header, "\\font_sans iwona", 0)
3847 sf = get_value(document.header, "\\font_sans", k)
3848 if sf in iwona_fonts:
3849 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
3850 document.header[k] = "\\font_sans default"
3853 def revert_new_libertines(document):
3854 " Revert new libertine font definition to LaTeX "
3856 if find_token(document.header, "\\use_non_tex_fonts true", 0) != -1:
3859 i = find_token(document.header, "\\font_typewriter libertine-mono", 0)
3861 preamble = "\\usepackage"
3862 sc = find_token(document.header, "\\font_tt_scale", 0)
3864 scval = get_value(document.header, "\\font_tt_scale", sc)
3866 preamble += "[scale=%f]" % (float(scval) / 100)
3867 document.header[sc] = "\\font_tt_scale 100"
3868 preamble += "{libertineMono-type1}"
3869 add_to_preamble(document, [preamble])
3870 document.header[i] = "\\font_typewriter default"
3872 k = find_token(document.header, "\\font_sans biolinum", 0)
3874 preamble = "\\usepackage"
3876 j = find_token(document.header, "\\font_osf true", 0)
3881 sc = find_token(document.header, "\\font_sf_scale", 0)
3883 scval = get_value(document.header, "\\font_sf_scale", sc)
3885 options += ",scale=%f" % (float(scval) / 100)
3886 document.header[sc] = "\\font_sf_scale 100"
3888 preamble += "[" + options +"]"
3889 preamble += "{biolinum-type1}"
3890 add_to_preamble(document, [preamble])
3891 document.header[k] = "\\font_sans default"
3894 def convert_lyxframes(document):
3895 " Converts old beamer frames to new style "
3897 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3898 if document.textclass not in beamer_classes:
3901 framebeg = ["BeginFrame", "BeginPlainFrame"]
3902 frameend = ["Frame", "PlainFrame", "EndFrame", "BeginFrame", "BeginPlainFrame", "AgainFrame",
3903 "Section", "Section*", "Subsection", "Subsection*", "Subsubsection", "Subsubsection*"]
3904 for lay in framebeg:
3907 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
3910 parent = get_containing_layout(document.body, i)
3911 if parent == False or parent[1] != i:
3912 document.warning("Wrong parent layout!")
3915 frametype = parent[0]
3919 # Step I: Convert ERT arguments
3920 # FIXME: See restrictions in convert_beamerframeargs method
3921 ertend = convert_beamerframeargs(document, i, parbeg)
3924 # Step II: Now rename the layout and convert the title to an argument
3925 j = find_end_of_layout(document.body, i)
3926 document.body[j : j + 1] = ['\\end_layout', '', '\\end_inset', '', '\\end_layout']
3927 if lay == "BeginFrame":
3928 document.body[i] = "\\begin_layout Frame"
3930 document.body[i] = "\\begin_layout PlainFrame"
3931 document.body[ertend + 1 : ertend + 1] = ['\\begin_inset Argument 4',
3932 'status open', '', '\\begin_layout Plain Layout']
3933 # Step III: find real frame end
3937 fend = find_token(document.body, "\\begin_layout", jj)
3939 document.warning("Malformed LyX document: No real frame end!")
3941 val = get_value(document.body, "\\begin_layout", fend)
3942 if val not in frameend:
3945 old = document.body[fend]
3946 if val == frametype:
3947 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
3948 # consider explicit EndFrames between two identical frame types
3949 elif val == "EndFrame":
3950 nextlayout = find_token(document.body, "\\begin_layout", fend + 1)
3951 if nextlayout != -1 and get_value(document.body, "\\begin_layout", nextlayout) == frametype:
3952 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
3954 document.body[fend : fend] = ['\\end_deeper']
3956 document.body[fend : fend] = ['\\end_deeper']
3957 document.body[j + 1 : j + 1] = ['', '\\begin_deeper']
3962 def remove_endframes(document):
3963 " Remove deprecated beamer endframes "
3965 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3966 if document.textclass not in beamer_classes:
3971 i = find_token_exact(document.body, "\\begin_layout EndFrame", i)
3974 j = find_end_of_layout(document.body, i)
3976 document.warning("Malformed LyX document: Missing \\end_layout to EndFrame")
3979 del document.body[i : j + 1]
3982 def revert_powerdot_flexes(document):
3983 " Reverts powerdot flex insets "
3985 if document.textclass != "powerdot":
3988 flexes = {"Onslide" : "\\onslide",
3989 "Onslide*" : "\\onslide*",
3990 "Onslide+" : "\\onslide+"}
3991 rx = re.compile(r'^\\begin_inset Flex (.+)$')
3995 i = find_token(document.body, "\\begin_inset Flex", i)
3998 m = rx.match(document.body[i])
4000 flextype = m.group(1)
4001 z = find_end_of_inset(document.body, i)
4003 document.warning("Can't find end of Flex " + flextype + " inset.")
4006 if flextype in flexes:
4007 pre = put_cmd_in_ert(flexes[flextype])
4008 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
4010 argend = find_end_of_inset(document.body, arg)
4012 document.warning("Can't find end of Argument!")
4015 # Find containing paragraph layout
4016 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
4017 endPlain = find_end_of_layout(document.body, beginPlain)
4018 argcontent = document.body[beginPlain + 1 : endPlain]
4020 z = z - len(document.body[arg : argend + 1])
4022 del document.body[arg : argend + 1]
4023 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
4024 pre += put_cmd_in_ert("{")
4025 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4026 endPlain = find_end_of_layout(document.body, beginPlain)
4028 z = z - len(document.body[i : beginPlain + 1])
4030 document.body[i : beginPlain + 1] = pre
4031 post = put_cmd_in_ert("}")
4032 document.body[z - 2 : z + 1] = post
4036 def revert_powerdot_pause(document):
4037 " Reverts powerdot pause layout to ERT "
4039 if document.textclass != "powerdot":
4044 i = find_token(document.body, "\\begin_layout Pause", i)
4047 j = find_end_of_layout(document.body, i)
4049 document.warning("Malformed LyX document: Can't find end of Pause layout")
4053 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\pause")
4054 for p in range(i, j):
4057 arg = find_token(document.body, "\\begin_inset Argument 1", i, j)
4059 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4060 endPlain = find_end_of_layout(document.body, beginPlain)
4061 endInset = find_end_of_inset(document.body, p)
4062 content = document.body[beginPlain + 1 : endPlain]
4064 endlay = endlay - len(document.body[p : endInset + 1])
4066 del document.body[p : endInset + 1]
4067 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4069 document.body[i : i + 1] = subst
4073 def revert_powerdot_itemargs(document):
4074 " Reverts powerdot item arguments to ERT "
4076 if document.textclass != "powerdot":
4080 list_layouts = ["Itemize", "ItemizeType1", "Enumerate", "EnumerateType1"]
4081 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4084 i = find_token(document.body, "\\begin_inset Argument", i)
4087 # Find containing paragraph layout
4088 parent = get_containing_layout(document.body, i)
4090 document.warning("Malformed LyX document: Can't find parent paragraph layout")
4095 realparbeg = parent[3]
4096 layoutname = parent[0]
4098 for p in range(parbeg, parend):
4102 if layoutname in list_layouts:
4103 m = rx.match(document.body[p])
4106 if argnr == "item:1":
4107 j = find_end_of_inset(document.body, i)
4108 # Find containing paragraph layout
4109 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4110 endPlain = find_end_of_layout(document.body, beginPlain)
4111 content = document.body[beginPlain + 1 : endPlain]
4112 del document.body[i:j+1]
4113 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4114 document.body[realparbeg : realparbeg] = subst
4115 elif argnr == "item:2":
4116 j = find_end_of_inset(document.body, i)
4117 # Find containing paragraph layout
4118 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4119 endPlain = find_end_of_layout(document.body, beginPlain)
4120 content = document.body[beginPlain + 1 : endPlain]
4121 del document.body[i:j+1]
4122 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
4123 document.body[realparbeg : realparbeg] = subst
4128 def revert_powerdot_columns(document):
4129 " Reverts powerdot twocolumn to TeX-code "
4130 if document.textclass != "powerdot":
4133 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4136 i = find_token(document.body, "\\begin_layout Twocolumn", i)
4139 j = find_end_of_layout(document.body, i)
4141 document.warning("Malformed LyX document: Can't find end of Twocolumn layout")
4145 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
4146 endlay += len(put_cmd_in_ert("}"))
4147 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\twocolumn")
4148 for p in range(i, j):
4151 m = rx.match(document.body[p])
4155 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4156 endPlain = find_end_of_layout(document.body, beginPlain)
4157 endInset = find_end_of_inset(document.body, p)
4158 content = document.body[beginPlain + 1 : endPlain]
4160 endlay = endlay - len(document.body[p : endInset + 1])
4162 del document.body[p : endInset + 1]
4163 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4165 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4166 endPlain = find_end_of_layout(document.body, beginPlain)
4167 endInset = find_end_of_inset(document.body, p)
4168 content = document.body[beginPlain + 1 : endPlain]
4170 endlay = endlay - len(document.body[p : endInset + 1])
4172 del document.body[p : endInset + 1]
4173 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
4175 subst += put_cmd_in_ert("{")
4176 document.body[i : i + 1] = subst
4180 def revert_mbox_fbox(document):
4181 'Convert revert mbox/fbox boxes to TeX-code'
4184 i = find_token(document.body, "\\begin_inset Box", i)
4187 j = find_token(document.body, "width", i)
4189 document.warning("Malformed LyX document: Can't find box width")
4191 width = get_value(document.body, "width", j)
4192 k = find_end_of_inset(document.body, j)
4194 document.warning("Malformed LyX document: Can't find end of box inset")
4197 BeginLayout = find_token(document.body, "\\begin_layout Plain Layout", j)
4198 EndLayout = find_token(document.body, "\\end_layout", BeginLayout)
4199 # replace if width is ""
4201 document.body[EndLayout:k + 1] = put_cmd_in_ert("}")
4202 if document.body[i] == "\\begin_inset Box Frameless":
4203 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\mbox{")
4204 if document.body[i] == "\\begin_inset Box Boxed":
4205 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\fbox{")
4209 def revert_starred_caption(document):
4210 " Reverts unnumbered longtable caption insets "
4214 i = find_token(document.body, "\\begin_inset Caption LongTableNoNumber", i)
4217 # This is not equivalent, but since the caption inset is a full blown
4218 # text inset a true conversion to ERT is too difficult.
4219 document.body[i] = "\\begin_inset Caption Standard"
4223 def revert_forced_local_layout(document):
4226 i = find_token(document.header, "\\begin_forced_local_layout", i)
4229 j = find_end_of(document.header, i, "\\begin_forced_local_layout", "\\end_forced_local_layout")
4231 # this should not happen
4233 regexp = re.compile(r'\s*forcelocal', re.IGNORECASE)
4234 k = find_re(document.header, regexp, i, j)
4236 del document.header[k]
4238 k = find_re(document.header, regexp, i, j)
4239 k = find_token(document.header, "\\begin_local_layout", 0)
4241 document.header[i] = "\\begin_local_layout"
4242 document.header[j] = "\\end_local_layout"
4244 l = find_end_of(document.header, k, "\\begin_local_layout", "\\end_local_layout")
4246 # this should not happen
4248 lines = document.header[i+1 : j]
4250 document.header[k+1 : k+1] = lines
4251 document.header[i : j ] = []
4253 document.header[i : j ] = []
4254 document.header[k+1 : k+1] = lines
4257 def revert_aa1(document):
4258 " Reverts InsetArguments of aa to TeX-code "
4259 if document.textclass == "aa":
4263 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4265 revert_Argument_to_TeX_brace(document, i, 0, 1, 4, False, False)
4271 def revert_aa2(document):
4272 " Reverts InsetArguments of aa to TeX-code "
4273 if document.textclass == "aa":
4277 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4279 document.body[i] = "\\begin_layout Abstract"
4285 def revert_tibetan(document):
4286 "Set the document language for Tibetan to English"
4288 if document.language == "tibetan":
4289 document.language = "english"
4290 i = find_token(document.header, "\\language", 0)
4292 document.header[i] = "\\language english"
4294 while j < len(document.body):
4295 j = find_token(document.body, "\\lang tibetan", j)
4297 document.body[j] = document.body[j].replace("\\lang tibetan", "\\lang english")
4300 j = len(document.body)
4309 # The idea here is that we will have a sequence of chunk paragraphs.
4310 # We want to convert them to paragraphs in one or several chunk insets.
4311 # Individual chunks are terminated by the character @ on the last line.
4312 # This line will be discarded, and following lines are treated as new
4313 # chunks, which go into their own insets.
4314 # The first line of a chunk should look like: <<CONTENT>>=
4315 # We will discard the delimiters, and put the CONTENT into the
4316 # optional argument of the inset, if the CONTENT is non-empty.
4317 def convert_chunks(document):
4318 first_re = re.compile(r'<<(.*)>>=(.*)')
4321 # find start of a block of chunks
4322 i = find_token(document.body, "\\begin_layout Chunk", file_pos)
4328 chunk_started = False
4331 # process the one we just found
4332 j = find_end_of_layout(document.body, i)
4334 document.warning("Malformed LyX documents. Can't find end of Chunk layout!")
4335 # there is no point continuing, as we will run into the same error again.
4337 this_chunk = "".join(document.body[i + 1:j])
4339 # there may be empty lines between chunks
4340 # we just skip them.
4341 if not chunk_started:
4342 if this_chunk != "":
4344 chunk_started = True
4347 contents.append(document.body[i + 1:j])
4349 # look for potential chunk terminator
4350 # on the last line of the chunk paragraph
4351 if document.body[j - 1] == "@":
4354 # look for subsequent chunk paragraph
4355 i = find_token(document.body, "\\begin_layout", j)
4359 if get_value(document.body, "\\begin_layout", i) != "Chunk":
4362 file_pos = end = j + 1
4364 # The last chunk should simply have an "@" in it
4365 # or at least end with "@" (can happen if @ is
4366 # preceded by a newline)
4367 lastpar = ''.join(contents[-1])
4368 if not lastpar.endswith("@"):
4369 document.warning("Unexpected chunk content: chunk not terminated by '@'!")
4373 # chunk par only contains "@". Just drop it.
4376 # chunk par contains more. Only drop the "@".
4379 # The first line should look like: <<CONTENT>>=
4380 # We want the CONTENT
4381 optarg = ' '.join(contents[0])
4383 # We can already have real chunk content in
4384 # the first par (separated from the options by a newline).
4385 # We collect such stuff to re-insert it later.
4388 match = first_re.search(optarg)
4390 optarg = match.groups()[0]
4391 if match.groups()[1] != "":
4393 for c in contents[0]:
4394 if c.endswith(">>="):
4398 postoptstuff.append(c)
4399 # We have stripped everything. This can be deleted.
4402 newstuff = ['\\begin_layout Standard',
4403 '\\begin_inset Flex Chunk',
4405 '\\begin_layout Plain Layout', '']
4407 # If we have a non-empty optional argument, insert it.
4408 if match and optarg != "":
4410 ['\\begin_inset Argument 1',
4412 '\\begin_layout Plain Layout',
4417 # Since we already opened a Plain layout, the first paragraph
4418 # does not need to do that.
4421 newstuff.extend(postoptstuff)
4422 newstuff.append('\\end_layout')
4426 newstuff.extend(['', '\\begin_layout Plain Layout', ''])
4430 newstuff.append('\\end_layout')
4432 newstuff.extend(['', '\\end_inset', '', '\\end_layout', ''])
4434 document.body[start:end] = newstuff
4436 file_pos += len(newstuff) - (end - start)
4439 def revert_chunks(document):
4442 i = find_token(document.body, "\\begin_inset Flex Chunk", i)
4446 iend = find_end_of_inset(document.body, i)
4448 document.warning("Can't find end of Chunk!")
4452 # Look for optional argument
4454 ostart = find_token(document.body, "\\begin_inset Argument 1", i, iend)
4456 oend = find_end_of_inset(document.body, ostart)
4457 k = find_token(document.body, "\\begin_layout Plain Layout", ostart, oend)
4459 document.warning("Malformed LyX document: Can't find argument contents!")
4461 m = find_end_of_layout(document.body, k)
4462 optarg = "".join(document.body[k+1:m])
4465 # We now remove the optional argument, so we have something
4466 # uniform on which to work
4467 document.body[ostart : oend + 1] = []
4468 # iend is now invalid
4469 iend = find_end_of_inset(document.body, i)
4471 retval = get_containing_layout(document.body, i)
4473 document.warning("Can't find containing layout for Chunk!")
4476 (lname, lstart, lend, pstart) = retval
4477 # we now want to work through the various paragraphs, and collect their contents
4481 k = find_token(document.body, "\\begin_layout Plain Layout", k, lend)
4484 j = find_end_of_layout(document.body, k)
4486 document.warning("Can't find end of layout inside chunk!")
4488 parlist.append(document.body[k+1:j])
4490 # we now need to wrap all of these paragraphs in chunks
4493 newlines.extend(["\\begin_layout Chunk", "", "<<" + optarg + ">>=", "\\end_layout", ""])
4494 for stuff in parlist:
4495 newlines.extend(["\\begin_layout Chunk"] + stuff + ["\\end_layout", ""])
4496 newlines.extend(["\\begin_layout Chunk", "", "@", "\\end_layout", ""])
4497 # replace old content with new content
4498 document.body[lstart : lend + 1] = newlines
4499 i = lstart + len(newlines)
4506 supported_versions = ["2.1.0","2.1"]
4509 [415, [convert_undertilde]],
4511 [417, [convert_japanese_encodings]],
4512 [418, [convert_justification]],
4514 [420, [convert_biblio_style]],
4515 [421, [convert_longtable_captions]],
4516 [422, [convert_use_packages]],
4517 [423, [convert_use_mathtools]],
4518 [424, [convert_cite_engine_type]],
4519 # No convert_cancel, since cancel will be loaded automatically
4520 # in format 425 without any possibility to switch it off.
4521 # This has been fixed in format 464.
4525 [428, [convert_cell_rotation]],
4526 [429, [convert_table_rotation]],
4527 [430, [convert_listoflistings]],
4528 [431, [convert_use_amssymb]],
4530 [433, [convert_armenian]],
4538 [441, [convert_mdnomath]],
4543 [446, [convert_latexargs]],
4544 [447, [convert_IEEEtran, convert_AASTeX, convert_AGUTeX, convert_IJMP, convert_SIGPLAN, convert_SIGGRAPH, convert_EuropeCV, convert_Initials, convert_ModernCV]],
4545 [448, [convert_literate]],
4548 [451, [convert_beamerargs, convert_againframe_args, convert_corollary_args, convert_quote_args]],
4549 [452, [convert_beamerblocks]],
4550 [453, [convert_use_stmaryrd]],
4551 [454, [convert_overprint]],
4553 [456, [convert_epigraph]],
4554 [457, [convert_use_stackrel]],
4555 [458, [convert_captioninsets, convert_captionlayouts]],
4560 [463, [convert_encodings]],
4561 [464, [convert_use_cancel]],
4562 [465, [convert_lyxframes, remove_endframes]],
4568 [471, [convert_cite_engine_type_default]],
4571 [474, [convert_chunks]],
4575 [473, [revert_chunks]],
4576 [472, [revert_tibetan]],
4577 [471, [revert_aa1,revert_aa2]],
4578 [470, [revert_cite_engine_type_default]],
4579 [469, [revert_forced_local_layout]],
4580 [468, [revert_starred_caption]],
4581 [467, [revert_mbox_fbox]],
4582 [466, [revert_iwona_fonts]],
4583 [465, [revert_powerdot_flexes, revert_powerdot_pause, revert_powerdot_itemargs, revert_powerdot_columns]],
4585 [463, [revert_use_cancel]],
4586 [462, [revert_encodings]],
4587 [461, [revert_new_libertines]],
4588 [460, [revert_kurier_fonts]],
4589 [459, [revert_IEEEtran_3]],
4590 [458, [revert_fragileframe, revert_newframes]],
4591 [457, [revert_captioninsets, revert_captionlayouts]],
4592 [456, [revert_use_stackrel]],
4593 [455, [revert_epigraph]],
4594 [454, [revert_frametitle]],
4595 [453, [revert_overprint]],
4596 [452, [revert_use_stmaryrd]],
4597 [451, [revert_beamerblocks]],
4598 [450, [revert_beamerargs, revert_beamerargs2, revert_beamerargs3, revert_beamerflex]],
4599 [449, [revert_garamondx, revert_garamondx_newtxmath]],
4600 [448, [revert_itemargs]],
4601 [447, [revert_literate]],
4602 [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]],
4603 [445, [revert_latexargs]],
4604 [444, [revert_uop]],
4605 [443, [revert_biolinum]],
4607 [441, [revert_newtxmath]],
4608 [440, [revert_mdnomath]],
4609 [439, [revert_mathfonts]],
4610 [438, [revert_minionpro]],
4611 [437, [revert_ipadeco, revert_ipachar]],
4612 [436, [revert_texgyre]],
4613 [435, [revert_mathdesign]],
4614 [434, [revert_txtt]],
4615 [433, [revert_libertine]],
4616 [432, [revert_armenian]],
4617 [431, [revert_languages, revert_ancientgreek]],
4618 [430, [revert_use_amssymb]],
4619 [429, [revert_listoflistings]],
4620 [428, [revert_table_rotation]],
4621 [427, [revert_cell_rotation]],
4622 [426, [revert_tipa]],
4623 [425, [revert_verbatim]],
4624 [424, [revert_cancel]],
4625 [423, [revert_cite_engine_type]],
4626 [422, [revert_use_mathtools]],
4627 [421, [revert_use_packages]],
4628 [420, [revert_longtable_captions]],
4629 [419, [revert_biblio_style]],
4630 [418, [revert_australian]],
4631 [417, [revert_justification]],
4632 [416, [revert_japanese_encodings]],
4633 [415, [revert_negative_space, revert_math_spaces]],
4634 [414, [revert_undertilde]],
4635 [413, [revert_visible_space]]
4639 if __name__ == "__main__":