1 # -*- coding: utf-8 -*-
2 # This file is part of lyx2lyx
3 # Copyright (C) 2011 The LyX team
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 """ Convert files to the file format generated by LyX 2.1"""
25 # Uncomment only what you need to import, please.
27 from parser_tools import count_pars_in_inset, del_token, find_token, find_token_exact, \
28 find_token_backwards, find_end_of, find_end_of_inset, find_end_of_layout, \
29 find_end_of_sequence, find_re, get_option_value, get_containing_layout, \
30 get_containing_inset, get_value, get_quoted_value, set_option_value
32 #from parser_tools import find_token, find_end_of, find_tokens, \
33 #find_end_of_inset, find_end_of_layout, \
34 #is_in_inset, del_token, check_token
36 from lyx2lyx_tools import add_to_preamble, put_cmd_in_ert, get_ert
38 #from lyx2lyx_tools import insert_to_preamble, \
39 # lyx2latex, latex_length, revert_flex_inset, \
40 # revert_font_attrs, hex2ratio, str2bool
42 ####################################################################
43 # Private helper functions
45 #def remove_option(lines, m, option):
46 #''' removes option from line m. returns whether we did anything '''
47 #l = lines[m].find(option)
50 #val = lines[m][l:].split('"')[1]
51 #lines[m] = lines[m][:l - 1] + lines[m][l+len(option + '="' + val + '"'):]
55 def revert_Argument_to_TeX_brace(document, line, endline, n, nmax, environment, opt):
57 Reverts an InsetArgument to TeX-code
59 revert_Argument_to_TeX_brace(document, LineOfBegin, LineOfEnd, StartArgument, EndArgument, isEnvironment, isOpt)
60 LineOfBegin is the line of the \\begin_layout or \\begin_inset statement
61 LineOfEnd is the line of the \end_layout or \end_inset statement, if "0" is given, the end of the file is used instead
62 StartArgument is the number of the first argument that needs to be converted
63 EndArgument is the number of the last argument that needs to be converted or the last defined one
64 isEnvironment must be true, if the layout is for a LaTeX environment
65 isOpt must be true, if the argument is an optional one
69 while lineArg != -1 and n < nmax + 1:
70 lineArg = find_token(document.body, "\\begin_inset Argument " + str(n), line)
71 if lineArg > endline and endline != 0:
74 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", lineArg)
75 # we have to assure that no other inset is in the Argument
76 beginInset = find_token(document.body, "\\begin_inset", beginPlain)
77 endInset = find_token(document.body, "\\end_inset", beginPlain)
80 while beginInset < endInset and beginInset != -1:
81 beginInset = find_token(document.body, "\\begin_inset", k)
82 endInset = find_token(document.body, "\\end_inset", l)
85 if environment == False:
87 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}{")
88 del(document.body[lineArg : beginPlain + 1])
91 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("]")
92 document.body[lineArg : beginPlain + 1] = put_cmd_in_ert("[")
95 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}")
96 document.body[lineArg : beginPlain + 1] = put_cmd_in_ert("{")
102 def convert_TeX_brace_to_Argument(document, line, n, nmax, inset, environment, opt):
104 Converts TeX code for mandatory arguments to an InsetArgument
105 The conversion of TeX code for optional arguments must be done with another routine
106 !!! Be careful if the braces are different in your case as expected here:
107 - "}{" separates mandatory arguments of commands
108 - "}" + "{" separates mandatory arguments of commands
109 - "}" + " " + "{" separates mandatory arguments of commands
110 - { and } surround a mandatory argument of an environment
112 convert_TeX_brace_to_Argument(document, LineOfBeginLayout/Inset, StartArgument, EndArgument, isInset, isEnvironment, isOpt)
113 LineOfBeginLayout/Inset is the line of the \\begin_layout or \\begin_inset statement
114 StartArgument is the number of the first ERT that needs to be converted
115 EndArgument is the number of the last ERT that needs to be converted
116 isInset must be true, if braces inside an InsetLayout needs to be converted
117 isEnvironment must be true, if the layout is for a LaTeX environment
118 isOpt must be true, if the argument is an optional one
120 Todo: this routine can currently handle only one mandatory argument of environments
123 end_layout = find_end_of_layout(document.body, line)
128 lineERT = find_token(document.body, "\\begin_inset ERT", lineERT, end_layout)
131 if environment == False:
132 end_ERT = find_end_of_inset(document.body, lineERT)
134 document.warning("Can't find end of ERT!!")
136 # Note that this only checks for ][ or }{ at the beginning of a line
138 bracePair = find_token(document.body, "][", lineERT, end_ERT)
140 bracePair = find_token(document.body, "}{", lineERT, end_ERT)
142 end = find_token(document.body, "\\end_inset", bracePair)
143 document.body[lineERT : end_ERT + 1] = ["\\end_layout", "", "\\end_inset"]
145 # in the case that n > 1 we have optional arguments before
146 # therefore detect them if any
148 # first check if there is an argument
149 lineArg = find_token(document.body, "\\begin_inset Argument", line)
150 if lineArg < lineERT and lineArg != -1:
151 # we have an argument, so now search backwards for its end
152 # we must now assure that we don't find other insets like e.g. a newline
153 endInsetArg = lineERT
154 endLayoutArg = endInsetArg
155 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
156 endInsetArg = endInsetArg - 1
157 endLayoutArg = endInsetArg
158 endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
159 endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
160 line = endInsetArg + 1
162 document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
164 document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
166 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
171 # no brace pair found
172 # now check the case that we have "}" + "{" in two ERTs
174 endBrace = find_token(document.body, "]", lineERT, end_layout)
176 endBrace = find_token(document.body, "}", lineERT, end_layout)
177 if endBrace == lineERT + 5:
179 beginBrace = find_token(document.body, "[", endBrace, end_layout)
181 beginBrace = find_token(document.body, "{", endBrace, end_layout)
182 # assure that the ERTs are consecutive (11 or 12 depending if there is a space between the ERTs or not)
183 if beginBrance != -1 and (beginBrace == endBrace + 11 or beginBrace == endBrace + 12):
184 end = find_token(document.body, "\\end_inset", beginBrace)
185 document.body[lineERT : end + 1] = ["\\end_layout", "", "\\end_inset"]
187 # in the case that n > 1 we have optional arguments before
188 # therefore detect them if any
190 # first check if there is an argument
191 lineArg = find_token(document.body, "\\begin_inset Argument", line)
192 if lineArg < lineERT and lineArg != -1:
193 # we have an argument, so now search backwards for its end
194 # we must now assure that we don't find other insets like e.g. a newline
195 endInsetArg = lineERT
196 endLayoutArg = endInsetArg
197 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
198 endInsetArg = endInsetArg - 1
199 endLayoutArg = endInsetArg
200 endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
201 endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
202 line = endInsetArg + 1
204 document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
206 document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
208 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
211 # set the line where the next argument will be inserted
212 if beginBrace == endBrace + 11:
220 if environment == True:
221 # FIXME This version of the routine does not check for and pass over
222 # arguments before n. So it attempts to process the argument in the
223 # document, no matter what has been specified.
225 # The other branch does do that, but probably that code would be better
226 # in a single location: Skip all those arguments, then process the ones
228 end_ERT = find_end_of_inset(document.body, lineERT)
230 document.warning("Can't find end of ERT!!")
232 # Note that this only checks for [ or { at the beginning of a line
234 opening = find_token(document.body, "[", lineERT, end_ERT)
236 opening = find_token(document.body, "{", lineERT, end_ERT)
238 lineERT2 = find_token(document.body, "\\begin_inset ERT", end_ERT, end_layout)
240 # argument in a single ERT
241 # strip off the opening bracket
242 document.body[opening] = document.body[opening][1:]
243 ertcontlastline = end_ERT - 3
244 if (opt and document.body[ertcontlastline].endswith("]")) or document.body[ertcontlastline].endswith("}"):
245 # strip off the closing bracket
246 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
247 end2 = find_token(document.body, "\\end_inset", ertcontlastline)
248 document.body[lineERT : lineERT + 1] = ["\\begin_inset Argument " + str(n)]
250 end_ERT2 = find_end_of_inset(document.body, lineERT2)
252 document.warning("Can't find end of second ERT!!")
255 closing = find_token(document.body, "]", lineERT2, end_ERT2)
257 closing = find_token(document.body, "}", lineERT2, end_ERT2)
258 if closing != -1: # assure that the "}" is in this ERT
259 end2 = find_token(document.body, "\\end_inset", closing)
260 document.body[lineERT2 : end2 + 1] = ["\\end_layout", "", "\\end_inset"]
261 document.body[lineERT : end_ERT + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
264 document.warning("Unable to process argument!")
268 ###############################################################################
270 ### Conversion and reversion routines
272 ###############################################################################
274 def revert_visible_space(document):
275 "Revert InsetSpace visible into its ERT counterpart"
278 i = find_token(document.body, "\\begin_inset space \\textvisiblespace{}", i)
281 end = find_end_of_inset(document.body, i)
282 subst = put_cmd_in_ert("\\textvisiblespace{}")
283 document.body[i:end + 1] = subst
286 undertilde_commands = ["utilde"]
287 def convert_undertilde(document):
288 " Load undertilde automatically "
289 i = find_token(document.header, "\\use_mathdots" , 0)
291 i = find_token(document.header, "\\use_mhchem" , 0)
293 i = find_token(document.header, "\\use_esint" , 0)
295 document.warning("Malformed LyX document: Can't find \\use_mathdots.")
297 j = find_token(document.preamble, "\\usepackage{undertilde}", 0)
299 # package was loaded in the preamble, convert this to header setting for round trip
300 document.header.insert(i + 1, "\\use_undertilde 2") # on
301 del document.preamble[j]
305 j = find_token(document.body, '\\begin_inset Formula', j)
308 k = find_end_of_inset(document.body, j)
310 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(j))
313 code = "\n".join(document.body[j:k])
314 for c in undertilde_commands:
315 if code.find("\\%s" % c) != -1:
316 # at least one of the commands was found - need to switch package off
317 document.header.insert(i + 1, "\\use_undertilde 0") # off
320 # no command was found - set to auto (bug 9069)
321 document.header.insert(i + 1, "\\use_undertilde 1") # auto
325 def revert_undertilde(document):
326 " Load undertilde if used in the document "
327 regexp = re.compile(r'(\\use_undertilde)')
328 i = find_re(document.header, regexp, 0)
329 value = "1" # default is auto
331 value = get_value(document.header, "\\use_undertilde" , i).split()[0]
332 del document.header[i]
333 if value == "2": # on
334 add_to_preamble(document, ["\\usepackage{undertilde}"])
335 elif value == "1": # auto
338 i = find_token(document.body, '\\begin_inset Formula', i)
341 j = find_end_of_inset(document.body, i)
343 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
346 code = "\n".join(document.body[i:j])
347 for c in undertilde_commands:
348 if code.find("\\%s" % c) != -1:
349 add_to_preamble(document, ["\\usepackage{undertilde}"])
354 def revert_negative_space(document):
355 "Revert InsetSpace negmedspace and negthickspace into its TeX-code counterpart"
360 i = find_token(document.body, "\\begin_inset space \\negmedspace{}", i)
362 j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
364 # load amsmath in the preamble if not already loaded if we are at the end of checking
366 i = find_token(document.header, "\\use_amsmath 2", 0)
368 add_to_preamble(document, ["\\@ifundefined{negthickspace}{\\usepackage{amsmath}}"])
372 end = find_end_of_inset(document.body, i)
373 subst = put_cmd_in_ert("\\negmedspace{}")
374 document.body[i:end + 1] = subst
375 j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
378 end = find_end_of_inset(document.body, j)
379 subst = put_cmd_in_ert("\\negthickspace{}")
380 document.body[j:end + 1] = subst
384 def revert_math_spaces(document):
385 "Revert formulas with protected custom space and protected hfills to TeX-code"
388 i = find_token(document.body, "\\begin_inset Formula", i)
391 j = document.body[i].find("\\hspace*")
393 end = find_end_of_inset(document.body, i)
394 subst = put_cmd_in_ert(document.body[i][21:])
395 document.body[i:end + 1] = subst
399 def convert_japanese_encodings(document):
400 " Rename the japanese encodings to names understood by platex "
402 "EUC-JP-pLaTeX": "euc",
404 "SJIS-pLaTeX": "sjis"
406 i = find_token(document.header, "\\inputencoding" , 0)
409 val = get_value(document.header, "\\inputencoding", i)
410 if val in list(jap_enc_dict.keys()):
411 document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
414 def revert_japanese_encodings(document):
415 " Revert the japanese encodings name changes "
417 "euc": "EUC-JP-pLaTeX",
419 "sjis": "SJIS-pLaTeX"
421 i = find_token(document.header, "\\inputencoding" , 0)
424 val = get_value(document.header, "\\inputencoding", i)
425 if val in list(jap_enc_dict.keys()):
426 document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
429 def convert_justification(document):
430 " Add the \\justification buffer param"
431 i = find_token(document.header, "\\suppress_date" , 0)
433 i = find_token(document.header, "\\paperorientation" , 0)
435 i = find_token(document.header, "\\use_indices" , 0)
437 i = find_token(document.header, "\\use_bibtopic" , 0)
439 document.warning("Malformed LyX document: Missing \\suppress_date.")
441 document.header.insert(i + 1, "\\justification true")
444 def revert_justification(document):
445 " Revert the \\justification buffer param"
446 if not del_token(document.header, '\\justification', 0):
447 document.warning("Malformed LyX document: Missing \\justification.")
450 def revert_australian(document):
451 "Set English language variants Australian and Newzealand to English"
453 if document.language == "australian" or document.language == "newzealand":
454 document.language = "english"
455 i = find_token(document.header, "\\language", 0)
457 document.header[i] = "\\language english"
460 j = find_token(document.body, "\\lang australian", j)
462 j = find_token(document.body, "\\lang newzealand", 0)
466 document.body[j] = document.body[j].replace("\\lang newzealand", "\\lang english")
468 document.body[j] = document.body[j].replace("\\lang australian", "\\lang english")
472 def convert_biblio_style(document):
473 "Add a sensible default for \\biblio_style based on the citation engine."
474 i = find_token(document.header, "\\cite_engine", 0)
476 engine = get_value(document.header, "\\cite_engine", i).split("_")[0]
477 style = {"basic": "plain", "natbib": "plainnat", "jurabib": "jurabib"}
478 document.header.insert(i + 1, "\\biblio_style " + style[engine])
481 def revert_biblio_style(document):
482 "BibTeX insets with default option use the style defined by \\biblio_style."
483 i = find_token(document.header, "\\biblio_style" , 0)
485 document.warning("No \\biblio_style line. Nothing to do.")
488 default_style = get_value(document.header, "\\biblio_style", i)
489 del document.header[i]
491 # We are looking for bibtex insets having the default option
494 i = find_token(document.body, "\\begin_inset CommandInset bibtex", i)
497 j = find_end_of_inset(document.body, i)
499 document.warning("Malformed LyX document: Can't find end of bibtex inset at line " + str(i))
502 k = find_token(document.body, "options", i, j)
504 options = get_quoted_value(document.body, "options", k)
505 if "default" in options.split(","):
506 document.body[k] = 'options "%s"' \
507 % options.replace("default", default_style)
511 def handle_longtable_captions(document, forward):
514 begin_table = find_token(document.body, '<lyxtabular version=', begin_table)
515 if begin_table == -1:
517 end_table = find_end_of(document.body, begin_table, '<lyxtabular', '</lyxtabular>')
519 document.warning("Malformed LyX document: Could not find end of table.")
522 fline = find_token(document.body, "<features", begin_table, end_table)
524 document.warning("Can't find features for inset at line " + str(begin_table))
527 p = document.body[fline].find("islongtable")
532 numrows = get_option_value(document.body[begin_table], "rows")
534 numrows = int(numrows)
536 document.warning(document.body[begin_table])
537 document.warning("Unable to determine rows!")
538 begin_table = end_table
540 begin_row = begin_table
541 for row in range(numrows):
542 begin_row = find_token(document.body, '<row', begin_row, end_table)
544 document.warning("Can't find row " + str(row + 1))
546 end_row = find_end_of(document.body, begin_row, '<row', '</row>')
548 document.warning("Can't find end of row " + str(row + 1))
551 if (get_option_value(document.body[begin_row], 'caption') == 'true' and
552 get_option_value(document.body[begin_row], 'endfirsthead') != 'true' and
553 get_option_value(document.body[begin_row], 'endhead') != 'true' and
554 get_option_value(document.body[begin_row], 'endfoot') != 'true' and
555 get_option_value(document.body[begin_row], 'endlastfoot') != 'true'):
556 document.body[begin_row] = set_option_value(document.body[begin_row], 'caption', 'true", endfirsthead="true')
557 elif get_option_value(document.body[begin_row], 'caption') == 'true':
558 if get_option_value(document.body[begin_row], 'endfirsthead') == 'true':
559 document.body[begin_row] = set_option_value(document.body[begin_row], 'endfirsthead', 'false')
560 if get_option_value(document.body[begin_row], 'endhead') == 'true':
561 document.body[begin_row] = set_option_value(document.body[begin_row], 'endhead', 'false')
562 if get_option_value(document.body[begin_row], 'endfoot') == 'true':
563 document.body[begin_row] = set_option_value(document.body[begin_row], 'endfoot', 'false')
564 if get_option_value(document.body[begin_row], 'endlastfoot') == 'true':
565 document.body[begin_row] = set_option_value(document.body[begin_row], 'endlastfoot', 'false')
567 # since there could be a tabular inside this one, we
568 # cannot jump to end.
572 def convert_longtable_captions(document):
573 "Add a firsthead flag to caption rows"
574 handle_longtable_captions(document, True)
577 def revert_longtable_captions(document):
578 "remove head/foot flag from caption rows"
579 handle_longtable_captions(document, False)
582 def convert_use_packages(document):
583 "use_xxx yyy => use_package xxx yyy"
584 packages = ["amsmath", "esint", "mathdots", "mhchem", "undertilde"]
586 i = find_token(document.header, "\\use_%s" % p, 0)
588 value = get_value(document.header, "\\use_%s" % p, i)
589 document.header[i] = "\\use_package %s %s" % (p, value)
592 def revert_use_packages(document):
593 "use_package xxx yyy => use_xxx yyy"
594 packages = ["amsmath", "esint", "mhchem", "mathdots", "undertilde"]
595 # the order is arbitrary for the use_package version, and not all packages need to be given.
596 # Ensure a complete list and correct order (important for older LyX versions and especially lyx2lyx)
597 # first loop: find line with first package
600 regexp = re.compile(r'(\\use_package\s+%s)' % p)
601 i = find_re(document.header, regexp, 0)
602 if i != -1 and (j < 0 or i < j):
604 # second loop: replace or insert packages in front of all existing ones
606 regexp = re.compile(r'(\\use_package\s+%s)' % p)
607 i = find_re(document.header, regexp, 0)
609 value = get_value(document.header, "\\use_package %s" % p, i).split()[1]
610 del document.header[i]
611 document.header.insert(j, "\\use_%s %s" % (p, value))
613 document.header.insert(j, "\\use_%s 1" % p)
617 def convert_use_package(document, pkg, commands, oldauto):
618 # oldauto defines how the version we are converting from behaves:
619 # if it is true, the old version uses the package automatically.
620 # if it is false, the old version never uses the package.
621 i = find_token(document.header, "\\use_package", 0)
623 document.warning("Malformed LyX document: Can't find \\use_package.")
625 j = find_token(document.preamble, "\\usepackage{" + pkg + "}", 0)
627 # package was loaded in the preamble, convert this to header setting for round trip
628 document.header.insert(i + 1, "\\use_package " + pkg + " 2") # on
629 del document.preamble[j]
630 # If oldauto is true we have two options:
631 # We can either set the package to auto - this is correct for files in
632 # format 425 to 463, and may create a conflict for older files which use
633 # any command in commands with a different definition.
634 # Or we can look whether any command in commands is used, and set it to
635 # auto if not and to off if yes. This will not create a conflict, but will
636 # create uncompilable documents for files in format 425 to 463, which use
637 # any command in commands.
638 # We choose the first option since its error is less likely.
640 document.header.insert(i + 1, "\\use_package " + pkg + " 1") # auto
644 j = find_token(document.body, '\\begin_inset Formula', j)
647 k = find_end_of_inset(document.body, j)
649 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(j))
652 code = "\n".join(document.body[j:k])
654 if code.find("\\%s" % c) != -1:
655 # at least one of the commands was found - need to switch package off
656 document.header.insert(i + 1, "\\use_package " + pkg + " 0") # off
659 # no command was found - set to auto (bug 9069)
660 document.header.insert(i + 1, "\\use_package " + pkg + " 1") # auto
663 def revert_use_package(document, pkg, commands, oldauto):
664 # oldauto defines how the version we are reverting to behaves:
665 # if it is true, the old version uses the package automatically.
666 # if it is false, the old version never uses the package.
667 regexp = re.compile(r'(\\use_package\s+%s)' % pkg)
668 i = find_re(document.header, regexp, 0)
669 value = "1" # default is auto
671 value = get_value(document.header, "\\use_package" , i).split()[1]
672 del document.header[i]
673 if value == "2": # on
674 add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
675 elif value == "1" and not oldauto: # auto
678 i = find_token(document.body, '\\begin_inset Formula', i)
681 j = find_end_of_inset(document.body, i)
683 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
686 code = "\n".join(document.body[i:j])
688 if code.find("\\%s" % c) != -1:
689 add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
694 mathtools_commands = ["mathclap", "mathllap", "mathrlap", \
695 "lgathered", "rgathered", "vcentcolon", "dblcolon", \
696 "coloneqq", "Coloneqq", "coloneq", "Coloneq", "eqqcolon", \
697 "Eqqcolon", "eqcolon", "Eqcolon", "colonapprox", \
698 "Colonapprox", "colonsim", "Colonsim"]
699 def convert_use_mathtools(document):
700 "insert use_package mathtools"
701 convert_use_package(document, "mathtools", mathtools_commands, False)
704 def revert_use_mathtools(document):
705 "remove use_package mathtools"
706 revert_use_package(document, "mathtools", mathtools_commands, False)
709 # commands provided by stmaryrd.sty but LyX uses other packages:
710 # boxdot lightning, bigtriangledown, bigtriangleup
711 stmaryrd_commands = ["shortleftarrow", "shortrightarrow", "shortuparrow", \
712 "shortdownarrow", "Yup", "Ydown", "Yleft", "Yright", \
713 "varcurlyvee", "varcurlywedge", "minuso", "baro", \
714 "sslash", "bbslash", "moo", "varotimes", "varoast", \
715 "varobar", "varodot", "varoslash", "varobslash", \
716 "varocircle", "varoplus", "varominus", "boxast", \
717 "boxbar", "boxslash", "boxbslash", "boxcircle", \
718 "boxbox", "boxempty", "merge", "vartimes", \
719 "fatsemi", "sswarrow", "ssearrow", "curlywedgeuparrow", \
720 "curlywedgedownarrow", "fatslash", "fatbslash", "lbag", \
721 "rbag", "varbigcirc", "leftrightarroweq", \
722 "curlyveedownarrow", "curlyveeuparrow", "nnwarrow", \
723 "nnearrow", "leftslice", "rightslice", "varolessthan", \
724 "varogreaterthan", "varovee", "varowedge", "talloblong", \
725 "interleave", "obar", "obslash", "olessthan", \
726 "ogreaterthan", "ovee", "owedge", "oblong", "inplus", \
727 "niplus", "nplus", "subsetplus", "supsetplus", \
728 "subsetpluseq", "supsetpluseq", "Lbag", "Rbag", \
729 "llbracket", "rrbracket", "llparenthesis", \
730 "rrparenthesis", "binampersand", "bindnasrepma", \
731 "trianglelefteqslant", "trianglerighteqslant", \
732 "ntrianglelefteqslant", "ntrianglerighteqslant", \
733 "llfloor", "rrfloor", "llceil", "rrceil", "arrownot", \
734 "Arrownot", "Mapstochar", "mapsfromchar", "Mapsfromchar", \
735 "leftrightarrowtriangle", "leftarrowtriangle", \
736 "rightarrowtriangle", \
737 "bigcurlyvee", "bigcurlywedge", "bigsqcap", "bigbox", \
738 "bigparallel", "biginterleave", "bignplus", \
739 "varcopyright", "longarrownot", "Longarrownot", \
740 "Mapsto", "mapsfrom", "Mapsfrom" "Longmapsto", \
741 "longmapsfrom", "Longmapsfrom"]
742 def convert_use_stmaryrd(document):
743 "insert use_package stmaryrd"
744 convert_use_package(document, "stmaryrd", stmaryrd_commands, False)
747 def revert_use_stmaryrd(document):
748 "remove use_package stmaryrd"
749 revert_use_package(document, "stmaryrd", stmaryrd_commands, False)
752 stackrel_commands = ["stackrel"]
753 def convert_use_stackrel(document):
754 "insert use_package stackrel"
755 convert_use_package(document, "stackrel", stackrel_commands, False)
758 def revert_use_stackrel(document):
759 "remove use_package stackrel"
760 revert_use_package(document, "stackrel", stackrel_commands, False)
763 def convert_cite_engine_type(document):
764 "Determine the \\cite_engine_type from the citation engine."
765 i = find_token(document.header, "\\cite_engine", 0)
768 engine = get_value(document.header, "\\cite_engine", i)
770 engine, type = engine.split("_")
772 type = {"basic": "numerical", "jurabib": "authoryear"}[engine]
773 document.header[i] = "\\cite_engine " + engine
774 document.header.insert(i + 1, "\\cite_engine_type " + type)
777 def revert_cite_engine_type(document):
778 "Natbib had the type appended with an underscore."
779 engine_type = "numerical"
780 i = find_token(document.header, "\\cite_engine_type" , 0)
782 document.warning("No \\cite_engine_type line. Assuming numerical.")
784 engine_type = get_value(document.header, "\\cite_engine_type", i)
785 del document.header[i]
787 # We are looking for the natbib citation engine
788 i = find_token(document.header, "\\cite_engine natbib", 0)
791 document.header[i] = "\\cite_engine natbib_" + engine_type
794 def convert_cite_engine_type_default(document):
795 "Convert \\cite_engine_type to default for the basic citation engine."
796 i = find_token(document.header, "\\cite_engine basic", 0)
799 i = find_token(document.header, "\\cite_engine_type" , 0)
802 document.header[i] = "\\cite_engine_type default"
805 def revert_cite_engine_type_default(document):
806 """Revert \\cite_engine_type default.
808 Revert to numerical for the basic cite engine, otherwise to authoryear."""
809 engine_type = "authoryear"
810 i = find_token(document.header, "\\cite_engine_type default" , 0)
813 j = find_token(document.header, "\\cite_engine basic", 0)
815 engine_type = "numerical"
816 document.header[i] = "\\cite_engine_type " + engine_type
819 cancel_commands = ["cancel", "bcancel", "xcancel", "cancelto"]
820 # this is the same, as revert_use_cancel() except for the default
821 def revert_cancel(document):
822 "add cancel to the preamble if necessary"
823 revert_use_package(document, "cancel", cancel_commands, False)
826 def revert_verbatim(document, starred = False):
827 " Revert verbatim environments completely to TeX-code. "
831 layout_name = "Verbatim"
832 latex_name = "verbatim"
834 layout_name = "Verbatim*"
835 latex_name = "verbatim*"
837 subst_end = ['\\end_layout', '', '\\begin_layout Plain Layout',
839 '\\begin_layout Plain Layout', '', '',
841 'end{%s}' % (latex_name),
842 '\\end_layout', '', '\\end_inset',
843 '', '', '\\end_layout']
844 subst_begin = ['\\begin_layout Standard', '\\noindent',
845 '\\begin_inset ERT', 'status open', '',
846 '\\begin_layout Plain Layout', '', '', '\\backslash',
847 'begin{%s}' % (latex_name),
848 '\\end_layout', '', '\\begin_layout Plain Layout', '']
851 i = find_token(document.body, "\\begin_layout %s" % (layout_name), i)
854 j = find_end_of_layout(document.body, i)
856 document.warning("Malformed LyX document: Can't find end of %s layout" \
860 # delete all line breaks insets (there are no other insets)
863 n = find_token(document.body, "\\begin_inset Newline newline", l, j)
865 n = find_token(document.body, "\\begin_inset Newline linebreak", l, j)
868 m = find_end_of_inset(document.body, n)
869 del(document.body[m:m+1])
870 document.body[n:n+1] = ['\\end_layout', '', '\\begin_layout Plain Layout']
872 # we deleted a line, so the end of the inset moved forward.
873 # FIXME But we also added some lines, didn't we? I think this
876 # consecutive verbatim environments need to be connected
877 k = find_token(document.body, "\\begin_layout %s" % (layout_name), j)
878 if k == j + 2 and consecutive == False:
880 document.body[j:j+1] = ['\\end_layout', '', '\\begin_layout Plain Layout']
881 document.body[i:i+1] = subst_begin
883 if k == j + 2 and consecutive == True:
884 document.body[j:j+1] = ['\\end_layout', '', '\\begin_layout Plain Layout']
885 del(document.body[i:i+1])
887 if k != j + 2 and consecutive == True:
888 document.body[j:j+1] = subst_end
889 # the next paragraph must not be indented
890 # FIXME This seems to be causing problems, because of the
891 # hardcoded use of 19. We should figure out exactly where
892 # this needs to go by searching for the right tag.
893 document.body[j+19:j+19] = ['\\noindent']
894 del(document.body[i:i+1])
898 document.body[j:j+1] = subst_end
899 # the next paragraph must not be indented
900 # FIXME This seems to be causing problems, because of the
901 # hardcoded use of 19. We should figure out exactly where
902 # this needs to go by searching for the right tag.
903 document.body[j+19:j+19] = ['\\noindent']
904 document.body[i:i+1] = subst_begin
907 def revert_tipa(document):
908 " Revert native TIPA insets to mathed or ERT. "
911 i = find_token(document.body, "\\begin_inset IPA", i)
914 j = find_end_of_inset(document.body, i)
916 document.warning("Malformed LyX document: Can't find end of IPA inset")
920 n = find_token(document.body, "\\begin_layout", i, j)
922 document.warning("Malformed LyX document: IPA inset has no embedded layout")
925 m = find_end_of_layout(document.body, n)
927 document.warning("Malformed LyX document: Can't find end of embedded layout")
930 content = document.body[n+1:m]
931 p = find_token(document.body, "\\begin_layout", m, j)
932 if p != -1 or len(content) > 1:
934 content = document.body[i+1:j]
936 # IPA insets with multiple pars need to be wrapped by \begin{IPA}...\end{IPA}
937 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}")
938 add_to_preamble(document, ["\\usepackage{tipa,tipx}"])
940 # single-par IPA insets can be reverted to mathed
941 document.body[i:j+1] = ["\\begin_inset Formula $\\text{\\textipa{" + content[0] + "}}$", "\\end_inset"]
945 def revert_cell_rotation(document):
946 "Revert cell rotations to TeX-code"
948 load_rotating = False
952 # first, let's find out if we need to do anything
953 i = find_token(document.body, '<cell ', i)
956 j = document.body[i].find('rotate="')
958 k = document.body[i].find('"', j + 8)
959 value = document.body[i][j + 8 : k]
961 rgx = re.compile(r' rotate="[^"]+?"')
962 # remove rotate option
963 document.body[i] = rgx.sub('', document.body[i])
965 rgx = re.compile(r' rotate="[^"]+?"')
966 document.body[i] = rgx.sub(' rotate="true"', document.body[i])
968 rgx = re.compile(r' rotate="[^"]+?"')
970 # remove rotate option
971 document.body[i] = rgx.sub('', document.body[i])
973 document.body[i + 5 : i + 5] = \
974 put_cmd_in_ert("\\end{turn}")
975 document.body[i + 4 : i + 4] = \
976 put_cmd_in_ert("\\begin{turn}{" + value + "}")
982 add_to_preamble(document, ["\\@ifundefined{turnbox}{\\usepackage{rotating}}{}"])
985 def convert_cell_rotation(document):
986 'Convert cell rotation statements from "true" to "90"'
990 # first, let's find out if we need to do anything
991 i = find_token(document.body, '<cell ', i)
994 j = document.body[i].find('rotate="true"')
996 rgx = re.compile(r'rotate="[^"]+?"')
997 # convert "true" to "90"
998 document.body[i] = rgx.sub('rotate="90"', document.body[i])
1003 def revert_table_rotation(document):
1004 "Revert table rotations to TeX-code"
1006 load_rotating = False
1010 # first, let's find out if we need to do anything
1011 i = find_token(document.body, '<features ', i)
1014 j = document.body[i].find('rotate="')
1016 end_table = find_token(document.body, '</lyxtabular>', j)
1017 k = document.body[i].find('"', j + 8)
1018 value = document.body[i][j + 8 : k]
1020 rgx = re.compile(r' rotate="[^"]+?"')
1021 # remove rotate option
1022 document.body[i] = rgx.sub('', document.body[i])
1024 rgx = re.compile(r'rotate="[^"]+?"')
1025 document.body[i] = rgx.sub('rotate="true"', document.body[i])
1027 rgx = re.compile(r' rotate="[^"]+?"')
1028 load_rotating = True
1029 # remove rotate option
1030 document.body[i] = rgx.sub('', document.body[i])
1032 document.body[end_table + 3 : end_table + 3] = \
1033 put_cmd_in_ert("\\end{turn}")
1034 document.body[i - 2 : i - 2] = \
1035 put_cmd_in_ert("\\begin{turn}{" + value + "}")
1041 add_to_preamble(document, ["\\@ifundefined{turnbox}{\\usepackage{rotating}}{}"])
1044 def convert_table_rotation(document):
1045 'Convert table rotation statements from "true" to "90"'
1049 # first, let's find out if we need to do anything
1050 i = find_token(document.body, '<features ', i)
1053 j = document.body[i].find('rotate="true"')
1055 rgx = re.compile(r'rotate="[^"]+?"')
1056 # convert "true" to "90"
1057 document.body[i] = rgx.sub('rotate="90"', document.body[i])
1062 def convert_listoflistings(document):
1063 'Convert ERT \lstlistoflistings to TOC lstlistoflistings inset'
1064 # We can support roundtrip because the command is so simple
1067 i = find_token(document.body, "\\begin_inset ERT", i)
1070 j = find_end_of_inset(document.body, i)
1072 document.warning("Malformed LyX document: Can't find end of ERT inset")
1075 ert = get_ert(document.body, i)
1076 if ert == "\\lstlistoflistings{}":
1077 document.body[i:j] = ["\\begin_inset CommandInset toc", "LatexCommand lstlistoflistings", ""]
1083 def revert_listoflistings(document):
1084 'Convert TOC lstlistoflistings inset to ERT lstlistoflistings'
1087 i = find_token(document.body, "\\begin_inset CommandInset toc", i)
1090 if document.body[i+1] == "LatexCommand lstlistoflistings":
1091 j = find_end_of_inset(document.body, i)
1093 document.warning("Malformed LyX document: Can't find end of TOC inset")
1096 subst = put_cmd_in_ert("\\lstlistoflistings{}")
1097 document.body[i:j+1] = subst
1098 add_to_preamble(document, ["\\usepackage{listings}"])
1102 def convert_use_amssymb(document):
1103 "insert use_package amssymb"
1104 regexp = re.compile(r'(\\use_package\s+amsmath)')
1105 i = find_re(document.header, regexp, 0)
1107 document.warning("Malformed LyX document: Can't find \\use_package amsmath.")
1109 value = get_value(document.header, "\\use_package" , i).split()[1]
1112 useamsmath = int(value)
1114 document.warning("Invalid \\use_package amsmath: " + value + ". Assuming auto.")
1116 j = find_token(document.preamble, "\\usepackage{amssymb}", 0)
1118 document.header.insert(i + 1, "\\use_package amssymb %d" % useamsmath)
1120 document.header.insert(i + 1, "\\use_package amssymb 2")
1121 del document.preamble[j]
1124 def revert_use_amssymb(document):
1125 "remove use_package amssymb"
1126 regexp1 = re.compile(r'(\\use_package\s+amsmath)')
1127 regexp2 = re.compile(r'(\\use_package\s+amssymb)')
1128 i = find_re(document.header, regexp1, 0)
1129 j = find_re(document.header, regexp2, 0)
1130 value1 = "1" # default is auto
1131 value2 = "1" # default is auto
1133 value1 = get_value(document.header, "\\use_package" , i).split()[1]
1135 value2 = get_value(document.header, "\\use_package" , j).split()[1]
1136 del document.header[j]
1137 if value1 != value2 and value2 == "2": # on
1138 add_to_preamble(document, ["\\usepackage{amssymb}"])
1141 def convert_use_cancel(document):
1142 "insert use_package cancel"
1143 convert_use_package(document, "cancel", cancel_commands, True)
1146 def revert_use_cancel(document):
1147 "remove use_package cancel"
1148 revert_use_package(document, "cancel", cancel_commands, True)
1151 def revert_ancientgreek(document):
1152 "Set the document language for ancientgreek to greek"
1154 if document.language == "ancientgreek":
1155 document.language = "greek"
1156 i = find_token(document.header, "\\language", 0)
1158 document.header[i] = "\\language greek"
1161 j = find_token(document.body, "\\lang ancientgreek", j)
1165 document.body[j] = document.body[j].replace("\\lang ancientgreek", "\\lang greek")
1169 def revert_languages(document):
1170 "Set the document language for new supported languages to English"
1173 "coptic", "divehi", "hindi", "kurmanji", "lao", "marathi", "occitan", "sanskrit",
1174 "syriac", "tamil", "telugu", "urdu"
1176 for n in range(len(languages)):
1177 if document.language == languages[n]:
1178 document.language = "english"
1179 i = find_token(document.header, "\\language", 0)
1181 document.header[i] = "\\language english"
1183 while j < len(document.body):
1184 j = find_token(document.body, "\\lang " + languages[n], j)
1186 document.body[j] = document.body[j].replace("\\lang " + languages[n], "\\lang english")
1189 j = len(document.body)
1192 def convert_armenian(document):
1193 "Use polyglossia and thus non-TeX fonts for Armenian"
1195 if document.language == "armenian":
1196 i = find_token(document.header, "\\use_non_tex_fonts", 0)
1198 document.header[i] = "\\use_non_tex_fonts true"
1201 def revert_armenian(document):
1202 "Use ArmTeX and thus TeX fonts for Armenian"
1204 if document.language == "armenian":
1205 i = find_token(document.header, "\\use_non_tex_fonts", 0)
1207 document.header[i] = "\\use_non_tex_fonts false"
1210 def revert_libertine(document):
1211 " Revert native libertine font definition to LaTeX "
1213 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1214 i = find_token(document.header, "\\font_roman libertine", 0)
1217 j = find_token(document.header, "\\font_osf true", 0)
1220 preamble = "\\usepackage"
1222 document.header[j] = "\\font_osf false"
1225 preamble += "[lining]"
1226 preamble += "{libertine-type1}"
1227 add_to_preamble(document, [preamble])
1228 document.header[i] = "\\font_roman default"
1231 def revert_txtt(document):
1232 " Revert native txtt font definition to LaTeX "
1234 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1235 i = find_token(document.header, "\\font_typewriter txtt", 0)
1237 preamble = "\\renewcommand{\\ttdefault}{txtt}"
1238 add_to_preamble(document, [preamble])
1239 document.header[i] = "\\font_typewriter default"
1242 def revert_mathdesign(document):
1243 " Revert native mathdesign font definition to LaTeX "
1245 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1251 i = find_token(document.header, "\\font_roman", 0)
1254 val = get_value(document.header, "\\font_roman", i)
1255 if val in list(mathdesign_dict.keys()):
1256 preamble = "\\usepackage[%s" % mathdesign_dict[val]
1258 j = find_token(document.header, "\\font_osf true", 0)
1261 document.header[j] = "\\font_osf false"
1262 l = find_token(document.header, "\\font_sc true", 0)
1265 document.header[l] = "\\font_sc false"
1267 preamble += ",expert"
1268 preamble += "]{mathdesign}"
1269 add_to_preamble(document, [preamble])
1270 document.header[i] = "\\font_roman default"
1273 def revert_texgyre(document):
1274 " Revert native TeXGyre font definition to LaTeX "
1276 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1277 texgyre_fonts = ["tgadventor", "tgbonum", "tgchorus", "tgcursor", \
1278 "tgheros", "tgpagella", "tgschola", "tgtermes"]
1279 i = find_token(document.header, "\\font_roman", 0)
1281 val = get_value(document.header, "\\font_roman", i)
1282 if val in texgyre_fonts:
1283 preamble = "\\usepackage{%s}" % val
1284 add_to_preamble(document, [preamble])
1285 document.header[i] = "\\font_roman default"
1286 i = find_token(document.header, "\\font_sans", 0)
1288 val = get_value(document.header, "\\font_sans", i)
1289 if val in texgyre_fonts:
1290 preamble = "\\usepackage{%s}" % val
1291 add_to_preamble(document, [preamble])
1292 document.header[i] = "\\font_sans default"
1293 i = find_token(document.header, "\\font_typewriter", 0)
1295 val = get_value(document.header, "\\font_typewriter", i)
1296 if val in texgyre_fonts:
1297 preamble = "\\usepackage{%s}" % val
1298 add_to_preamble(document, [preamble])
1299 document.header[i] = "\\font_typewriter default"
1302 def revert_ipadeco(document):
1303 " Revert IPA decorations to ERT "
1306 i = find_token(document.body, "\\begin_inset IPADeco", i)
1309 end = find_end_of_inset(document.body, i)
1311 document.warning("Can't find end of inset at line " + str(i))
1314 line = document.body[i]
1315 rx = re.compile(r'\\begin_inset IPADeco (.*)$')
1317 decotype = m.group(1)
1318 if decotype != "toptiebar" and decotype != "bottomtiebar":
1319 document.warning("Invalid IPADeco type: " + decotype)
1322 blay = find_token(document.body, "\\begin_layout Plain Layout", i, end)
1324 document.warning("Can't find layout for inset at line " + str(i))
1327 bend = find_end_of_layout(document.body, blay)
1329 document.warning("Malformed LyX document: Could not find end of IPADeco inset's layout.")
1332 substi = ["\\begin_inset ERT", "status collapsed", "",
1333 "\\begin_layout Plain Layout", "", "", "\\backslash",
1334 decotype + "{", "\\end_layout", "", "\\end_inset"]
1335 substj = ["\\size default", "", "\\begin_inset ERT", "status collapsed", "",
1336 "\\begin_layout Plain Layout", "", "}", "\\end_layout", "", "\\end_inset"]
1337 # do the later one first so as not to mess up the numbering
1338 document.body[bend:end + 1] = substj
1339 document.body[i:blay + 1] = substi
1340 i = end + len(substi) + len(substj) - (end - bend) - (blay - i) - 2
1341 add_to_preamble(document, "\\usepackage{tipa}")
1344 def revert_ipachar(document):
1345 ' Revert \\IPAChar to ERT '
1348 while i < len(document.body):
1349 m = re.match(r'(.*)\\IPAChar \\(\w+\{\w+\})(.*)', document.body[i])
1353 ipachar = m.group(2)
1356 '\\begin_inset ERT',
1357 'status collapsed', '',
1358 '\\begin_layout Standard',
1359 '', '', '\\backslash',
1364 document.body[i: i+1] = subst
1369 add_to_preamble(document, "\\usepackage{tone}")
1372 def revert_minionpro(document):
1373 " Revert native MinionPro font definition to LaTeX "
1375 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1376 i = find_token(document.header, "\\font_roman minionpro", 0)
1379 j = find_token(document.header, "\\font_osf true", 0)
1382 preamble = "\\usepackage"
1384 document.header[j] = "\\font_osf false"
1387 preamble += "{MinionPro}"
1388 add_to_preamble(document, [preamble])
1389 document.header[i] = "\\font_roman default"
1392 def revert_mathfonts(document):
1393 " Revert native math font definitions to LaTeX "
1395 i = find_token(document.header, "\\font_math", 0)
1398 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1399 val = get_value(document.header, "\\font_math", i)
1400 if val == "eulervm":
1401 add_to_preamble(document, "\\usepackage{eulervm}")
1402 elif val == "default":
1404 "lmodern": "\\renewcommand{\\rmdefault}{lmr}",
1405 "minionpro": "\\usepackage[onlytext,lf]{MinionPro}",
1406 "minionpro-osf": "\\usepackage[onlytext]{MinionPro}",
1407 "palatino": "\\renewcommand{\\rmdefault}{ppl}",
1408 "palatino-osf": "\\renewcommand{\\rmdefault}{pplj}",
1409 "times": "\\renewcommand{\\rmdefault}{ptm}",
1410 "utopia": "\\renewcommand{\\rmdefault}{futs}",
1411 "utopia-osf": "\\renewcommand{\\rmdefault}{futj}",
1413 j = find_token(document.header, "\\font_roman", 0)
1415 rm = get_value(document.header, "\\font_roman", j)
1416 k = find_token(document.header, "\\font_osf true", 0)
1419 if rm in list(mathfont_dict.keys()):
1420 add_to_preamble(document, mathfont_dict[rm])
1421 document.header[j] = "\\font_roman default"
1423 document.header[k] = "\\font_osf false"
1424 del document.header[i]
1427 def revert_mdnomath(document):
1428 " Revert mathdesign and fourier without math "
1430 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1432 "md-charter": "mdbch",
1433 "md-utopia": "mdput",
1434 "md-garamond": "mdugm"
1436 i = find_token(document.header, "\\font_roman", 0)
1439 val = get_value(document.header, "\\font_roman", i)
1440 if val in list(mathdesign_dict.keys()):
1441 j = find_token(document.header, "\\font_math", 0)
1443 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1444 mval = get_value(document.header, "\\font_math", j)
1445 if mval == "default":
1446 document.header[i] = "\\font_roman default"
1447 add_to_preamble(document, "\\renewcommand{\\rmdefault}{%s}" % mathdesign_dict[val])
1449 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1452 def convert_mathfonts(document):
1453 document.header.insert(-1, "\\font_math auto")
1456 def convert_mdnomath(document):
1457 " Change mathdesign font name "
1459 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1461 "mdbch": "md-charter",
1462 "mdput": "md-utopia",
1463 "mdugm": "md-garamond"
1465 i = find_token(document.header, "\\font_roman", 0)
1468 val = get_value(document.header, "\\font_roman", i)
1469 if val in list(mathdesign_dict.keys()):
1470 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1473 def revert_newtxmath(document):
1474 " Revert native newtxmath definitions to LaTeX "
1476 i = find_token(document.header, "\\font_math", 0)
1479 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1480 val = get_value(document.header, "\\font_math", i)
1482 "libertine-ntxm": "\\usepackage[libertine]{newtxmath}",
1483 "minion-ntxm": "\\usepackage[minion]{newtxmath}",
1484 "newtxmath": "\\usepackage{newtxmath}",
1486 if val in list(mathfont_dict.keys()):
1487 add_to_preamble(document, mathfont_dict[val])
1488 document.header[i] = "\\font_math auto"
1491 def revert_biolinum(document):
1492 " Revert native biolinum font definition to LaTeX "
1494 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1495 i = find_token(document.header, "\\font_sans biolinum", 0)
1498 j = find_token(document.header, "\\font_osf true", 0)
1501 preamble = "\\usepackage"
1504 preamble += "{biolinum-type1}"
1505 add_to_preamble(document, [preamble])
1506 document.header[i] = "\\font_sans default"
1509 def revert_uop(document):
1510 " Revert native URW Classico (Optima) font definition to LaTeX "
1512 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1513 i = find_token(document.header, "\\font_sans uop", 0)
1515 preamble = "\\renewcommand{\\sfdefault}{uop}"
1516 add_to_preamble(document, [preamble])
1517 document.header[i] = "\\font_sans default"
1520 def convert_latexargs(document):
1521 " Convert InsetArgument to new syntax "
1523 if find_token(document.body, "\\begin_inset Argument", 0) == -1:
1527 # A list of layouts (document classes) with only optional or no arguments.
1528 # These can be safely converted to the new syntax
1529 # (I took the liberty to add some of my personal layouts/modules here; JSP)
1530 safe_layouts = ["aa", "aapaper", "aastex", "achemso", "acmsiggraph", "AEA",
1531 "agu-dtd", "agums", "agutex", "amsart", "amsbook", "apa",
1532 "arab-article", "armenian-article", "article-beamer", "article",
1533 "beamer", "book", "broadway", "chess", "cl2emult", "ctex-article",
1534 "ctex-book", "ctex-report", "dinbrief", "docbook-book", "docbook-chapter",
1535 "docbook", "docbook-section", "doublecol-new", "dtk", "ectaart", "egs",
1536 "elsarticle", "elsart", "entcs", "europecv", "extarticle", "extbook",
1537 "extletter", "extreport", "foils", "frletter", "g-brief2", "g-brief",
1538 "heb-article", "heb-letter", "hollywood", "IEEEtran", "ijmpc", "ijmpd",
1539 "iopart", "isprs", "jarticle", "jasatex", "jbook", "jgrga", "jreport",
1540 "jsarticle", "jsbeamer", "jsbook", "jss", "kluwer", "latex8", "letter", "lettre",
1541 "literate-article", "literate-book", "literate-report", "llncs", "ltugboat",
1542 "memoir", "moderncv", "mwart", "mwbk", "mwrep", "paper", "powerdot",
1543 "recipebook", "report", "revtex4", "revtex", "scrartcl", "scrarticle-beamer",
1544 "scrbook", "scrlettr", "scrlttr2", "scrreprt", "seminar", "siamltex",
1545 "sigplanconf", "simplecv", "singlecol", "singlecol-new", "slides", "spie",
1546 "svglobal3", "svglobal", "svjog", "svmono", "svmult", "svprobth", "tarticle",
1547 "tbook", "treport", "tufte-book", "tufte-handout"]
1548 # A list of "safe" modules, same as above
1549 safe_modules = ["biblatex", "beameraddons", "beamer-resenumerate", "beamersession", "braille",
1550 "customHeadersFooters", "endnotes", "enumitem", "eqs-within-sections", "figs-within-sections",
1551 "fix-cm", "fixltx2e", "foottoend", "hanging", "jscharstyles", "knitr", "lilypond",
1552 "linguistics", "linguisticx", "logicalmkup", "minimalistic", "nomindex", "noweb",
1553 "pdfcomment", "sweave", "tabs-within-sections", "theorems-ams-bytype",
1554 "theorems-ams-extended-bytype", "theorems-ams-extended", "theorems-ams", "theorems-bytype",
1555 "theorems-chap-bytype", "theorems-chap", "theorems-named", "theorems-sec-bytype",
1556 "theorems-sec", "theorems-starred", "theorems-std", "todonotes"]
1557 # Modules we need to take care of
1558 caveat_modules = ["initials"]
1559 # information about the relevant styles in caveat_modules (number of opt and req args)
1560 # use this if we get more caveat_modules. For now, use hard coding (see below).
1561 # initials = [{'Layout' : 'Initial', 'opt' : 1, 'req' : 1}]
1563 # Is this a known safe layout?
1564 safe_layout = document.textclass in safe_layouts
1566 document.warning("Lyx2lyx knows nothing about textclass '%s'. "
1567 "Please check if short title insets have been converted correctly."
1568 % document.textclass)
1569 # Do we use unsafe or unknown modules
1570 mods = document.get_module_list()
1571 unknown_modules = False
1572 used_caveat_modules = list()
1574 if mod in safe_modules:
1576 if mod in caveat_modules:
1577 used_caveat_modules.append(mod)
1579 unknown_modules = True
1580 document.warning("Lyx2lyx knows nothing about module '%s'. "
1581 "Please check if short title insets have been converted correctly."
1586 i = find_token(document.body, "\\begin_inset Argument", i)
1590 if not safe_layout or unknown_modules:
1591 # We cannot do more here since we have no access to this layout.
1592 # InsetArgument itself will do the real work
1593 # (see InsetArgument::updateBuffer())
1594 document.body[i] = "\\begin_inset Argument 999"
1598 # Find containing paragraph layout
1599 parent = get_containing_layout(document.body, i)
1601 document.warning("Malformed LyX document: Can't find parent paragraph layout")
1608 if len(used_caveat_modules) > 0:
1609 # We know for now that this must be the initials module with the Initial layout
1610 # If we get more such modules, we need some automating.
1611 if parent[0] == "Initial":
1612 # Layout has 1 opt and 1 req arg.
1613 # Count the actual arguments
1615 for p in range(parbeg, parend):
1616 if document.body[p] == "\\begin_inset Argument":
1621 # Collect all arguments in this paragraph
1623 for p in range(parbeg, parend):
1624 if document.body[p] == "\\begin_inset Argument":
1626 if allowed_opts != -1:
1627 # We have less arguments than opt + required.
1628 # required must take precedence.
1629 if argnr > allowed_opts and argnr < first_req:
1631 document.body[p] = "\\begin_inset Argument %d" % argnr
1635 def revert_latexargs(document):
1636 " Revert InsetArgument to old syntax "
1639 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
1642 # Search for Argument insets
1643 i = find_token(document.body, "\\begin_inset Argument", i)
1646 m = rx.match(document.body[i])
1648 # No ID: inset already reverted
1651 # Find containing paragraph layout
1652 parent = get_containing_layout(document.body, i)
1654 document.warning("Malformed LyX document: Can't find parent paragraph layout")
1659 # Do not set realparbeg to parent[3], since this does not work if we
1660 # have another inset (e.g. label or index) before the first argument
1661 # inset (this is the case in the user guide of LyX 2.0.8)
1663 # Collect all arguments in this paragraph
1665 for p in range(parbeg, parend):
1666 m = rx.match(document.body[p])
1669 # This is the first argument inset
1671 val = int(m.group(1))
1672 j = find_end_of_inset(document.body, p)
1673 # Revert to old syntax
1674 document.body[p] = "\\begin_inset Argument"
1676 document.warning("Malformed LyX document: Can't find end of Argument inset")
1679 args[val] = document.body[p : j + 1]
1681 realparend = realparend - len(document.body[p : j + 1])
1682 # Remove arg inset at this position
1683 del document.body[p : j + 1]
1687 # No argument inset found
1688 realparbeg = parent[3]
1689 # Now sort the arg insets
1691 for f in sorted(args):
1694 # Insert the sorted arg insets at paragraph begin
1695 document.body[realparbeg : realparbeg] = subst
1697 i = realparbeg + 1 + len(subst)
1700 def revert_IEEEtran(document):
1702 Reverts InsetArgument of
1705 Biography without photo
1708 if document.textclass != "IEEEtran":
1711 layouts = {"Page headings": False,
1712 "Biography without photo": True}
1714 for layout in list(layouts.keys()):
1717 i = find_token(document.body, '\\begin_layout ' + layout, i)
1720 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, layouts[layout], False)
1725 i = find_token(document.body, '\\begin_inset Flex Paragraph Start', i)
1728 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1733 i = find_token_exact(document.body, "\\begin_layout Biography", i)
1737 if document.body[i] == "\\begin_layout Biography without photo":
1741 # start with the second argument, therefore 2
1742 revert_Argument_to_TeX_brace(document, i, 0, 2, 2, True, False)
1746 def revert_IEEEtran_2(document):
1748 Reverts Flex Paragraph Start to TeX-code
1750 if document.textclass == "IEEEtran":
1753 begin = find_token(document.body, "\\begin_inset Flex Paragraph Start", begin)
1756 end1 = find_end_of_inset(document.body, begin)
1757 document.body[end1 - 2 : end1 + 1] = put_cmd_in_ert("}")
1758 document.body[begin : begin + 4] = put_cmd_in_ert("\\IEEEPARstart{")
1762 def convert_IEEEtran(document):
1767 Biography without photo
1770 if document.textclass != "IEEEtran":
1773 layouts = {"Page headings": False,
1774 "Biography without photo": True}
1776 for layout in list(layouts.keys()):
1779 i = find_token(document.body, '\\begin_layout ' + layout, i)
1782 convert_TeX_brace_to_Argument(document, i, 1, 1, False, layouts[layout], False)
1787 i = find_token_exact(document.body, "\\begin_layout Biography", i)
1791 if document.body[i] == "\\begin_layout Biography without photo":
1795 # the argument we want to convert is the second one
1796 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, False)
1800 def revert_AASTeX(document):
1801 " Reverts InsetArgument of Altaffilation to TeX-code "
1802 if document.textclass == "aastex":
1805 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1808 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1812 def convert_AASTeX(document):
1813 " Converts ERT of Altaffilation to InsetArgument "
1814 if document.textclass == "aastex":
1817 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1820 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1824 def revert_AGUTeX(document):
1825 " Reverts InsetArgument of Author affiliation to TeX-code "
1826 if document.textclass == "agutex":
1829 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1832 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1836 def convert_AGUTeX(document):
1837 " Converts ERT of Author affiliation to InsetArgument "
1838 if document.textclass == "agutex":
1841 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1844 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1848 def revert_IJMP(document):
1849 " Reverts InsetArgument of MarkBoth to TeX-code "
1850 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1853 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1856 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1860 def convert_IJMP(document):
1861 " Converts ERT of MarkBoth to InsetArgument "
1862 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1865 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1868 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1872 def revert_SIGPLAN(document):
1873 " Reverts InsetArguments of SIGPLAN to TeX-code "
1874 if document.textclass == "sigplanconf":
1879 i = find_token(document.body, "\\begin_layout Conference", i)
1881 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1884 j = find_token(document.body, "\\begin_layout Author", j)
1886 revert_Argument_to_TeX_brace(document, j, 0, 1, 2, False, False)
1888 if i == -1 and j == -1:
1892 def convert_SIGPLAN(document):
1893 " Converts ERT of SIGPLAN to InsetArgument "
1894 if document.textclass == "sigplanconf":
1899 i = find_token(document.body, "\\begin_layout Conference", i)
1901 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1904 j = find_token(document.body, "\\begin_layout Author", j)
1906 convert_TeX_brace_to_Argument(document, j, 1, 2, False, False, False)
1908 if i == -1 and j == -1:
1912 def revert_SIGGRAPH(document):
1913 " Reverts InsetArgument of Flex CRcat to TeX-code "
1914 if document.textclass == "acmsiggraph":
1917 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1920 revert_Argument_to_TeX_brace(document, i, 0, 1, 3, False, False)
1924 def convert_SIGGRAPH(document):
1925 " Converts ERT of Flex CRcat to InsetArgument "
1926 if document.textclass == "acmsiggraph":
1929 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1932 convert_TeX_brace_to_Argument(document, i, 1, 3, True, False, False)
1936 def revert_EuropeCV(document):
1937 " Reverts InsetArguments of europeCV to TeX-code "
1938 if document.textclass == "europecv":
1945 i = find_token(document.body, "\\begin_layout Item", i)
1947 revert_Argument_to_TeX_brace(document, i, 0, 2, 2, False, False)
1950 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1952 revert_Argument_to_TeX_brace(document, j, 0, 2, 2, False, False)
1955 k = find_token(document.body, "\\begin_layout Language", k)
1957 revert_Argument_to_TeX_brace(document, k, 0, 2, 6, False, False)
1960 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1962 revert_Argument_to_TeX_brace(document, m, 0, 2, 6, False, False)
1964 if i == -1 and j == -1 and k == -1 and m == -1:
1968 def convert_EuropeCV(document):
1969 " Converts ERT of europeCV to InsetArgument "
1970 if document.textclass == "europecv":
1977 i = find_token(document.body, "\\begin_layout Item", i)
1979 convert_TeX_brace_to_Argument(document, i, 2, 2, False, False, False)
1982 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1984 convert_TeX_brace_to_Argument(document, j, 2, 2, False, False, False)
1987 k = find_token(document.body, "\\begin_layout Language", k)
1989 convert_TeX_brace_to_Argument(document, k, 2, 6, False, False, False)
1992 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1994 convert_TeX_brace_to_Argument(document, m, 2, 6, False, False, False)
1996 if i == -1 and j == -1 and k == -1 and m == -1:
2000 def revert_ModernCV(document):
2001 " Reverts InsetArguments of modernCV to TeX-code "
2002 if document.textclass == "moderncv":
2010 j = find_token(document.body, "\\begin_layout Entry", j)
2012 revert_Argument_to_TeX_brace(document, j, 0, 1, 5, False, False)
2015 k = find_token(document.body, "\\begin_layout Item", k)
2017 revert_Argument_to_TeX_brace(document, k, 0, 1, 1, False, False)
2020 m = find_token(document.body, "\\begin_layout ItemWithComment", m)
2022 revert_Argument_to_TeX_brace(document, m, 0, 1, 2, False, False)
2023 document.body[m] = document.body[m].replace("\\begin_layout ItemWithComment", "\\begin_layout Language")
2026 o = find_token(document.body, "\\begin_layout DoubleItem", o)
2028 revert_Argument_to_TeX_brace(document, o, 0, 1, 3, False, False)
2029 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout Computer")
2032 p = find_token(document.body, "\\begin_layout Social", p)
2034 revert_Argument_to_TeX_brace(document, p, 0, 1, 1, False, True)
2036 if j == -1 and k == -1 and m == -1 and o == -1 and p == -1:
2040 def revert_ModernCV_2(document):
2041 " Reverts the Flex:Column inset of modernCV to TeX-code "
2042 if document.textclass == "moderncv":
2046 flex = find_token(document.body, "\\begin_inset Flex Column", flex)
2049 flexEnd = find_end_of_inset(document.body, flex)
2050 wasOpt = revert_Argument_to_TeX_brace(document, flex, flexEnd, 1, 1, False, True)
2051 revert_Argument_to_TeX_brace(document, flex, 0, 2, 2, False, False)
2052 flexEnd = find_end_of_inset(document.body, flex)
2054 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn")
2056 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn{")
2057 document.body[flexEnd + 4 : flexEnd + 7] = put_cmd_in_ert("}")
2061 def revert_ModernCV_3(document):
2062 " Reverts the Column style of modernCV to TeX-code "
2063 if document.textclass == "moderncv":
2064 # revert the layouts
2065 revert_ModernCV(document)
2067 # get the position of the end of the last column inset
2068 LastFlexEnd = revert_ModernCV_2(document)
2070 p = find_token(document.body, "\\begin_layout Columns", p)
2073 pEnd = find_end_of_layout(document.body, p)
2074 document.body[p] = document.body[p].replace("\\begin_layout Columns", "\\begin_layout Standard")
2075 if LastFlexEnd != -1:
2076 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\begin{cvcolumns}")
2077 document.body[LastFlexEnd + 24 : LastFlexEnd + 24] = put_cmd_in_ert("\\end{cvcolumns}")
2081 def revert_ModernCV_4(document):
2082 " Reverts the style Social to TeX-code "
2083 if document.textclass == "moderncv":
2084 # revert the layouts
2085 revert_ModernCV(document)
2088 p = find_token(document.body, "\\begin_layout Social", p)
2091 pEnd = find_end_of_layout(document.body, p)
2092 document.body[p] = document.body[p].replace("\\begin_layout Social", "\\begin_layout Standard")
2093 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\social")
2094 hasOpt = find_token(document.body, "[", p + 9)
2096 document.body[p + 30 : p + 30] = put_cmd_in_ert("{")
2097 document.body[p + 41 : p + 41] = put_cmd_in_ert("}")
2099 document.body[p + 11 : p + 11] = put_cmd_in_ert("{")
2100 document.body[p + 21 : p + 21] = put_cmd_in_ert("}")
2104 def convert_ModernCV(document):
2105 " Converts ERT of modernCV to InsetArgument "
2106 if document.textclass == "moderncv":
2114 i = find_token(document.body, "\\begin_layout DoubleItem", i)
2116 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
2117 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout DoubleListItem")
2120 j = find_token(document.body, "\\begin_layout Entry", j)
2122 convert_TeX_brace_to_Argument(document, j, 1, 5, False, False, False)
2125 k = find_token(document.body, "\\begin_layout Item", k)
2127 convert_TeX_brace_to_Argument(document, k, 1, 1, False, False, False)
2130 m = find_token(document.body, "\\begin_layout Language", m)
2132 convert_TeX_brace_to_Argument(document, m, 1, 2, False, False, False)
2134 if i == -1 and j == -1 and k == -1 and m == -1:
2138 def revert_Initials(document):
2139 " Reverts InsetArgument of Initial to TeX-code "
2142 i = find_token(document.body, "\\begin_layout Initial", i)
2145 # first arg (optional) and second arg (first mandatory) are supported in LyX 2.0.x
2146 revert_Argument_to_TeX_brace(document, i, 0, 3, 3, False, False)
2150 def convert_Initials(document):
2151 " Converts ERT of Initial to InsetArgument "
2154 i = find_token(document.body, "\\begin_layout Initial", i)
2157 convert_TeX_brace_to_Argument(document, i, 3, 3, False, False, False)
2161 def revert_literate(document):
2162 " Revert Literate document to old format "
2163 if del_token(document.header, "noweb", 0):
2164 document.textclass = "literate-" + document.textclass
2167 i = find_token(document.body, "\\begin_layout Chunk", i)
2170 document.body[i] = "\\begin_layout Scrap"
2174 def convert_literate(document):
2175 " Convert Literate document to new format"
2176 i = find_token(document.header, "\\textclass", 0)
2177 if (i != -1) and "literate-" in document.header[i]:
2178 document.textclass = document.header[i].replace("\\textclass literate-", "")
2179 j = find_token(document.header, "\\begin_modules", 0)
2181 document.header.insert(j + 1, "noweb")
2183 document.header.insert(i + 1, "\\end_modules")
2184 document.header.insert(i + 1, "noweb")
2185 document.header.insert(i + 1, "\\begin_modules")
2188 i = find_token(document.body, "\\begin_layout Scrap", i)
2191 document.body[i] = "\\begin_layout Chunk"
2195 def revert_itemargs(document):
2196 " Reverts \\item arguments to TeX-code "
2199 i = find_token(document.body, "\\begin_inset Argument item:", i)
2202 j = find_end_of_inset(document.body, i)
2203 # Find containing paragraph layout
2204 parent = get_containing_layout(document.body, i)
2206 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2210 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2211 endPlain = find_end_of_layout(document.body, beginPlain)
2212 content = document.body[beginPlain + 1 : endPlain]
2213 del document.body[i:j+1]
2214 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2215 document.body[parbeg : parbeg] = subst
2219 def revert_garamondx_newtxmath(document):
2220 " Revert native garamond newtxmath definition to LaTeX "
2222 i = find_token(document.header, "\\font_math", 0)
2225 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2226 val = get_value(document.header, "\\font_math", i)
2227 if val == "garamondx-ntxm":
2228 add_to_preamble(document, "\\usepackage[garamondx]{newtxmath}")
2229 document.header[i] = "\\font_math auto"
2232 def revert_garamondx(document):
2233 " Revert native garamond font definition to LaTeX "
2235 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2236 i = find_token(document.header, "\\font_roman garamondx", 0)
2239 j = find_token(document.header, "\\font_osf true", 0)
2242 preamble = "\\usepackage"
2244 preamble += "[osfI]"
2245 preamble += "{garamondx}"
2246 add_to_preamble(document, [preamble])
2247 document.header[i] = "\\font_roman default"
2250 def convert_beamerargs(document):
2251 " Converts beamer arguments to new layout "
2253 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2254 if document.textclass not in beamer_classes:
2257 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2258 list_layouts = ["Itemize", "Enumerate", "Description"]
2259 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
2263 i = find_token(document.body, "\\begin_inset Argument", i)
2266 # Find containing paragraph layout
2267 parent = get_containing_layout(document.body, i)
2269 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2274 layoutname = parent[0]
2275 for p in range(parbeg, parend):
2276 if layoutname in shifted_layouts:
2277 m = rx.match(document.body[p])
2279 argnr = int(m.group(1))
2281 document.body[p] = "\\begin_inset Argument %d" % argnr
2282 if layoutname == "AgainFrame":
2283 m = rx.match(document.body[p])
2285 document.body[p] = "\\begin_inset Argument 3"
2286 if document.body[p + 4] == "\\begin_inset ERT":
2287 if document.body[p + 9].startswith("<"):
2288 # This is an overlay specification
2290 document.body[p + 9] = document.body[p + 9][1:]
2291 if document.body[p + 9].endswith(">"):
2293 document.body[p + 9] = document.body[p + 9][:-1]
2295 document.body[p] = "\\begin_inset Argument 2"
2296 if layoutname in list_layouts:
2297 m = rx.match(document.body[p])
2299 if m.group(1) == "1":
2300 if document.body[p + 4] == "\\begin_inset ERT":
2301 if document.body[p + 9].startswith("<"):
2302 # This is an overlay specification
2304 document.body[p + 9] = document.body[p + 9][1:]
2305 if document.body[p + 9].endswith(">"):
2307 document.body[p + 9] = document.body[p + 9][:-1]
2308 elif document.body[p + 4].startswith("<"):
2309 # This is an overlay specification (without ERT)
2311 document.body[p + 4] = document.body[p + 4][1:]
2312 if document.body[p + 4].endswith(">"):
2314 document.body[p + 4] = document.body[p + 4][:-1]
2315 elif layoutname != "Itemize":
2317 document.body[p] = "\\begin_inset Argument 2"
2322 # Helper function for the frame conversion routines
2324 # FIXME: This method currently requires the arguments to be either
2325 # * In one (whole) ERT each: <ERT>[<arg1>]</ERT><ERT><arg2></ERT><ERT>[arg3]</ERT>
2326 # * Altogether in one whole ERT: <ERT>[<arg1>]<arg2>[arg3]</ERT>
2327 # If individual arguments mix ERT and non-ERT or are splitted
2328 # over several ERTs, the parsing fails.
2329 def convert_beamerframeargs(document, i, parbeg):
2332 if document.body[parbeg] != "\\begin_inset ERT":
2334 ertend = find_end_of_inset(document.body, parbeg)
2336 document.warning("Malformed LyX document: missing ERT \\end_inset")
2338 ertcont = parbeg + 5
2339 if document.body[ertcont].startswith("[<"):
2340 # This is a default overlay specification
2342 document.body[ertcont] = document.body[ertcont][2:]
2343 if document.body[ertcont].endswith(">]"):
2345 document.body[ertcont] = document.body[ertcont][:-2]
2346 elif document.body[ertcont].endswith("]"):
2348 tok = document.body[ertcont].find('>][')
2350 subst = [document.body[ertcont][:tok],
2351 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2352 'status collapsed', '', '\\begin_layout Plain Layout',
2353 document.body[ertcont][tok + 3:-1]]
2354 document.body[ertcont : ertcont + 1] = subst
2356 # Convert to ArgInset
2357 document.body[parbeg] = "\\begin_inset Argument 2"
2358 elif document.body[ertcont].startswith("<"):
2359 # This is an overlay specification
2361 document.body[ertcont] = document.body[ertcont][1:]
2362 if document.body[ertcont].endswith(">"):
2364 document.body[ertcont] = document.body[ertcont][:-1]
2365 # Convert to ArgInset
2366 document.body[parbeg] = "\\begin_inset Argument 1"
2367 elif document.body[ertcont].endswith(">]"):
2369 tok = document.body[ertcont].find('>[<')
2371 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2372 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2373 'status collapsed', '', '\\begin_layout Plain Layout',
2374 document.body[ertcont][tok + 3:-2]]
2375 # Convert to ArgInset
2376 document.body[parbeg] = "\\begin_inset Argument 1"
2378 elif document.body[ertcont].endswith("]"):
2380 tok = document.body[ertcont].find('>[<')
2383 tokk = document.body[ertcont].find('>][')
2385 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2386 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2387 'status collapsed', '', '\\begin_layout Plain Layout',
2388 document.body[ertcont][tok + 3:tokk],
2389 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2390 'status collapsed', '', '\\begin_layout Plain Layout',
2391 document.body[ertcont][tokk + 3:-1]]
2394 tokk = document.body[ertcont].find('>[')
2396 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tokk],
2397 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2398 'status collapsed', '', '\\begin_layout Plain Layout',
2399 document.body[ertcont][tokk + 2:-1]]
2401 # Convert to ArgInset
2402 document.body[parbeg] = "\\begin_inset Argument 1"
2403 elif document.body[ertcont].startswith("["):
2404 # This is an ERT option
2406 document.body[ertcont] = document.body[ertcont][1:]
2407 if document.body[ertcont].endswith("]"):
2409 document.body[ertcont] = document.body[ertcont][:-1]
2410 # Convert to ArgInset
2411 document.body[parbeg] = "\\begin_inset Argument 3"
2417 def convert_againframe_args(document):
2418 " Converts beamer AgainFrame to new layout "
2420 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2421 if document.textclass not in beamer_classes:
2426 i = find_token(document.body, "\\begin_layout AgainFrame", i)
2429 parent = get_containing_layout(document.body, i)
2431 document.warning("Wrong parent layout!")
2435 # Convert ERT arguments
2436 # FIXME: See restrictions in convert_beamerframeargs method
2437 ertend = convert_beamerframeargs(document, i, parbeg)
2443 def convert_corollary_args(document):
2444 " Converts beamer corrolary-style ERT arguments native InsetArgs "
2446 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2447 if document.textclass not in beamer_classes:
2450 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2451 for lay in corollary_layouts:
2454 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2457 parent = get_containing_layout(document.body, i)
2459 document.warning("Wrong parent layout!")
2463 if document.body[parbeg] == "\\begin_inset ERT":
2464 ertcontfirstline = parbeg + 5
2465 # Find the last ERT in this paragraph (which might also be the first)
2466 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
2467 if lastertbeg == -1:
2468 document.warning("Last ERT not found!")
2470 lastertend = find_end_of_inset(document.body, lastertbeg)
2471 if lastertend == -1:
2472 document.warning("End of last ERT not found!")
2474 ertcontlastline = lastertend - 3
2475 if document.body[ertcontfirstline].startswith("<"):
2476 # This is an overlay specification
2478 document.body[ertcontfirstline] = document.body[ertcontfirstline][1:]
2479 if document.body[ertcontlastline].endswith(">"):
2481 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
2482 if ertcontfirstline < ertcontlastline:
2483 # Multiline ERT. Might contain TeX code. Embrace in ERT.
2484 document.body[ertcontlastline : ertcontlastline + 1] = [
2485 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
2486 document.body[ertcontfirstline : ertcontfirstline + 1] = [
2487 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
2488 'status collapsed', '', '\\begin_layout Plain Layout',
2489 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
2490 document.body[ertcontfirstline]]
2492 # Convert to ArgInset
2493 document.body[parbeg] = "\\begin_inset Argument 1"
2494 elif document.body[ertcontlastline].endswith("]"):
2496 tok = document.body[ertcontfirstline].find('>[')
2498 if ertcontfirstline < ertcontlastline:
2499 # Multiline ERT. Might contain TeX code. Embrace in ERT.
2500 document.body[ertcontlastline : ertcontlastline + 1] = [
2501 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
2502 document.body[ertcontfirstline : ertcontfirstline + 1] = [document.body[ertcontfirstline][:tok],
2503 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2504 'status collapsed', '', '\\begin_layout Plain Layout',
2505 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
2506 document.body[ertcontfirstline][tok + 2:-1]]
2508 document.body[ertcontfirstline : ertcontfirstline + 1] = [document.body[ertcontfirstline][:tok],
2509 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2510 'status collapsed', '', '\\begin_layout Plain Layout',
2511 document.body[ertcontfirstline][tok + 2:-1]]
2512 # Convert to ArgInset
2513 document.body[parbeg] = "\\begin_inset Argument 1"
2516 elif document.body[ertcontlastline].startswith("["):
2517 if document.body[ertcontlastline].endswith("]"):
2518 # This is an ERT option
2520 document.body[ertcontlastline] = document.body[ertcontlastline][1:]
2522 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
2523 # Convert to ArgInset
2524 document.body[parbeg] = "\\begin_inset Argument 2"
2526 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, True)
2533 def convert_quote_args(document):
2534 " Converts beamer quote style ERT args to native InsetArgs "
2536 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2537 if document.textclass not in beamer_classes:
2540 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2541 for lay in quote_layouts:
2544 i = find_token(document.body, "\\begin_layout " + lay, i)
2547 parent = get_containing_layout(document.body, i)
2549 document.warning("Wrong parent layout!")
2553 if document.body[parbeg] == "\\begin_inset ERT":
2554 if document.body[i + 6].startswith("<"):
2555 # This is an overlay specification
2557 document.body[i + 6] = document.body[i + 6][1:]
2558 if document.body[i + 6].endswith(">"):
2560 document.body[i + 6] = document.body[i + 6][:-1]
2561 # Convert to ArgInset
2562 document.body[i + 1] = "\\begin_inset Argument 1"
2566 def cleanup_beamerargs(document):
2567 " Clean up empty ERTs (conversion artefacts) "
2569 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2570 if document.textclass not in beamer_classes:
2575 i = find_token(document.body, "\\begin_inset Argument", i)
2578 j = find_end_of_inset(document.body, i)
2580 document.warning("Malformed LyX document: Can't find end of Argument inset")
2584 ertbeg = find_token(document.body, "\\begin_inset ERT", i, j)
2587 ertend = find_end_of_inset(document.body, ertbeg)
2589 document.warning("Malformed LyX document: Can't find end of ERT inset")
2591 stripped = [line for line in document.body[ertbeg : ertend + 1] if line.strip()]
2592 if len(stripped) == 5:
2593 # This is an empty ERT
2594 offset = len(document.body[ertbeg : ertend + 1])
2595 del document.body[ertbeg : ertend + 1]
2602 def revert_beamerargs(document):
2603 " Reverts beamer arguments to old layout "
2605 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2606 if document.textclass not in beamer_classes:
2610 list_layouts = ["Itemize", "Enumerate", "Description"]
2611 headings = ["Part", "Section", "Section*", "Subsection", "Subsection*",
2612 "Subsubsection", "Subsubsection*", "FrameSubtitle", "NoteItem"]
2613 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2614 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2615 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2618 i = find_token(document.body, "\\begin_inset Argument", i)
2621 # Find containing paragraph layout
2622 parent = get_containing_layout(document.body, i)
2624 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2629 realparbeg = parent[3]
2630 layoutname = parent[0]
2632 for p in range(parbeg, parend):
2636 if layoutname in headings:
2637 m = rx.match(document.body[p])
2641 # Find containing paragraph layout
2642 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2643 endPlain = find_end_of_layout(document.body, beginPlain)
2644 endInset = find_end_of_inset(document.body, p)
2645 argcontent = document.body[beginPlain + 1 : endPlain]
2647 realparend = realparend - len(document.body[p : endInset + 1])
2649 del document.body[p : endInset + 1]
2650 if layoutname == "FrameSubtitle":
2651 pre = put_cmd_in_ert("\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2652 elif layoutname == "NoteItem":
2653 pre = put_cmd_in_ert("\\note<") + argcontent + put_cmd_in_ert(">[item]")
2654 elif layoutname.endswith('*'):
2655 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower()[:-1] + "<") + argcontent + put_cmd_in_ert(">*")
2657 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2658 secarg = find_token(document.body, "\\begin_inset Argument 2", parbeg, parend)
2660 # Find containing paragraph layout
2661 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", secarg)
2662 endPlain = find_end_of_layout(document.body, beginPlain)
2663 endInset = find_end_of_inset(document.body, secarg)
2664 argcontent = document.body[beginPlain + 1 : endPlain]
2666 realparend = realparend - len(document.body[secarg : endInset + 1])
2667 del document.body[secarg : endInset + 1]
2668 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2669 pre += put_cmd_in_ert("{")
2670 document.body[parbeg] = "\\begin_layout Standard"
2671 document.body[realparbeg : realparbeg] = pre
2672 pe = find_end_of_layout(document.body, parbeg)
2673 post = put_cmd_in_ert("}")
2674 document.body[pe : pe] = post
2675 realparend += len(pre) + len(post)
2676 if layoutname == "AgainFrame":
2677 m = rx.match(document.body[p])
2681 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2682 endPlain = find_end_of_layout(document.body, beginPlain)
2683 endInset = find_end_of_inset(document.body, p)
2684 content = document.body[beginPlain + 1 : endPlain]
2686 realparend = realparend - len(document.body[p : endInset + 1])
2688 del document.body[p : endInset + 1]
2689 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2690 document.body[realparbeg : realparbeg] = subst
2691 if layoutname == "Overprint":
2692 m = rx.match(document.body[p])
2696 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2697 endPlain = find_end_of_layout(document.body, beginPlain)
2698 endInset = find_end_of_inset(document.body, p)
2699 content = document.body[beginPlain + 1 : endPlain]
2701 realparend = realparend - len(document.body[p : endInset + 1])
2703 del document.body[p : endInset + 1]
2704 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2705 document.body[realparbeg : realparbeg] = subst
2706 if layoutname == "OverlayArea":
2707 m = rx.match(document.body[p])
2711 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2712 endPlain = find_end_of_layout(document.body, beginPlain)
2713 endInset = find_end_of_inset(document.body, p)
2714 content = document.body[beginPlain + 1 : endPlain]
2716 realparend = realparend - len(document.body[p : endInset + 1])
2718 del document.body[p : endInset + 1]
2719 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2720 document.body[realparbeg : realparbeg] = subst
2721 if layoutname in list_layouts:
2722 m = rx.match(document.body[p])
2726 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2727 endPlain = find_end_of_layout(document.body, beginPlain)
2728 endInset = find_end_of_inset(document.body, p)
2729 content = document.body[beginPlain + 1 : endPlain]
2730 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2731 realparend = realparend + len(subst) - len(content)
2732 document.body[beginPlain + 1 : endPlain] = subst
2733 elif argnr == "item:1":
2734 j = find_end_of_inset(document.body, i)
2735 # Find containing paragraph layout
2736 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2737 endPlain = find_end_of_layout(document.body, beginPlain)
2738 content = document.body[beginPlain + 1 : endPlain]
2739 del document.body[i:j+1]
2740 if layoutname == "Description":
2741 # Description only has one (overlay) item arg
2742 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2743 # This must be put after the first space (begin of decription body
2744 # in LyX's arkward description list syntax)
2745 # Try to find that place ...
2746 rxx = re.compile(r'^([^\\ ]+ )(.*)$')
2747 for q in range(parbeg, parend):
2748 m = rxx.match(document.body[q])
2750 # We found it. Now insert the ERT argument just there:
2751 document.body[q : q] = [m.group(1), ''] + subst + ['', m.group(2)]
2754 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2755 document.body[realparbeg : realparbeg] = subst
2756 elif argnr == "item:2":
2757 j = find_end_of_inset(document.body, i)
2758 # Find containing paragraph layout
2759 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2760 endPlain = find_end_of_layout(document.body, beginPlain)
2761 content = document.body[beginPlain + 1 : endPlain]
2762 del document.body[i:j+1]
2763 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2764 document.body[realparbeg : realparbeg] = subst
2765 if layoutname in quote_layouts:
2766 m = rx.match(document.body[p])
2770 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2771 endPlain = find_end_of_layout(document.body, beginPlain)
2772 endInset = find_end_of_inset(document.body, p)
2773 content = document.body[beginPlain + 1 : endPlain]
2775 realparend = realparend - len(document.body[p : endInset + 1])
2777 del document.body[p : endInset + 1]
2778 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2779 document.body[realparbeg : realparbeg] = subst
2780 if layoutname in corollary_layouts:
2781 m = rx.match(document.body[p])
2785 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2786 endPlain = find_end_of_layout(document.body, beginPlain)
2787 endInset = find_end_of_inset(document.body, p)
2788 content = document.body[beginPlain + 1 : endPlain]
2790 realparend = realparend - len(document.body[p : endInset + 1])
2792 del document.body[p : endInset + 1]
2793 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2794 document.body[realparbeg : realparbeg] = subst
2799 def revert_beamerargs2(document):
2800 " Reverts beamer arguments to old layout, step 2 "
2802 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2803 if document.textclass not in beamer_classes:
2807 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2808 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2809 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2812 i = find_token(document.body, "\\begin_inset Argument", i)
2815 # Find containing paragraph layout
2816 parent = get_containing_layout(document.body, i)
2818 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2823 realparbeg = parent[3]
2824 layoutname = parent[0]
2826 for p in range(parbeg, parend):
2830 if layoutname in shifted_layouts:
2831 m = rx.match(document.body[p])
2835 document.body[p] = "\\begin_inset Argument 1"
2836 if layoutname in corollary_layouts:
2837 m = rx.match(document.body[p])
2841 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2842 endPlain = find_end_of_layout(document.body, beginPlain)
2843 endInset = find_end_of_inset(document.body, p)
2844 content = document.body[beginPlain + 1 : endPlain]
2846 realparend = realparend - len(document.body[p : endInset + 1])
2848 del document.body[p : endInset + 1]
2849 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2850 document.body[realparbeg : realparbeg] = subst
2851 if layoutname == "OverlayArea":
2852 m = rx.match(document.body[p])
2856 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2857 endPlain = find_end_of_layout(document.body, beginPlain)
2858 endInset = find_end_of_inset(document.body, p)
2859 content = document.body[beginPlain + 1 : endPlain]
2861 realparend = realparend - len(document.body[p : endInset + 1])
2863 del document.body[p : endInset + 1]
2864 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2865 document.body[realparbeg : realparbeg] = subst
2866 if layoutname == "AgainFrame":
2867 m = rx.match(document.body[p])
2871 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2872 endPlain = find_end_of_layout(document.body, beginPlain)
2873 endInset = find_end_of_inset(document.body, p)
2874 content = document.body[beginPlain + 1 : endPlain]
2876 realparend = realparend - len(document.body[p : endInset + 1])
2878 del document.body[p : endInset + 1]
2879 subst = put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
2880 document.body[realparbeg : realparbeg] = subst
2884 def revert_beamerargs3(document):
2885 " Reverts beamer arguments to old layout, step 3 "
2887 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2888 if document.textclass not in beamer_classes:
2891 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2894 i = find_token(document.body, "\\begin_inset Argument", i)
2897 # Find containing paragraph layout
2898 parent = get_containing_layout(document.body, i)
2900 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2905 realparbeg = parent[3]
2906 layoutname = parent[0]
2908 for p in range(parbeg, parend):
2912 if layoutname == "AgainFrame":
2913 m = rx.match(document.body[p])
2917 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2918 endPlain = find_end_of_layout(document.body, beginPlain)
2919 endInset = find_end_of_inset(document.body, p)
2920 content = document.body[beginPlain + 1 : endPlain]
2922 realparend = realparend - len(document.body[p : endInset + 1])
2924 del document.body[p : endInset + 1]
2925 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2926 document.body[realparbeg : realparbeg] = subst
2930 def revert_beamerflex(document):
2931 " Reverts beamer Flex insets "
2933 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2934 if document.textclass not in beamer_classes:
2937 new_flexes = {"Bold" : "\\textbf", "Emphasize" : "\\emph", "Only" : "\\only",
2938 "Uncover" : "\\uncover", "Visible" : "\\visible",
2939 "Invisible" : "\\invisible", "Alternative" : "\\alt",
2940 "Beamer_Note" : "\\note"}
2941 old_flexes = {"Alert" : "\\alert", "Structure" : "\\structure"}
2942 rx = re.compile(r'^\\begin_inset Flex (.+)$')
2946 i = find_token(document.body, "\\begin_inset Flex", i)
2949 m = rx.match(document.body[i])
2951 flextype = m.group(1)
2952 z = find_end_of_inset(document.body, i)
2954 document.warning("Can't find end of Flex " + flextype + " inset.")
2957 if flextype in new_flexes:
2958 pre = put_cmd_in_ert(new_flexes[flextype])
2959 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2961 argend = find_end_of_inset(document.body, arg)
2963 document.warning("Can't find end of Argument!")
2966 # Find containing paragraph layout
2967 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2968 endPlain = find_end_of_layout(document.body, beginPlain)
2969 argcontent = document.body[beginPlain + 1 : endPlain]
2971 z = z - len(document.body[arg : argend + 1])
2973 del document.body[arg : argend + 1]
2974 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2975 arg = find_token(document.body, "\\begin_inset Argument 2", i, z)
2977 argend = find_end_of_inset(document.body, arg)
2979 document.warning("Can't find end of Argument!")
2982 # Find containing paragraph layout
2983 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2984 endPlain = find_end_of_layout(document.body, beginPlain)
2985 argcontent = document.body[beginPlain + 1 : endPlain]
2987 z = z - len(document.body[arg : argend + 1])
2989 del document.body[arg : argend + 1]
2990 if flextype == "Alternative":
2991 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
2993 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2994 pre += put_cmd_in_ert("{")
2995 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2996 endPlain = find_end_of_layout(document.body, beginPlain)
2998 z = z - len(document.body[i : beginPlain + 1])
3000 document.body[i : beginPlain + 1] = pre
3001 post = put_cmd_in_ert("}")
3002 document.body[z - 2 : z + 1] = post
3003 elif flextype in old_flexes:
3004 pre = put_cmd_in_ert(old_flexes[flextype])
3005 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
3009 argend = find_end_of_inset(document.body, arg)
3011 document.warning("Can't find end of Argument!")
3014 # Find containing paragraph layout
3015 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3016 endPlain = find_end_of_layout(document.body, beginPlain)
3017 argcontent = document.body[beginPlain + 1 : endPlain]
3019 z = z - len(document.body[arg : argend + 1])
3021 del document.body[arg : argend + 1]
3022 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
3023 pre += put_cmd_in_ert("{")
3024 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
3025 endPlain = find_end_of_layout(document.body, beginPlain)
3027 z = z - len(document.body[i : beginPlain + 1])
3029 document.body[i : beginPlain + 1] = pre
3030 post = put_cmd_in_ert("}")
3031 document.body[z - 2 : z + 1] = post
3036 def revert_beamerblocks(document):
3037 " Reverts beamer block arguments to ERT "
3039 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3040 if document.textclass not in beamer_classes:
3043 blocks = ["Block", "ExampleBlock", "AlertBlock"]
3045 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3048 i = find_token(document.body, "\\begin_inset Argument", i)
3051 # Find containing paragraph layout
3052 parent = get_containing_layout(document.body, i)
3054 document.warning("Malformed LyX document: Can't find parent paragraph layout")
3059 realparbeg = parent[3]
3060 layoutname = parent[0]
3062 for p in range(parbeg, parend):
3066 if layoutname in blocks:
3067 m = rx.match(document.body[p])
3071 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3072 endPlain = find_end_of_layout(document.body, beginPlain)
3073 endInset = find_end_of_inset(document.body, p)
3074 content = document.body[beginPlain + 1 : endPlain]
3076 realparend = realparend - len(document.body[p : endInset + 1])
3078 del document.body[p : endInset + 1]
3079 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3080 document.body[realparbeg : realparbeg] = subst
3082 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3083 endPlain = find_end_of_layout(document.body, beginPlain)
3084 endInset = find_end_of_inset(document.body, p)
3085 content = document.body[beginPlain + 1 : endPlain]
3087 realparend = realparend - len(document.body[p : endInset + 1])
3089 del document.body[p : endInset + 1]
3090 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3091 document.body[realparbeg : realparbeg] = subst
3096 def convert_beamerblocks(document):
3097 " Converts beamer block ERT args to native InsetArgs "
3099 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3100 if document.textclass not in beamer_classes:
3103 blocks = ["Block", "ExampleBlock", "AlertBlock"]
3107 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
3110 parent = get_containing_layout(document.body, i)
3111 if parent == False or parent[1] != i:
3112 document.warning("Wrong parent layout!")
3119 # If the paragraph starts with a language switch, adjust parbeg
3120 if len(document.body[parbeg]) == 0 and parbeg < parend \
3121 and document.body[parbeg + 1].startswith("\\lang"):
3123 if document.body[parbeg] == "\\begin_inset ERT":
3124 ertcontfirstline = parbeg + 5
3128 # Find the last ERT in this paragraph used for arguments
3129 # (which might also be the first)
3130 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
3131 if lastertbeg == -1:
3132 document.warning("Last ERT not found!")
3134 lastertend = find_end_of_inset(document.body, lastertbeg)
3135 if lastertend == -1:
3136 document.warning("End of last ERT not found!")
3138 # Is this ERT really used for an argument?
3139 # Note: This will fail when non-argument ERTs actually use brackets
3141 regexp = re.compile(r'.*[>\]\}]', re.IGNORECASE)
3142 cbracket = find_re(document.body, regexp, lastertbeg, lastertend)
3145 if lastertbeg == parbeg:
3148 if lastertbeg == -1 or lastertend == -1:
3150 ertcontlastline = lastertend - 3
3152 if document.body[ertcontfirstline].lstrip().startswith("<"):
3153 # This is an overlay specification
3155 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3156 if document.body[ertcontlastline].rstrip().endswith(">"):
3158 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3159 # Convert to ArgInset
3160 document.body[parbeg] = "\\begin_inset Argument 1"
3161 elif document.body[ertcontlastline].rstrip().endswith("}"):
3163 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3165 ertcontdivline = ertcontfirstline
3166 tok = document.body[ertcontdivline].find('>{')
3168 regexp = re.compile(r'.*>\{', re.IGNORECASE)
3169 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3170 tok = document.body[ertcontdivline].find('>{')
3172 if ertcontfirstline < ertcontlastline:
3173 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3174 document.body[ertcontlastline : ertcontlastline + 1] = [
3175 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3176 if ertcontdivline == ertcontfirstline:
3177 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3178 '\\end_layout', '', '\\end_inset', '',
3179 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3180 'status collapsed', '', '\\begin_layout Plain Layout',
3181 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3182 document.body[ertcontdivline][tok + 2:]]
3184 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3185 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3186 'status collapsed', '', '\\begin_layout Plain Layout',
3187 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3188 document.body[ertcontdivline][tok + 2:]]
3190 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3191 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3192 'status collapsed', '', '\\begin_layout Plain Layout',
3193 document.body[ertcontdivline][tok + 2:]]
3195 # check if have delimiters in two different ERTs
3196 tok = document.body[ertcontdivline].find('>')
3198 regexp = re.compile(r'.*>', re.IGNORECASE)
3199 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3200 tok = document.body[ertcontdivline].find('>')
3202 tokk = document.body[ertcontdivline].find('{')
3204 regexp = re.compile(r'.*\{', re.IGNORECASE)
3205 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, lastertend)
3206 tokk = document.body[ertcontdivlinetwo].find('{')
3208 if ertcontfirstline < ertcontlastline:
3209 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3210 document.body[ertcontlastline : ertcontlastline + 1] = [
3211 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3212 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3213 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3214 '\\end_inset', '', '', '\\begin_inset Argument 2',
3215 'status collapsed', '', '\\begin_layout Plain Layout',
3216 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3217 document.body[ertcontdivlinetwo][tokk + 1:]]
3219 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3220 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3221 'status collapsed', '', '\\begin_layout Plain Layout',
3222 document.body[ertcontdivlinetwo][tokk + 1:]]
3223 # Convert to ArgInset
3224 if ertcontfirstline < ertcontlastline:
3225 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3226 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 1',
3227 'status collapsed', '', '\\begin_layout Plain Layout',
3228 '\\begin_inset ERT', '']
3230 document.body[parbeg] = "\\begin_inset Argument 1"
3231 elif document.body[ertcontfirstline].lstrip().startswith("{"):
3232 # This is the block title
3233 if document.body[ertcontlastline].rstrip().endswith("}"):
3234 # strip off the braces
3235 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3236 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3237 if ertcontfirstline < ertcontlastline:
3238 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3239 document.body[parend : parend + 1] = [
3240 document.body[parend], '\\end_inset', '', '\\end_layout']
3241 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3242 'status collapsed', '', '\\begin_layout Plain Layout',
3243 '\\begin_inset ERT', '']
3245 # Convert to ArgInset
3246 document.body[parbeg] = "\\begin_inset Argument 2"
3247 # the overlay argument can also follow the title, so ...
3248 elif document.body[ertcontlastline].rstrip().endswith(">"):
3250 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3252 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3254 ertcontdivline = ertcontfirstline
3255 tok = document.body[ertcontdivline].find('}<')
3257 regexp = re.compile(r'.*\}<', re.IGNORECASE)
3258 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3259 tok = document.body[ertcontdivline].find('}<')
3261 if ertcontfirstline < ertcontlastline:
3262 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3263 document.body[ertcontlastline : ertcontlastline + 1] = [
3264 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3265 if ertcontdivline == ertcontfirstline:
3266 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3267 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3268 'status collapsed', '', '\\begin_layout Plain Layout',
3269 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3270 document.body[ertcontdivline][tok + 2:]]
3272 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3273 '\\end_layout', '', '\\end_inset', '',
3274 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3275 'status collapsed', '', '\\begin_layout Plain Layout',
3276 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3277 document.body[ertcontdivline][tok + 2:]]
3279 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3280 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3281 'status collapsed', '', '\\begin_layout Plain Layout',
3282 document.body[ertcontdivline][tok + 2:]]
3284 # check if have delimiters in two different ERTs
3285 tok = document.body[ertcontdivline].find('}')
3287 regexp = re.compile(r'.*\}', re.IGNORECASE)
3288 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3289 tok = document.body[ertcontdivline].find('}')
3291 tokk = document.body[ertcontdivline].find('<')
3293 regexp = re.compile(r'.*<', re.IGNORECASE)
3294 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, lastertend)
3295 tokk = document.body[ertcontdivlinetwo].find('<')
3297 if ertcontfirstline < ertcontlastline:
3298 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3299 document.body[ertcontlastline : ertcontlastline + 1] = [
3300 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3301 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3302 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3303 '\\end_inset', '', '', '\\begin_inset Argument 1',
3304 'status collapsed', '', '\\begin_layout Plain Layout',
3305 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3306 document.body[ertcontdivlinetwo][tokk + 1:]]
3308 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3309 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3310 'status collapsed', '', '\\begin_layout Plain Layout',
3311 document.body[ertcontdivlinetwo][tokk + 1:]]
3312 # Convert to ArgInset
3313 if ertcontfirstline < ertcontlastline:
3314 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3315 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3316 'status collapsed', '', '\\begin_layout Plain Layout',
3317 '\\begin_inset ERT', '']
3319 document.body[parbeg] = "\\begin_inset Argument 2"
3320 elif count_pars_in_inset(document.body, ertcontfirstline) > 1:
3321 # Multipar ERT. Skip this.
3324 # ERT has contents after the closing bracket. We cannot convert this.
3325 # convert_TeX_brace_to_Argument cannot either.
3326 #convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, False)
3330 j = find_end_of_layout(document.body, i)
3332 document.warning("end of layout not found!")
3333 k = find_token(document.body, "\\begin_inset Argument", i, j)
3335 document.warning("InsetArgument not found!")
3337 l = find_end_of_inset(document.body, k)
3338 m = find_token(document.body, "\\begin_inset ERT", l, j)
3341 ertcontfirstline = m + 5
3346 def convert_overprint(document):
3347 " Convert old beamer overprint layouts to ERT "
3349 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3350 if document.textclass not in beamer_classes:
3355 i = find_token(document.body, "\\begin_layout Overprint", i)
3358 # Find end of sequence
3359 j = find_end_of_sequence(document.body, i)
3361 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3365 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3367 if document.body[j] == "\\end_deeper":
3368 esubst = ["", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3370 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3371 endseq = endseq + len(esubst) - len(document.body[j : j])
3372 document.body[j : j] = esubst
3373 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3375 argend = find_end_of_layout(document.body, argbeg)
3377 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3380 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3381 endPlain = find_end_of_layout(document.body, beginPlain)
3382 content = document.body[beginPlain + 1 : endPlain]
3384 endseq = endseq - len(document.body[argbeg : argend + 1])
3386 del document.body[argbeg : argend + 1]
3387 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3389 endseq = endseq - len(document.body[i : i])
3390 document.body[i : i] = subst + ["\\end_layout"]
3391 endseq += len(subst)
3393 for p in range(i, endseq):
3394 if document.body[p] == "\\begin_layout Overprint":
3395 document.body[p] = "\\begin_layout Standard"
3400 def revert_overprint(document):
3401 " Revert old beamer overprint layouts to ERT "
3403 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3404 if document.textclass not in beamer_classes:
3409 i = find_token(document.body, "\\begin_layout Overprint", i)
3412 # Find end of sequence
3413 j = find_end_of_sequence(document.body, i)
3415 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3419 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3420 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}")
3421 endseq = endseq + len(esubst) - len(document.body[j : j])
3422 if document.body[j] == "\\end_deeper":
3423 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3425 document.body[j : j] = ["\\end_layout", ""] + esubst
3428 if document.body[r] == "\\begin_deeper":
3429 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3431 document.body[r] = ""
3432 document.body[s] = ""
3436 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3438 # Is this really our argument?
3439 nested = find_token(document.body, "\\begin_deeper", i, argbeg)
3441 argend = find_end_of_inset(document.body, argbeg)
3443 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3446 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3447 endPlain = find_end_of_layout(document.body, beginPlain)
3448 content = document.body[beginPlain + 1 : endPlain]
3450 endseq = endseq - len(document.body[argbeg : argend])
3452 del document.body[argbeg : argend + 1]
3453 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3455 endseq = endseq - len(document.body[i : i])
3456 document.body[i : i] = subst + ["\\end_layout"]
3457 endseq += len(subst)
3463 if document.body[p] == "\\begin_layout Overprint":
3464 q = find_end_of_layout(document.body, p)
3466 document.warning("Malformed LyX document. Cannot find end of Overprint layout!")
3469 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\onslide")
3470 argbeg = find_token(document.body, "\\begin_inset Argument item:1", p, q)
3472 argend = find_end_of_inset(document.body, argbeg)
3474 document.warning("Malformed LyX document. Cannot find end of Overprint item argument!")
3477 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3478 endPlain = find_end_of_layout(document.body, beginPlain)
3479 content = document.body[beginPlain + 1 : endPlain]
3481 endseq = endseq - len(document.body[argbeg : argend + 1])
3483 del document.body[argbeg : argend + 1]
3484 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3485 endseq = endseq - len(document.body[p : p + 1]) + len(subst)
3486 document.body[p : p + 1] = subst
3492 def revert_frametitle(document):
3493 " Reverts beamer frametitle layout to ERT "
3495 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3496 if document.textclass not in beamer_classes:
3499 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3502 i = find_token(document.body, "\\begin_layout FrameTitle", i)
3505 j = find_end_of_layout(document.body, i)
3507 document.warning("Malformed LyX document: Can't find end of FrameTitle layout")
3511 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
3512 endlay += len(put_cmd_in_ert("}"))
3513 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\frametitle")
3514 for p in range(i, j):
3517 m = rx.match(document.body[p])
3521 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3522 endPlain = find_end_of_layout(document.body, beginPlain)
3523 endInset = find_end_of_inset(document.body, p)
3524 content = document.body[beginPlain + 1 : endPlain]
3526 endlay = endlay - len(document.body[p : endInset + 1])
3528 del document.body[p : endInset + 1]
3529 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3531 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3532 endPlain = find_end_of_layout(document.body, beginPlain)
3533 endInset = find_end_of_inset(document.body, p)
3534 content = document.body[beginPlain + 1 : endPlain]
3536 endlay = endlay - len(document.body[p : endInset + 1])
3538 del document.body[p : endInset + 1]
3539 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3541 subst += put_cmd_in_ert("{")
3542 document.body[i : i + 1] = subst
3546 def convert_epigraph(document):
3547 " Converts memoir epigraph to new syntax "
3549 if document.textclass != "memoir":
3554 i = find_token(document.body, "\\begin_layout Epigraph", i)
3557 j = find_end_of_layout(document.body, i)
3559 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3564 ert = find_token(document.body, "\\begin_inset ERT", i, j)
3566 endInset = find_end_of_inset(document.body, ert)
3567 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", ert)
3568 endPlain = find_end_of_layout(document.body, beginPlain)
3569 ertcont = beginPlain + 2
3570 if document.body[ertcont] == "}{":
3572 # Convert to ArgInset
3573 endlay = endlay - 2 * len(document.body[j])
3574 begsubst = ['\\begin_inset Argument post:1', 'status collapsed', '',
3575 '\\begin_layout Plain Layout']
3576 endsubst = ['\\end_layout', '', '\\end_inset', '', document.body[j]]
3577 document.body[j : j + 1] = endsubst
3578 document.body[endInset + 1 : endInset + 1] = begsubst
3580 endlay += len(begsubst) + len(endsubst)
3581 endlay = endlay - len(document.body[ert : endInset + 1])
3582 del document.body[ert : endInset + 1]
3587 def revert_epigraph(document):
3588 " Reverts memoir epigraph argument to ERT "
3590 if document.textclass != "memoir":
3595 i = find_token(document.body, "\\begin_layout Epigraph", i)
3598 j = find_end_of_layout(document.body, i)
3600 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3605 p = find_token(document.body, "\\begin_layout Argument post:1", i, j)
3607 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3608 endPlain = find_end_of_layout(document.body, beginPlain)
3609 endInset = find_end_of_inset(document.body, p)
3610 content = document.body[beginPlain + 1 : endPlain]
3612 endlay = endlay - len(document.body[p : endInset + 1])
3614 del document.body[p : endInset + 1]
3615 subst += put_cmd_in_ert("}{") + content
3617 subst += put_cmd_in_ert("}{")
3619 document.body[j : j] = subst + document.body[j : j]
3623 def convert_captioninsets(document):
3624 " Converts caption insets to new syntax "
3628 i = find_token(document.body, "\\begin_inset Caption", i)
3631 document.body[i] = "\\begin_inset Caption Standard"
3635 def revert_captioninsets(document):
3636 " Reverts caption insets to old syntax "
3640 i = find_token(document.body, "\\begin_inset Caption Standard", i)
3643 document.body[i] = "\\begin_inset Caption"
3647 def convert_captionlayouts(document):
3648 " Convert caption layouts to caption insets. "
3651 "Captionabove": "Above",
3652 "Captionbelow": "Below",
3653 "FigCaption" : "FigCaption",
3654 "Table_Caption" : "Table",
3655 "CenteredCaption" : "Centered",
3656 "Bicaption" : "Bicaption",
3659 for captype in caption_dict.keys():
3662 i = find_token(document.body, "\\begin_layout " + captype, i)
3665 j = find_end_of_layout(document.body, i)
3667 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3670 document.body[j:j] = ["\\end_layout", "", "\\end_inset", "", ""]
3671 document.body[i:i+1] = ["\\begin_layout %s" % document.default_layout,
3672 "\\begin_inset Caption %s" % caption_dict[captype], "",
3673 "\\begin_layout %s" % document.default_layout]
3677 def revert_captionlayouts(document):
3678 " Revert caption insets to caption layouts. "
3681 "Above" : "Captionabove",
3682 "Below" : "Captionbelow",
3683 "FigCaption" : "FigCaption",
3684 "Table" : "Table_Caption",
3685 "Centered" : "CenteredCaption",
3686 "Bicaption" : "Bicaption",
3690 rx = re.compile(r'^\\begin_inset Caption (\S+)$')
3692 i = find_token(document.body, "\\begin_inset Caption", i)
3696 m = rx.match(document.body[i])
3700 if val not in list(caption_dict.keys()):
3704 # We either need to delete the previous \begin_layout line, or we
3705 # need to end the previous layout if this inset is not in the first
3706 # position of the paragraph.
3707 layout_before = find_token_backwards(document.body, "\\begin_layout", i)
3708 if layout_before == -1:
3709 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3711 layout_line = document.body[layout_before]
3712 del_layout_before = True
3713 l = layout_before + 1
3715 if document.body[l] != "":
3716 del_layout_before = False
3719 if del_layout_before:
3720 del document.body[layout_before:i]
3723 document.body[i:i] = ["\\end_layout", ""]
3726 # Find start of layout in the inset and end of inset
3727 j = find_token(document.body, "\\begin_layout", i)
3729 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3731 k = find_end_of_inset(document.body, i)
3733 document.warning("Malformed LyX document: Missing `\\end_inset'.")
3736 # We either need to delete the following \end_layout line, or we need
3737 # to restart the old layout if this inset is not at the paragraph end.
3738 layout_after = find_token(document.body, "\\end_layout", k)
3739 if layout_after == -1:
3740 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3742 del_layout_after = True
3744 while l < layout_after:
3745 if document.body[l] != "":
3746 del_layout_after = False
3749 if del_layout_after:
3750 del document.body[k+1:layout_after+1]
3752 document.body[k+1:k+1] = [layout_line, ""]
3754 # delete \begin_layout and \end_inset and replace \begin_inset with
3755 # "\begin_layout XXX". This works because we can only have one
3756 # paragraph in the caption inset: The old \end_layout will be recycled.
3757 del document.body[k]
3758 if document.body[k] == "":
3759 del document.body[k]
3760 del document.body[j]
3761 if document.body[j] == "":
3762 del document.body[j]
3763 document.body[i] = "\\begin_layout %s" % caption_dict[val]
3764 if document.body[i+1] == "":
3765 del document.body[i+1]
3769 def revert_fragileframe(document):
3770 " Reverts beamer FragileFrame layout to ERT "
3772 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3773 if document.textclass not in beamer_classes:
3778 i = find_token(document.body, "\\begin_layout FragileFrame", i)
3781 # Find end of sequence
3782 j = find_end_of_sequence(document.body, i)
3784 document.warning("Malformed LyX document. Cannot find end of FragileFrame sequence!")
3788 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{frame}")
3789 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{frame}")
3790 endseq = endseq + len(esubst) - len(document.body[j : j])
3791 if document.body[j] == "\\end_deeper":
3792 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3794 document.body[j : j] = esubst
3795 for q in range(i, j):
3796 if document.body[q] == "\\begin_layout FragileFrame":
3797 document.body[q] = "\\begin_layout %s" % document.default_layout
3800 if document.body[r] == "\\begin_deeper":
3801 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3803 document.body[r] = ""
3804 document.body[s] = ""
3808 for p in range(1, 5):
3809 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, j)
3812 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3813 endPlain = find_end_of_layout(document.body, beginPlain)
3814 endInset = find_end_of_inset(document.body, arg)
3815 content = document.body[beginPlain + 1 : endPlain]
3817 j = j - len(document.body[arg : endInset + 1])
3819 del document.body[arg : endInset + 1]
3820 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3822 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3823 endPlain = find_end_of_layout(document.body, beginPlain)
3824 endInset = find_end_of_inset(document.body, arg)
3825 content = document.body[beginPlain + 1 : endPlain]
3827 j = j - len(document.body[arg : endInset + 1])
3829 del document.body[arg : endInset + 1]
3830 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3832 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3833 endPlain = find_end_of_layout(document.body, beginPlain)
3834 endInset = find_end_of_inset(document.body, arg)
3835 content = document.body[beginPlain + 1 : endPlain]
3837 j = j - len(document.body[arg : endInset + 1])
3839 del document.body[arg : endInset + 1]
3840 subst += put_cmd_in_ert("[fragile,") + content + put_cmd_in_ert("]")
3842 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3843 endPlain = find_end_of_layout(document.body, beginPlain)
3844 endInset = find_end_of_inset(document.body, arg)
3845 content = document.body[beginPlain + 1 : endPlain]
3847 j = j - len(document.body[arg : endInset + 1])
3849 del document.body[arg : endInset + 1]
3850 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3852 subst += put_cmd_in_ert("[fragile]")
3854 document.body[i : i + 1] = subst
3858 def revert_newframes(document):
3859 " Reverts beamer Frame and PlainFrame layouts to old forms "
3861 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3862 if document.textclass not in beamer_classes:
3866 "Frame" : "BeginFrame",
3867 "PlainFrame" : "BeginPlainFrame",
3870 rx = re.compile(r'^\\begin_layout (\S+)$')
3873 i = find_token(document.body, "\\begin_layout", i)
3877 m = rx.match(document.body[i])
3881 if val not in list(frame_dict.keys()):
3884 # Find end of sequence
3885 j = find_end_of_sequence(document.body, i)
3887 document.warning("Malformed LyX document. Cannot find end of Frame sequence!")
3891 subst = ["\\begin_layout %s" % frame_dict[val]]
3892 esubst = ["", "\\begin_layout EndFrame", "", "\\end_layout"]
3893 endseq = endseq + len(esubst) - len(document.body[j : j])
3894 if document.body[j] == "\\end_deeper":
3895 document.body[j : j] = esubst
3897 document.body[j+1 : j+1] = esubst
3898 for q in range(i, j):
3899 if document.body[q] == "\\begin_layout %s" % val:
3900 document.body[q] = "\\begin_layout %s" % document.default_layout
3903 if document.body[r] == "\\begin_deeper":
3904 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3906 document.body[r] = ""
3907 document.body[s] = ""
3911 l = find_end_of_layout(document.body, i)
3912 for p in range(1, 5):
3913 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, l)
3916 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3917 endPlain = find_end_of_layout(document.body, beginPlain)
3918 endInset = find_end_of_inset(document.body, arg)
3919 content = document.body[beginPlain + 1 : endPlain]
3921 l = l - len(document.body[arg : endInset + 1])
3923 del document.body[arg : endInset + 1]
3924 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3926 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3927 endPlain = find_end_of_layout(document.body, beginPlain)
3928 endInset = find_end_of_inset(document.body, arg)
3929 content = document.body[beginPlain + 1 : endPlain]
3931 l = l - len(document.body[arg : endInset + 1])
3933 del document.body[arg : endInset + 1]
3934 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3936 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3937 endPlain = find_end_of_layout(document.body, beginPlain)
3938 endInset = find_end_of_inset(document.body, arg)
3939 content = document.body[beginPlain + 1 : endPlain]
3941 l = l - len(document.body[arg : endInset + 1])
3943 del document.body[arg : endInset + 1]
3944 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3946 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3947 endPlain = find_end_of_layout(document.body, beginPlain)
3948 endInset = find_end_of_inset(document.body, arg)
3949 content = document.body[beginPlain + 1 : endPlain]
3951 l = l - len(document.body[arg : endInset + 1])
3953 del document.body[arg : endInset + 1]
3956 document.body[i : i + 1] = subst
3959 # known encodings that do not change their names (same LyX and LaTeX names)
3960 known_enc_tuple = ("auto", "default", "ansinew", "applemac", "armscii8", "ascii",
3961 "cp437", "cp437de", "cp850", "cp852", "cp855", "cp858", "cp862", "cp865", "cp866",
3962 "cp1250", "cp1251", "cp1252", "cp1255", "cp1256", "cp1257", "koi8-r", "koi8-u",
3963 "pt154", "pt254", "tis620-0", "utf8", "utf8x", "utf8-plain")
3965 def convert_encodings(document):
3966 "Use the LyX names of the encodings instead of the LaTeX names."
3967 LaTeX2LyX_enc_dict = {
3968 "8859-6": "iso8859-6",
3969 "8859-8": "iso8859-8",
3971 "euc": "euc-jp-platex",
3976 "iso88595": "iso8859-5",
3977 "iso-8859-7": "iso8859-7",
3979 "jis": "jis-platex",
3981 "l7xenc": "iso8859-13",
3982 "latin1": "iso8859-1",
3983 "latin2": "iso8859-2",
3984 "latin3": "iso8859-3",
3985 "latin4": "iso8859-4",
3986 "latin5": "iso8859-9",
3987 "latin9": "iso8859-15",
3988 "latin10": "iso8859-16",
3989 "SJIS": "shift-jis",
3990 "sjis": "shift-jis-platex",
3993 i = find_token(document.header, "\\inputencoding" , 0)
3996 val = get_value(document.header, "\\inputencoding", i)
3997 if val in list(LaTeX2LyX_enc_dict.keys()):
3998 document.header[i] = "\\inputencoding %s" % LaTeX2LyX_enc_dict[val]
3999 elif val not in known_enc_tuple:
4000 document.warning("Ignoring unknown input encoding: `%s'" % val)
4003 def revert_encodings(document):
4004 """Revert to using the LaTeX names of the encodings instead of the LyX names.
4005 Also revert utf8-platex to sjis, the language default when using Japanese.
4007 LyX2LaTeX_enc_dict = {
4012 "euc-jp-platex": "euc",
4015 "iso8859-1": "latin1",
4016 "iso8859-2": "latin2",
4017 "iso8859-3": "latin3",
4018 "iso8859-4": "latin4",
4019 "iso8859-5": "iso88595",
4020 "iso8859-6": "8859-6",
4021 "iso8859-7": "iso-8859-7",
4022 "iso8859-8": "8859-8",
4023 "iso8859-9": "latin5",
4024 "iso8859-13": "l7xenc",
4025 "iso8859-15": "latin9",
4026 "iso8859-16": "latin10",
4028 "jis-platex": "jis",
4029 "shift-jis": "SJIS",
4030 "shift-jis-platex": "sjis",
4032 "utf8-platex": "sjis"
4034 i = find_token(document.header, "\\inputencoding" , 0)
4037 val = get_value(document.header, "\\inputencoding", i)
4038 if val in list(LyX2LaTeX_enc_dict.keys()):
4039 document.header[i] = "\\inputencoding %s" % LyX2LaTeX_enc_dict[val]
4040 elif val not in known_enc_tuple:
4041 document.warning("Ignoring unknown input encoding: `%s'" % val)
4044 def revert_IEEEtran_3(document):
4046 Reverts Flex Insets to TeX-code
4048 if document.textclass == "IEEEtran":
4054 h = find_token(document.body, "\\begin_inset Flex Author Mark", h)
4056 endh = find_end_of_inset(document.body, h)
4057 document.body[endh - 2 : endh + 1] = put_cmd_in_ert("}")
4058 document.body[h : h + 4] = put_cmd_in_ert("\\IEEEauthorrefmark{")
4061 i = find_token(document.body, "\\begin_inset Flex Author Name", i)
4063 endi = find_end_of_inset(document.body, i)
4064 document.body[endi - 2 : endi + 1] = put_cmd_in_ert("}")
4065 document.body[i : i + 4] = put_cmd_in_ert("\\IEEEauthorblockN{")
4068 j = find_token(document.body, "\\begin_inset Flex Author Affiliation", j)
4070 endj = find_end_of_inset(document.body, j)
4071 document.body[endj - 2 : endj + 1] = put_cmd_in_ert("}")
4072 document.body[j : j + 4] = put_cmd_in_ert("\\IEEEauthorblockA{")
4074 if i == -1 and j == -1 and h == -1:
4078 def revert_kurier_fonts(document):
4079 " Revert kurier font definition to LaTeX "
4081 i = find_token(document.header, "\\font_math", 0)
4083 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4084 val = get_value(document.header, "\\font_math", i)
4085 if val == "kurier-math":
4086 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
4087 "\\usepackage[math]{kurier}\n" \
4088 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
4089 document.header[i] = "\\font_math auto"
4091 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4092 kurier_fonts = ["kurier", "kurierc", "kurierl", "kurierlc"]
4093 k = find_token(document.header, "\\font_sans kurier", 0)
4095 sf = get_value(document.header, "\\font_sans", k)
4096 if sf in kurier_fonts:
4097 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4098 document.header[k] = "\\font_sans default"
4100 def revert_iwona_fonts(document):
4101 " Revert iwona font definition to LaTeX "
4103 i = find_token(document.header, "\\font_math", 0)
4105 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4106 val = get_value(document.header, "\\font_math", i)
4107 if val == "iwona-math":
4108 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
4109 "\\usepackage[math]{iwona}\n" \
4110 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
4111 document.header[i] = "\\font_math auto"
4113 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4114 iwona_fonts = ["iwona", "iwonac", "iwonal", "iwonalc"]
4115 k = find_token(document.header, "\\font_sans iwona", 0)
4117 sf = get_value(document.header, "\\font_sans", k)
4118 if sf in iwona_fonts:
4119 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4120 document.header[k] = "\\font_sans default"
4123 def revert_new_libertines(document):
4124 " Revert new libertine font definition to LaTeX "
4126 if find_token(document.header, "\\use_non_tex_fonts true", 0) != -1:
4129 i = find_token(document.header, "\\font_typewriter libertine-mono", 0)
4131 preamble = "\\usepackage"
4132 sc = find_token(document.header, "\\font_tt_scale", 0)
4134 scval = get_value(document.header, "\\font_tt_scale", sc)
4136 preamble += "[scale=%f]" % (float(scval) / 100)
4137 document.header[sc] = "\\font_tt_scale 100"
4138 preamble += "{libertineMono-type1}"
4139 add_to_preamble(document, [preamble])
4140 document.header[i] = "\\font_typewriter default"
4142 k = find_token(document.header, "\\font_sans biolinum", 0)
4144 preamble = "\\usepackage"
4146 j = find_token(document.header, "\\font_osf true", 0)
4151 sc = find_token(document.header, "\\font_sf_scale", 0)
4153 scval = get_value(document.header, "\\font_sf_scale", sc)
4155 options += ",scale=%f" % (float(scval) / 100)
4156 document.header[sc] = "\\font_sf_scale 100"
4158 preamble += "[" + options +"]"
4159 preamble += "{biolinum-type1}"
4160 add_to_preamble(document, [preamble])
4161 document.header[k] = "\\font_sans default"
4164 def convert_lyxframes(document):
4165 " Converts old beamer frames to new style "
4167 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4168 if document.textclass not in beamer_classes:
4171 framebeg = ["BeginFrame", "BeginPlainFrame"]
4172 frameend = ["Frame", "PlainFrame", "EndFrame", "BeginFrame", "BeginPlainFrame", "AgainFrame",
4173 "Section", "Section*", "Subsection", "Subsection*", "Subsubsection", "Subsubsection*"]
4174 for lay in framebeg:
4177 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
4180 parent = get_containing_layout(document.body, i)
4181 if parent == False or parent[1] != i:
4182 document.warning("Wrong parent layout!")
4185 frametype = parent[0]
4189 # Step I: Convert ERT arguments
4190 # FIXME: See restrictions in convert_beamerframeargs method
4191 ertend = convert_beamerframeargs(document, i, parbeg)
4194 # Step II: Now rename the layout and convert the title to an argument
4195 j = find_end_of_layout(document.body, i)
4196 document.body[j : j + 1] = ['\\end_layout', '', '\\end_inset', '', '\\end_layout']
4197 if lay == "BeginFrame":
4198 document.body[i] = "\\begin_layout Frame"
4200 document.body[i] = "\\begin_layout PlainFrame"
4201 document.body[ertend + 1 : ertend + 1] = ['\\begin_inset Argument 4',
4202 'status open', '', '\\begin_layout Plain Layout']
4203 # Step III: find real frame end
4206 inInset = get_containing_inset(document.body, i)
4208 fend = find_token(document.body, "\\begin_layout", jj)
4210 document.warning("Malformed LyX document: No real frame end!")
4212 val = get_value(document.body, "\\begin_layout", fend)
4213 if val not in frameend:
4216 # is this frame nested in an inset (e.g., Note)?
4217 if inInset != False:
4218 # if so, end the frame inside the inset
4219 if inInset[2] < fend:
4221 if val == frametype:
4222 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4223 # consider explicit EndFrames between two identical frame types
4224 elif val == "EndFrame":
4225 nextlayout = find_token(document.body, "\\begin_layout", fend + 1)
4226 if nextlayout != -1 and get_value(document.body, "\\begin_layout", nextlayout) == frametype:
4227 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4229 document.body[fend : fend] = ['\\end_deeper']
4231 document.body[fend : fend] = ['\\end_deeper']
4232 document.body[j + 1 : j + 1] = ['', '\\begin_deeper']
4237 def remove_endframes(document):
4238 " Remove deprecated beamer endframes "
4240 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4241 if document.textclass not in beamer_classes:
4246 i = find_token_exact(document.body, "\\begin_layout EndFrame", i)
4249 j = find_end_of_layout(document.body, i)
4251 document.warning("Malformed LyX document: Missing \\end_layout to EndFrame")
4254 del document.body[i : j + 1]
4257 def revert_powerdot_flexes(document):
4258 " Reverts powerdot flex insets "
4260 if document.textclass != "powerdot":
4263 flexes = {"Onslide" : "\\onslide",
4264 "Onslide*" : "\\onslide*",
4265 "Onslide+" : "\\onslide+"}
4266 rx = re.compile(r'^\\begin_inset Flex (.+)$')
4270 i = find_token(document.body, "\\begin_inset Flex", i)
4273 m = rx.match(document.body[i])
4275 flextype = m.group(1)
4276 z = find_end_of_inset(document.body, i)
4278 document.warning("Can't find end of Flex " + flextype + " inset.")
4281 if flextype in flexes:
4282 pre = put_cmd_in_ert(flexes[flextype])
4283 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
4285 argend = find_end_of_inset(document.body, arg)
4287 document.warning("Can't find end of Argument!")
4290 # Find containing paragraph layout
4291 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
4292 endPlain = find_end_of_layout(document.body, beginPlain)
4293 argcontent = document.body[beginPlain + 1 : endPlain]
4295 z = z - len(document.body[arg : argend + 1])
4297 del document.body[arg : argend + 1]
4298 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
4299 pre += put_cmd_in_ert("{")
4300 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4301 endPlain = find_end_of_layout(document.body, beginPlain)
4303 z = z - len(document.body[i : beginPlain + 1])
4305 document.body[i : beginPlain + 1] = pre
4306 post = put_cmd_in_ert("}")
4307 document.body[z - 2 : z + 1] = post
4311 def revert_powerdot_pause(document):
4312 " Reverts powerdot pause layout to ERT "
4314 if document.textclass != "powerdot":
4319 i = find_token(document.body, "\\begin_layout Pause", i)
4322 j = find_end_of_layout(document.body, i)
4324 document.warning("Malformed LyX document: Can't find end of Pause layout")
4328 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\pause")
4329 for p in range(i, j):
4332 arg = find_token(document.body, "\\begin_inset Argument 1", i, j)
4334 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4335 endPlain = find_end_of_layout(document.body, beginPlain)
4336 endInset = find_end_of_inset(document.body, p)
4337 content = document.body[beginPlain + 1 : endPlain]
4339 endlay = endlay - len(document.body[p : endInset + 1])
4341 del document.body[p : endInset + 1]
4342 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4344 document.body[i : i + 1] = subst
4348 def revert_powerdot_itemargs(document):
4349 " Reverts powerdot item arguments to ERT "
4351 if document.textclass != "powerdot":
4355 list_layouts = ["Itemize", "ItemizeType1", "Enumerate", "EnumerateType1"]
4356 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4359 i = find_token(document.body, "\\begin_inset Argument", i)
4362 # Find containing paragraph layout
4363 parent = get_containing_layout(document.body, i)
4365 document.warning("Malformed LyX document: Can't find parent paragraph layout")
4370 realparbeg = parent[3]
4371 layoutname = parent[0]
4373 for p in range(parbeg, parend):
4377 if layoutname in list_layouts:
4378 m = rx.match(document.body[p])
4381 if argnr == "item:1":
4382 j = find_end_of_inset(document.body, i)
4383 # Find containing paragraph layout
4384 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4385 endPlain = find_end_of_layout(document.body, beginPlain)
4386 content = document.body[beginPlain + 1 : endPlain]
4387 del document.body[i:j+1]
4388 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4389 document.body[realparbeg : realparbeg] = subst
4390 elif argnr == "item:2":
4391 j = find_end_of_inset(document.body, i)
4392 # Find containing paragraph layout
4393 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4394 endPlain = find_end_of_layout(document.body, beginPlain)
4395 content = document.body[beginPlain + 1 : endPlain]
4396 del document.body[i:j+1]
4397 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
4398 document.body[realparbeg : realparbeg] = subst
4403 def revert_powerdot_columns(document):
4404 " Reverts powerdot twocolumn to TeX-code "
4405 if document.textclass != "powerdot":
4408 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4411 i = find_token(document.body, "\\begin_layout Twocolumn", i)
4414 j = find_end_of_layout(document.body, i)
4416 document.warning("Malformed LyX document: Can't find end of Twocolumn layout")
4420 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
4421 endlay += len(put_cmd_in_ert("}"))
4422 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\twocolumn")
4423 for p in range(i, j):
4426 m = rx.match(document.body[p])
4430 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4431 endPlain = find_end_of_layout(document.body, beginPlain)
4432 endInset = find_end_of_inset(document.body, p)
4433 content = document.body[beginPlain + 1 : endPlain]
4435 endlay = endlay - len(document.body[p : endInset + 1])
4437 del document.body[p : endInset + 1]
4438 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4440 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4441 endPlain = find_end_of_layout(document.body, beginPlain)
4442 endInset = find_end_of_inset(document.body, p)
4443 content = document.body[beginPlain + 1 : endPlain]
4445 endlay = endlay - len(document.body[p : endInset + 1])
4447 del document.body[p : endInset + 1]
4448 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
4450 subst += put_cmd_in_ert("{")
4451 document.body[i : i + 1] = subst
4455 def revert_mbox_fbox(document):
4456 'Convert revert mbox/fbox boxes to TeX-code'
4459 i = find_token(document.body, "\\begin_inset Box", i)
4462 j = find_token(document.body, "width", i)
4464 document.warning("Malformed LyX document: Can't find box width")
4466 width = get_value(document.body, "width", j)
4467 k = find_end_of_inset(document.body, j)
4469 document.warning("Malformed LyX document: Can't find end of box inset")
4472 BeginLayout = find_token(document.body, "\\begin_layout Plain Layout", j)
4473 EndLayout = find_end_of_layout(document.body, BeginLayout)
4474 # replace if width is ""
4476 document.body[EndLayout:k + 1] = put_cmd_in_ert("}")
4477 if document.body[i] == "\\begin_inset Box Frameless":
4478 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\mbox{")
4479 if document.body[i] == "\\begin_inset Box Boxed":
4480 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\fbox{")
4484 def revert_starred_caption(document):
4485 " Reverts unnumbered longtable caption insets "
4489 i = find_token(document.body, "\\begin_inset Caption LongTableNoNumber", i)
4492 # This is not equivalent, but since the caption inset is a full blown
4493 # text inset a true conversion to ERT is too difficult.
4494 document.body[i] = "\\begin_inset Caption Standard"
4498 def revert_forced_local_layout(document):
4501 i = find_token(document.header, "\\begin_forced_local_layout", i)
4504 j = find_end_of(document.header, i, "\\begin_forced_local_layout", "\\end_forced_local_layout")
4506 # this should not happen
4508 regexp = re.compile(r'\s*forcelocal', re.IGNORECASE)
4509 k = find_re(document.header, regexp, i, j)
4511 del document.header[k]
4513 k = find_re(document.header, regexp, i, j)
4514 k = find_token(document.header, "\\begin_local_layout", 0)
4516 document.header[i] = "\\begin_local_layout"
4517 document.header[j] = "\\end_local_layout"
4519 l = find_end_of(document.header, k, "\\begin_local_layout", "\\end_local_layout")
4521 # this should not happen
4523 lines = document.header[i+1 : j]
4525 document.header[k+1 : k+1] = lines
4526 document.header[i : j ] = []
4528 document.header[i : j ] = []
4529 document.header[k+1 : k+1] = lines
4532 def revert_aa1(document):
4533 " Reverts InsetArguments of aa to TeX-code "
4534 if document.textclass == "aa":
4538 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4540 revert_Argument_to_TeX_brace(document, i, 0, 1, 4, False, False)
4546 def revert_aa2(document):
4547 " Reverts InsetArguments of aa to TeX-code "
4548 if document.textclass == "aa":
4552 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4554 document.body[i] = "\\begin_layout Abstract"
4560 def revert_tibetan(document):
4561 "Set the document language for Tibetan to English"
4563 if document.language == "tibetan":
4564 document.language = "english"
4565 i = find_token(document.header, "\\language", 0)
4567 document.header[i] = "\\language english"
4569 while j < len(document.body):
4570 j = find_token(document.body, "\\lang tibetan", j)
4572 document.body[j] = document.body[j].replace("\\lang tibetan", "\\lang english")
4575 j = len(document.body)
4584 # The idea here is that we will have a sequence of chunk paragraphs.
4585 # We want to convert them to paragraphs in one or several chunk insets.
4586 # Individual chunks are terminated by the character @ on the last line.
4587 # This line will be discarded, and following lines are treated as new
4588 # chunks, which go into their own insets.
4589 # The first line of a chunk should look like: <<CONTENT>>=
4590 # We will discard the delimiters, and put the CONTENT into the
4591 # optional argument of the inset, if the CONTENT is non-empty.
4592 def convert_chunks(document):
4593 first_re = re.compile(r'<<(.*)>>=(.*)')
4596 # find start of a block of chunks
4597 i = find_token(document.body, "\\begin_layout Chunk", file_pos)
4603 chunk_started = False
4606 # process the one we just found
4607 j = find_end_of_layout(document.body, i)
4609 document.warning("Malformed LyX documents. Can't find end of Chunk layout!")
4610 # there is no point continuing, as we will run into the same error again.
4612 this_chunk = "".join(document.body[i + 1:j])
4614 # there may be empty lines between chunks
4615 # we just skip them.
4616 if not chunk_started:
4617 if this_chunk != "":
4619 chunk_started = True
4622 contents.append(document.body[i + 1:j])
4624 # look for potential chunk terminator
4625 # on the last line of the chunk paragraph
4626 if document.body[j - 1] == "@":
4629 # look for subsequent chunk paragraph
4630 i = find_token(document.body, "\\begin_layout", j)
4634 if get_value(document.body, "\\begin_layout", i) != "Chunk":
4637 file_pos = end = j + 1
4639 # The last chunk should simply have an "@" in it
4640 # or at least end with "@" (can happen if @ is
4641 # preceded by a newline)
4643 if len(contents) > 0:
4644 lastpar = ''.join(contents[-1])
4645 if not lastpar.endswith("@"):
4646 document.warning("Unexpected chunk content: chunk not terminated by '@'!")
4647 if len(contents) == 0:
4648 # convert empty chunk layouts to Standard
4649 document.body[start] = "\\begin_layout Standard"
4653 # chunk par only contains "@". Just drop it.
4656 # chunk par contains more. Only drop the "@".
4659 # The first line should look like: <<CONTENT>>=
4660 # We want the CONTENT
4661 optarg = ' '.join(contents[0])
4663 # We can already have real chunk content in
4664 # the first par (separated from the options by a newline).
4665 # We collect such stuff to re-insert it later.
4668 match = first_re.search(optarg)
4670 optarg = match.groups()[0]
4671 if match.groups()[1] != "":
4673 for c in contents[0]:
4674 if c.endswith(">>="):
4678 postoptstuff.append(c)
4679 # We have stripped everything. This can be deleted.
4682 newstuff = ['\\begin_layout Standard']
4684 # Maintain paragraph parameters
4685 par_params = ["\\noindent", "\\indent", "\\indent-toggle", "\\leftindent",
4686 "\\start_of_appendix", "\\paragraph_spacing", "\\align",
4687 "\\labelwidthstring"]
4690 if document.body[parms].split(' ', 1)[0] not in par_params:
4692 newstuff.extend([document.body[parms]])
4696 ['\\begin_inset Flex Chunk',
4698 '\\begin_layout Plain Layout', ''])
4700 # If we have a non-empty optional argument, insert it.
4701 if match and optarg != "":
4703 ['\\begin_inset Argument 1',
4705 '\\begin_layout Plain Layout',
4710 # Since we already opened a Plain layout, the first paragraph
4711 # does not need to do that.
4714 # we need to replace newlines with new layouts
4716 started_text = False
4717 for lno in range(0,len(postoptstuff)):
4718 if postoptstuff[lno].startswith("\\begin_inset Newline newline"):
4720 elif start_newline != -1:
4721 if postoptstuff[lno].startswith("\\end_inset"):
4722 # replace that bit, but only if we already have some text
4723 # and we're not at the end except for a blank line
4724 if started_text and \
4725 (lno != len(postoptstuff) - 2 or postoptstuff[-1] != ""):
4726 newstuff.extend(['\\end_layout', '\n', '\\begin_layout Plain Layout', '\n'])
4730 newstuff.extend([postoptstuff[lno]])
4731 newstuff.append('\\end_layout')
4735 newstuff.extend(['', '\\begin_layout Plain Layout', ''])
4739 newstuff.append('\\end_layout')
4741 newstuff.extend(['', '\\end_inset', '', '\\end_layout', ''])
4743 document.body[start:end] = newstuff
4745 file_pos += len(newstuff) - (end - start)
4748 def revert_chunks(document):
4751 i = find_token(document.body, "\\begin_inset Flex Chunk", i)
4755 iend = find_end_of_inset(document.body, i)
4757 document.warning("Can't find end of Chunk!")
4761 # Look for optional argument
4763 ostart = find_token(document.body, "\\begin_inset Argument 1", i, iend)
4765 oend = find_end_of_inset(document.body, ostart)
4766 k = find_token(document.body, "\\begin_layout Plain Layout", ostart, oend)
4768 document.warning("Malformed LyX document: Can't find argument contents!")
4770 m = find_end_of_layout(document.body, k)
4771 optarg = "".join(document.body[k+1:m])
4773 # We now remove the optional argument, so we have something
4774 # uniform on which to work
4775 document.body[ostart : oend + 1] = []
4776 # iend is now invalid
4777 iend = find_end_of_inset(document.body, i)
4779 retval = get_containing_layout(document.body, i)
4781 document.warning("Can't find containing layout for Chunk!")
4784 (lname, lstart, lend, pstart) = retval
4785 # we now want to work through the various paragraphs, and collect their contents
4789 k = find_token(document.body, "\\begin_layout Plain Layout", k, lend)
4792 j = find_end_of_layout(document.body, k)
4794 document.warning("Can't find end of layout inside chunk!")
4796 parlist.append(document.body[k+1:j])
4798 # we now need to wrap all of these paragraphs in chunks
4800 newlines.extend(["\\begin_layout Chunk", "", "<<" + optarg + ">>=", "\\end_layout", ""])
4801 for stuff in parlist:
4802 newlines.extend(["\\begin_layout Chunk"] + stuff + ["\\end_layout", ""])
4803 newlines.extend(["\\begin_layout Chunk", "", "@", "\\end_layout", ""])
4804 # replace old content with new content
4805 document.body[lstart : lend + 1] = newlines
4806 i = lstart + len(newlines)
4813 supported_versions = ["2.1.0","2.1"]
4816 [415, [convert_undertilde]],
4818 [417, [convert_japanese_encodings]],
4819 [418, [convert_justification]],
4821 [420, [convert_biblio_style]],
4822 [421, [convert_longtable_captions]],
4823 [422, [convert_use_packages]],
4824 [423, [convert_use_mathtools]],
4825 [424, [convert_cite_engine_type]],
4826 # No convert_cancel, since cancel will be loaded automatically
4827 # in format 425 without any possibility to switch it off.
4828 # This has been fixed in format 464.
4832 [428, [convert_cell_rotation]],
4833 [429, [convert_table_rotation]],
4834 [430, [convert_listoflistings]],
4835 [431, [convert_use_amssymb]],
4837 [433, [convert_armenian]],
4844 [440, [convert_mathfonts]],
4845 [441, [convert_mdnomath]],
4850 [446, [convert_latexargs]],
4851 [447, [convert_IEEEtran, convert_AASTeX, convert_AGUTeX, convert_IJMP, convert_SIGPLAN, convert_SIGGRAPH, convert_EuropeCV, convert_Initials, convert_ModernCV]],
4852 [448, [convert_literate]],
4855 [451, [convert_beamerargs, convert_againframe_args, convert_corollary_args, convert_quote_args]],
4856 [452, [convert_beamerblocks]],
4857 [453, [convert_use_stmaryrd]],
4858 [454, [convert_overprint]],
4860 [456, [convert_epigraph]],
4861 [457, [convert_use_stackrel]],
4862 [458, [convert_captioninsets, convert_captionlayouts]],
4867 [463, [convert_encodings]],
4868 [464, [convert_use_cancel]],
4869 [465, [convert_lyxframes, remove_endframes]],
4875 [471, [convert_cite_engine_type_default]],
4878 [474, [convert_chunks, cleanup_beamerargs]],
4882 [473, [revert_chunks]],
4883 [472, [revert_tibetan]],
4884 [471, [revert_aa1,revert_aa2]],
4885 [470, [revert_cite_engine_type_default]],
4886 [469, [revert_forced_local_layout]],
4887 [468, [revert_starred_caption]],
4888 [467, [revert_mbox_fbox]],
4889 [466, [revert_iwona_fonts]],
4890 [465, [revert_powerdot_flexes, revert_powerdot_pause, revert_powerdot_itemargs, revert_powerdot_columns]],
4892 [463, [revert_use_cancel]],
4893 [462, [revert_encodings]],
4894 [461, [revert_new_libertines]],
4895 [460, [revert_kurier_fonts]],
4896 [459, [revert_IEEEtran_3]],
4897 [458, [revert_fragileframe, revert_newframes]],
4898 [457, [revert_captioninsets, revert_captionlayouts]],
4899 [456, [revert_use_stackrel]],
4900 [455, [revert_epigraph]],
4901 [454, [revert_frametitle]],
4902 [453, [revert_overprint]],
4903 [452, [revert_use_stmaryrd]],
4904 [451, [revert_beamerblocks]],
4905 [450, [revert_beamerargs, revert_beamerargs2, revert_beamerargs3, revert_beamerflex]],
4906 [449, [revert_garamondx, revert_garamondx_newtxmath]],
4907 [448, [revert_itemargs]],
4908 [447, [revert_literate]],
4909 [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]],
4910 [445, [revert_latexargs]],
4911 [444, [revert_uop]],
4912 [443, [revert_biolinum]],
4914 [441, [revert_newtxmath]],
4915 [440, [revert_mdnomath]],
4916 [439, [revert_mathfonts]],
4917 [438, [revert_minionpro]],
4918 [437, [revert_ipadeco, revert_ipachar]],
4919 [436, [revert_texgyre]],
4920 [435, [revert_mathdesign]],
4921 [434, [revert_txtt]],
4922 [433, [revert_libertine]],
4923 [432, [revert_armenian]],
4924 [431, [revert_languages, revert_ancientgreek]],
4925 [430, [revert_use_amssymb]],
4926 [429, [revert_listoflistings]],
4927 [428, [revert_table_rotation]],
4928 [427, [revert_cell_rotation]],
4929 [426, [revert_tipa]],
4930 [425, [revert_verbatim]],
4931 [424, [revert_cancel]],
4932 [423, [revert_cite_engine_type]],
4933 [422, [revert_use_mathtools]],
4934 [421, [revert_use_packages]],
4935 [420, [revert_longtable_captions]],
4936 [419, [revert_biblio_style]],
4937 [418, [revert_australian]],
4938 [417, [revert_justification]],
4939 [416, [revert_japanese_encodings]],
4940 [415, [revert_negative_space, revert_math_spaces]],
4941 [414, [revert_undertilde]],
4942 [413, [revert_visible_space]]
4946 if __name__ == "__main__":