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_complete_lines, del_token, \
28 find_token, find_token_exact, \
29 find_token_backwards, find_end_of, find_end_of_inset, find_end_of_layout, \
30 find_end_of_sequence, find_re, get_option_value, get_containing_layout, \
31 get_containing_inset, get_value, get_quoted_value, set_option_value
33 #from parser_tools import find_token, find_end_of, find_tokens, \
34 #find_end_of_inset, find_end_of_layout, \
35 #is_in_inset, del_token, check_token
37 from lyx2lyx_tools import add_to_preamble, put_cmd_in_ert, get_ert
39 #from lyx2lyx_tools import insert_to_preamble, \
40 # lyx2latex, latex_length, revert_flex_inset, \
41 # revert_font_attrs, hex2ratio, str2bool
43 ####################################################################
44 # Private helper functions
46 #def remove_option(lines, m, option):
47 #''' removes option from line m. returns whether we did anything '''
48 #l = lines[m].find(option)
51 #val = lines[m][l:].split('"')[1]
52 #lines[m] = lines[m][:l - 1] + lines[m][l+len(option + '="' + val + '"'):]
56 def revert_Argument_to_TeX_brace(document, line, endline, n, nmax, environment, opt):
58 Reverts an InsetArgument to TeX-code
60 revert_Argument_to_TeX_brace(document, LineOfBegin, LineOfEnd, StartArgument, EndArgument, isEnvironment, isOpt)
61 LineOfBegin is the line of the \\begin_layout or \\begin_inset statement
62 LineOfEnd is the line of the \end_layout or \end_inset statement, if "0" is given, the end of the file is used instead
63 StartArgument is the number of the first argument that needs to be converted
64 EndArgument is the number of the last argument that needs to be converted or the last defined one
65 isEnvironment must be true, if the layout is for a LaTeX environment
66 isOpt must be true, if the argument is an optional one
70 while lineArg != -1 and n < nmax + 1:
71 lineArg = find_token(document.body, "\\begin_inset Argument " + str(n), line)
72 if lineArg > endline and endline != 0:
75 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", lineArg)
76 # we have to assure that no other inset is in the Argument
77 beginInset = find_token(document.body, "\\begin_inset", beginPlain)
78 endInset = find_token(document.body, "\\end_inset", beginPlain)
81 while beginInset < endInset and beginInset != -1:
82 beginInset = find_token(document.body, "\\begin_inset", k)
83 endInset = find_token(document.body, "\\end_inset", l)
86 if environment == False:
88 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}{")
89 del(document.body[lineArg : beginPlain + 1])
92 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("]")
93 document.body[lineArg : beginPlain + 1] = put_cmd_in_ert("[")
96 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}")
97 document.body[lineArg : beginPlain + 1] = put_cmd_in_ert("{")
103 def convert_TeX_brace_to_Argument(document, line, n, nmax, inset, environment, opt):
105 Converts TeX code for mandatory arguments to an InsetArgument
106 The conversion of TeX code for optional arguments must be done with another routine
107 !!! Be careful if the braces are different in your case as expected here:
108 - "}{" separates mandatory arguments of commands
109 - "}" + "{" separates mandatory arguments of commands
110 - "}" + " " + "{" separates mandatory arguments of commands
111 - { and } surround a mandatory argument of an environment
113 convert_TeX_brace_to_Argument(document, LineOfBeginLayout/Inset, StartArgument, EndArgument, isInset, isEnvironment, isOpt)
114 LineOfBeginLayout/Inset is the line of the \\begin_layout or \\begin_inset statement
115 StartArgument is the number of the first ERT that needs to be converted
116 EndArgument is the number of the last ERT that needs to be converted
117 isInset must be true, if braces inside an InsetLayout needs to be converted
118 isEnvironment must be true, if the layout is for a LaTeX environment
119 isOpt must be true, if the argument is an optional one
121 Todo: this routine can currently handle only one mandatory argument of environments
124 end_layout = find_end_of_layout(document.body, line)
129 lineERT = find_token(document.body, "\\begin_inset ERT", lineERT, end_layout)
132 if environment == False:
133 end_ERT = find_end_of_inset(document.body, lineERT)
135 document.warning("Can't find end of ERT!!")
137 # Note that this only checks for ][ or }{ at the beginning of a line
139 bracePair = find_token(document.body, "][", lineERT, end_ERT)
141 bracePair = find_token(document.body, "}{", lineERT, end_ERT)
143 end = find_token(document.body, "\\end_inset", bracePair)
144 document.body[lineERT : end_ERT + 1] = ["\\end_layout", "", "\\end_inset"]
146 # in the case that n > 1 we have optional arguments before
147 # therefore detect them if any
149 # first check if there is an argument
150 lineArg = find_token(document.body, "\\begin_inset Argument", line)
151 if lineArg < lineERT and lineArg != -1:
152 # we have an argument, so now search backwards for its end
153 # we must now assure that we don't find other insets like e.g. a newline
154 endInsetArg = lineERT
155 endLayoutArg = endInsetArg
156 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
157 endInsetArg = endInsetArg - 1
158 endLayoutArg = endInsetArg
159 endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
160 endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
161 line = endInsetArg + 1
163 document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
165 document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
167 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
172 # no brace pair found
173 # now check the case that we have "}" + "{" in two ERTs
175 endBrace = find_token(document.body, "]", lineERT, end_layout)
177 endBrace = find_token(document.body, "}", lineERT, end_layout)
178 if endBrace == lineERT + 5:
180 beginBrace = find_token(document.body, "[", endBrace, end_layout)
182 beginBrace = find_token(document.body, "{", endBrace, end_layout)
183 # assure that the ERTs are consecutive (11 or 12 depending if there is a space between the ERTs or not)
184 if beginBrance != -1 and (beginBrace == endBrace + 11 or beginBrace == endBrace + 12):
185 end = find_token(document.body, "\\end_inset", beginBrace)
186 document.body[lineERT : end + 1] = ["\\end_layout", "", "\\end_inset"]
188 # in the case that n > 1 we have optional arguments before
189 # therefore detect them if any
191 # first check if there is an argument
192 lineArg = find_token(document.body, "\\begin_inset Argument", line)
193 if lineArg < lineERT and lineArg != -1:
194 # we have an argument, so now search backwards for its end
195 # we must now assure that we don't find other insets like e.g. a newline
196 endInsetArg = lineERT
197 endLayoutArg = endInsetArg
198 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
199 endInsetArg = endInsetArg - 1
200 endLayoutArg = endInsetArg
201 endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
202 endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
203 line = endInsetArg + 1
205 document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
207 document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
209 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
212 # set the line where the next argument will be inserted
213 if beginBrace == endBrace + 11:
221 if environment == True:
222 # FIXME This version of the routine does not check for and pass over
223 # arguments before n. So it attempts to process the argument in the
224 # document, no matter what has been specified.
226 # The other branch does do that, but probably that code would be better
227 # in a single location: Skip all those arguments, then process the ones
229 end_ERT = find_end_of_inset(document.body, lineERT)
231 document.warning("Can't find end of ERT!!")
233 # Note that this only checks for [ or { at the beginning of a line
235 opening = find_token(document.body, "[", lineERT, end_ERT)
237 opening = find_token(document.body, "{", lineERT, end_ERT)
239 lineERT2 = find_token(document.body, "\\begin_inset ERT", end_ERT, end_layout)
241 # argument in a single ERT
242 # strip off the opening bracket
243 document.body[opening] = document.body[opening][1:]
244 ertcontlastline = end_ERT - 3
245 if (opt and document.body[ertcontlastline].endswith("]")) or document.body[ertcontlastline].endswith("}"):
246 # strip off the closing bracket
247 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
248 end2 = find_token(document.body, "\\end_inset", ertcontlastline)
249 document.body[lineERT : lineERT + 1] = ["\\begin_inset Argument " + str(n)]
251 end_ERT2 = find_end_of_inset(document.body, lineERT2)
253 document.warning("Can't find end of second ERT!!")
256 closing = find_token(document.body, "]", lineERT2, end_ERT2)
258 closing = find_token(document.body, "}", lineERT2, end_ERT2)
259 if closing != -1: # assure that the "}" is in this ERT
260 end2 = find_token(document.body, "\\end_inset", closing)
261 document.body[lineERT2 : end2 + 1] = ["\\end_layout", "", "\\end_inset"]
262 document.body[lineERT : end_ERT + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
265 document.warning("Unable to process argument!")
269 ###############################################################################
271 ### Conversion and reversion routines
273 ###############################################################################
275 def revert_visible_space(document):
276 "Revert InsetSpace visible into its ERT counterpart"
279 i = find_token(document.body, "\\begin_inset space \\textvisiblespace{}", i)
282 end = find_end_of_inset(document.body, i)
283 subst = put_cmd_in_ert("\\textvisiblespace{}")
284 document.body[i:end + 1] = subst
287 undertilde_commands = ["utilde"]
288 def convert_undertilde(document):
289 " Load undertilde automatically "
290 i = find_token(document.header, "\\use_mathdots" , 0)
292 i = find_token(document.header, "\\use_mhchem" , 0)
294 i = find_token(document.header, "\\use_esint" , 0)
296 document.warning("Malformed LyX document: Can't find \\use_mathdots.")
298 j = find_token(document.preamble, "\\usepackage{undertilde}", 0)
300 # package was loaded in the preamble, convert this to header setting for round trip
301 document.header.insert(i + 1, "\\use_undertilde 2") # on
302 del document.preamble[j]
306 j = find_token(document.body, '\\begin_inset Formula', j)
309 k = find_end_of_inset(document.body, j)
311 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(j))
314 code = "\n".join(document.body[j:k])
315 for c in undertilde_commands:
316 if code.find("\\%s" % c) != -1:
317 # at least one of the commands was found - need to switch package off
318 document.header.insert(i + 1, "\\use_undertilde 0") # off
321 # no command was found - set to auto (bug 9069)
322 document.header.insert(i + 1, "\\use_undertilde 1") # auto
326 def revert_undertilde(document):
327 " Load undertilde if used in the document "
328 regexp = re.compile(r'(\\use_undertilde)')
329 i = find_re(document.header, regexp, 0)
330 value = "1" # default is auto
332 value = get_value(document.header, "\\use_undertilde" , i).split()[0]
333 del document.header[i]
334 if value == "2": # on
335 add_to_preamble(document, ["\\usepackage{undertilde}"])
336 elif value == "1": # auto
339 i = find_token(document.body, '\\begin_inset Formula', i)
342 j = find_end_of_inset(document.body, i)
344 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
347 code = "\n".join(document.body[i:j])
348 for c in undertilde_commands:
349 if code.find("\\%s" % c) != -1:
350 add_to_preamble(document, ["\\usepackage{undertilde}"])
355 def revert_negative_space(document):
356 "Revert InsetSpace negmedspace and negthickspace into its TeX-code counterpart"
361 i = find_token(document.body, "\\begin_inset space \\negmedspace{}", i)
363 j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
365 # load amsmath in the preamble if not already loaded if we are at the end of checking
367 i = find_token(document.header, "\\use_amsmath 2", 0)
369 add_to_preamble(document, ["\\@ifundefined{negthickspace}{\\usepackage{amsmath}}"])
373 end = find_end_of_inset(document.body, i)
374 subst = put_cmd_in_ert("\\negmedspace{}")
375 document.body[i:end + 1] = subst
376 j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
379 end = find_end_of_inset(document.body, j)
380 subst = put_cmd_in_ert("\\negthickspace{}")
381 document.body[j:end + 1] = subst
385 def revert_math_spaces(document):
386 "Revert formulas with protected custom space and protected hfills to TeX-code"
389 i = find_token(document.body, "\\begin_inset Formula", i)
392 j = document.body[i].find("\\hspace*")
394 end = find_end_of_inset(document.body, i)
395 subst = put_cmd_in_ert(document.body[i][21:])
396 document.body[i:end + 1] = subst
400 def convert_japanese_encodings(document):
401 " Rename the japanese encodings to names understood by platex "
403 "EUC-JP-pLaTeX": "euc",
405 "SJIS-pLaTeX": "sjis"
407 i = find_token(document.header, "\\inputencoding" , 0)
410 val = get_value(document.header, "\\inputencoding", i)
411 if val in list(jap_enc_dict.keys()):
412 document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
415 def revert_japanese_encodings(document):
416 " Revert the japanese encodings name changes "
418 "euc": "EUC-JP-pLaTeX",
420 "sjis": "SJIS-pLaTeX"
422 i = find_token(document.header, "\\inputencoding" , 0)
425 val = get_value(document.header, "\\inputencoding", i)
426 if val in list(jap_enc_dict.keys()):
427 document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
430 def convert_justification(document):
431 " Add the \\justification buffer param"
432 i = find_token(document.header, "\\suppress_date" , 0)
434 i = find_token(document.header, "\\paperorientation" , 0)
436 i = find_token(document.header, "\\use_indices" , 0)
438 i = find_token(document.header, "\\use_bibtopic" , 0)
440 document.warning("Malformed LyX document: Missing \\suppress_date.")
442 document.header.insert(i + 1, "\\justification true")
445 def revert_justification(document):
446 " Revert the \\justification buffer param"
447 if not del_token(document.header, '\\justification', 0):
448 document.warning("Malformed LyX document: Missing \\justification.")
451 def revert_australian(document):
452 "Set English language variants Australian and Newzealand to English"
454 if document.language == "australian" or document.language == "newzealand":
455 document.language = "english"
456 i = find_token(document.header, "\\language", 0)
458 document.header[i] = "\\language english"
461 j = find_token(document.body, "\\lang australian", j)
463 j = find_token(document.body, "\\lang newzealand", 0)
467 document.body[j] = document.body[j].replace("\\lang newzealand", "\\lang english")
469 document.body[j] = document.body[j].replace("\\lang australian", "\\lang english")
473 def convert_biblio_style(document):
474 "Add a sensible default for \\biblio_style based on the citation engine."
475 i = find_token(document.header, "\\cite_engine", 0)
477 engine = get_value(document.header, "\\cite_engine", i).split("_")[0]
478 style = {"basic": "plain", "natbib": "plainnat", "jurabib": "jurabib"}
479 document.header.insert(i + 1, "\\biblio_style " + style[engine])
482 def revert_biblio_style(document):
483 "BibTeX insets with default option use the style defined by \\biblio_style."
484 i = find_token(document.header, "\\biblio_style" , 0)
486 document.warning("No \\biblio_style line. Nothing to do.")
489 default_style = get_value(document.header, "\\biblio_style", i)
490 del document.header[i]
492 # We are looking for bibtex insets having the default option
495 i = find_token(document.body, "\\begin_inset CommandInset bibtex", i)
498 j = find_end_of_inset(document.body, i)
500 document.warning("Malformed LyX document: Can't find end of bibtex inset at line " + str(i))
503 k = find_token(document.body, "options", i, j)
505 options = get_quoted_value(document.body, "options", k)
506 if "default" in options.split(","):
507 document.body[k] = 'options "%s"' \
508 % options.replace("default", default_style)
512 def handle_longtable_captions(document, forward):
515 begin_table = find_token(document.body, '<lyxtabular version=', begin_table)
516 if begin_table == -1:
518 end_table = find_end_of(document.body, begin_table, '<lyxtabular', '</lyxtabular>')
520 document.warning("Malformed LyX document: Could not find end of table.")
523 fline = find_token(document.body, "<features", begin_table, end_table)
525 document.warning("Can't find features for inset at line " + str(begin_table))
528 p = document.body[fline].find("islongtable")
533 numrows = get_option_value(document.body[begin_table], "rows")
535 numrows = int(numrows)
537 document.warning(document.body[begin_table])
538 document.warning("Unable to determine rows!")
539 begin_table = end_table
541 begin_row = begin_table
542 for row in range(numrows):
543 begin_row = find_token(document.body, '<row', begin_row, end_table)
545 document.warning("Can't find row " + str(row + 1))
547 end_row = find_end_of(document.body, begin_row, '<row', '</row>')
549 document.warning("Can't find end of row " + str(row + 1))
552 if (get_option_value(document.body[begin_row], 'caption') == 'true' and
553 get_option_value(document.body[begin_row], 'endfirsthead') != 'true' and
554 get_option_value(document.body[begin_row], 'endhead') != 'true' and
555 get_option_value(document.body[begin_row], 'endfoot') != 'true' and
556 get_option_value(document.body[begin_row], 'endlastfoot') != 'true'):
557 document.body[begin_row] = set_option_value(document.body[begin_row], 'caption', 'true", endfirsthead="true')
558 elif get_option_value(document.body[begin_row], 'caption') == 'true':
559 if get_option_value(document.body[begin_row], 'endfirsthead') == 'true':
560 document.body[begin_row] = set_option_value(document.body[begin_row], 'endfirsthead', 'false')
561 if get_option_value(document.body[begin_row], 'endhead') == 'true':
562 document.body[begin_row] = set_option_value(document.body[begin_row], 'endhead', 'false')
563 if get_option_value(document.body[begin_row], 'endfoot') == 'true':
564 document.body[begin_row] = set_option_value(document.body[begin_row], 'endfoot', 'false')
565 if get_option_value(document.body[begin_row], 'endlastfoot') == 'true':
566 document.body[begin_row] = set_option_value(document.body[begin_row], 'endlastfoot', 'false')
568 # since there could be a tabular inside this one, we
569 # cannot jump to end.
573 def convert_longtable_captions(document):
574 "Add a firsthead flag to caption rows"
575 handle_longtable_captions(document, True)
578 def revert_longtable_captions(document):
579 "remove head/foot flag from caption rows"
580 handle_longtable_captions(document, False)
583 def convert_use_packages(document):
584 "use_xxx yyy => use_package xxx yyy"
585 packages = ["amsmath", "esint", "mathdots", "mhchem", "undertilde"]
587 i = find_token(document.header, "\\use_%s" % p, 0)
589 value = get_value(document.header, "\\use_%s" % p, i)
590 document.header[i] = "\\use_package %s %s" % (p, value)
593 def revert_use_packages(document):
594 "use_package xxx yyy => use_xxx yyy"
595 packages = ["amsmath", "esint", "mhchem", "mathdots", "undertilde"]
596 # the order is arbitrary for the use_package version, and not all packages need to be given.
597 # Ensure a complete list and correct order (important for older LyX versions and especially lyx2lyx)
598 # first loop: find line with first package
601 regexp = re.compile(r'(\\use_package\s+%s)' % p)
602 i = find_re(document.header, regexp, 0)
603 if i != -1 and (j < 0 or i < j):
605 # second loop: replace or insert packages in front of all existing ones
607 regexp = re.compile(r'(\\use_package\s+%s)' % p)
608 i = find_re(document.header, regexp, 0)
610 value = get_value(document.header, "\\use_package %s" % p, i).split()[1]
611 del document.header[i]
612 document.header.insert(j, "\\use_%s %s" % (p, value))
614 document.header.insert(j, "\\use_%s 1" % p)
618 def convert_use_package(document, pkg, commands, oldauto):
619 # oldauto defines how the version we are converting from behaves:
620 # if it is true, the old version uses the package automatically.
621 # if it is false, the old version never uses the package.
622 i = find_token(document.header, "\\use_package")
624 document.warning("Malformed LyX document: Can't find \\use_package.")
626 packageline = "\\usepackage{%s}" % pkg
627 if (del_complete_lines(document.preamble,
628 ['% Added by lyx2lyx', packageline]) or
629 del_complete_lines(document.preamble, [packageline])):
630 # package was loaded in the preamble, convert this to header setting
631 document.header.insert(i + 1, "\\use_package " + pkg + " 2") # on
632 # If oldauto is true we have two options:
633 # We can either set the package to auto - this is correct for files in
634 # format 425 to 463, and may create a conflict for older files which use
635 # any command in commands with a different definition.
636 # Or we can look whether any command in commands is used, and set it to
637 # auto if not and to off if yes. This will not create a conflict, but will
638 # create uncompilable documents for files in format 425 to 463, which use
639 # any command in commands.
640 # We choose the first option since its error is less likely.
642 document.header.insert(i + 1, "\\use_package " + pkg + " 1") # auto
646 j = find_token(document.body, '\\begin_inset Formula', j)
649 k = find_end_of_inset(document.body, j)
651 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(j))
654 code = "\n".join(document.body[j:k])
656 if code.find("\\%s" % c) != -1:
657 # at least one of the commands was found - need to switch package off
658 document.header.insert(i + 1, "\\use_package " + pkg + " 0") # off
661 # no command was found - set to auto (bug 9069)
662 document.header.insert(i + 1, "\\use_package " + pkg + " 1") # auto
665 def revert_use_package(document, pkg, commands, oldauto):
666 # oldauto defines how the version we are reverting to behaves:
667 # if it is true, the old version uses the package automatically.
668 # if it is false, the old version never uses the package.
669 regexp = re.compile(r'(\\use_package\s+%s)' % pkg)
670 i = find_re(document.header, regexp, 0)
671 value = "1" # default is auto
673 value = get_value(document.header, "\\use_package" , i).split()[1]
674 del document.header[i]
675 if value == "2": # on
676 add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
677 elif value == "1" and not oldauto: # auto
680 i = find_token(document.body, '\\begin_inset Formula', i)
683 j = find_end_of_inset(document.body, i)
685 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
688 code = "\n".join(document.body[i:j])
690 if code.find("\\%s" % c) != -1:
691 add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
696 mathtools_commands = ["mathclap", "mathllap", "mathrlap", \
697 "lgathered", "rgathered", "vcentcolon", "dblcolon", \
698 "coloneqq", "Coloneqq", "coloneq", "Coloneq", "eqqcolon", \
699 "Eqqcolon", "eqcolon", "Eqcolon", "colonapprox", \
700 "Colonapprox", "colonsim", "Colonsim"]
701 def convert_use_mathtools(document):
702 "insert use_package mathtools"
703 convert_use_package(document, "mathtools", mathtools_commands, False)
706 def revert_use_mathtools(document):
707 "remove use_package mathtools"
708 revert_use_package(document, "mathtools", mathtools_commands, False)
711 # commands provided by stmaryrd.sty but LyX uses other packages:
712 # boxdot lightning, bigtriangledown, bigtriangleup
713 stmaryrd_commands = ["shortleftarrow", "shortrightarrow", "shortuparrow", \
714 "shortdownarrow", "Yup", "Ydown", "Yleft", "Yright", \
715 "varcurlyvee", "varcurlywedge", "minuso", "baro", \
716 "sslash", "bbslash", "moo", "varotimes", "varoast", \
717 "varobar", "varodot", "varoslash", "varobslash", \
718 "varocircle", "varoplus", "varominus", "boxast", \
719 "boxbar", "boxslash", "boxbslash", "boxcircle", \
720 "boxbox", "boxempty", "merge", "vartimes", \
721 "fatsemi", "sswarrow", "ssearrow", "curlywedgeuparrow", \
722 "curlywedgedownarrow", "fatslash", "fatbslash", "lbag", \
723 "rbag", "varbigcirc", "leftrightarroweq", \
724 "curlyveedownarrow", "curlyveeuparrow", "nnwarrow", \
725 "nnearrow", "leftslice", "rightslice", "varolessthan", \
726 "varogreaterthan", "varovee", "varowedge", "talloblong", \
727 "interleave", "obar", "obslash", "olessthan", \
728 "ogreaterthan", "ovee", "owedge", "oblong", "inplus", \
729 "niplus", "nplus", "subsetplus", "supsetplus", \
730 "subsetpluseq", "supsetpluseq", "Lbag", "Rbag", \
731 "llbracket", "rrbracket", "llparenthesis", \
732 "rrparenthesis", "binampersand", "bindnasrepma", \
733 "trianglelefteqslant", "trianglerighteqslant", \
734 "ntrianglelefteqslant", "ntrianglerighteqslant", \
735 "llfloor", "rrfloor", "llceil", "rrceil", "arrownot", \
736 "Arrownot", "Mapstochar", "mapsfromchar", "Mapsfromchar", \
737 "leftrightarrowtriangle", "leftarrowtriangle", \
738 "rightarrowtriangle", \
739 "bigcurlyvee", "bigcurlywedge", "bigsqcap", "bigbox", \
740 "bigparallel", "biginterleave", "bignplus", \
741 "varcopyright", "longarrownot", "Longarrownot", \
742 "Mapsto", "mapsfrom", "Mapsfrom" "Longmapsto", \
743 "longmapsfrom", "Longmapsfrom"]
744 def convert_use_stmaryrd(document):
745 "insert use_package stmaryrd"
746 convert_use_package(document, "stmaryrd", stmaryrd_commands, False)
749 def revert_use_stmaryrd(document):
750 "remove use_package stmaryrd"
751 revert_use_package(document, "stmaryrd", stmaryrd_commands, False)
754 stackrel_commands = ["stackrel"]
755 def convert_use_stackrel(document):
756 "insert use_package stackrel"
757 convert_use_package(document, "stackrel", stackrel_commands, False)
760 def revert_use_stackrel(document):
761 "remove use_package stackrel"
762 revert_use_package(document, "stackrel", stackrel_commands, False)
765 def convert_cite_engine_type(document):
766 "Determine the \\cite_engine_type from the citation engine."
767 i = find_token(document.header, "\\cite_engine", 0)
770 engine = get_value(document.header, "\\cite_engine", i)
772 engine, type = engine.split("_")
774 type = {"basic": "numerical", "jurabib": "authoryear"}[engine]
775 document.header[i] = "\\cite_engine " + engine
776 document.header.insert(i + 1, "\\cite_engine_type " + type)
779 def revert_cite_engine_type(document):
780 "Natbib had the type appended with an underscore."
781 engine_type = "numerical"
782 i = find_token(document.header, "\\cite_engine_type" , 0)
784 document.warning("No \\cite_engine_type line. Assuming numerical.")
786 engine_type = get_value(document.header, "\\cite_engine_type", i)
787 del document.header[i]
789 # We are looking for the natbib citation engine
790 i = find_token(document.header, "\\cite_engine natbib", 0)
793 document.header[i] = "\\cite_engine natbib_" + engine_type
796 def convert_cite_engine_type_default(document):
797 "Convert \\cite_engine_type to default for the basic citation engine."
798 i = find_token(document.header, "\\cite_engine basic", 0)
801 i = find_token(document.header, "\\cite_engine_type" , 0)
804 document.header[i] = "\\cite_engine_type default"
807 def revert_cite_engine_type_default(document):
808 """Revert \\cite_engine_type default.
810 Revert to numerical for the basic cite engine, otherwise to authoryear."""
811 engine_type = "authoryear"
812 i = find_token(document.header, "\\cite_engine_type default" , 0)
815 j = find_token(document.header, "\\cite_engine basic", 0)
817 engine_type = "numerical"
818 document.header[i] = "\\cite_engine_type " + engine_type
821 cancel_commands = ["cancel", "bcancel", "xcancel", "cancelto"]
822 # this is the same, as revert_use_cancel() except for the default
823 def revert_cancel(document):
824 "add cancel to the preamble if necessary"
825 revert_use_package(document, "cancel", cancel_commands, False)
828 def revert_verbatim(document, starred = False):
829 " Revert verbatim environments completely to TeX-code. "
833 layout_name = "Verbatim"
834 latex_name = "verbatim"
836 layout_name = "Verbatim*"
837 latex_name = "verbatim*"
839 subst_end = ['\\end_layout', '', '\\begin_layout Plain Layout',
841 '\\begin_layout Plain Layout', '', '',
843 'end{%s}' % (latex_name),
844 '\\end_layout', '', '\\end_inset',
845 '', '', '\\end_layout']
846 subst_begin = ['\\begin_layout Standard', '\\noindent',
847 '\\begin_inset ERT', 'status open', '',
848 '\\begin_layout Plain Layout', '', '', '\\backslash',
849 'begin{%s}' % (latex_name),
850 '\\end_layout', '', '\\begin_layout Plain Layout', '']
853 i = find_token(document.body, "\\begin_layout %s" % (layout_name), i)
856 j = find_end_of_layout(document.body, i)
858 document.warning("Malformed LyX document: Can't find end of %s layout" \
862 # delete all line breaks insets (there are no other insets)
865 n = find_token(document.body, "\\begin_inset Newline newline", l, j)
867 n = find_token(document.body, "\\begin_inset Newline linebreak", l, j)
870 m = find_end_of_inset(document.body, n)
871 del(document.body[m:m+1])
872 document.body[n:n+1] = ['\\end_layout', '', '\\begin_layout Plain Layout']
874 # we deleted a line, so the end of the inset moved forward.
875 # FIXME But we also added some lines, didn't we? I think this
878 # consecutive verbatim environments need to be connected
879 k = find_token(document.body, "\\begin_layout %s" % (layout_name), j)
880 if k == j + 2 and consecutive == False:
882 document.body[j:j+1] = ['\\end_layout', '', '\\begin_layout Plain Layout']
883 document.body[i:i+1] = subst_begin
885 if k == j + 2 and consecutive == True:
886 document.body[j:j+1] = ['\\end_layout', '', '\\begin_layout Plain Layout']
887 del(document.body[i:i+1])
889 if k != j + 2 and consecutive == True:
890 document.body[j:j+1] = subst_end
891 # the next paragraph must not be indented
892 # FIXME This seems to be causing problems, because of the
893 # hardcoded use of 19. We should figure out exactly where
894 # this needs to go by searching for the right tag.
895 document.body[j+19:j+19] = ['\\noindent']
896 del(document.body[i:i+1])
900 document.body[j:j+1] = subst_end
901 # the next paragraph must not be indented
902 # FIXME This seems to be causing problems, because of the
903 # hardcoded use of 19. We should figure out exactly where
904 # this needs to go by searching for the right tag.
905 document.body[j+19:j+19] = ['\\noindent']
906 document.body[i:i+1] = subst_begin
909 def revert_tipa(document):
910 " Revert native TIPA insets to mathed or ERT. "
913 i = find_token(document.body, "\\begin_inset IPA", i)
916 j = find_end_of_inset(document.body, i)
918 document.warning("Malformed LyX document: Can't find end of IPA inset")
922 n = find_token(document.body, "\\begin_layout", i, j)
924 document.warning("Malformed LyX document: IPA inset has no embedded layout")
927 m = find_end_of_layout(document.body, n)
929 document.warning("Malformed LyX document: Can't find end of embedded layout")
932 content = document.body[n+1:m]
933 p = find_token(document.body, "\\begin_layout", m, j)
934 if p != -1 or len(content) > 1:
936 content = document.body[i+1:j]
938 # IPA insets with multiple pars need to be wrapped by \begin{IPA}...\end{IPA}
939 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}")
940 add_to_preamble(document, ["\\usepackage{tipa,tipx}"])
942 # single-par IPA insets can be reverted to mathed
943 document.body[i:j+1] = ["\\begin_inset Formula $\\text{\\textipa{" + content[0] + "}}$", "\\end_inset"]
947 def revert_cell_rotation(document):
948 "Revert cell rotations to TeX-code"
950 load_rotating = False
954 # first, let's find out if we need to do anything
955 i = find_token(document.body, '<cell ', i)
958 j = document.body[i].find('rotate="')
960 k = document.body[i].find('"', j + 8)
961 value = document.body[i][j + 8 : k]
963 rgx = re.compile(r' rotate="[^"]+?"')
964 # remove rotate option
965 document.body[i] = rgx.sub('', document.body[i])
967 rgx = re.compile(r' rotate="[^"]+?"')
968 document.body[i] = rgx.sub(' rotate="true"', document.body[i])
970 rgx = re.compile(r' rotate="[^"]+?"')
972 # remove rotate option
973 document.body[i] = rgx.sub('', document.body[i])
975 document.body[i + 5 : i + 5] = \
976 put_cmd_in_ert("\\end{turn}")
977 document.body[i + 4 : i + 4] = \
978 put_cmd_in_ert("\\begin{turn}{" + value + "}")
984 add_to_preamble(document, ["\\@ifundefined{turnbox}{\\usepackage{rotating}}{}"])
987 def convert_cell_rotation(document):
988 'Convert cell rotation statements from "true" to "90"'
992 # first, let's find out if we need to do anything
993 i = find_token(document.body, '<cell ', i)
996 j = document.body[i].find('rotate="true"')
998 rgx = re.compile(r'rotate="[^"]+?"')
999 # convert "true" to "90"
1000 document.body[i] = rgx.sub('rotate="90"', document.body[i])
1005 def revert_table_rotation(document):
1006 "Revert table rotations to TeX-code"
1008 load_rotating = False
1012 # first, let's find out if we need to do anything
1013 i = find_token(document.body, '<features ', i)
1016 j = document.body[i].find('rotate="')
1018 end_table = find_token(document.body, '</lyxtabular>', j)
1019 k = document.body[i].find('"', j + 8)
1020 value = document.body[i][j + 8 : k]
1022 rgx = re.compile(r' rotate="[^"]+?"')
1023 # remove rotate option
1024 document.body[i] = rgx.sub('', document.body[i])
1026 rgx = re.compile(r'rotate="[^"]+?"')
1027 document.body[i] = rgx.sub('rotate="true"', document.body[i])
1029 rgx = re.compile(r' rotate="[^"]+?"')
1030 load_rotating = True
1031 # remove rotate option
1032 document.body[i] = rgx.sub('', document.body[i])
1034 document.body[end_table + 3 : end_table + 3] = \
1035 put_cmd_in_ert("\\end{turn}")
1036 document.body[i - 2 : i - 2] = \
1037 put_cmd_in_ert("\\begin{turn}{" + value + "}")
1043 add_to_preamble(document, ["\\@ifundefined{turnbox}{\\usepackage{rotating}}{}"])
1046 def convert_table_rotation(document):
1047 'Convert table rotation statements from "true" to "90"'
1051 # first, let's find out if we need to do anything
1052 i = find_token(document.body, '<features ', i)
1055 j = document.body[i].find('rotate="true"')
1057 rgx = re.compile(r'rotate="[^"]+?"')
1058 # convert "true" to "90"
1059 document.body[i] = rgx.sub('rotate="90"', document.body[i])
1064 def convert_listoflistings(document):
1065 'Convert ERT \lstlistoflistings to TOC lstlistoflistings inset'
1066 # We can support roundtrip because the command is so simple
1069 i = find_token(document.body, "\\begin_inset ERT", i)
1072 j = find_end_of_inset(document.body, i)
1074 document.warning("Malformed LyX document: Can't find end of ERT inset")
1077 ert = get_ert(document.body, i)
1078 if ert == "\\lstlistoflistings{}":
1079 document.body[i:j] = ["\\begin_inset CommandInset toc", "LatexCommand lstlistoflistings", ""]
1085 def revert_listoflistings(document):
1086 'Convert TOC lstlistoflistings inset to ERT lstlistoflistings'
1089 i = find_token(document.body, "\\begin_inset CommandInset toc", i)
1092 if document.body[i+1] == "LatexCommand lstlistoflistings":
1093 j = find_end_of_inset(document.body, i)
1095 document.warning("Malformed LyX document: Can't find end of TOC inset")
1098 subst = put_cmd_in_ert("\\lstlistoflistings{}")
1099 document.body[i:j+1] = subst
1100 add_to_preamble(document, ["\\usepackage{listings}"])
1104 def convert_use_amssymb(document):
1105 "insert use_package amssymb"
1106 regexp = re.compile(r'(\\use_package\s+amsmath)')
1107 i = find_re(document.header, regexp, 0)
1109 document.warning("Malformed LyX document: Can't find \\use_package amsmath.")
1111 value = get_value(document.header, "\\use_package" , i).split()[1]
1114 useamsmath = int(value)
1116 document.warning("Invalid \\use_package amsmath: " + value + ". Assuming auto.")
1118 j = find_token(document.preamble, "\\usepackage{amssymb}", 0)
1120 document.header.insert(i + 1, "\\use_package amssymb %d" % useamsmath)
1122 document.header.insert(i + 1, "\\use_package amssymb 2")
1123 del document.preamble[j]
1126 def revert_use_amssymb(document):
1127 "remove use_package amssymb"
1128 regexp1 = re.compile(r'(\\use_package\s+amsmath)')
1129 regexp2 = re.compile(r'(\\use_package\s+amssymb)')
1130 i = find_re(document.header, regexp1, 0)
1131 j = find_re(document.header, regexp2, 0)
1132 value1 = "1" # default is auto
1133 value2 = "1" # default is auto
1135 value1 = get_value(document.header, "\\use_package" , i).split()[1]
1137 value2 = get_value(document.header, "\\use_package" , j).split()[1]
1138 del document.header[j]
1139 if value1 != value2 and value2 == "2": # on
1140 add_to_preamble(document, ["\\usepackage{amssymb}"])
1143 def convert_use_cancel(document):
1144 "insert use_package cancel"
1145 convert_use_package(document, "cancel", cancel_commands, True)
1148 def revert_use_cancel(document):
1149 "remove use_package cancel"
1150 revert_use_package(document, "cancel", cancel_commands, True)
1153 def revert_ancientgreek(document):
1154 "Set the document language for ancientgreek to greek"
1156 if document.language == "ancientgreek":
1157 document.language = "greek"
1158 i = find_token(document.header, "\\language", 0)
1160 document.header[i] = "\\language greek"
1163 j = find_token(document.body, "\\lang ancientgreek", j)
1167 document.body[j] = document.body[j].replace("\\lang ancientgreek", "\\lang greek")
1171 def revert_languages(document):
1172 "Set the document language for new supported languages to English"
1175 "coptic", "divehi", "hindi", "kurmanji", "lao", "marathi", "occitan", "sanskrit",
1176 "syriac", "tamil", "telugu", "urdu"
1178 for n in range(len(languages)):
1179 if document.language == languages[n]:
1180 document.language = "english"
1181 i = find_token(document.header, "\\language", 0)
1183 document.header[i] = "\\language english"
1185 while j < len(document.body):
1186 j = find_token(document.body, "\\lang " + languages[n], j)
1188 document.body[j] = document.body[j].replace("\\lang " + languages[n], "\\lang english")
1191 j = len(document.body)
1194 def convert_armenian(document):
1195 "Use polyglossia and thus non-TeX fonts for Armenian"
1197 if document.language == "armenian":
1198 i = find_token(document.header, "\\use_non_tex_fonts", 0)
1200 document.header[i] = "\\use_non_tex_fonts true"
1203 def revert_armenian(document):
1204 "Use ArmTeX and thus TeX fonts for Armenian"
1206 if document.language == "armenian":
1207 i = find_token(document.header, "\\use_non_tex_fonts", 0)
1209 document.header[i] = "\\use_non_tex_fonts false"
1212 def revert_libertine(document):
1213 " Revert native libertine font definition to LaTeX "
1215 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1216 i = find_token(document.header, "\\font_roman libertine", 0)
1219 j = find_token(document.header, "\\font_osf true", 0)
1222 preamble = "\\usepackage"
1224 document.header[j] = "\\font_osf false"
1227 preamble += "[lining]"
1228 preamble += "{libertine-type1}"
1229 add_to_preamble(document, [preamble])
1230 document.header[i] = "\\font_roman default"
1233 def revert_txtt(document):
1234 " Revert native txtt font definition to LaTeX "
1236 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1237 i = find_token(document.header, "\\font_typewriter txtt", 0)
1239 preamble = "\\renewcommand{\\ttdefault}{txtt}"
1240 add_to_preamble(document, [preamble])
1241 document.header[i] = "\\font_typewriter default"
1244 def revert_mathdesign(document):
1245 " Revert native mathdesign font definition to LaTeX "
1247 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1253 i = find_token(document.header, "\\font_roman", 0)
1256 val = get_value(document.header, "\\font_roman", i)
1257 if val in list(mathdesign_dict.keys()):
1258 preamble = "\\usepackage[%s" % mathdesign_dict[val]
1260 j = find_token(document.header, "\\font_osf true", 0)
1263 document.header[j] = "\\font_osf false"
1264 l = find_token(document.header, "\\font_sc true", 0)
1267 document.header[l] = "\\font_sc false"
1269 preamble += ",expert"
1270 preamble += "]{mathdesign}"
1271 add_to_preamble(document, [preamble])
1272 document.header[i] = "\\font_roman default"
1275 def revert_texgyre(document):
1276 " Revert native TeXGyre font definition to LaTeX "
1278 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1279 texgyre_fonts = ["tgadventor", "tgbonum", "tgchorus", "tgcursor", \
1280 "tgheros", "tgpagella", "tgschola", "tgtermes"]
1281 i = find_token(document.header, "\\font_roman", 0)
1283 val = get_value(document.header, "\\font_roman", i)
1284 if val in texgyre_fonts:
1285 preamble = "\\usepackage{%s}" % val
1286 add_to_preamble(document, [preamble])
1287 document.header[i] = "\\font_roman default"
1288 i = find_token(document.header, "\\font_sans", 0)
1290 val = get_value(document.header, "\\font_sans", i)
1291 if val in texgyre_fonts:
1292 preamble = "\\usepackage{%s}" % val
1293 add_to_preamble(document, [preamble])
1294 document.header[i] = "\\font_sans default"
1295 i = find_token(document.header, "\\font_typewriter", 0)
1297 val = get_value(document.header, "\\font_typewriter", i)
1298 if val in texgyre_fonts:
1299 preamble = "\\usepackage{%s}" % val
1300 add_to_preamble(document, [preamble])
1301 document.header[i] = "\\font_typewriter default"
1304 def revert_ipadeco(document):
1305 " Revert IPA decorations to ERT "
1308 i = find_token(document.body, "\\begin_inset IPADeco", i)
1311 end = find_end_of_inset(document.body, i)
1313 document.warning("Can't find end of inset at line " + str(i))
1316 line = document.body[i]
1317 rx = re.compile(r'\\begin_inset IPADeco (.*)$')
1319 decotype = m.group(1)
1320 if decotype != "toptiebar" and decotype != "bottomtiebar":
1321 document.warning("Invalid IPADeco type: " + decotype)
1324 blay = find_token(document.body, "\\begin_layout Plain Layout", i, end)
1326 document.warning("Can't find layout for inset at line " + str(i))
1329 bend = find_end_of_layout(document.body, blay)
1331 document.warning("Malformed LyX document: Could not find end of IPADeco inset's layout.")
1334 substi = ["\\begin_inset ERT", "status collapsed", "",
1335 "\\begin_layout Plain Layout", "", "", "\\backslash",
1336 decotype + "{", "\\end_layout", "", "\\end_inset"]
1337 substj = ["\\size default", "", "\\begin_inset ERT", "status collapsed", "",
1338 "\\begin_layout Plain Layout", "", "}", "\\end_layout", "", "\\end_inset"]
1339 # do the later one first so as not to mess up the numbering
1340 document.body[bend:end + 1] = substj
1341 document.body[i:blay + 1] = substi
1342 i = end + len(substi) + len(substj) - (end - bend) - (blay - i) - 2
1343 add_to_preamble(document, "\\usepackage{tipa}")
1346 def revert_ipachar(document):
1347 ' Revert \\IPAChar to ERT '
1350 while i < len(document.body):
1351 m = re.match(r'(.*)\\IPAChar \\(\w+\{\w+\})(.*)', document.body[i])
1355 ipachar = m.group(2)
1358 '\\begin_inset ERT',
1359 'status collapsed', '',
1360 '\\begin_layout Standard',
1361 '', '', '\\backslash',
1366 document.body[i: i+1] = subst
1371 add_to_preamble(document, "\\usepackage{tone}")
1374 def revert_minionpro(document):
1375 " Revert native MinionPro font definition to LaTeX "
1377 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1378 i = find_token(document.header, "\\font_roman minionpro", 0)
1381 j = find_token(document.header, "\\font_osf true", 0)
1384 preamble = "\\usepackage"
1386 document.header[j] = "\\font_osf false"
1389 preamble += "{MinionPro}"
1390 add_to_preamble(document, [preamble])
1391 document.header[i] = "\\font_roman default"
1394 def revert_mathfonts(document):
1395 " Revert native math font definitions to LaTeX "
1397 i = find_token(document.header, "\\font_math", 0)
1400 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1401 val = get_value(document.header, "\\font_math", i)
1402 if val == "eulervm":
1403 add_to_preamble(document, "\\usepackage{eulervm}")
1404 elif val == "default":
1406 "lmodern": "\\renewcommand{\\rmdefault}{lmr}",
1407 "minionpro": "\\usepackage[onlytext,lf]{MinionPro}",
1408 "minionpro-osf": "\\usepackage[onlytext]{MinionPro}",
1409 "palatino": "\\renewcommand{\\rmdefault}{ppl}",
1410 "palatino-osf": "\\renewcommand{\\rmdefault}{pplj}",
1411 "times": "\\renewcommand{\\rmdefault}{ptm}",
1412 "utopia": "\\renewcommand{\\rmdefault}{futs}",
1413 "utopia-osf": "\\renewcommand{\\rmdefault}{futj}",
1415 j = find_token(document.header, "\\font_roman", 0)
1417 rm = get_value(document.header, "\\font_roman", j)
1418 k = find_token(document.header, "\\font_osf true", 0)
1421 if rm in list(mathfont_dict.keys()):
1422 add_to_preamble(document, mathfont_dict[rm])
1423 document.header[j] = "\\font_roman default"
1425 document.header[k] = "\\font_osf false"
1426 del document.header[i]
1429 def revert_mdnomath(document):
1430 " Revert mathdesign and fourier without math "
1432 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1434 "md-charter": "mdbch",
1435 "md-utopia": "mdput",
1436 "md-garamond": "mdugm"
1438 i = find_token(document.header, "\\font_roman", 0)
1441 val = get_value(document.header, "\\font_roman", i)
1442 if val in list(mathdesign_dict.keys()):
1443 j = find_token(document.header, "\\font_math", 0)
1445 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1446 mval = get_value(document.header, "\\font_math", j)
1447 if mval == "default":
1448 document.header[i] = "\\font_roman default"
1449 add_to_preamble(document, "\\renewcommand{\\rmdefault}{%s}" % mathdesign_dict[val])
1451 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1454 def convert_mathfonts(document):
1455 document.header.insert(-1, "\\font_math auto")
1458 def convert_mdnomath(document):
1459 " Change mathdesign font name "
1461 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1463 "mdbch": "md-charter",
1464 "mdput": "md-utopia",
1465 "mdugm": "md-garamond"
1467 i = find_token(document.header, "\\font_roman", 0)
1470 val = get_value(document.header, "\\font_roman", i)
1471 if val in list(mathdesign_dict.keys()):
1472 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1475 def revert_newtxmath(document):
1476 " Revert native newtxmath definitions to LaTeX "
1478 i = find_token(document.header, "\\font_math", 0)
1481 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1482 val = get_value(document.header, "\\font_math", i)
1484 "libertine-ntxm": "\\usepackage[libertine]{newtxmath}",
1485 "minion-ntxm": "\\usepackage[minion]{newtxmath}",
1486 "newtxmath": "\\usepackage{newtxmath}",
1488 if val in list(mathfont_dict.keys()):
1489 add_to_preamble(document, mathfont_dict[val])
1490 document.header[i] = "\\font_math auto"
1493 def revert_biolinum(document):
1494 " Revert native biolinum font definition to LaTeX "
1496 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1497 i = find_token(document.header, "\\font_sans biolinum", 0)
1500 j = find_token(document.header, "\\font_osf true", 0)
1503 preamble = "\\usepackage"
1506 preamble += "{biolinum-type1}"
1507 add_to_preamble(document, [preamble])
1508 document.header[i] = "\\font_sans default"
1511 def revert_uop(document):
1512 " Revert native URW Classico (Optima) font definition to LaTeX "
1514 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1515 i = find_token(document.header, "\\font_sans uop", 0)
1517 preamble = "\\renewcommand{\\sfdefault}{uop}"
1518 add_to_preamble(document, [preamble])
1519 document.header[i] = "\\font_sans default"
1522 def convert_latexargs(document):
1523 " Convert InsetArgument to new syntax "
1525 if find_token(document.body, "\\begin_inset Argument", 0) == -1:
1529 # A list of layouts (document classes) with only optional or no arguments.
1530 # These can be safely converted to the new syntax
1531 # (I took the liberty to add some of my personal layouts/modules here; JSP)
1532 safe_layouts = ["aa", "aapaper", "aastex", "achemso", "acmsiggraph", "AEA",
1533 "agu-dtd", "agums", "agutex", "amsart", "amsbook", "apa",
1534 "arab-article", "armenian-article", "article-beamer", "article",
1535 "beamer", "book", "broadway", "chess", "cl2emult", "ctex-article",
1536 "ctex-book", "ctex-report", "dinbrief", "docbook-book", "docbook-chapter",
1537 "docbook", "docbook-section", "doublecol-new", "dtk", "ectaart", "egs",
1538 "elsarticle", "elsart", "entcs", "europecv", "extarticle", "extbook",
1539 "extletter", "extreport", "foils", "frletter", "g-brief2", "g-brief",
1540 "heb-article", "heb-letter", "hollywood", "IEEEtran", "ijmpc", "ijmpd",
1541 "iopart", "isprs", "jarticle", "jasatex", "jbook", "jgrga", "jreport",
1542 "jsarticle", "jsbeamer", "jsbook", "jss", "kluwer", "latex8", "letter", "lettre",
1543 "literate-article", "literate-book", "literate-report", "llncs", "ltugboat",
1544 "memoir", "moderncv", "mwart", "mwbk", "mwrep", "paper", "powerdot",
1545 "recipebook", "report", "revtex4", "revtex", "scrartcl", "scrarticle-beamer",
1546 "scrbook", "scrlettr", "scrlttr2", "scrreprt", "seminar", "siamltex",
1547 "sigplanconf", "simplecv", "singlecol", "singlecol-new", "slides", "spie",
1548 "svglobal3", "svglobal", "svjog", "svmono", "svmult", "svprobth", "tarticle",
1549 "tbook", "treport", "tufte-book", "tufte-handout"]
1550 # A list of "safe" modules, same as above
1551 safe_modules = ["biblatex", "beameraddons", "beamer-resenumerate", "beamersession", "braille",
1552 "customHeadersFooters", "endnotes", "enumitem", "eqs-within-sections", "figs-within-sections",
1553 "fix-cm", "fixltx2e", "foottoend", "hanging", "jscharstyles", "knitr", "lilypond",
1554 "linguistics", "linguisticx", "logicalmkup", "minimalistic", "nomindex", "noweb",
1555 "pdfcomment", "sweave", "tabs-within-sections", "theorems-ams-bytype",
1556 "theorems-ams-extended-bytype", "theorems-ams-extended", "theorems-ams", "theorems-bytype",
1557 "theorems-chap-bytype", "theorems-chap", "theorems-named", "theorems-sec-bytype",
1558 "theorems-sec", "theorems-starred", "theorems-std", "todonotes"]
1559 # Modules we need to take care of
1560 caveat_modules = ["initials"] # TODO: , "graphicboxes", "bicaption"]
1561 # information about the relevant styles in caveat_modules (number of opt and req args)
1562 # use this if we get more caveat_modules. For now, use hard coding (see below).
1563 # initials = [{'Layout' : 'Initial', 'opt' : 1, 'req' : 1}]
1564 # graphicboxes = { ... }
1566 # Is this a known safe layout?
1567 safe_layout = document.textclass in safe_layouts
1569 document.warning("Lyx2lyx knows nothing about textclass '%s'. "
1570 "Please check if short title insets have been converted correctly."
1571 % document.textclass)
1572 # Do we use unsafe or unknown modules
1573 mods = document.get_module_list()
1574 unknown_modules = False
1575 used_caveat_modules = list()
1577 if mod in safe_modules:
1579 if mod in caveat_modules:
1580 used_caveat_modules.append(mod)
1582 unknown_modules = True
1583 document.warning("Lyx2lyx knows nothing about module '%s'. "
1584 "Please check if short title insets have been converted correctly."
1589 i = find_token(document.body, "\\begin_inset Argument", i)
1593 if not safe_layout or unknown_modules:
1594 # We cannot do more here since we have no access to this layout.
1595 # InsetArgument itself will do the real work
1596 # (see InsetArgument::updateBuffer())
1597 document.body[i] = "\\begin_inset Argument 999"
1601 # Find containing paragraph layout
1602 parent = get_containing_layout(document.body, i)
1604 document.warning("Malformed LyX document: Can't find parent paragraph layout")
1611 if len(used_caveat_modules) > 0:
1612 # We know for now that this must be the initials module with the Initial layout
1613 # If we get more such modules, we need some automating.
1614 if parent[0] == "Initial":
1615 # Layout has 1 opt and 1 req arg.
1616 # Count the actual arguments
1618 for p in range(parbeg, parend):
1619 if document.body[p] == "\\begin_inset Argument":
1624 # Collect all arguments in this paragraph
1626 for p in range(parbeg, parend):
1627 if document.body[p] == "\\begin_inset Argument":
1629 if allowed_opts != -1:
1630 # We have less arguments than opt + required.
1631 # required must take precedence.
1632 if argnr > allowed_opts and argnr < first_req:
1634 document.body[p] = "\\begin_inset Argument %d" % argnr
1638 def revert_latexargs(document):
1639 " Revert InsetArgument to old syntax "
1642 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
1645 # Search for Argument insets
1646 i = find_token(document.body, "\\begin_inset Argument", i)
1649 m = rx.match(document.body[i])
1651 # No ID: inset already reverted
1654 # Find containing paragraph layout
1655 parent = get_containing_layout(document.body, i)
1657 document.warning("Malformed LyX document: Can't find parent paragraph layout")
1662 # Do not set realparbeg to parent[3], since this does not work if we
1663 # have another inset (e.g. label or index) before the first argument
1664 # inset (this is the case in the user guide of LyX 2.0.8)
1666 # Collect all arguments in this paragraph
1668 for p in range(parbeg, parend):
1669 m = rx.match(document.body[p])
1672 # This is the first argument inset
1674 val = int(m.group(1))
1675 j = find_end_of_inset(document.body, p)
1676 # Revert to old syntax
1677 document.body[p] = "\\begin_inset Argument"
1679 document.warning("Malformed LyX document: Can't find end of Argument inset")
1682 args[val] = document.body[p : j + 1]
1684 realparend = realparend - len(document.body[p : j + 1])
1685 # Remove arg inset at this position
1686 del document.body[p : j + 1]
1690 # No argument inset found
1691 realparbeg = parent[3]
1692 # Now sort the arg insets
1694 for f in sorted(args):
1697 # Insert the sorted arg insets at paragraph begin
1698 document.body[realparbeg : realparbeg] = subst
1700 i = realparbeg + 1 + len(subst)
1703 def revert_IEEEtran(document):
1705 Reverts InsetArgument of
1708 Biography without photo
1711 if document.textclass != "IEEEtran":
1714 layouts = {"Page headings": False,
1715 "Biography without photo": True}
1717 for layout in list(layouts.keys()):
1720 i = find_token(document.body, '\\begin_layout ' + layout, i)
1723 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, layouts[layout], False)
1728 i = find_token(document.body, '\\begin_inset Flex Paragraph Start', i)
1731 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1736 i = find_token_exact(document.body, "\\begin_layout Biography", i)
1740 if document.body[i] == "\\begin_layout Biography without photo":
1744 # start with the second argument, therefore 2
1745 revert_Argument_to_TeX_brace(document, i, 0, 2, 2, True, False)
1749 def revert_IEEEtran_2(document):
1751 Reverts Flex Paragraph Start to TeX-code
1753 if document.textclass == "IEEEtran":
1756 begin = find_token(document.body, "\\begin_inset Flex Paragraph Start", begin)
1759 end1 = find_end_of_inset(document.body, begin)
1760 document.body[end1 - 2 : end1 + 1] = put_cmd_in_ert("}")
1761 document.body[begin : begin + 4] = put_cmd_in_ert("\\IEEEPARstart{")
1765 def convert_IEEEtran(document):
1770 Biography without photo
1773 if document.textclass != "IEEEtran":
1776 layouts = {"Page headings": False,
1777 "Biography without photo": True}
1779 for layout in list(layouts.keys()):
1782 i = find_token(document.body, '\\begin_layout ' + layout, i)
1785 convert_TeX_brace_to_Argument(document, i, 1, 1, False, layouts[layout], False)
1790 i = find_token_exact(document.body, "\\begin_layout Biography", i)
1794 if document.body[i] == "\\begin_layout Biography without photo":
1798 # the argument we want to convert is the second one
1799 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, False)
1803 def revert_AASTeX(document):
1804 " Reverts InsetArgument of Altaffilation to TeX-code "
1805 if document.textclass == "aastex":
1808 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1811 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1815 def convert_AASTeX(document):
1816 " Converts ERT of Altaffilation to InsetArgument "
1817 if document.textclass == "aastex":
1820 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1823 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1827 def revert_AGUTeX(document):
1828 " Reverts InsetArgument of Author affiliation to TeX-code "
1829 if document.textclass == "agutex":
1832 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1835 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1839 def convert_AGUTeX(document):
1840 " Converts ERT of Author affiliation to InsetArgument "
1841 if document.textclass == "agutex":
1844 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1847 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1851 def revert_IJMP(document):
1852 " Reverts InsetArgument of MarkBoth to TeX-code "
1853 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1856 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1859 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1863 def convert_IJMP(document):
1864 " Converts ERT of MarkBoth to InsetArgument "
1865 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1868 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1871 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1875 def revert_SIGPLAN(document):
1876 " Reverts InsetArguments of SIGPLAN to TeX-code "
1877 if document.textclass == "sigplanconf":
1882 i = find_token(document.body, "\\begin_layout Conference", i)
1884 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1887 j = find_token(document.body, "\\begin_layout Author", j)
1889 revert_Argument_to_TeX_brace(document, j, 0, 1, 2, False, False)
1891 if i == -1 and j == -1:
1895 def convert_SIGPLAN(document):
1896 " Converts ERT of SIGPLAN to InsetArgument "
1897 if document.textclass == "sigplanconf":
1902 i = find_token(document.body, "\\begin_layout Conference", i)
1904 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1907 j = find_token(document.body, "\\begin_layout Author", j)
1909 convert_TeX_brace_to_Argument(document, j, 1, 2, False, False, False)
1911 if i == -1 and j == -1:
1915 def revert_SIGGRAPH(document):
1916 " Reverts InsetArgument of Flex CRcat to TeX-code "
1917 if document.textclass == "acmsiggraph":
1920 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1923 revert_Argument_to_TeX_brace(document, i, 0, 1, 3, False, False)
1927 def convert_SIGGRAPH(document):
1928 " Converts ERT of Flex CRcat to InsetArgument "
1929 if document.textclass == "acmsiggraph":
1932 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1935 convert_TeX_brace_to_Argument(document, i, 1, 3, True, False, False)
1939 def revert_EuropeCV(document):
1940 " Reverts InsetArguments of europeCV to TeX-code "
1941 if document.textclass == "europecv":
1948 i = find_token(document.body, "\\begin_layout Item", i)
1950 revert_Argument_to_TeX_brace(document, i, 0, 2, 2, False, False)
1953 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1955 revert_Argument_to_TeX_brace(document, j, 0, 2, 2, False, False)
1958 k = find_token(document.body, "\\begin_layout Language", k)
1960 revert_Argument_to_TeX_brace(document, k, 0, 2, 6, False, False)
1963 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1965 revert_Argument_to_TeX_brace(document, m, 0, 2, 6, False, False)
1967 if i == -1 and j == -1 and k == -1 and m == -1:
1971 def convert_EuropeCV(document):
1972 " Converts ERT of europeCV to InsetArgument "
1973 if document.textclass == "europecv":
1980 i = find_token(document.body, "\\begin_layout Item", i)
1982 convert_TeX_brace_to_Argument(document, i, 2, 2, False, False, False)
1985 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1987 convert_TeX_brace_to_Argument(document, j, 2, 2, False, False, False)
1990 k = find_token(document.body, "\\begin_layout Language", k)
1992 convert_TeX_brace_to_Argument(document, k, 2, 6, False, False, False)
1995 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1997 convert_TeX_brace_to_Argument(document, m, 2, 6, False, False, False)
1999 if i == -1 and j == -1 and k == -1 and m == -1:
2003 def revert_ModernCV(document):
2004 " Reverts InsetArguments of modernCV to TeX-code "
2005 if document.textclass == "moderncv":
2013 j = find_token(document.body, "\\begin_layout Entry", j)
2015 revert_Argument_to_TeX_brace(document, j, 0, 1, 5, False, False)
2018 k = find_token(document.body, "\\begin_layout Item", k)
2020 revert_Argument_to_TeX_brace(document, k, 0, 1, 1, False, False)
2023 m = find_token(document.body, "\\begin_layout ItemWithComment", m)
2025 revert_Argument_to_TeX_brace(document, m, 0, 1, 2, False, False)
2026 document.body[m] = document.body[m].replace("\\begin_layout ItemWithComment", "\\begin_layout Language")
2029 o = find_token(document.body, "\\begin_layout DoubleItem", o)
2031 revert_Argument_to_TeX_brace(document, o, 0, 1, 3, False, False)
2032 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout Computer")
2035 p = find_token(document.body, "\\begin_layout Social", p)
2037 revert_Argument_to_TeX_brace(document, p, 0, 1, 1, False, True)
2039 if j == -1 and k == -1 and m == -1 and o == -1 and p == -1:
2043 def revert_ModernCV_2(document):
2044 " Reverts the Flex:Column inset of modernCV to TeX-code "
2045 if document.textclass == "moderncv":
2049 flex = find_token(document.body, "\\begin_inset Flex Column", flex)
2052 flexEnd = find_end_of_inset(document.body, flex)
2053 wasOpt = revert_Argument_to_TeX_brace(document, flex, flexEnd, 1, 1, False, True)
2054 revert_Argument_to_TeX_brace(document, flex, 0, 2, 2, False, False)
2055 flexEnd = find_end_of_inset(document.body, flex)
2057 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn")
2059 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn{")
2060 document.body[flexEnd + 4 : flexEnd + 7] = put_cmd_in_ert("}")
2064 def revert_ModernCV_3(document):
2065 " Reverts the Column style of modernCV to TeX-code "
2066 if document.textclass == "moderncv":
2067 # revert the layouts
2068 revert_ModernCV(document)
2070 # get the position of the end of the last column inset
2071 LastFlexEnd = revert_ModernCV_2(document)
2073 p = find_token(document.body, "\\begin_layout Columns", p)
2076 pEnd = find_end_of_layout(document.body, p)
2077 document.body[p] = document.body[p].replace("\\begin_layout Columns", "\\begin_layout Standard")
2078 if LastFlexEnd != -1:
2079 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\begin{cvcolumns}")
2080 document.body[LastFlexEnd + 24 : LastFlexEnd + 24] = put_cmd_in_ert("\\end{cvcolumns}")
2084 def revert_ModernCV_4(document):
2085 " Reverts the style Social to TeX-code "
2086 if document.textclass == "moderncv":
2087 # revert the layouts
2088 revert_ModernCV(document)
2091 p = find_token(document.body, "\\begin_layout Social", p)
2094 pEnd = find_end_of_layout(document.body, p)
2095 document.body[p] = document.body[p].replace("\\begin_layout Social", "\\begin_layout Standard")
2096 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\social")
2097 hasOpt = find_token(document.body, "[", p + 9)
2099 document.body[p + 30 : p + 30] = put_cmd_in_ert("{")
2100 document.body[p + 41 : p + 41] = put_cmd_in_ert("}")
2102 document.body[p + 11 : p + 11] = put_cmd_in_ert("{")
2103 document.body[p + 21 : p + 21] = put_cmd_in_ert("}")
2107 def convert_ModernCV(document):
2108 " Converts ERT of modernCV to InsetArgument "
2109 if document.textclass == "moderncv":
2117 i = find_token(document.body, "\\begin_layout DoubleItem", i)
2119 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
2120 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout DoubleListItem")
2123 j = find_token(document.body, "\\begin_layout Entry", j)
2125 convert_TeX_brace_to_Argument(document, j, 1, 5, False, False, False)
2128 k = find_token(document.body, "\\begin_layout Item", k)
2130 convert_TeX_brace_to_Argument(document, k, 1, 1, False, False, False)
2133 m = find_token(document.body, "\\begin_layout Language", m)
2135 convert_TeX_brace_to_Argument(document, m, 1, 2, False, False, False)
2137 if i == -1 and j == -1 and k == -1 and m == -1:
2141 def revert_Initials(document):
2142 " Reverts InsetArgument of Initial to TeX-code "
2145 i = find_token(document.body, "\\begin_layout Initial", i)
2148 # first arg (optional) and second arg (first mandatory) are supported in LyX 2.0.x
2149 revert_Argument_to_TeX_brace(document, i, 0, 3, 3, False, False)
2153 def convert_Initials(document):
2154 " Converts ERT of Initial to InsetArgument "
2157 i = find_token(document.body, "\\begin_layout Initial", i)
2160 convert_TeX_brace_to_Argument(document, i, 3, 3, False, False, False)
2164 def revert_literate(document):
2165 " Revert Literate document to old format "
2166 if del_token(document.header, "noweb", 0):
2167 document.textclass = "literate-" + document.textclass
2170 i = find_token(document.body, "\\begin_layout Chunk", i)
2173 document.body[i] = "\\begin_layout Scrap"
2177 def convert_literate(document):
2178 " Convert Literate document to new format"
2179 i = find_token(document.header, "\\textclass", 0)
2180 if (i != -1) and "literate-" in document.header[i]:
2181 document.textclass = document.header[i].replace("\\textclass literate-", "")
2182 j = find_token(document.header, "\\begin_modules", 0)
2184 document.header.insert(j + 1, "noweb")
2186 document.header.insert(i + 1, "\\end_modules")
2187 document.header.insert(i + 1, "noweb")
2188 document.header.insert(i + 1, "\\begin_modules")
2191 i = find_token(document.body, "\\begin_layout Scrap", i)
2194 document.body[i] = "\\begin_layout Chunk"
2198 def revert_itemargs(document):
2199 " Reverts \\item arguments to TeX-code "
2202 i = find_token(document.body, "\\begin_inset Argument item:", i)
2205 j = find_end_of_inset(document.body, i)
2206 # Find containing paragraph layout
2207 parent = get_containing_layout(document.body, i)
2209 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2213 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2214 endPlain = find_end_of_layout(document.body, beginPlain)
2215 content = document.body[beginPlain + 1 : endPlain]
2216 del document.body[i:j+1]
2217 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2218 document.body[parbeg : parbeg] = subst
2222 def revert_garamondx_newtxmath(document):
2223 " Revert native garamond newtxmath definition to LaTeX "
2225 i = find_token(document.header, "\\font_math", 0)
2228 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2229 val = get_value(document.header, "\\font_math", i)
2230 if val == "garamondx-ntxm":
2231 add_to_preamble(document, "\\usepackage[garamondx]{newtxmath}")
2232 document.header[i] = "\\font_math auto"
2235 def revert_garamondx(document):
2236 " Revert native garamond font definition to LaTeX "
2238 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2239 i = find_token(document.header, "\\font_roman garamondx", 0)
2242 j = find_token(document.header, "\\font_osf true", 0)
2245 preamble = "\\usepackage"
2247 preamble += "[osfI]"
2248 preamble += "{garamondx}"
2249 add_to_preamble(document, [preamble])
2250 document.header[i] = "\\font_roman default"
2253 def convert_beamerargs(document):
2254 " Converts beamer arguments to new layout "
2256 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2257 if document.textclass not in beamer_classes:
2260 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2261 list_layouts = ["Itemize", "Enumerate", "Description"]
2262 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
2266 i = find_token(document.body, "\\begin_inset Argument", i)
2269 # Find containing paragraph layout
2270 parent = get_containing_layout(document.body, i)
2272 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2277 layoutname = parent[0]
2278 for p in range(parbeg, parend):
2279 if layoutname in shifted_layouts:
2280 m = rx.match(document.body[p])
2282 argnr = int(m.group(1))
2284 document.body[p] = "\\begin_inset Argument %d" % argnr
2285 if layoutname == "AgainFrame":
2286 m = rx.match(document.body[p])
2288 document.body[p] = "\\begin_inset Argument 3"
2289 if document.body[p + 4] == "\\begin_inset ERT":
2290 if document.body[p + 9].startswith("<"):
2291 # This is an overlay specification
2293 document.body[p + 9] = document.body[p + 9][1:]
2294 if document.body[p + 9].endswith(">"):
2296 document.body[p + 9] = document.body[p + 9][:-1]
2298 document.body[p] = "\\begin_inset Argument 2"
2299 if layoutname in list_layouts:
2300 m = rx.match(document.body[p])
2302 if m.group(1) == "1":
2303 if document.body[p + 4] == "\\begin_inset ERT":
2304 if document.body[p + 9].startswith("<"):
2305 # This is an overlay specification
2307 document.body[p + 9] = document.body[p + 9][1:]
2308 if document.body[p + 9].endswith(">"):
2310 document.body[p + 9] = document.body[p + 9][:-1]
2311 elif document.body[p + 4].startswith("<"):
2312 # This is an overlay specification (without ERT)
2314 document.body[p + 4] = document.body[p + 4][1:]
2315 if document.body[p + 4].endswith(">"):
2317 document.body[p + 4] = document.body[p + 4][:-1]
2318 elif layoutname != "Itemize":
2320 document.body[p] = "\\begin_inset Argument 2"
2325 # Helper function for the frame conversion routines
2327 # FIXME: This method currently requires the arguments to be either
2328 # * In one (whole) ERT each: <ERT>[<arg1>]</ERT><ERT><arg2></ERT><ERT>[arg3]</ERT>
2329 # * Altogether in one whole ERT: <ERT>[<arg1>]<arg2>[arg3]</ERT>
2330 # If individual arguments mix ERT and non-ERT or are splitted
2331 # over several ERTs, the parsing fails.
2332 def convert_beamerframeargs(document, i, parbeg):
2335 if document.body[parbeg] != "\\begin_inset ERT":
2337 ertend = find_end_of_inset(document.body, parbeg)
2339 document.warning("Malformed LyX document: missing ERT \\end_inset")
2341 ertcont = parbeg + 5
2342 if document.body[ertcont].startswith("[<"):
2343 # This is a default overlay specification
2345 document.body[ertcont] = document.body[ertcont][2:]
2346 if document.body[ertcont].endswith(">]"):
2348 document.body[ertcont] = document.body[ertcont][:-2]
2349 elif document.body[ertcont].endswith("]"):
2351 tok = document.body[ertcont].find('>][')
2353 subst = [document.body[ertcont][:tok],
2354 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2355 'status collapsed', '', '\\begin_layout Plain Layout',
2356 document.body[ertcont][tok + 3:-1]]
2357 document.body[ertcont : ertcont + 1] = subst
2359 # Convert to ArgInset
2360 document.body[parbeg] = "\\begin_inset Argument 2"
2361 elif document.body[ertcont].startswith("<"):
2362 # This is an overlay specification
2364 document.body[ertcont] = document.body[ertcont][1:]
2365 if document.body[ertcont].endswith(">"):
2367 document.body[ertcont] = document.body[ertcont][:-1]
2368 # Convert to ArgInset
2369 document.body[parbeg] = "\\begin_inset Argument 1"
2370 elif document.body[ertcont].endswith(">]"):
2372 tok = document.body[ertcont].find('>[<')
2374 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2375 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2376 'status collapsed', '', '\\begin_layout Plain Layout',
2377 document.body[ertcont][tok + 3:-2]]
2378 # Convert to ArgInset
2379 document.body[parbeg] = "\\begin_inset Argument 1"
2381 elif document.body[ertcont].endswith("]"):
2383 tok = document.body[ertcont].find('>[<')
2386 tokk = document.body[ertcont].find('>][')
2388 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2389 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2390 'status collapsed', '', '\\begin_layout Plain Layout',
2391 document.body[ertcont][tok + 3:tokk],
2392 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2393 'status collapsed', '', '\\begin_layout Plain Layout',
2394 document.body[ertcont][tokk + 3:-1]]
2397 tokk = document.body[ertcont].find('>[')
2399 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tokk],
2400 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2401 'status collapsed', '', '\\begin_layout Plain Layout',
2402 document.body[ertcont][tokk + 2:-1]]
2404 # Convert to ArgInset
2405 document.body[parbeg] = "\\begin_inset Argument 1"
2406 elif document.body[ertcont].startswith("["):
2407 # This is an ERT option
2409 document.body[ertcont] = document.body[ertcont][1:]
2410 if document.body[ertcont].endswith("]"):
2412 document.body[ertcont] = document.body[ertcont][:-1]
2413 # Convert to ArgInset
2414 document.body[parbeg] = "\\begin_inset Argument 3"
2420 def convert_againframe_args(document):
2421 " Converts beamer AgainFrame to new layout "
2423 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2424 if document.textclass not in beamer_classes:
2429 i = find_token(document.body, "\\begin_layout AgainFrame", i)
2432 parent = get_containing_layout(document.body, i)
2434 document.warning("Wrong parent layout!")
2438 # Convert ERT arguments
2439 # FIXME: See restrictions in convert_beamerframeargs method
2440 ertend = convert_beamerframeargs(document, i, parbeg)
2446 def convert_corollary_args(document):
2447 " Converts beamer corrolary-style ERT arguments native InsetArgs "
2449 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2450 if document.textclass not in beamer_classes:
2453 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2454 for lay in corollary_layouts:
2457 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2460 parent = get_containing_layout(document.body, i)
2462 document.warning("Wrong parent layout!")
2466 if document.body[parbeg] == "\\begin_inset ERT":
2467 ertcontfirstline = parbeg + 5
2468 # Find the last ERT in this paragraph (which might also be the first)
2469 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
2470 if lastertbeg == -1:
2471 document.warning("Last ERT not found!")
2473 lastertend = find_end_of_inset(document.body, lastertbeg)
2474 if lastertend == -1:
2475 document.warning("End of last ERT not found!")
2477 ertcontlastline = lastertend - 3
2478 if document.body[ertcontfirstline].startswith("<"):
2479 # This is an overlay specification
2481 document.body[ertcontfirstline] = document.body[ertcontfirstline][1:]
2482 if document.body[ertcontlastline].endswith(">"):
2484 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
2485 if ertcontfirstline < ertcontlastline:
2486 # Multiline ERT. Might contain TeX code. Embrace in ERT.
2487 document.body[ertcontlastline : ertcontlastline + 1] = [
2488 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
2489 document.body[ertcontfirstline : ertcontfirstline + 1] = [
2490 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
2491 'status collapsed', '', '\\begin_layout Plain Layout',
2492 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
2493 document.body[ertcontfirstline]]
2495 # Convert to ArgInset
2496 document.body[parbeg] = "\\begin_inset Argument 1"
2497 elif document.body[ertcontlastline].endswith("]"):
2499 tok = document.body[ertcontfirstline].find('>[')
2501 if ertcontfirstline < ertcontlastline:
2502 # Multiline ERT. Might contain TeX code. Embrace in ERT.
2503 document.body[ertcontlastline : ertcontlastline + 1] = [
2504 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
2505 document.body[ertcontfirstline : ertcontfirstline + 1] = [document.body[ertcontfirstline][:tok],
2506 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2507 'status collapsed', '', '\\begin_layout Plain Layout',
2508 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
2509 document.body[ertcontfirstline][tok + 2:-1]]
2511 document.body[ertcontfirstline : ertcontfirstline + 1] = [document.body[ertcontfirstline][:tok],
2512 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2513 'status collapsed', '', '\\begin_layout Plain Layout',
2514 document.body[ertcontfirstline][tok + 2:-1]]
2515 # Convert to ArgInset
2516 document.body[parbeg] = "\\begin_inset Argument 1"
2519 elif document.body[ertcontlastline].startswith("["):
2520 if document.body[ertcontlastline].endswith("]"):
2521 # This is an ERT option
2523 document.body[ertcontlastline] = document.body[ertcontlastline][1:]
2525 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
2526 # Convert to ArgInset
2527 document.body[parbeg] = "\\begin_inset Argument 2"
2529 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, True)
2536 def convert_quote_args(document):
2537 " Converts beamer quote style ERT args to native InsetArgs "
2539 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2540 if document.textclass not in beamer_classes:
2543 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2544 for lay in quote_layouts:
2547 i = find_token(document.body, "\\begin_layout " + lay, i)
2550 parent = get_containing_layout(document.body, i)
2552 document.warning("Wrong parent layout!")
2556 if document.body[parbeg] == "\\begin_inset ERT":
2557 if document.body[i + 6].startswith("<"):
2558 # This is an overlay specification
2560 document.body[i + 6] = document.body[i + 6][1:]
2561 if document.body[i + 6].endswith(">"):
2563 document.body[i + 6] = document.body[i + 6][:-1]
2564 # Convert to ArgInset
2565 document.body[i + 1] = "\\begin_inset Argument 1"
2569 def cleanup_beamerargs(document):
2570 " Clean up empty ERTs (conversion artefacts) "
2572 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2573 if document.textclass not in beamer_classes:
2578 i = find_token(document.body, "\\begin_inset Argument", i)
2581 j = find_end_of_inset(document.body, i)
2583 document.warning("Malformed LyX document: Can't find end of Argument inset")
2587 ertbeg = find_token(document.body, "\\begin_inset ERT", i, j)
2590 ertend = find_end_of_inset(document.body, ertbeg)
2592 document.warning("Malformed LyX document: Can't find end of ERT inset")
2594 stripped = [line for line in document.body[ertbeg : ertend + 1] if line.strip()]
2595 if len(stripped) == 5:
2596 # This is an empty ERT
2597 offset = len(document.body[ertbeg : ertend + 1])
2598 del document.body[ertbeg : ertend + 1]
2605 def revert_beamerargs(document):
2606 " Reverts beamer arguments to old layout "
2608 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2609 if document.textclass not in beamer_classes:
2613 list_layouts = ["Itemize", "Enumerate", "Description"]
2614 headings = ["Part", "Section", "Section*", "Subsection", "Subsection*",
2615 "Subsubsection", "Subsubsection*", "FrameSubtitle", "NoteItem"]
2616 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2617 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2618 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2621 i = find_token(document.body, "\\begin_inset Argument", i)
2624 # Find containing paragraph layout
2625 parent = get_containing_layout(document.body, i)
2627 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2632 realparbeg = parent[3]
2633 layoutname = parent[0]
2635 for p in range(parbeg, parend):
2639 if layoutname in headings:
2640 m = rx.match(document.body[p])
2644 # Find containing paragraph layout
2645 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2646 endPlain = find_end_of_layout(document.body, beginPlain)
2647 endInset = find_end_of_inset(document.body, p)
2648 argcontent = document.body[beginPlain + 1 : endPlain]
2650 realparend = realparend - len(document.body[p : endInset + 1])
2652 del document.body[p : endInset + 1]
2653 if layoutname == "FrameSubtitle":
2654 pre = put_cmd_in_ert("\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2655 elif layoutname == "NoteItem":
2656 pre = put_cmd_in_ert("\\note<") + argcontent + put_cmd_in_ert(">[item]")
2657 elif layoutname.endswith('*'):
2658 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower()[:-1] + "<") + argcontent + put_cmd_in_ert(">*")
2660 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2661 secarg = find_token(document.body, "\\begin_inset Argument 2", parbeg, parend)
2663 # Find containing paragraph layout
2664 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", secarg)
2665 endPlain = find_end_of_layout(document.body, beginPlain)
2666 endInset = find_end_of_inset(document.body, secarg)
2667 argcontent = document.body[beginPlain + 1 : endPlain]
2669 realparend = realparend - len(document.body[secarg : endInset + 1])
2670 del document.body[secarg : endInset + 1]
2671 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2672 pre += put_cmd_in_ert("{")
2673 document.body[parbeg] = "\\begin_layout Standard"
2674 document.body[realparbeg : realparbeg] = pre
2675 pe = find_end_of_layout(document.body, parbeg)
2676 post = put_cmd_in_ert("}")
2677 document.body[pe : pe] = post
2678 realparend += len(pre) + len(post)
2679 if layoutname == "AgainFrame":
2680 m = rx.match(document.body[p])
2684 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2685 endPlain = find_end_of_layout(document.body, beginPlain)
2686 endInset = find_end_of_inset(document.body, p)
2687 content = document.body[beginPlain + 1 : endPlain]
2689 realparend = realparend - len(document.body[p : endInset + 1])
2691 del document.body[p : endInset + 1]
2692 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2693 document.body[realparbeg : realparbeg] = subst
2694 if layoutname == "Overprint":
2695 m = rx.match(document.body[p])
2699 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2700 endPlain = find_end_of_layout(document.body, beginPlain)
2701 endInset = find_end_of_inset(document.body, p)
2702 content = document.body[beginPlain + 1 : endPlain]
2704 realparend = realparend - len(document.body[p : endInset + 1])
2706 del document.body[p : endInset + 1]
2707 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2708 document.body[realparbeg : realparbeg] = subst
2709 if layoutname == "OverlayArea":
2710 m = rx.match(document.body[p])
2714 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2715 endPlain = find_end_of_layout(document.body, beginPlain)
2716 endInset = find_end_of_inset(document.body, p)
2717 content = document.body[beginPlain + 1 : endPlain]
2719 realparend = realparend - len(document.body[p : endInset + 1])
2721 del document.body[p : endInset + 1]
2722 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2723 document.body[realparbeg : realparbeg] = subst
2724 if layoutname in list_layouts:
2725 m = rx.match(document.body[p])
2729 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2730 endPlain = find_end_of_layout(document.body, beginPlain)
2731 endInset = find_end_of_inset(document.body, p)
2732 content = document.body[beginPlain + 1 : endPlain]
2733 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2734 realparend = realparend + len(subst) - len(content)
2735 document.body[beginPlain + 1 : endPlain] = subst
2736 elif argnr == "item:1":
2737 j = find_end_of_inset(document.body, i)
2738 # Find containing paragraph layout
2739 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2740 endPlain = find_end_of_layout(document.body, beginPlain)
2741 content = document.body[beginPlain + 1 : endPlain]
2742 del document.body[i:j+1]
2743 if layoutname == "Description":
2744 # Description only has one (overlay) item arg
2745 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2746 # This must be put after the first space (begin of decription body
2747 # in LyX's arkward description list syntax)
2748 # Try to find that place ...
2749 rxx = re.compile(r'^([^\\ ]+ )(.*)$')
2750 for q in range(parbeg, parend):
2751 m = rxx.match(document.body[q])
2753 # We found it. Now insert the ERT argument just there:
2754 document.body[q : q] = [m.group(1), ''] + subst + ['', m.group(2)]
2757 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2758 document.body[realparbeg : realparbeg] = subst
2759 elif argnr == "item:2":
2760 j = find_end_of_inset(document.body, i)
2761 # Find containing paragraph layout
2762 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2763 endPlain = find_end_of_layout(document.body, beginPlain)
2764 content = document.body[beginPlain + 1 : endPlain]
2765 del document.body[i:j+1]
2766 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2767 document.body[realparbeg : realparbeg] = subst
2768 if layoutname in quote_layouts:
2769 m = rx.match(document.body[p])
2773 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2774 endPlain = find_end_of_layout(document.body, beginPlain)
2775 endInset = find_end_of_inset(document.body, p)
2776 content = document.body[beginPlain + 1 : endPlain]
2778 realparend = realparend - len(document.body[p : endInset + 1])
2780 del document.body[p : endInset + 1]
2781 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2782 document.body[realparbeg : realparbeg] = subst
2783 if layoutname in corollary_layouts:
2784 m = rx.match(document.body[p])
2788 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2789 endPlain = find_end_of_layout(document.body, beginPlain)
2790 endInset = find_end_of_inset(document.body, p)
2791 content = document.body[beginPlain + 1 : endPlain]
2793 realparend = realparend - len(document.body[p : endInset + 1])
2795 del document.body[p : endInset + 1]
2796 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2797 document.body[realparbeg : realparbeg] = subst
2802 def revert_beamerargs2(document):
2803 " Reverts beamer arguments to old layout, step 2 "
2805 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2806 if document.textclass not in beamer_classes:
2810 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2811 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2812 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2815 i = find_token(document.body, "\\begin_inset Argument", i)
2818 # Find containing paragraph layout
2819 parent = get_containing_layout(document.body, i)
2821 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2826 realparbeg = parent[3]
2827 layoutname = parent[0]
2829 for p in range(parbeg, parend):
2833 if layoutname in shifted_layouts:
2834 m = rx.match(document.body[p])
2838 document.body[p] = "\\begin_inset Argument 1"
2839 if layoutname in corollary_layouts:
2840 m = rx.match(document.body[p])
2844 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2845 endPlain = find_end_of_layout(document.body, beginPlain)
2846 endInset = find_end_of_inset(document.body, p)
2847 content = document.body[beginPlain + 1 : endPlain]
2849 realparend = realparend - len(document.body[p : endInset + 1])
2851 del document.body[p : endInset + 1]
2852 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2853 document.body[realparbeg : realparbeg] = subst
2854 if layoutname == "OverlayArea":
2855 m = rx.match(document.body[p])
2859 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2860 endPlain = find_end_of_layout(document.body, beginPlain)
2861 endInset = find_end_of_inset(document.body, p)
2862 content = document.body[beginPlain + 1 : endPlain]
2864 realparend = realparend - len(document.body[p : endInset + 1])
2866 del document.body[p : endInset + 1]
2867 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2868 document.body[realparbeg : realparbeg] = subst
2869 if layoutname == "AgainFrame":
2870 m = rx.match(document.body[p])
2874 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2875 endPlain = find_end_of_layout(document.body, beginPlain)
2876 endInset = find_end_of_inset(document.body, p)
2877 content = document.body[beginPlain + 1 : endPlain]
2879 realparend = realparend - len(document.body[p : endInset + 1])
2881 del document.body[p : endInset + 1]
2882 subst = put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
2883 document.body[realparbeg : realparbeg] = subst
2887 def revert_beamerargs3(document):
2888 " Reverts beamer arguments to old layout, step 3 "
2890 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2891 if document.textclass not in beamer_classes:
2894 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2897 i = find_token(document.body, "\\begin_inset Argument", i)
2900 # Find containing paragraph layout
2901 parent = get_containing_layout(document.body, i)
2903 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2908 realparbeg = parent[3]
2909 layoutname = parent[0]
2911 for p in range(parbeg, parend):
2915 if layoutname == "AgainFrame":
2916 m = rx.match(document.body[p])
2920 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2921 endPlain = find_end_of_layout(document.body, beginPlain)
2922 endInset = find_end_of_inset(document.body, p)
2923 content = document.body[beginPlain + 1 : endPlain]
2925 realparend = realparend - len(document.body[p : endInset + 1])
2927 del document.body[p : endInset + 1]
2928 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2929 document.body[realparbeg : realparbeg] = subst
2933 def revert_beamerflex(document):
2934 " Reverts beamer Flex insets "
2936 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2937 if document.textclass not in beamer_classes:
2940 new_flexes = {"Bold" : "\\textbf", "Emphasize" : "\\emph", "Only" : "\\only",
2941 "Uncover" : "\\uncover", "Visible" : "\\visible",
2942 "Invisible" : "\\invisible", "Alternative" : "\\alt",
2943 "Beamer_Note" : "\\note"}
2944 old_flexes = {"Alert" : "\\alert", "Structure" : "\\structure"}
2945 rx = re.compile(r'^\\begin_inset Flex (.+)$')
2949 i = find_token(document.body, "\\begin_inset Flex", i)
2952 m = rx.match(document.body[i])
2954 flextype = m.group(1)
2955 z = find_end_of_inset(document.body, i)
2957 document.warning("Can't find end of Flex " + flextype + " inset.")
2960 if flextype in new_flexes:
2961 pre = put_cmd_in_ert(new_flexes[flextype])
2962 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2964 argend = find_end_of_inset(document.body, arg)
2966 document.warning("Can't find end of Argument!")
2969 # Find containing paragraph layout
2970 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2971 endPlain = find_end_of_layout(document.body, beginPlain)
2972 argcontent = document.body[beginPlain + 1 : endPlain]
2974 z = z - len(document.body[arg : argend + 1])
2976 del document.body[arg : argend + 1]
2977 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2978 arg = find_token(document.body, "\\begin_inset Argument 2", i, z)
2980 argend = find_end_of_inset(document.body, arg)
2982 document.warning("Can't find end of Argument!")
2985 # Find containing paragraph layout
2986 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2987 endPlain = find_end_of_layout(document.body, beginPlain)
2988 argcontent = document.body[beginPlain + 1 : endPlain]
2990 z = z - len(document.body[arg : argend + 1])
2992 del document.body[arg : argend + 1]
2993 if flextype == "Alternative":
2994 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
2996 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2997 pre += put_cmd_in_ert("{")
2998 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2999 endPlain = find_end_of_layout(document.body, beginPlain)
3001 z = z - len(document.body[i : beginPlain + 1])
3003 document.body[i : beginPlain + 1] = pre
3004 post = put_cmd_in_ert("}")
3005 document.body[z - 2 : z + 1] = post
3006 elif flextype in old_flexes:
3007 pre = put_cmd_in_ert(old_flexes[flextype])
3008 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
3012 argend = find_end_of_inset(document.body, arg)
3014 document.warning("Can't find end of Argument!")
3017 # Find containing paragraph layout
3018 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3019 endPlain = find_end_of_layout(document.body, beginPlain)
3020 argcontent = document.body[beginPlain + 1 : endPlain]
3022 z = z - len(document.body[arg : argend + 1])
3024 del document.body[arg : argend + 1]
3025 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
3026 pre += put_cmd_in_ert("{")
3027 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
3028 endPlain = find_end_of_layout(document.body, beginPlain)
3030 z = z - len(document.body[i : beginPlain + 1])
3032 document.body[i : beginPlain + 1] = pre
3033 post = put_cmd_in_ert("}")
3034 document.body[z - 2 : z + 1] = post
3039 def revert_beamerblocks(document):
3040 " Reverts beamer block arguments to ERT "
3042 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3043 if document.textclass not in beamer_classes:
3046 blocks = ["Block", "ExampleBlock", "AlertBlock"]
3048 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3051 i = find_token(document.body, "\\begin_inset Argument", i)
3054 # Find containing paragraph layout
3055 parent = get_containing_layout(document.body, i)
3057 document.warning("Malformed LyX document: Can't find parent paragraph layout")
3062 realparbeg = parent[3]
3063 layoutname = parent[0]
3065 for p in range(parbeg, parend):
3069 if layoutname in blocks:
3070 m = rx.match(document.body[p])
3074 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3075 endPlain = find_end_of_layout(document.body, beginPlain)
3076 endInset = find_end_of_inset(document.body, p)
3077 content = document.body[beginPlain + 1 : endPlain]
3079 realparend = realparend - len(document.body[p : endInset + 1])
3081 del document.body[p : endInset + 1]
3082 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3083 document.body[realparbeg : realparbeg] = subst
3085 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3086 endPlain = find_end_of_layout(document.body, beginPlain)
3087 endInset = find_end_of_inset(document.body, p)
3088 content = document.body[beginPlain + 1 : endPlain]
3090 realparend = realparend - len(document.body[p : endInset + 1])
3092 del document.body[p : endInset + 1]
3093 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3094 document.body[realparbeg : realparbeg] = subst
3099 def convert_beamerblocks(document):
3100 " Converts beamer block ERT args to native InsetArgs "
3102 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3103 if document.textclass not in beamer_classes:
3106 blocks = ["Block", "ExampleBlock", "AlertBlock"]
3110 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
3113 parent = get_containing_layout(document.body, i)
3114 if parent == False or parent[1] != i:
3115 document.warning("Wrong parent layout!")
3122 # If the paragraph starts with a language switch, adjust parbeg
3123 if len(document.body[parbeg]) == 0 and parbeg < parend \
3124 and document.body[parbeg + 1].startswith("\\lang"):
3126 if document.body[parbeg] == "\\begin_inset ERT":
3127 ertcontfirstline = parbeg + 5
3131 # Find the last ERT in this paragraph used for arguments
3132 # (which might also be the first)
3133 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
3134 if lastertbeg == -1:
3135 document.warning("Last ERT not found!")
3137 lastertend = find_end_of_inset(document.body, lastertbeg)
3138 if lastertend == -1:
3139 document.warning("End of last ERT not found!")
3141 # Is this ERT really used for an argument?
3142 # Note: This will fail when non-argument ERTs actually use brackets
3144 regexp = re.compile(r'.*[>\]\}]', re.IGNORECASE)
3145 cbracket = find_re(document.body, regexp, lastertbeg, lastertend)
3148 if lastertbeg == parbeg:
3151 if lastertbeg == -1 or lastertend == -1:
3153 ertcontlastline = lastertend - 3
3155 if document.body[ertcontfirstline].lstrip().startswith("<"):
3156 # This is an overlay specification
3158 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3159 if document.body[ertcontlastline].rstrip().endswith(">"):
3161 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3162 # Convert to ArgInset
3163 document.body[parbeg] = "\\begin_inset Argument 1"
3164 elif document.body[ertcontlastline].rstrip().endswith("}"):
3166 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3168 ertcontdivline = ertcontfirstline
3169 tok = document.body[ertcontdivline].find('>{')
3171 regexp = re.compile(r'.*>\{', re.IGNORECASE)
3172 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3173 tok = document.body[ertcontdivline].find('>{')
3175 if ertcontfirstline < ertcontlastline:
3176 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3177 document.body[ertcontlastline : ertcontlastline + 1] = [
3178 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3179 if ertcontdivline == ertcontfirstline:
3180 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3181 '\\end_layout', '', '\\end_inset', '',
3182 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3183 'status collapsed', '', '\\begin_layout Plain Layout',
3184 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3185 document.body[ertcontdivline][tok + 2:]]
3187 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3188 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3189 'status collapsed', '', '\\begin_layout Plain Layout',
3190 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3191 document.body[ertcontdivline][tok + 2:]]
3193 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3194 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3195 'status collapsed', '', '\\begin_layout Plain Layout',
3196 document.body[ertcontdivline][tok + 2:]]
3198 # check if have delimiters in two different ERTs
3199 tok = document.body[ertcontdivline].find('>')
3201 regexp = re.compile(r'.*>', re.IGNORECASE)
3202 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3203 tok = document.body[ertcontdivline].find('>')
3205 tokk = document.body[ertcontdivline].find('{')
3207 regexp = re.compile(r'.*\{', re.IGNORECASE)
3208 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, lastertend)
3209 tokk = document.body[ertcontdivlinetwo].find('{')
3211 if ertcontfirstline < ertcontlastline:
3212 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3213 document.body[ertcontlastline : ertcontlastline + 1] = [
3214 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3215 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3216 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3217 '\\end_inset', '', '', '\\begin_inset Argument 2',
3218 'status collapsed', '', '\\begin_layout Plain Layout',
3219 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3220 document.body[ertcontdivlinetwo][tokk + 1:]]
3222 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3223 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3224 'status collapsed', '', '\\begin_layout Plain Layout',
3225 document.body[ertcontdivlinetwo][tokk + 1:]]
3226 # Convert to ArgInset
3227 if ertcontfirstline < ertcontlastline:
3228 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3229 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 1',
3230 'status collapsed', '', '\\begin_layout Plain Layout',
3231 '\\begin_inset ERT', '']
3233 document.body[parbeg] = "\\begin_inset Argument 1"
3234 elif document.body[ertcontfirstline].lstrip().startswith("{"):
3235 # This is the block title
3236 if document.body[ertcontlastline].rstrip().endswith("}"):
3237 # strip off the braces
3238 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3239 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3240 if ertcontfirstline < ertcontlastline:
3241 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3242 document.body[parend : parend + 1] = [
3243 document.body[parend], '\\end_inset', '', '\\end_layout']
3244 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3245 'status collapsed', '', '\\begin_layout Plain Layout',
3246 '\\begin_inset ERT', '']
3248 # Convert to ArgInset
3249 document.body[parbeg] = "\\begin_inset Argument 2"
3250 # the overlay argument can also follow the title, so ...
3251 elif document.body[ertcontlastline].rstrip().endswith(">"):
3253 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3255 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3257 ertcontdivline = ertcontfirstline
3258 tok = document.body[ertcontdivline].find('}<')
3260 regexp = re.compile(r'.*\}<', re.IGNORECASE)
3261 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3262 tok = document.body[ertcontdivline].find('}<')
3264 if ertcontfirstline < ertcontlastline:
3265 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3266 document.body[ertcontlastline : ertcontlastline + 1] = [
3267 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3268 if ertcontdivline == ertcontfirstline:
3269 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3270 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3271 'status collapsed', '', '\\begin_layout Plain Layout',
3272 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3273 document.body[ertcontdivline][tok + 2:]]
3275 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3276 '\\end_layout', '', '\\end_inset', '',
3277 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3278 'status collapsed', '', '\\begin_layout Plain Layout',
3279 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3280 document.body[ertcontdivline][tok + 2:]]
3282 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3283 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3284 'status collapsed', '', '\\begin_layout Plain Layout',
3285 document.body[ertcontdivline][tok + 2:]]
3287 # check if have delimiters in two different ERTs
3288 tok = document.body[ertcontdivline].find('}')
3290 regexp = re.compile(r'.*\}', re.IGNORECASE)
3291 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3292 tok = document.body[ertcontdivline].find('}')
3294 tokk = document.body[ertcontdivline].find('<')
3296 regexp = re.compile(r'.*<', re.IGNORECASE)
3297 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, lastertend)
3298 tokk = document.body[ertcontdivlinetwo].find('<')
3300 if ertcontfirstline < ertcontlastline:
3301 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3302 document.body[ertcontlastline : ertcontlastline + 1] = [
3303 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3304 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3305 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3306 '\\end_inset', '', '', '\\begin_inset Argument 1',
3307 'status collapsed', '', '\\begin_layout Plain Layout',
3308 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3309 document.body[ertcontdivlinetwo][tokk + 1:]]
3311 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3312 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3313 'status collapsed', '', '\\begin_layout Plain Layout',
3314 document.body[ertcontdivlinetwo][tokk + 1:]]
3315 # Convert to ArgInset
3316 if ertcontfirstline < ertcontlastline:
3317 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3318 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3319 'status collapsed', '', '\\begin_layout Plain Layout',
3320 '\\begin_inset ERT', '']
3322 document.body[parbeg] = "\\begin_inset Argument 2"
3323 elif count_pars_in_inset(document.body, ertcontfirstline) > 1:
3324 # Multipar ERT. Skip this.
3327 # ERT has contents after the closing bracket. We cannot convert this.
3328 # convert_TeX_brace_to_Argument cannot either.
3329 #convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, False)
3333 j = find_end_of_layout(document.body, i)
3335 document.warning("end of layout not found!")
3336 k = find_token(document.body, "\\begin_inset Argument", i, j)
3338 document.warning("InsetArgument not found!")
3340 l = find_end_of_inset(document.body, k)
3341 m = find_token(document.body, "\\begin_inset ERT", l, j)
3344 ertcontfirstline = m + 5
3349 def convert_overprint(document):
3350 " Convert old beamer overprint layouts to ERT "
3352 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3353 if document.textclass not in beamer_classes:
3358 i = find_token(document.body, "\\begin_layout Overprint", i)
3361 # Find end of sequence
3362 j = find_end_of_sequence(document.body, i)
3364 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3368 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3370 if document.body[j] == "\\end_deeper":
3371 esubst = ["", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3373 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3374 endseq = endseq + len(esubst) - len(document.body[j : j])
3375 document.body[j : j] = esubst
3376 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3378 argend = find_end_of_layout(document.body, argbeg)
3380 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3383 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3384 endPlain = find_end_of_layout(document.body, beginPlain)
3385 content = document.body[beginPlain + 1 : endPlain]
3387 endseq = endseq - len(document.body[argbeg : argend + 1])
3389 del document.body[argbeg : argend + 1]
3390 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3392 endseq = endseq - len(document.body[i : i])
3393 document.body[i : i] = subst + ["\\end_layout"]
3394 endseq += len(subst)
3396 for p in range(i, endseq):
3397 if document.body[p] == "\\begin_layout Overprint":
3398 document.body[p] = "\\begin_layout Standard"
3403 def revert_overprint(document):
3404 " Revert old beamer overprint layouts to ERT "
3406 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3407 if document.textclass not in beamer_classes:
3412 i = find_token(document.body, "\\begin_layout Overprint", i)
3415 # Find end of sequence
3416 j = find_end_of_sequence(document.body, i)
3418 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3422 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3423 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}")
3424 endseq = endseq + len(esubst) - len(document.body[j : j])
3425 if document.body[j] == "\\end_deeper":
3426 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3428 document.body[j : j] = ["\\end_layout", ""] + esubst
3431 if document.body[r] == "\\begin_deeper":
3432 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3434 document.body[r] = ""
3435 document.body[s] = ""
3439 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3441 # Is this really our argument?
3442 nested = find_token(document.body, "\\begin_deeper", i, argbeg)
3444 argend = find_end_of_inset(document.body, argbeg)
3446 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3449 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3450 endPlain = find_end_of_layout(document.body, beginPlain)
3451 content = document.body[beginPlain + 1 : endPlain]
3453 endseq = endseq - len(document.body[argbeg : argend])
3455 del document.body[argbeg : argend + 1]
3456 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3458 endseq = endseq - len(document.body[i : i])
3459 document.body[i : i] = subst + ["\\end_layout"]
3460 endseq += len(subst)
3466 if document.body[p] == "\\begin_layout Overprint":
3467 q = find_end_of_layout(document.body, p)
3469 document.warning("Malformed LyX document. Cannot find end of Overprint layout!")
3472 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\onslide")
3473 argbeg = find_token(document.body, "\\begin_inset Argument item:1", p, q)
3475 argend = find_end_of_inset(document.body, argbeg)
3477 document.warning("Malformed LyX document. Cannot find end of Overprint item argument!")
3480 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3481 endPlain = find_end_of_layout(document.body, beginPlain)
3482 content = document.body[beginPlain + 1 : endPlain]
3484 endseq = endseq - len(document.body[argbeg : argend + 1])
3486 del document.body[argbeg : argend + 1]
3487 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3488 endseq = endseq - len(document.body[p : p + 1]) + len(subst)
3489 document.body[p : p + 1] = subst
3495 def revert_frametitle(document):
3496 " Reverts beamer frametitle layout to ERT "
3498 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3499 if document.textclass not in beamer_classes:
3502 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3505 i = find_token(document.body, "\\begin_layout FrameTitle", i)
3508 j = find_end_of_layout(document.body, i)
3510 document.warning("Malformed LyX document: Can't find end of FrameTitle layout")
3514 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
3515 endlay += len(put_cmd_in_ert("}"))
3516 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\frametitle")
3517 for p in range(i, j):
3520 m = rx.match(document.body[p])
3524 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3525 endPlain = find_end_of_layout(document.body, beginPlain)
3526 endInset = find_end_of_inset(document.body, p)
3527 content = document.body[beginPlain + 1 : endPlain]
3529 endlay = endlay - len(document.body[p : endInset + 1])
3531 del document.body[p : endInset + 1]
3532 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3534 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3535 endPlain = find_end_of_layout(document.body, beginPlain)
3536 endInset = find_end_of_inset(document.body, p)
3537 content = document.body[beginPlain + 1 : endPlain]
3539 endlay = endlay - len(document.body[p : endInset + 1])
3541 del document.body[p : endInset + 1]
3542 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3544 subst += put_cmd_in_ert("{")
3545 document.body[i : i + 1] = subst
3549 def convert_epigraph(document):
3550 " Converts memoir epigraph to new syntax "
3552 if document.textclass != "memoir":
3557 i = find_token(document.body, "\\begin_layout Epigraph", i)
3560 j = find_end_of_layout(document.body, i)
3562 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3567 ert = find_token(document.body, "\\begin_inset ERT", i, j)
3569 endInset = find_end_of_inset(document.body, ert)
3570 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", ert)
3571 endPlain = find_end_of_layout(document.body, beginPlain)
3572 ertcont = beginPlain + 2
3573 if document.body[ertcont] == "}{":
3575 # Convert to ArgInset
3576 endlay = endlay - 2 * len(document.body[j])
3577 begsubst = ['\\begin_inset Argument post:1', 'status collapsed', '',
3578 '\\begin_layout Plain Layout']
3579 endsubst = ['\\end_layout', '', '\\end_inset', '', document.body[j]]
3580 document.body[j : j + 1] = endsubst
3581 document.body[endInset + 1 : endInset + 1] = begsubst
3583 endlay += len(begsubst) + len(endsubst)
3584 endlay = endlay - len(document.body[ert : endInset + 1])
3585 del document.body[ert : endInset + 1]
3590 def revert_epigraph(document):
3591 " Reverts memoir epigraph argument to ERT "
3593 if document.textclass != "memoir":
3598 i = find_token(document.body, "\\begin_layout Epigraph", i)
3601 j = find_end_of_layout(document.body, i)
3603 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3608 p = find_token(document.body, "\\begin_layout Argument post:1", i, j)
3610 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3611 endPlain = find_end_of_layout(document.body, beginPlain)
3612 endInset = find_end_of_inset(document.body, p)
3613 content = document.body[beginPlain + 1 : endPlain]
3615 endlay = endlay - len(document.body[p : endInset + 1])
3617 del document.body[p : endInset + 1]
3618 subst += put_cmd_in_ert("}{") + content
3620 subst += put_cmd_in_ert("}{")
3622 document.body[j : j] = subst + document.body[j : j]
3626 def convert_captioninsets(document):
3627 " Converts caption insets to new syntax "
3631 i = find_token(document.body, "\\begin_inset Caption", i)
3634 document.body[i] = "\\begin_inset Caption Standard"
3638 def revert_captioninsets(document):
3639 " Reverts caption insets to old syntax "
3643 i = find_token(document.body, "\\begin_inset Caption Standard", i)
3646 document.body[i] = "\\begin_inset Caption"
3650 def convert_captionlayouts(document):
3651 " Convert caption layouts to caption insets. "
3654 "Captionabove": "Above",
3655 "Captionbelow": "Below",
3656 "FigCaption" : "FigCaption",
3657 "Table_Caption" : "Table",
3658 "CenteredCaption" : "Centered",
3659 "Bicaption" : "Bicaption",
3662 for captype in caption_dict.keys():
3665 i = find_token(document.body, "\\begin_layout " + captype, i)
3668 j = find_end_of_layout(document.body, i)
3670 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3673 document.body[j:j] = ["\\end_layout", "", "\\end_inset", "", ""]
3674 document.body[i:i+1] = ["\\begin_layout %s" % document.default_layout,
3675 "\\begin_inset Caption %s" % caption_dict[val], "",
3676 "\\begin_layout %s" % document.default_layout]
3680 def revert_captionlayouts(document):
3681 " Revert caption insets to caption layouts. "
3684 "Above" : "Captionabove",
3685 "Below" : "Captionbelow",
3686 "FigCaption" : "FigCaption",
3687 "Table" : "Table_Caption",
3688 "Centered" : "CenteredCaption",
3689 "Bicaption" : "Bicaption",
3693 rx = re.compile(r'^\\begin_inset Caption (\S+)$')
3695 i = find_token(document.body, "\\begin_inset Caption", i)
3699 m = rx.match(document.body[i])
3703 if val not in list(caption_dict.keys()):
3707 # We either need to delete the previous \begin_layout line, or we
3708 # need to end the previous layout if this inset is not in the first
3709 # position of the paragraph.
3710 layout_before = find_token_backwards(document.body, "\\begin_layout", i)
3711 if layout_before == -1:
3712 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3714 layout_line = document.body[layout_before]
3715 del_layout_before = True
3716 l = layout_before + 1
3718 if document.body[l] != "":
3719 del_layout_before = False
3722 if del_layout_before:
3723 del document.body[layout_before:i]
3726 document.body[i:i] = ["\\end_layout", ""]
3729 # Find start of layout in the inset and end of inset
3730 j = find_token(document.body, "\\begin_layout", i)
3732 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3734 k = find_end_of_inset(document.body, i)
3736 document.warning("Malformed LyX document: Missing `\\end_inset'.")
3739 # We either need to delete the following \end_layout line, or we need
3740 # to restart the old layout if this inset is not at the paragraph end.
3741 layout_after = find_token(document.body, "\\end_layout", k)
3742 if layout_after == -1:
3743 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3745 del_layout_after = True
3747 while l < layout_after:
3748 if document.body[l] != "":
3749 del_layout_after = False
3752 if del_layout_after:
3753 del document.body[k+1:layout_after+1]
3755 document.body[k+1:k+1] = [layout_line, ""]
3757 # delete \begin_layout and \end_inset and replace \begin_inset with
3758 # "\begin_layout XXX". This works because we can only have one
3759 # paragraph in the caption inset: The old \end_layout will be recycled.
3760 del document.body[k]
3761 if document.body[k] == "":
3762 del document.body[k]
3763 del document.body[j]
3764 if document.body[j] == "":
3765 del document.body[j]
3766 document.body[i] = "\\begin_layout %s" % caption_dict[val]
3767 if document.body[i+1] == "":
3768 del document.body[i+1]
3772 def revert_fragileframe(document):
3773 " Reverts beamer FragileFrame layout to ERT "
3775 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3776 if document.textclass not in beamer_classes:
3781 i = find_token(document.body, "\\begin_layout FragileFrame", i)
3784 # Find end of sequence
3785 j = find_end_of_sequence(document.body, i)
3787 document.warning("Malformed LyX document. Cannot find end of FragileFrame sequence!")
3791 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{frame}")
3792 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{frame}")
3793 endseq = endseq + len(esubst) - len(document.body[j : j])
3794 if document.body[j] == "\\end_deeper":
3795 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3797 document.body[j : j] = esubst
3798 for q in range(i, j):
3799 if document.body[q] == "\\begin_layout FragileFrame":
3800 document.body[q] = "\\begin_layout %s" % document.default_layout
3803 if document.body[r] == "\\begin_deeper":
3804 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3806 document.body[r] = ""
3807 document.body[s] = ""
3811 for p in range(1, 5):
3812 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, j)
3815 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3816 endPlain = find_end_of_layout(document.body, beginPlain)
3817 endInset = find_end_of_inset(document.body, arg)
3818 content = document.body[beginPlain + 1 : endPlain]
3820 j = j - len(document.body[arg : endInset + 1])
3822 del document.body[arg : endInset + 1]
3823 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3825 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3826 endPlain = find_end_of_layout(document.body, beginPlain)
3827 endInset = find_end_of_inset(document.body, arg)
3828 content = document.body[beginPlain + 1 : endPlain]
3830 j = j - len(document.body[arg : endInset + 1])
3832 del document.body[arg : endInset + 1]
3833 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3835 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3836 endPlain = find_end_of_layout(document.body, beginPlain)
3837 endInset = find_end_of_inset(document.body, arg)
3838 content = document.body[beginPlain + 1 : endPlain]
3840 j = j - len(document.body[arg : endInset + 1])
3842 del document.body[arg : endInset + 1]
3843 subst += put_cmd_in_ert("[fragile,") + content + put_cmd_in_ert("]")
3845 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3846 endPlain = find_end_of_layout(document.body, beginPlain)
3847 endInset = find_end_of_inset(document.body, arg)
3848 content = document.body[beginPlain + 1 : endPlain]
3850 j = j - len(document.body[arg : endInset + 1])
3852 del document.body[arg : endInset + 1]
3853 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3855 subst += put_cmd_in_ert("[fragile]")
3857 document.body[i : i + 1] = subst
3861 def revert_newframes(document):
3862 " Reverts beamer Frame and PlainFrame layouts to old forms "
3864 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3865 if document.textclass not in beamer_classes:
3869 "Frame" : "BeginFrame",
3870 "PlainFrame" : "BeginPlainFrame",
3873 rx = re.compile(r'^\\begin_layout (\S+)$')
3876 i = find_token(document.body, "\\begin_layout", i)
3880 m = rx.match(document.body[i])
3884 if val not in list(frame_dict.keys()):
3887 # Find end of sequence
3888 j = find_end_of_sequence(document.body, i)
3890 document.warning("Malformed LyX document. Cannot find end of Frame sequence!")
3894 subst = ["\\begin_layout %s" % frame_dict[val]]
3895 esubst = ["", "\\begin_layout EndFrame", "", "\\end_layout"]
3896 endseq = endseq + len(esubst) - len(document.body[j : j])
3897 if document.body[j] == "\\end_deeper":
3898 document.body[j : j] = esubst
3900 document.body[j+1 : j+1] = esubst
3901 for q in range(i, j):
3902 if document.body[q] == "\\begin_layout %s" % val:
3903 document.body[q] = "\\begin_layout %s" % document.default_layout
3906 if document.body[r] == "\\begin_deeper":
3907 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3909 document.body[r] = ""
3910 document.body[s] = ""
3914 l = find_end_of_layout(document.body, i)
3915 for p in range(1, 5):
3916 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, l)
3919 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3920 endPlain = find_end_of_layout(document.body, beginPlain)
3921 endInset = find_end_of_inset(document.body, arg)
3922 content = document.body[beginPlain + 1 : endPlain]
3924 l = l - len(document.body[arg : endInset + 1])
3926 del document.body[arg : endInset + 1]
3927 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3929 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3930 endPlain = find_end_of_layout(document.body, beginPlain)
3931 endInset = find_end_of_inset(document.body, arg)
3932 content = document.body[beginPlain + 1 : endPlain]
3934 l = l - len(document.body[arg : endInset + 1])
3936 del document.body[arg : endInset + 1]
3937 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3939 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3940 endPlain = find_end_of_layout(document.body, beginPlain)
3941 endInset = find_end_of_inset(document.body, arg)
3942 content = document.body[beginPlain + 1 : endPlain]
3944 l = l - len(document.body[arg : endInset + 1])
3946 del document.body[arg : endInset + 1]
3947 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3949 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3950 endPlain = find_end_of_layout(document.body, beginPlain)
3951 endInset = find_end_of_inset(document.body, arg)
3952 content = document.body[beginPlain + 1 : endPlain]
3954 l = l - len(document.body[arg : endInset + 1])
3956 del document.body[arg : endInset + 1]
3959 document.body[i : i + 1] = subst
3962 # known encodings that do not change their names (same LyX and LaTeX names)
3963 known_enc_tuple = ("auto", "default", "ansinew", "applemac", "armscii8", "ascii",
3964 "cp437", "cp437de", "cp850", "cp852", "cp855", "cp858", "cp862", "cp865", "cp866",
3965 "cp1250", "cp1251", "cp1252", "cp1255", "cp1256", "cp1257", "koi8-r", "koi8-u",
3966 "pt154", "pt254", "tis620-0", "utf8", "utf8x", "utf8-plain")
3968 def convert_encodings(document):
3969 "Use the LyX names of the encodings instead of the LaTeX names."
3970 LaTeX2LyX_enc_dict = {
3971 "8859-6": "iso8859-6",
3972 "8859-8": "iso8859-8",
3974 "euc": "euc-jp-platex",
3979 "iso88595": "iso8859-5",
3980 "iso-8859-7": "iso8859-7",
3982 "jis": "jis-platex",
3984 "l7xenc": "iso8859-13",
3985 "latin1": "iso8859-1",
3986 "latin2": "iso8859-2",
3987 "latin3": "iso8859-3",
3988 "latin4": "iso8859-4",
3989 "latin5": "iso8859-9",
3990 "latin9": "iso8859-15",
3991 "latin10": "iso8859-16",
3992 "SJIS": "shift-jis",
3993 "sjis": "shift-jis-platex",
3996 i = find_token(document.header, "\\inputencoding" , 0)
3999 val = get_value(document.header, "\\inputencoding", i)
4000 if val in list(LaTeX2LyX_enc_dict.keys()):
4001 document.header[i] = "\\inputencoding %s" % LaTeX2LyX_enc_dict[val]
4002 elif val not in known_enc_tuple:
4003 document.warning("Ignoring unknown input encoding: `%s'" % val)
4006 def revert_encodings(document):
4007 """Revert to using the LaTeX names of the encodings instead of the LyX names.
4008 Also revert utf8-platex to sjis, the language default when using Japanese.
4010 LyX2LaTeX_enc_dict = {
4015 "euc-jp-platex": "euc",
4018 "iso8859-1": "latin1",
4019 "iso8859-2": "latin2",
4020 "iso8859-3": "latin3",
4021 "iso8859-4": "latin4",
4022 "iso8859-5": "iso88595",
4023 "iso8859-6": "8859-6",
4024 "iso8859-7": "iso-8859-7",
4025 "iso8859-8": "8859-8",
4026 "iso8859-9": "latin5",
4027 "iso8859-13": "l7xenc",
4028 "iso8859-15": "latin9",
4029 "iso8859-16": "latin10",
4031 "jis-platex": "jis",
4032 "shift-jis": "SJIS",
4033 "shift-jis-platex": "sjis",
4035 "utf8-platex": "sjis"
4037 i = find_token(document.header, "\\inputencoding" , 0)
4040 val = get_value(document.header, "\\inputencoding", i)
4041 if val in list(LyX2LaTeX_enc_dict.keys()):
4042 document.header[i] = "\\inputencoding %s" % LyX2LaTeX_enc_dict[val]
4043 elif val not in known_enc_tuple:
4044 document.warning("Ignoring unknown input encoding: `%s'" % val)
4047 def revert_IEEEtran_3(document):
4049 Reverts Flex Insets to TeX-code
4051 if document.textclass == "IEEEtran":
4057 h = find_token(document.body, "\\begin_inset Flex Author Mark", h)
4059 endh = find_end_of_inset(document.body, h)
4060 document.body[endh - 2 : endh + 1] = put_cmd_in_ert("}")
4061 document.body[h : h + 4] = put_cmd_in_ert("\\IEEEauthorrefmark{")
4064 i = find_token(document.body, "\\begin_inset Flex Author Name", i)
4066 endi = find_end_of_inset(document.body, i)
4067 document.body[endi - 2 : endi + 1] = put_cmd_in_ert("}")
4068 document.body[i : i + 4] = put_cmd_in_ert("\\IEEEauthorblockN{")
4071 j = find_token(document.body, "\\begin_inset Flex Author Affiliation", j)
4073 endj = find_end_of_inset(document.body, j)
4074 document.body[endj - 2 : endj + 1] = put_cmd_in_ert("}")
4075 document.body[j : j + 4] = put_cmd_in_ert("\\IEEEauthorblockA{")
4077 if i == -1 and j == -1 and h == -1:
4081 def revert_kurier_fonts(document):
4082 " Revert kurier font definition to LaTeX "
4084 i = find_token(document.header, "\\font_math", 0)
4086 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4087 val = get_value(document.header, "\\font_math", i)
4088 if val == "kurier-math":
4089 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
4090 "\\usepackage[math]{kurier}\n" \
4091 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
4092 document.header[i] = "\\font_math auto"
4094 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4095 kurier_fonts = ["kurier", "kurierc", "kurierl", "kurierlc"]
4096 k = find_token(document.header, "\\font_sans kurier", 0)
4098 sf = get_value(document.header, "\\font_sans", k)
4099 if sf in kurier_fonts:
4100 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4101 document.header[k] = "\\font_sans default"
4103 def revert_iwona_fonts(document):
4104 " Revert iwona font definition to LaTeX "
4106 i = find_token(document.header, "\\font_math", 0)
4108 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4109 val = get_value(document.header, "\\font_math", i)
4110 if val == "iwona-math":
4111 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
4112 "\\usepackage[math]{iwona}\n" \
4113 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
4114 document.header[i] = "\\font_math auto"
4116 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4117 iwona_fonts = ["iwona", "iwonac", "iwonal", "iwonalc"]
4118 k = find_token(document.header, "\\font_sans iwona", 0)
4120 sf = get_value(document.header, "\\font_sans", k)
4121 if sf in iwona_fonts:
4122 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4123 document.header[k] = "\\font_sans default"
4126 def revert_new_libertines(document):
4127 " Revert new libertine font definition to LaTeX "
4129 if find_token(document.header, "\\use_non_tex_fonts true", 0) != -1:
4132 i = find_token(document.header, "\\font_typewriter libertine-mono", 0)
4134 preamble = "\\usepackage"
4135 sc = find_token(document.header, "\\font_tt_scale", 0)
4137 scval = get_value(document.header, "\\font_tt_scale", sc)
4139 preamble += "[scale=%f]" % (float(scval) / 100)
4140 document.header[sc] = "\\font_tt_scale 100"
4141 preamble += "{libertineMono-type1}"
4142 add_to_preamble(document, [preamble])
4143 document.header[i] = "\\font_typewriter default"
4145 k = find_token(document.header, "\\font_sans biolinum", 0)
4147 preamble = "\\usepackage"
4149 j = find_token(document.header, "\\font_osf true", 0)
4154 sc = find_token(document.header, "\\font_sf_scale", 0)
4156 scval = get_value(document.header, "\\font_sf_scale", sc)
4158 options += ",scale=%f" % (float(scval) / 100)
4159 document.header[sc] = "\\font_sf_scale 100"
4161 preamble += "[" + options +"]"
4162 preamble += "{biolinum-type1}"
4163 add_to_preamble(document, [preamble])
4164 document.header[k] = "\\font_sans default"
4167 def convert_lyxframes(document):
4168 " Converts old beamer frames to new style "
4170 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4171 if document.textclass not in beamer_classes:
4174 framebeg = ["BeginFrame", "BeginPlainFrame"]
4175 frameend = ["Frame", "PlainFrame", "EndFrame", "BeginFrame", "BeginPlainFrame", "AgainFrame",
4176 "Section", "Section*", "Subsection", "Subsection*", "Subsubsection", "Subsubsection*"]
4177 for lay in framebeg:
4180 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
4183 parent = get_containing_layout(document.body, i)
4184 if parent == False or parent[1] != i:
4185 document.warning("Wrong parent layout!")
4188 frametype = parent[0]
4192 # Step I: Convert ERT arguments
4193 # FIXME: See restrictions in convert_beamerframeargs method
4194 ertend = convert_beamerframeargs(document, i, parbeg)
4197 # Step II: Now rename the layout and convert the title to an argument
4198 j = find_end_of_layout(document.body, i)
4199 document.body[j : j + 1] = ['\\end_layout', '', '\\end_inset', '', '\\end_layout']
4200 if lay == "BeginFrame":
4201 document.body[i] = "\\begin_layout Frame"
4203 document.body[i] = "\\begin_layout PlainFrame"
4204 document.body[ertend + 1 : ertend + 1] = ['\\begin_inset Argument 4',
4205 'status open', '', '\\begin_layout Plain Layout']
4206 # Step III: find real frame end
4209 inInset = get_containing_inset(document.body, i)
4211 fend = find_token(document.body, "\\begin_layout", jj)
4213 document.warning("Malformed LyX document: No real frame end!")
4215 val = get_value(document.body, "\\begin_layout", fend)
4216 if val not in frameend:
4219 # is this frame nested in an inset (e.g., Note)?
4220 if inInset != False:
4221 # if so, end the frame inside the inset
4222 if inInset[2] < fend:
4224 if val == frametype:
4225 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4226 # consider explicit EndFrames between two identical frame types
4227 elif val == "EndFrame":
4228 nextlayout = find_token(document.body, "\\begin_layout", fend + 1)
4229 if nextlayout != -1 and get_value(document.body, "\\begin_layout", nextlayout) == frametype:
4230 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4232 document.body[fend : fend] = ['\\end_deeper']
4234 document.body[fend : fend] = ['\\end_deeper']
4235 document.body[j + 1 : j + 1] = ['', '\\begin_deeper']
4240 def remove_endframes(document):
4241 " Remove deprecated beamer endframes "
4243 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4244 if document.textclass not in beamer_classes:
4249 i = find_token_exact(document.body, "\\begin_layout EndFrame", i)
4252 j = find_end_of_layout(document.body, i)
4254 document.warning("Malformed LyX document: Missing \\end_layout to EndFrame")
4257 del document.body[i : j + 1]
4260 def revert_powerdot_flexes(document):
4261 " Reverts powerdot flex insets "
4263 if document.textclass != "powerdot":
4266 flexes = {"Onslide" : "\\onslide",
4267 "Onslide*" : "\\onslide*",
4268 "Onslide+" : "\\onslide+"}
4269 rx = re.compile(r'^\\begin_inset Flex (.+)$')
4273 i = find_token(document.body, "\\begin_inset Flex", i)
4276 m = rx.match(document.body[i])
4278 flextype = m.group(1)
4279 z = find_end_of_inset(document.body, i)
4281 document.warning("Can't find end of Flex " + flextype + " inset.")
4284 if flextype in flexes:
4285 pre = put_cmd_in_ert(flexes[flextype])
4286 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
4288 argend = find_end_of_inset(document.body, arg)
4290 document.warning("Can't find end of Argument!")
4293 # Find containing paragraph layout
4294 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
4295 endPlain = find_end_of_layout(document.body, beginPlain)
4296 argcontent = document.body[beginPlain + 1 : endPlain]
4298 z = z - len(document.body[arg : argend + 1])
4300 del document.body[arg : argend + 1]
4301 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
4302 pre += put_cmd_in_ert("{")
4303 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4304 endPlain = find_end_of_layout(document.body, beginPlain)
4306 z = z - len(document.body[i : beginPlain + 1])
4308 document.body[i : beginPlain + 1] = pre
4309 post = put_cmd_in_ert("}")
4310 document.body[z - 2 : z + 1] = post
4314 def revert_powerdot_pause(document):
4315 " Reverts powerdot pause layout to ERT "
4317 if document.textclass != "powerdot":
4322 i = find_token(document.body, "\\begin_layout Pause", i)
4325 j = find_end_of_layout(document.body, i)
4327 document.warning("Malformed LyX document: Can't find end of Pause layout")
4331 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\pause")
4332 for p in range(i, j):
4335 arg = find_token(document.body, "\\begin_inset Argument 1", i, j)
4337 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4338 endPlain = find_end_of_layout(document.body, beginPlain)
4339 endInset = find_end_of_inset(document.body, p)
4340 content = document.body[beginPlain + 1 : endPlain]
4342 endlay = endlay - len(document.body[p : endInset + 1])
4344 del document.body[p : endInset + 1]
4345 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4347 document.body[i : i + 1] = subst
4351 def revert_powerdot_itemargs(document):
4352 " Reverts powerdot item arguments to ERT "
4354 if document.textclass != "powerdot":
4358 list_layouts = ["Itemize", "ItemizeType1", "Enumerate", "EnumerateType1"]
4359 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4362 i = find_token(document.body, "\\begin_inset Argument", i)
4365 # Find containing paragraph layout
4366 parent = get_containing_layout(document.body, i)
4368 document.warning("Malformed LyX document: Can't find parent paragraph layout")
4373 realparbeg = parent[3]
4374 layoutname = parent[0]
4376 for p in range(parbeg, parend):
4380 if layoutname in list_layouts:
4381 m = rx.match(document.body[p])
4384 if argnr == "item:1":
4385 j = find_end_of_inset(document.body, i)
4386 # Find containing paragraph layout
4387 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4388 endPlain = find_end_of_layout(document.body, beginPlain)
4389 content = document.body[beginPlain + 1 : endPlain]
4390 del document.body[i:j+1]
4391 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4392 document.body[realparbeg : realparbeg] = subst
4393 elif argnr == "item:2":
4394 j = find_end_of_inset(document.body, i)
4395 # Find containing paragraph layout
4396 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4397 endPlain = find_end_of_layout(document.body, beginPlain)
4398 content = document.body[beginPlain + 1 : endPlain]
4399 del document.body[i:j+1]
4400 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
4401 document.body[realparbeg : realparbeg] = subst
4406 def revert_powerdot_columns(document):
4407 " Reverts powerdot twocolumn to TeX-code "
4408 if document.textclass != "powerdot":
4411 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4414 i = find_token(document.body, "\\begin_layout Twocolumn", i)
4417 j = find_end_of_layout(document.body, i)
4419 document.warning("Malformed LyX document: Can't find end of Twocolumn layout")
4423 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
4424 endlay += len(put_cmd_in_ert("}"))
4425 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\twocolumn")
4426 for p in range(i, j):
4429 m = rx.match(document.body[p])
4433 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4434 endPlain = find_end_of_layout(document.body, beginPlain)
4435 endInset = find_end_of_inset(document.body, p)
4436 content = document.body[beginPlain + 1 : endPlain]
4438 endlay = endlay - len(document.body[p : endInset + 1])
4440 del document.body[p : endInset + 1]
4441 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4443 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4444 endPlain = find_end_of_layout(document.body, beginPlain)
4445 endInset = find_end_of_inset(document.body, p)
4446 content = document.body[beginPlain + 1 : endPlain]
4448 endlay = endlay - len(document.body[p : endInset + 1])
4450 del document.body[p : endInset + 1]
4451 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
4453 subst += put_cmd_in_ert("{")
4454 document.body[i : i + 1] = subst
4458 def revert_mbox_fbox(document):
4459 'Convert revert mbox/fbox boxes to TeX-code'
4462 i = find_token(document.body, "\\begin_inset Box", i)
4465 j = find_token(document.body, "width", i)
4467 document.warning("Malformed LyX document: Can't find box width")
4469 width = get_value(document.body, "width", j)
4470 k = find_end_of_inset(document.body, j)
4472 document.warning("Malformed LyX document: Can't find end of box inset")
4475 BeginLayout = find_token(document.body, "\\begin_layout Plain Layout", j)
4476 EndLayout = find_end_of_layout(document.body, BeginLayout)
4477 # replace if width is ""
4479 document.body[EndLayout:k + 1] = put_cmd_in_ert("}")
4480 if document.body[i] == "\\begin_inset Box Frameless":
4481 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\mbox{")
4482 if document.body[i] == "\\begin_inset Box Boxed":
4483 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\fbox{")
4487 def revert_starred_caption(document):
4488 " Reverts unnumbered longtable caption insets "
4492 i = find_token(document.body, "\\begin_inset Caption LongTableNoNumber", i)
4495 # This is not equivalent, but since the caption inset is a full blown
4496 # text inset a true conversion to ERT is too difficult.
4497 document.body[i] = "\\begin_inset Caption Standard"
4501 def revert_forced_local_layout(document):
4504 i = find_token(document.header, "\\begin_forced_local_layout", i)
4507 j = find_end_of(document.header, i, "\\begin_forced_local_layout", "\\end_forced_local_layout")
4509 # this should not happen
4511 regexp = re.compile(r'\s*forcelocal', re.IGNORECASE)
4512 k = find_re(document.header, regexp, i, j)
4514 del document.header[k]
4516 k = find_re(document.header, regexp, i, j)
4517 k = find_token(document.header, "\\begin_local_layout", 0)
4519 document.header[i] = "\\begin_local_layout"
4520 document.header[j] = "\\end_local_layout"
4522 l = find_end_of(document.header, k, "\\begin_local_layout", "\\end_local_layout")
4524 # this should not happen
4526 lines = document.header[i+1 : j]
4528 document.header[k+1 : k+1] = lines
4529 document.header[i : j ] = []
4531 document.header[i : j ] = []
4532 document.header[k+1 : k+1] = lines
4535 def revert_aa1(document):
4536 " Reverts InsetArguments of aa to TeX-code "
4537 if document.textclass == "aa":
4541 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4543 revert_Argument_to_TeX_brace(document, i, 0, 1, 4, False, False)
4549 def revert_aa2(document):
4550 " Reverts InsetArguments of aa to TeX-code "
4551 if document.textclass == "aa":
4555 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4557 document.body[i] = "\\begin_layout Abstract"
4563 def revert_tibetan(document):
4564 "Set the document language for Tibetan to English"
4566 if document.language == "tibetan":
4567 document.language = "english"
4568 i = find_token(document.header, "\\language", 0)
4570 document.header[i] = "\\language english"
4572 while j < len(document.body):
4573 j = find_token(document.body, "\\lang tibetan", j)
4575 document.body[j] = document.body[j].replace("\\lang tibetan", "\\lang english")
4578 j = len(document.body)
4587 # The idea here is that we will have a sequence of chunk paragraphs.
4588 # We want to convert them to paragraphs in one or several chunk insets.
4589 # Individual chunks are terminated by the character @ on the last line.
4590 # This line will be discarded, and following lines are treated as new
4591 # chunks, which go into their own insets.
4592 # The first line of a chunk should look like: <<CONTENT>>=
4593 # We will discard the delimiters, and put the CONTENT into the
4594 # optional argument of the inset, if the CONTENT is non-empty.
4595 def convert_chunks(document):
4596 first_re = re.compile(r'<<(.*)>>=(.*)')
4599 # find start of a block of chunks
4600 i = find_token(document.body, "\\begin_layout Chunk", file_pos)
4606 chunk_started = False
4609 # process the one we just found
4610 j = find_end_of_layout(document.body, i)
4612 document.warning("Malformed LyX documents. Can't find end of Chunk layout!")
4613 # there is no point continuing, as we will run into the same error again.
4615 this_chunk = "".join(document.body[i + 1:j])
4617 # there may be empty lines between chunks
4618 # we just skip them.
4619 if not chunk_started:
4620 if this_chunk != "":
4622 chunk_started = True
4625 contents.append(document.body[i + 1:j])
4627 # look for potential chunk terminator
4628 # on the last line of the chunk paragraph
4629 if document.body[j - 1] == "@":
4632 # look for subsequent chunk paragraph
4633 i = find_token(document.body, "\\begin_layout", j)
4637 if get_value(document.body, "\\begin_layout", i) != "Chunk":
4640 file_pos = end = j + 1
4642 # The last chunk should simply have an "@" in it
4643 # or at least end with "@" (can happen if @ is
4644 # preceded by a newline)
4646 if len(contents) > 0:
4647 lastpar = ''.join(contents[-1])
4648 if not lastpar.endswith("@"):
4649 document.warning("Unexpected chunk content: chunk not terminated by '@'!")
4650 if len(contents) == 0:
4651 # convert empty chunk layouts to Standard
4652 document.body[start] = "\\begin_layout Standard"
4656 # chunk par only contains "@". Just drop it.
4659 # chunk par contains more. Only drop the "@".
4662 # The first line should look like: <<CONTENT>>=
4663 # We want the CONTENT
4664 optarg = ' '.join(contents[0])
4666 # We can already have real chunk content in
4667 # the first par (separated from the options by a newline).
4668 # We collect such stuff to re-insert it later.
4671 match = first_re.search(optarg)
4673 optarg = match.groups()[0]
4674 if match.groups()[1] != "":
4676 for c in contents[0]:
4677 if c.endswith(">>="):
4681 postoptstuff.append(c)
4682 # We have stripped everything. This can be deleted.
4685 newstuff = ['\\begin_layout Standard']
4687 # Maintain paragraph parameters
4688 par_params = ["\\noindent", "\\indent", "\\indent-toggle", "\\leftindent",
4689 "\\start_of_appendix", "\\paragraph_spacing", "\\align",
4690 "\\labelwidthstring"]
4693 if document.body[parms].split(' ', 1)[0] not in par_params:
4695 newstuff.extend([document.body[parms]])
4699 ['\\begin_inset Flex Chunk',
4701 '\\begin_layout Plain Layout', ''])
4703 # If we have a non-empty optional argument, insert it.
4704 if match and optarg != "":
4706 ['\\begin_inset Argument 1',
4708 '\\begin_layout Plain Layout',
4713 # Since we already opened a Plain layout, the first paragraph
4714 # does not need to do that.
4717 # we need to replace newlines with new layouts
4719 started_text = False
4720 for lno in range(0,len(postoptstuff)):
4721 if postoptstuff[lno].startswith("\\begin_inset Newline newline"):
4723 elif start_newline != -1:
4724 if postoptstuff[lno].startswith("\\end_inset"):
4725 # replace that bit, but only if we already have some text
4726 # and we're not at the end except for a blank line
4727 if started_text and \
4728 (lno != len(postoptstuff) - 2 or postoptstuff[-1] != ""):
4729 newstuff.extend(['\\end_layout', '\n', '\\begin_layout Plain Layout', '\n'])
4733 newstuff.extend([postoptstuff[lno]])
4734 newstuff.append('\\end_layout')
4738 newstuff.extend(['', '\\begin_layout Plain Layout', ''])
4742 newstuff.append('\\end_layout')
4744 newstuff.extend(['', '\\end_inset', '', '\\end_layout', ''])
4746 document.body[start:end] = newstuff
4748 file_pos += len(newstuff) - (end - start)
4751 def revert_chunks(document):
4754 i = find_token(document.body, "\\begin_inset Flex Chunk", i)
4758 iend = find_end_of_inset(document.body, i)
4760 document.warning("Can't find end of Chunk!")
4764 # Look for optional argument
4766 ostart = find_token(document.body, "\\begin_inset Argument 1", i, iend)
4768 oend = find_end_of_inset(document.body, ostart)
4769 k = find_token(document.body, "\\begin_layout Plain Layout", ostart, oend)
4771 document.warning("Malformed LyX document: Can't find argument contents!")
4773 m = find_end_of_layout(document.body, k)
4774 optarg = "".join(document.body[k+1:m])
4776 # We now remove the optional argument, so we have something
4777 # uniform on which to work
4778 document.body[ostart : oend + 1] = []
4779 # iend is now invalid
4780 iend = find_end_of_inset(document.body, i)
4782 retval = get_containing_layout(document.body, i)
4784 document.warning("Can't find containing layout for Chunk!")
4787 (lname, lstart, lend, pstart) = retval
4788 # we now want to work through the various paragraphs, and collect their contents
4792 k = find_token(document.body, "\\begin_layout Plain Layout", k, lend)
4795 j = find_end_of_layout(document.body, k)
4797 document.warning("Can't find end of layout inside chunk!")
4799 parlist.append(document.body[k+1:j])
4801 # we now need to wrap all of these paragraphs in chunks
4803 newlines.extend(["\\begin_layout Chunk", "", "<<" + optarg + ">>=", "\\end_layout", ""])
4804 for stuff in parlist:
4805 newlines.extend(["\\begin_layout Chunk"] + stuff + ["\\end_layout", ""])
4806 newlines.extend(["\\begin_layout Chunk", "", "@", "\\end_layout", ""])
4807 # replace old content with new content
4808 document.body[lstart : lend + 1] = newlines
4809 i = lstart + len(newlines)
4816 supported_versions = ["2.1.0","2.1"]
4819 [415, [convert_undertilde]],
4821 [417, [convert_japanese_encodings]],
4822 [418, [convert_justification]],
4824 [420, [convert_biblio_style]],
4825 [421, [convert_longtable_captions]],
4826 [422, [convert_use_packages]],
4827 [423, [convert_use_mathtools]],
4828 [424, [convert_cite_engine_type]],
4829 # No convert_cancel, since cancel will be loaded automatically
4830 # in format 425 without any possibility to switch it off.
4831 # This has been fixed in format 464.
4835 [428, [convert_cell_rotation]],
4836 [429, [convert_table_rotation]],
4837 [430, [convert_listoflistings]],
4838 [431, [convert_use_amssymb]],
4840 [433, [convert_armenian]],
4847 [440, [convert_mathfonts]],
4848 [441, [convert_mdnomath]],
4853 [446, [convert_latexargs]],
4854 [447, [convert_IEEEtran, convert_AASTeX, convert_AGUTeX, convert_IJMP, convert_SIGPLAN, convert_SIGGRAPH, convert_EuropeCV, convert_Initials, convert_ModernCV]],
4855 [448, [convert_literate]],
4858 [451, [convert_beamerargs, convert_againframe_args, convert_corollary_args, convert_quote_args]],
4859 [452, [convert_beamerblocks]],
4860 [453, [convert_use_stmaryrd]],
4861 [454, [convert_overprint]],
4863 [456, [convert_epigraph]],
4864 [457, [convert_use_stackrel]],
4865 [458, [convert_captioninsets, convert_captionlayouts]],
4870 [463, [convert_encodings]],
4871 [464, [convert_use_cancel]],
4872 [465, [convert_lyxframes, remove_endframes]],
4878 [471, [convert_cite_engine_type_default]],
4881 [474, [convert_chunks, cleanup_beamerargs]],
4885 [473, [revert_chunks]],
4886 [472, [revert_tibetan]],
4887 [471, [revert_aa1,revert_aa2]],
4888 [470, [revert_cite_engine_type_default]],
4889 [469, [revert_forced_local_layout]],
4890 [468, [revert_starred_caption]],
4891 [467, [revert_mbox_fbox]],
4892 [466, [revert_iwona_fonts]],
4893 [465, [revert_powerdot_flexes, revert_powerdot_pause, revert_powerdot_itemargs, revert_powerdot_columns]],
4895 [463, [revert_use_cancel]],
4896 [462, [revert_encodings]],
4897 [461, [revert_new_libertines]],
4898 [460, [revert_kurier_fonts]],
4899 [459, [revert_IEEEtran_3]],
4900 [458, [revert_fragileframe, revert_newframes]],
4901 [457, [revert_captioninsets, revert_captionlayouts]],
4902 [456, [revert_use_stackrel]],
4903 [455, [revert_epigraph]],
4904 [454, [revert_frametitle]],
4905 [453, [revert_overprint]],
4906 [452, [revert_use_stmaryrd]],
4907 [451, [revert_beamerblocks]],
4908 [450, [revert_beamerargs, revert_beamerargs2, revert_beamerargs3, revert_beamerflex]],
4909 [449, [revert_garamondx, revert_garamondx_newtxmath]],
4910 [448, [revert_itemargs]],
4911 [447, [revert_literate]],
4912 [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]],
4913 [445, [revert_latexargs]],
4914 [444, [revert_uop]],
4915 [443, [revert_biolinum]],
4917 [441, [revert_newtxmath]],
4918 [440, [revert_mdnomath]],
4919 [439, [revert_mathfonts]],
4920 [438, [revert_minionpro]],
4921 [437, [revert_ipadeco, revert_ipachar]],
4922 [436, [revert_texgyre]],
4923 [435, [revert_mathdesign]],
4924 [434, [revert_txtt]],
4925 [433, [revert_libertine]],
4926 [432, [revert_armenian]],
4927 [431, [revert_languages, revert_ancientgreek]],
4928 [430, [revert_use_amssymb]],
4929 [429, [revert_listoflistings]],
4930 [428, [revert_table_rotation]],
4931 [427, [revert_cell_rotation]],
4932 [426, [revert_tipa]],
4933 [425, [revert_verbatim]],
4934 [424, [revert_cancel]],
4935 [423, [revert_cite_engine_type]],
4936 [422, [revert_use_mathtools]],
4937 [421, [revert_use_packages]],
4938 [420, [revert_longtable_captions]],
4939 [419, [revert_biblio_style]],
4940 [418, [revert_australian]],
4941 [417, [revert_justification]],
4942 [416, [revert_japanese_encodings]],
4943 [415, [revert_negative_space, revert_math_spaces]],
4944 [414, [revert_undertilde]],
4945 [413, [revert_visible_space]]
4949 if __name__ == "__main__":