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], 'endhead') == 'true':
560 document.body[begin_row] = set_option_value(document.body[begin_row], 'endhead', 'false')
561 if get_option_value(document.body[begin_row], 'endfoot') == 'true':
562 document.body[begin_row] = set_option_value(document.body[begin_row], 'endfoot', 'false')
563 if get_option_value(document.body[begin_row], 'endlastfoot') == 'true':
564 document.body[begin_row] = set_option_value(document.body[begin_row], 'endlastfoot', 'false')
566 # since there could be a tabular inside this one, we
567 # cannot jump to end.
571 def convert_longtable_captions(document):
572 "Add a firsthead flag to caption rows"
573 handle_longtable_captions(document, True)
576 def revert_longtable_captions(document):
577 "remove head/foot flag from caption rows"
578 handle_longtable_captions(document, False)
581 def convert_use_packages(document):
582 "use_xxx yyy => use_package xxx yyy"
583 packages = ["amsmath", "esint", "mathdots", "mhchem", "undertilde"]
585 i = find_token(document.header, "\\use_%s" % p, 0)
587 value = get_value(document.header, "\\use_%s" % p, i)
588 document.header[i] = "\\use_package %s %s" % (p, value)
591 def revert_use_packages(document):
592 "use_package xxx yyy => use_xxx yyy"
593 packages = ["amsmath", "esint", "mhchem", "mathdots", "undertilde"]
594 # the order is arbitrary for the use_package version, and not all packages need to be given.
595 # Ensure a complete list and correct order (important for older LyX versions and especially lyx2lyx)
596 # first loop: find line with first package
599 regexp = re.compile(r'(\\use_package\s+%s)' % p)
600 i = find_re(document.header, regexp, 0)
601 if i != -1 and (j < 0 or i < j):
603 # second loop: replace or insert packages in front of all existing ones
605 regexp = re.compile(r'(\\use_package\s+%s)' % p)
606 i = find_re(document.header, regexp, 0)
608 value = get_value(document.header, "\\use_package %s" % p, i).split()[1]
609 del document.header[i]
610 document.header.insert(j, "\\use_%s %s" % (p, value))
612 document.header.insert(j, "\\use_%s 1" % p)
616 def convert_use_package(document, pkg, commands, oldauto):
617 # oldauto defines how the version we are converting from behaves:
618 # if it is true, the old version uses the package automatically.
619 # if it is false, the old version never uses the package.
620 i = find_token(document.header, "\\use_package")
622 document.warning("Malformed LyX document: Can't find \\use_package.")
624 packageline = "\\usepackage{%s}" % pkg
625 if (del_complete_lines(document.preamble,
626 ['% Added by lyx2lyx', packageline]) or
627 del_complete_lines(document.preamble, [packageline])):
628 # package was loaded in the preamble, convert this to header setting
629 document.header.insert(i + 1, "\\use_package " + pkg + " 2") # on
630 # If oldauto is true we have two options:
631 # We can either set the package to auto - this is correct for files in
632 # format 425 to 463, and may create a conflict for older files which use
633 # any command in commands with a different definition.
634 # Or we can look whether any command in commands is used, and set it to
635 # auto if not and to off if yes. This will not create a conflict, but will
636 # create uncompilable documents for files in format 425 to 463, which use
637 # any command in commands.
638 # We choose the first option since its error is less likely.
640 document.header.insert(i + 1, "\\use_package " + pkg + " 1") # auto
644 j = find_token(document.body, '\\begin_inset Formula', j)
647 k = find_end_of_inset(document.body, j)
649 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(j))
652 code = "\n".join(document.body[j:k])
654 if code.find("\\%s" % c) != -1:
655 # at least one of the commands was found - need to switch package off
656 document.header.insert(i + 1, "\\use_package " + pkg + " 0") # off
659 # no command was found - set to auto (bug 9069)
660 document.header.insert(i + 1, "\\use_package " + pkg + " 1") # auto
663 def revert_use_package(document, pkg, commands, oldauto):
664 # oldauto defines how the version we are reverting to behaves:
665 # if it is true, the old version uses the package automatically.
666 # if it is false, the old version never uses the package.
667 regexp = re.compile(r'(\\use_package\s+%s)' % pkg)
668 i = find_re(document.header, regexp, 0)
669 value = "1" # default is auto
671 value = get_value(document.header, "\\use_package" , i).split()[1]
672 del document.header[i]
673 if value == "2": # on
674 add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
675 elif value == "1" and not oldauto: # auto
678 i = find_token(document.body, '\\begin_inset Formula', i)
681 j = find_end_of_inset(document.body, i)
683 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
686 code = "\n".join(document.body[i:j])
688 if code.find("\\%s" % c) != -1:
689 add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
694 mathtools_commands = ["mathclap", "mathllap", "mathrlap", \
695 "lgathered", "rgathered", "vcentcolon", "dblcolon", \
696 "coloneqq", "Coloneqq", "coloneq", "Coloneq", "eqqcolon", \
697 "Eqqcolon", "eqcolon", "Eqcolon", "colonapprox", \
698 "Colonapprox", "colonsim", "Colonsim"]
699 def convert_use_mathtools(document):
700 "insert use_package mathtools"
701 convert_use_package(document, "mathtools", mathtools_commands, False)
704 def revert_use_mathtools(document):
705 "remove use_package mathtools"
706 revert_use_package(document, "mathtools", mathtools_commands, False)
709 # commands provided by stmaryrd.sty but LyX uses other packages:
710 # boxdot lightning, bigtriangledown, bigtriangleup
711 stmaryrd_commands = ["shortleftarrow", "shortrightarrow", "shortuparrow", \
712 "shortdownarrow", "Yup", "Ydown", "Yleft", "Yright", \
713 "varcurlyvee", "varcurlywedge", "minuso", "baro", \
714 "sslash", "bbslash", "moo", "varotimes", "varoast", \
715 "varobar", "varodot", "varoslash", "varobslash", \
716 "varocircle", "varoplus", "varominus", "boxast", \
717 "boxbar", "boxslash", "boxbslash", "boxcircle", \
718 "boxbox", "boxempty", "merge", "vartimes", \
719 "fatsemi", "sswarrow", "ssearrow", "curlywedgeuparrow", \
720 "curlywedgedownarrow", "fatslash", "fatbslash", "lbag", \
721 "rbag", "varbigcirc", "leftrightarroweq", \
722 "curlyveedownarrow", "curlyveeuparrow", "nnwarrow", \
723 "nnearrow", "leftslice", "rightslice", "varolessthan", \
724 "varogreaterthan", "varovee", "varowedge", "talloblong", \
725 "interleave", "obar", "obslash", "olessthan", \
726 "ogreaterthan", "ovee", "owedge", "oblong", "inplus", \
727 "niplus", "nplus", "subsetplus", "supsetplus", \
728 "subsetpluseq", "supsetpluseq", "Lbag", "Rbag", \
729 "llbracket", "rrbracket", "llparenthesis", \
730 "rrparenthesis", "binampersand", "bindnasrepma", \
731 "trianglelefteqslant", "trianglerighteqslant", \
732 "ntrianglelefteqslant", "ntrianglerighteqslant", \
733 "llfloor", "rrfloor", "llceil", "rrceil", "arrownot", \
734 "Arrownot", "Mapstochar", "mapsfromchar", "Mapsfromchar", \
735 "leftrightarrowtriangle", "leftarrowtriangle", \
736 "rightarrowtriangle", \
737 "bigcurlyvee", "bigcurlywedge", "bigsqcap", "bigbox", \
738 "bigparallel", "biginterleave", "bignplus", \
739 "varcopyright", "longarrownot", "Longarrownot", \
740 "Mapsto", "mapsfrom", "Mapsfrom" "Longmapsto", \
741 "longmapsfrom", "Longmapsfrom"]
742 def convert_use_stmaryrd(document):
743 "insert use_package stmaryrd"
744 convert_use_package(document, "stmaryrd", stmaryrd_commands, False)
747 def revert_use_stmaryrd(document):
748 "remove use_package stmaryrd"
749 revert_use_package(document, "stmaryrd", stmaryrd_commands, False)
752 stackrel_commands = ["stackrel"]
753 def convert_use_stackrel(document):
754 "insert use_package stackrel"
755 convert_use_package(document, "stackrel", stackrel_commands, False)
758 def revert_use_stackrel(document):
759 "remove use_package stackrel"
760 revert_use_package(document, "stackrel", stackrel_commands, False)
763 def convert_cite_engine_type(document):
764 "Determine the \\cite_engine_type from the citation engine."
765 i = find_token(document.header, "\\cite_engine", 0)
768 engine = get_value(document.header, "\\cite_engine", i)
770 engine, type = engine.split("_")
772 type = {"basic": "numerical", "jurabib": "authoryear"}[engine]
773 document.header[i] = "\\cite_engine " + engine
774 document.header.insert(i + 1, "\\cite_engine_type " + type)
777 def revert_cite_engine_type(document):
778 "Natbib had the type appended with an underscore."
779 engine_type = "numerical"
780 i = find_token(document.header, "\\cite_engine_type" , 0)
782 document.warning("No \\cite_engine_type line. Assuming numerical.")
784 engine_type = get_value(document.header, "\\cite_engine_type", i)
785 del document.header[i]
787 # We are looking for the natbib citation engine
788 i = find_token(document.header, "\\cite_engine natbib", 0)
791 document.header[i] = "\\cite_engine natbib_" + engine_type
794 def convert_cite_engine_type_default(document):
795 "Convert \\cite_engine_type to default for the basic citation engine."
796 i = find_token(document.header, "\\cite_engine basic", 0)
799 i = find_token(document.header, "\\cite_engine_type" , 0)
802 document.header[i] = "\\cite_engine_type default"
805 def revert_cite_engine_type_default(document):
806 """Revert \\cite_engine_type default.
808 Revert to numerical for the basic cite engine, otherwise to authoryear."""
809 engine_type = "authoryear"
810 i = find_token(document.header, "\\cite_engine_type default" , 0)
813 j = find_token(document.header, "\\cite_engine basic", 0)
815 engine_type = "numerical"
816 document.header[i] = "\\cite_engine_type " + engine_type
819 cancel_commands = ["cancel", "bcancel", "xcancel", "cancelto"]
820 # this is the same, as revert_use_cancel() except for the default
821 def revert_cancel(document):
822 "add cancel to the preamble if necessary"
823 revert_use_package(document, "cancel", cancel_commands, False)
826 def revert_verbatim(document, starred = False):
827 " Revert verbatim environments completely to TeX-code. "
831 layout_name = "Verbatim"
832 latex_name = "verbatim"
834 layout_name = "Verbatim*"
835 latex_name = "verbatim*"
837 subst_end = ['\\end_layout', '', '\\begin_layout Plain Layout',
839 '\\begin_layout Plain Layout', '', '',
841 'end{%s}' % (latex_name),
842 '\\end_layout', '', '\\end_inset',
843 '', '', '\\end_layout']
844 subst_begin = ['\\begin_layout Standard', '\\noindent',
845 '\\begin_inset ERT', 'status open', '',
846 '\\begin_layout Plain Layout', '', '', '\\backslash',
847 'begin{%s}' % (latex_name),
848 '\\end_layout', '', '\\begin_layout Plain Layout', '']
851 i = find_token(document.body, "\\begin_layout %s" % (layout_name), i)
854 j = find_end_of_layout(document.body, i)
856 document.warning("Malformed LyX document: Can't find end of %s layout" \
860 # delete all line breaks insets (there are no other insets)
863 n = find_token(document.body, "\\begin_inset Newline newline", l, j)
865 n = find_token(document.body, "\\begin_inset Newline linebreak", l, j)
868 m = find_end_of_inset(document.body, n)
869 del(document.body[m:m+1])
870 document.body[n:n+1] = ['\\end_layout', '', '\\begin_layout Plain Layout']
872 # we deleted a line, so the end of the inset moved forward.
873 # FIXME But we also added some lines, didn't we? I think this
876 # consecutive verbatim environments need to be connected
877 k = find_token(document.body, "\\begin_layout %s" % (layout_name), j)
878 if k == j + 2 and consecutive == False:
880 document.body[j:j+1] = ['\\end_layout', '', '\\begin_layout Plain Layout']
881 document.body[i:i+1] = subst_begin
883 if k == j + 2 and consecutive == True:
884 document.body[j:j+1] = ['\\end_layout', '', '\\begin_layout Plain Layout']
885 del(document.body[i:i+1])
887 if k != j + 2 and consecutive == True:
888 document.body[j:j+1] = subst_end
889 # the next paragraph must not be indented
890 # FIXME This seems to be causing problems, because of the
891 # hardcoded use of 19. We should figure out exactly where
892 # this needs to go by searching for the right tag.
893 document.body[j+19:j+19] = ['\\noindent']
894 del(document.body[i:i+1])
898 document.body[j:j+1] = subst_end
899 # the next paragraph must not be indented
900 # FIXME This seems to be causing problems, because of the
901 # hardcoded use of 19. We should figure out exactly where
902 # this needs to go by searching for the right tag.
903 document.body[j+19:j+19] = ['\\noindent']
904 document.body[i:i+1] = subst_begin
907 def revert_tipa(document):
908 " Revert native TIPA insets to mathed or ERT. "
911 i = find_token(document.body, "\\begin_inset IPA", i)
914 j = find_end_of_inset(document.body, i)
916 document.warning("Malformed LyX document: Can't find end of IPA inset")
920 n = find_token(document.body, "\\begin_layout", i, j)
922 document.warning("Malformed LyX document: IPA inset has no embedded layout")
925 m = find_end_of_layout(document.body, n)
927 document.warning("Malformed LyX document: Can't find end of embedded layout")
930 content = document.body[n+1:m]
931 p = find_token(document.body, "\\begin_layout", m, j)
932 if p != -1 or len(content) > 1:
934 content = document.body[i+1:j]
936 # IPA insets with multiple pars need to be wrapped by \begin{IPA}...\end{IPA}
937 document.body[i:j+1] = ['\\end_layout', '', '\\begin_layout Standard'] + put_cmd_in_ert("\\begin{IPA}") + ['\\end_layout'] + content + ['\\begin_layout Standard'] + put_cmd_in_ert("\\end{IPA}")
938 add_to_preamble(document, ["\\usepackage{tipa,tipx}"])
940 # single-par IPA insets can be reverted to mathed
941 document.body[i:j+1] = ["\\begin_inset Formula $\\text{\\textipa{" + content[0] + "}}$", "\\end_inset"]
945 def revert_cell_rotation(document):
946 "Revert cell rotations to TeX-code"
948 load_rotating = False
952 # first, let's find out if we need to do anything
953 i = find_token(document.body, '<cell ', i)
956 j = document.body[i].find('rotate="')
958 k = document.body[i].find('"', j + 8)
959 value = document.body[i][j + 8 : k]
961 rgx = re.compile(r' rotate="[^"]+?"')
962 # remove rotate option
963 document.body[i] = rgx.sub('', document.body[i])
965 rgx = re.compile(r' rotate="[^"]+?"')
966 document.body[i] = rgx.sub(' rotate="true"', document.body[i])
968 rgx = re.compile(r' rotate="[^"]+?"')
970 # remove rotate option
971 document.body[i] = rgx.sub('', document.body[i])
973 document.body[i + 5 : i + 5] = \
974 put_cmd_in_ert("\\end{turn}")
975 document.body[i + 4 : i + 4] = \
976 put_cmd_in_ert("\\begin{turn}{" + value + "}")
982 add_to_preamble(document, ["\\@ifundefined{turnbox}{\\usepackage{rotating}}{}"])
985 def convert_cell_rotation(document):
986 'Convert cell rotation statements from "true" to "90"'
990 # first, let's find out if we need to do anything
991 i = find_token(document.body, '<cell ', i)
994 j = document.body[i].find('rotate="true"')
996 rgx = re.compile(r'rotate="[^"]+?"')
997 # convert "true" to "90"
998 document.body[i] = rgx.sub('rotate="90"', document.body[i])
1003 def revert_table_rotation(document):
1004 "Revert table rotations to TeX-code"
1006 load_rotating = False
1010 # first, let's find out if we need to do anything
1011 i = find_token(document.body, '<features ', i)
1014 j = document.body[i].find('rotate="')
1016 end_table = find_token(document.body, '</lyxtabular>', j)
1017 k = document.body[i].find('"', j + 8)
1018 value = document.body[i][j + 8 : k]
1020 rgx = re.compile(r' rotate="[^"]+?"')
1021 # remove rotate option
1022 document.body[i] = rgx.sub('', document.body[i])
1024 rgx = re.compile(r'rotate="[^"]+?"')
1025 document.body[i] = rgx.sub('rotate="true"', document.body[i])
1027 rgx = re.compile(r' rotate="[^"]+?"')
1028 load_rotating = True
1029 # remove rotate option
1030 document.body[i] = rgx.sub('', document.body[i])
1032 document.body[end_table + 3 : end_table + 3] = \
1033 put_cmd_in_ert("\\end{turn}")
1034 document.body[i - 2 : i - 2] = \
1035 put_cmd_in_ert("\\begin{turn}{" + value + "}")
1041 add_to_preamble(document, ["\\@ifundefined{turnbox}{\\usepackage{rotating}}{}"])
1044 def convert_table_rotation(document):
1045 'Convert table rotation statements from "true" to "90"'
1049 # first, let's find out if we need to do anything
1050 i = find_token(document.body, '<features ', i)
1053 j = document.body[i].find('rotate="true"')
1055 rgx = re.compile(r'rotate="[^"]+?"')
1056 # convert "true" to "90"
1057 document.body[i] = rgx.sub('rotate="90"', document.body[i])
1062 def convert_listoflistings(document):
1063 'Convert ERT \lstlistoflistings to TOC lstlistoflistings inset'
1064 # We can support roundtrip because the command is so simple
1067 i = find_token(document.body, "\\begin_inset ERT", i)
1070 j = find_end_of_inset(document.body, i)
1072 document.warning("Malformed LyX document: Can't find end of ERT inset")
1075 ert = get_ert(document.body, i)
1076 if ert == "\\lstlistoflistings{}":
1077 document.body[i:j] = ["\\begin_inset CommandInset toc", "LatexCommand lstlistoflistings", ""]
1083 def revert_listoflistings(document):
1084 'Convert TOC lstlistoflistings inset to ERT lstlistoflistings'
1087 i = find_token(document.body, "\\begin_inset CommandInset toc", i)
1090 if document.body[i+1] == "LatexCommand lstlistoflistings":
1091 j = find_end_of_inset(document.body, i)
1093 document.warning("Malformed LyX document: Can't find end of TOC inset")
1096 subst = put_cmd_in_ert("\\lstlistoflistings{}")
1097 document.body[i:j+1] = subst
1098 add_to_preamble(document, ["\\usepackage{listings}"])
1102 def convert_use_amssymb(document):
1103 "insert use_package amssymb"
1104 regexp = re.compile(r'(\\use_package\s+amsmath)')
1105 i = find_re(document.header, regexp, 0)
1107 document.warning("Malformed LyX document: Can't find \\use_package amsmath.")
1109 value = get_value(document.header, "\\use_package" , i).split()[1]
1112 useamsmath = int(value)
1114 document.warning("Invalid \\use_package amsmath: " + value + ". Assuming auto.")
1116 j = find_token(document.preamble, "\\usepackage{amssymb}", 0)
1118 document.header.insert(i + 1, "\\use_package amssymb %d" % useamsmath)
1120 document.header.insert(i + 1, "\\use_package amssymb 2")
1121 del document.preamble[j]
1124 def revert_use_amssymb(document):
1125 "remove use_package amssymb"
1126 regexp1 = re.compile(r'(\\use_package\s+amsmath)')
1127 regexp2 = re.compile(r'(\\use_package\s+amssymb)')
1128 i = find_re(document.header, regexp1, 0)
1129 j = find_re(document.header, regexp2, 0)
1130 value1 = "1" # default is auto
1131 value2 = "1" # default is auto
1133 value1 = get_value(document.header, "\\use_package" , i).split()[1]
1135 value2 = get_value(document.header, "\\use_package" , j).split()[1]
1136 del document.header[j]
1137 if value1 != value2 and value2 == "2": # on
1138 add_to_preamble(document, ["\\usepackage{amssymb}"])
1141 def convert_use_cancel(document):
1142 "insert use_package cancel"
1143 convert_use_package(document, "cancel", cancel_commands, True)
1146 def revert_use_cancel(document):
1147 "remove use_package cancel"
1148 revert_use_package(document, "cancel", cancel_commands, True)
1151 def revert_ancientgreek(document):
1152 "Set the document language for ancientgreek to greek"
1154 if document.language == "ancientgreek":
1155 document.language = "greek"
1156 i = find_token(document.header, "\\language", 0)
1158 document.header[i] = "\\language greek"
1161 j = find_token(document.body, "\\lang ancientgreek", j)
1165 document.body[j] = document.body[j].replace("\\lang ancientgreek", "\\lang greek")
1169 def revert_languages(document):
1170 "Set the document language for new supported languages to English"
1173 "coptic", "divehi", "hindi", "kurmanji", "lao", "marathi", "occitan", "sanskrit",
1174 "syriac", "tamil", "telugu", "urdu"
1176 for n in range(len(languages)):
1177 if document.language == languages[n]:
1178 document.language = "english"
1179 i = find_token(document.header, "\\language", 0)
1181 document.header[i] = "\\language english"
1183 while j < len(document.body):
1184 j = find_token(document.body, "\\lang " + languages[n], j)
1186 document.body[j] = document.body[j].replace("\\lang " + languages[n], "\\lang english")
1189 j = len(document.body)
1192 def convert_armenian(document):
1193 "Use polyglossia and thus non-TeX fonts for Armenian"
1195 if document.language == "armenian":
1196 i = find_token(document.header, "\\use_non_tex_fonts", 0)
1198 document.header[i] = "\\use_non_tex_fonts true"
1201 def revert_armenian(document):
1202 "Use ArmTeX and thus TeX fonts for Armenian"
1204 if document.language == "armenian":
1205 i = find_token(document.header, "\\use_non_tex_fonts", 0)
1207 document.header[i] = "\\use_non_tex_fonts false"
1210 def revert_libertine(document):
1211 " Revert native libertine font definition to LaTeX "
1213 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1214 i = find_token(document.header, "\\font_roman libertine", 0)
1217 j = find_token(document.header, "\\font_osf true", 0)
1220 preamble = "\\usepackage"
1222 document.header[j] = "\\font_osf false"
1225 preamble += "[lining]"
1226 preamble += "{libertine-type1}"
1227 add_to_preamble(document, [preamble])
1228 document.header[i] = "\\font_roman default"
1231 def revert_txtt(document):
1232 " Revert native txtt font definition to LaTeX "
1234 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1235 i = find_token(document.header, "\\font_typewriter txtt", 0)
1237 preamble = "\\renewcommand{\\ttdefault}{txtt}"
1238 add_to_preamble(document, [preamble])
1239 document.header[i] = "\\font_typewriter default"
1242 def revert_mathdesign(document):
1243 " Revert native mathdesign font definition to LaTeX "
1245 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1251 i = find_token(document.header, "\\font_roman", 0)
1254 val = get_value(document.header, "\\font_roman", i)
1255 if val in list(mathdesign_dict.keys()):
1256 preamble = "\\usepackage[%s" % mathdesign_dict[val]
1258 j = find_token(document.header, "\\font_osf true", 0)
1261 document.header[j] = "\\font_osf false"
1262 l = find_token(document.header, "\\font_sc true", 0)
1265 document.header[l] = "\\font_sc false"
1267 preamble += ",expert"
1268 preamble += "]{mathdesign}"
1269 add_to_preamble(document, [preamble])
1270 document.header[i] = "\\font_roman default"
1273 def revert_texgyre(document):
1274 " Revert native TeXGyre font definition to LaTeX "
1276 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1277 texgyre_fonts = ["tgadventor", "tgbonum", "tgchorus", "tgcursor", \
1278 "tgheros", "tgpagella", "tgschola", "tgtermes"]
1279 i = find_token(document.header, "\\font_roman", 0)
1281 val = get_value(document.header, "\\font_roman", i)
1282 if val in texgyre_fonts:
1283 preamble = "\\usepackage{%s}" % val
1284 add_to_preamble(document, [preamble])
1285 document.header[i] = "\\font_roman default"
1286 i = find_token(document.header, "\\font_sans", 0)
1288 val = get_value(document.header, "\\font_sans", i)
1289 if val in texgyre_fonts:
1290 preamble = "\\usepackage{%s}" % val
1291 add_to_preamble(document, [preamble])
1292 document.header[i] = "\\font_sans default"
1293 i = find_token(document.header, "\\font_typewriter", 0)
1295 val = get_value(document.header, "\\font_typewriter", i)
1296 if val in texgyre_fonts:
1297 preamble = "\\usepackage{%s}" % val
1298 add_to_preamble(document, [preamble])
1299 document.header[i] = "\\font_typewriter default"
1302 def revert_ipadeco(document):
1303 " Revert IPA decorations to ERT "
1306 i = find_token(document.body, "\\begin_inset IPADeco", i)
1309 end = find_end_of_inset(document.body, i)
1311 document.warning("Can't find end of inset at line " + str(i))
1314 line = document.body[i]
1315 rx = re.compile(r'\\begin_inset IPADeco (.*)$')
1317 decotype = m.group(1)
1318 if decotype != "toptiebar" and decotype != "bottomtiebar":
1319 document.warning("Invalid IPADeco type: " + decotype)
1322 blay = find_token(document.body, "\\begin_layout Plain Layout", i, end)
1324 document.warning("Can't find layout for inset at line " + str(i))
1327 bend = find_end_of_layout(document.body, blay)
1329 document.warning("Malformed LyX document: Could not find end of IPADeco inset's layout.")
1332 substi = ["\\begin_inset ERT", "status collapsed", "",
1333 "\\begin_layout Plain Layout", "", "", "\\backslash",
1334 decotype + "{", "\\end_layout", "", "\\end_inset"]
1335 substj = ["\\size default", "", "\\begin_inset ERT", "status collapsed", "",
1336 "\\begin_layout Plain Layout", "", "}", "\\end_layout", "", "\\end_inset"]
1337 # do the later one first so as not to mess up the numbering
1338 document.body[bend:end + 1] = substj
1339 document.body[i:blay + 1] = substi
1340 i = end + len(substi) + len(substj) - (end - bend) - (blay - i) - 2
1341 add_to_preamble(document, "\\usepackage{tipa}")
1344 def revert_ipachar(document):
1345 ' Revert \\IPAChar to ERT '
1348 while i < len(document.body):
1349 m = re.match(r'(.*)\\IPAChar \\(\w+\{\w+\})(.*)', document.body[i])
1353 ipachar = m.group(2)
1356 '\\begin_inset ERT',
1357 'status collapsed', '',
1358 '\\begin_layout Standard',
1359 '', '', '\\backslash',
1364 document.body[i: i+1] = subst
1369 add_to_preamble(document, "\\usepackage{tone}")
1372 def revert_minionpro(document):
1373 " Revert native MinionPro font definition to LaTeX "
1375 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1376 i = find_token(document.header, "\\font_roman minionpro", 0)
1379 j = find_token(document.header, "\\font_osf true", 0)
1382 preamble = "\\usepackage"
1384 document.header[j] = "\\font_osf false"
1387 preamble += "{MinionPro}"
1388 add_to_preamble(document, [preamble])
1389 document.header[i] = "\\font_roman default"
1392 def revert_mathfonts(document):
1393 " Revert native math font definitions to LaTeX "
1395 i = find_token(document.header, "\\font_math", 0)
1398 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1399 val = get_value(document.header, "\\font_math", i)
1400 if val == "eulervm":
1401 add_to_preamble(document, "\\usepackage{eulervm}")
1402 elif val == "default":
1404 "lmodern": "\\renewcommand{\\rmdefault}{lmr}",
1405 "minionpro": "\\usepackage[onlytext,lf]{MinionPro}",
1406 "minionpro-osf": "\\usepackage[onlytext]{MinionPro}",
1407 "palatino": "\\renewcommand{\\rmdefault}{ppl}",
1408 "palatino-osf": "\\renewcommand{\\rmdefault}{pplj}",
1409 "times": "\\renewcommand{\\rmdefault}{ptm}",
1410 "utopia": "\\renewcommand{\\rmdefault}{futs}",
1411 "utopia-osf": "\\renewcommand{\\rmdefault}{futj}",
1413 j = find_token(document.header, "\\font_roman", 0)
1415 rm = get_value(document.header, "\\font_roman", j)
1416 k = find_token(document.header, "\\font_osf true", 0)
1419 if rm in list(mathfont_dict.keys()):
1420 add_to_preamble(document, mathfont_dict[rm])
1421 document.header[j] = "\\font_roman default"
1423 document.header[k] = "\\font_osf false"
1424 del document.header[i]
1427 def revert_mdnomath(document):
1428 " Revert mathdesign and fourier without math "
1430 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1432 "md-charter": "mdbch",
1433 "md-utopia": "mdput",
1434 "md-garamond": "mdugm"
1436 i = find_token(document.header, "\\font_roman", 0)
1439 val = get_value(document.header, "\\font_roman", i)
1440 if val in list(mathdesign_dict.keys()):
1441 j = find_token(document.header, "\\font_math", 0)
1443 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1444 mval = get_value(document.header, "\\font_math", j)
1445 if mval == "default":
1446 document.header[i] = "\\font_roman default"
1447 add_to_preamble(document, "\\renewcommand{\\rmdefault}{%s}" % mathdesign_dict[val])
1449 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1452 def convert_mathfonts(document):
1453 document.header.insert(-1, "\\font_math auto")
1456 def convert_mdnomath(document):
1457 " Change mathdesign font name "
1459 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1461 "mdbch": "md-charter",
1462 "mdput": "md-utopia",
1463 "mdugm": "md-garamond"
1465 i = find_token(document.header, "\\font_roman", 0)
1468 val = get_value(document.header, "\\font_roman", i)
1469 if val in list(mathdesign_dict.keys()):
1470 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1473 def revert_newtxmath(document):
1474 " Revert native newtxmath definitions to LaTeX "
1476 i = find_token(document.header, "\\font_math", 0)
1479 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1480 val = get_value(document.header, "\\font_math", i)
1482 "libertine-ntxm": "\\usepackage[libertine]{newtxmath}",
1483 "minion-ntxm": "\\usepackage[minion]{newtxmath}",
1484 "newtxmath": "\\usepackage{newtxmath}",
1486 if val in list(mathfont_dict.keys()):
1487 add_to_preamble(document, mathfont_dict[val])
1488 document.header[i] = "\\font_math auto"
1491 def revert_biolinum(document):
1492 " Revert native biolinum font definition to LaTeX "
1494 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1495 i = find_token(document.header, "\\font_sans biolinum", 0)
1498 j = find_token(document.header, "\\font_osf true", 0)
1501 preamble = "\\usepackage"
1504 preamble += "{biolinum-type1}"
1505 add_to_preamble(document, [preamble])
1506 document.header[i] = "\\font_sans default"
1509 def revert_uop(document):
1510 " Revert native URW Classico (Optima) font definition to LaTeX "
1512 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1513 i = find_token(document.header, "\\font_sans uop", 0)
1515 preamble = "\\renewcommand{\\sfdefault}{uop}"
1516 add_to_preamble(document, [preamble])
1517 document.header[i] = "\\font_sans default"
1520 def convert_latexargs(document):
1521 " Convert InsetArgument to new syntax "
1523 if find_token(document.body, "\\begin_inset Argument", 0) == -1:
1527 # A list of layouts (document classes) with only optional or no arguments.
1528 # These can be safely converted to the new syntax
1529 # (I took the liberty to add some of my personal layouts/modules here; JSP)
1530 safe_layouts = ["aa", "aapaper", "aastex", "achemso", "acmsiggraph", "AEA",
1531 "agu-dtd", "agums", "agutex", "amsart", "amsbook", "apa",
1532 "arab-article", "armenian-article", "article-beamer", "article",
1533 "beamer", "book", "broadway", "chess", "cl2emult", "ctex-article",
1534 "ctex-book", "ctex-report", "dinbrief", "docbook-book", "docbook-chapter",
1535 "docbook", "docbook-section", "doublecol-new", "dtk", "ectaart", "egs",
1536 "elsarticle", "elsart", "entcs", "europecv", "extarticle", "extbook",
1537 "extletter", "extreport", "foils", "frletter", "g-brief2", "g-brief",
1538 "heb-article", "heb-letter", "hollywood", "IEEEtran", "ijmpc", "ijmpd",
1539 "iopart", "isprs", "jarticle", "jasatex", "jbook", "jgrga", "jreport",
1540 "jsarticle", "jsbeamer", "jsbook", "jss", "kluwer", "latex8", "letter", "lettre",
1541 "literate-article", "literate-book", "literate-report", "llncs", "ltugboat",
1542 "memoir", "moderncv", "mwart", "mwbk", "mwrep", "paper", "powerdot",
1543 "recipebook", "report", "revtex4", "revtex", "scrartcl", "scrarticle-beamer",
1544 "scrbook", "scrlettr", "scrlttr2", "scrreprt", "seminar", "siamltex",
1545 "sigplanconf", "simplecv", "singlecol", "singlecol-new", "slides", "spie",
1546 "svglobal3", "svglobal", "svjog", "svmono", "svmult", "svprobth", "tarticle",
1547 "tbook", "treport", "tufte-book", "tufte-handout"]
1548 # A list of "safe" modules, same as above
1549 safe_modules = ["biblatex", "beameraddons", "beamer-resenumerate", "beamersession", "braille",
1550 "customHeadersFooters", "endnotes", "enumitem", "eqs-within-sections", "figs-within-sections",
1551 "fix-cm", "fixltx2e", "foottoend", "hanging", "jscharstyles", "knitr", "lilypond",
1552 "linguistics", "linguisticx", "logicalmkup", "minimalistic", "nomindex", "noweb",
1553 "pdfcomment", "sweave", "tabs-within-sections", "theorems-ams-bytype",
1554 "theorems-ams-extended-bytype", "theorems-ams-extended", "theorems-ams", "theorems-bytype",
1555 "theorems-chap-bytype", "theorems-chap", "theorems-named", "theorems-sec-bytype",
1556 "theorems-sec", "theorems-starred", "theorems-std", "todonotes"]
1557 # Modules we need to take care of
1558 caveat_modules = ["initials"] # TODO: , "graphicboxes", "bicaption"]
1559 # information about the relevant styles in caveat_modules (number of opt and req args)
1560 # use this if we get more caveat_modules. For now, use hard coding (see below).
1561 # initials = [{'Layout' : 'Initial', 'opt' : 1, 'req' : 1}]
1562 # graphicboxes = { ... }
1564 # Is this a known safe layout?
1565 safe_layout = document.textclass in safe_layouts
1567 document.warning("Lyx2lyx knows nothing about textclass '%s'. "
1568 "Please check if short title insets have been converted correctly."
1569 % document.textclass)
1570 # Do we use unsafe or unknown modules
1571 mods = document.get_module_list()
1572 unknown_modules = False
1573 used_caveat_modules = list()
1575 if mod in safe_modules:
1577 if mod in caveat_modules:
1578 used_caveat_modules.append(mod)
1580 unknown_modules = True
1581 document.warning("Lyx2lyx knows nothing about module '%s'. "
1582 "Please check if short title insets have been converted correctly."
1587 i = find_token(document.body, "\\begin_inset Argument", i)
1591 if not safe_layout or unknown_modules:
1592 # We cannot do more here since we have no access to this layout.
1593 # InsetArgument itself will do the real work
1594 # (see InsetArgument::updateBuffer())
1595 document.body[i] = "\\begin_inset Argument 999"
1599 # Find containing paragraph layout
1600 parent = get_containing_layout(document.body, i)
1602 document.warning("Malformed LyX document: Can't find parent paragraph layout")
1609 if len(used_caveat_modules) > 0:
1610 # We know for now that this must be the initials module with the Initial layout
1611 # If we get more such modules, we need some automating.
1612 if parent[0] == "Initial":
1613 # Layout has 1 opt and 1 req arg.
1614 # Count the actual arguments
1616 for p in range(parbeg, parend):
1617 if document.body[p] == "\\begin_inset Argument":
1622 # Collect all arguments in this paragraph
1624 for p in range(parbeg, parend):
1625 if document.body[p] == "\\begin_inset Argument":
1627 if allowed_opts != -1:
1628 # We have less arguments than opt + required.
1629 # required must take precedence.
1630 if argnr > allowed_opts and argnr < first_req:
1632 document.body[p] = "\\begin_inset Argument %d" % argnr
1636 def revert_latexargs(document):
1637 " Revert InsetArgument to old syntax "
1640 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
1643 # Search for Argument insets
1644 i = find_token(document.body, "\\begin_inset Argument", i)
1647 m = rx.match(document.body[i])
1649 # No ID: inset already reverted
1652 # Find containing paragraph layout
1653 parent = get_containing_layout(document.body, i)
1655 document.warning("Malformed LyX document: Can't find parent paragraph layout")
1660 # Do not set realparbeg to parent[3], since this does not work if we
1661 # have another inset (e.g. label or index) before the first argument
1662 # inset (this is the case in the user guide of LyX 2.0.8)
1664 # Collect all arguments in this paragraph
1666 for p in range(parbeg, parend):
1667 m = rx.match(document.body[p])
1670 # This is the first argument inset
1672 val = int(m.group(1))
1673 j = find_end_of_inset(document.body, p)
1674 # Revert to old syntax
1675 document.body[p] = "\\begin_inset Argument"
1677 document.warning("Malformed LyX document: Can't find end of Argument inset")
1680 args[val] = document.body[p : j + 1]
1682 realparend = realparend - len(document.body[p : j + 1])
1683 # Remove arg inset at this position
1684 del document.body[p : j + 1]
1688 # No argument inset found
1689 realparbeg = parent[3]
1690 # Now sort the arg insets
1692 for f in sorted(args):
1695 # Insert the sorted arg insets at paragraph begin
1696 document.body[realparbeg : realparbeg] = subst
1698 i = realparbeg + 1 + len(subst)
1701 def revert_IEEEtran(document):
1703 Reverts InsetArgument of
1706 Biography without photo
1709 if document.textclass != "IEEEtran":
1712 layouts = {"Page headings": False,
1713 "Biography without photo": True}
1715 for layout in list(layouts.keys()):
1718 i = find_token(document.body, '\\begin_layout ' + layout, i)
1721 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, layouts[layout], False)
1726 i = find_token(document.body, '\\begin_inset Flex Paragraph Start', i)
1729 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1734 i = find_token_exact(document.body, "\\begin_layout Biography", i)
1738 if document.body[i] == "\\begin_layout Biography without photo":
1742 # start with the second argument, therefore 2
1743 revert_Argument_to_TeX_brace(document, i, 0, 2, 2, True, False)
1747 def revert_IEEEtran_2(document):
1749 Reverts Flex Paragraph Start to TeX-code
1751 if document.textclass == "IEEEtran":
1754 begin = find_token(document.body, "\\begin_inset Flex Paragraph Start", begin)
1757 end1 = find_end_of_inset(document.body, begin)
1758 document.body[end1 - 2 : end1 + 1] = put_cmd_in_ert("}")
1759 document.body[begin : begin + 4] = put_cmd_in_ert("\\IEEEPARstart{")
1763 def convert_IEEEtran(document):
1768 Biography without photo
1771 if document.textclass != "IEEEtran":
1774 layouts = {"Page headings": False,
1775 "Biography without photo": True}
1777 for layout in list(layouts.keys()):
1780 i = find_token(document.body, '\\begin_layout ' + layout, i)
1783 convert_TeX_brace_to_Argument(document, i, 1, 1, False, layouts[layout], False)
1788 i = find_token_exact(document.body, "\\begin_layout Biography", i)
1792 if document.body[i] == "\\begin_layout Biography without photo":
1796 # the argument we want to convert is the second one
1797 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, False)
1801 def revert_AASTeX(document):
1802 " Reverts InsetArgument of Altaffilation to TeX-code "
1803 if document.textclass == "aastex":
1806 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1809 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1813 def convert_AASTeX(document):
1814 " Converts ERT of Altaffilation to InsetArgument "
1815 if document.textclass == "aastex":
1818 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1821 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1825 def revert_AGUTeX(document):
1826 " Reverts InsetArgument of Author affiliation to TeX-code "
1827 if document.textclass == "agutex":
1830 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1833 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1837 def convert_AGUTeX(document):
1838 " Converts ERT of Author affiliation to InsetArgument "
1839 if document.textclass == "agutex":
1842 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1845 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1849 def revert_IJMP(document):
1850 " Reverts InsetArgument of MarkBoth to TeX-code "
1851 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1854 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1857 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1861 def convert_IJMP(document):
1862 " Converts ERT of MarkBoth to InsetArgument "
1863 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1866 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1869 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1873 def revert_SIGPLAN(document):
1874 " Reverts InsetArguments of SIGPLAN to TeX-code "
1875 if document.textclass == "sigplanconf":
1880 i = find_token(document.body, "\\begin_layout Conference", i)
1882 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1885 j = find_token(document.body, "\\begin_layout Author", j)
1887 revert_Argument_to_TeX_brace(document, j, 0, 1, 2, False, False)
1889 if i == -1 and j == -1:
1893 def convert_SIGPLAN(document):
1894 " Converts ERT of SIGPLAN to InsetArgument "
1895 if document.textclass == "sigplanconf":
1900 i = find_token(document.body, "\\begin_layout Conference", i)
1902 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1905 j = find_token(document.body, "\\begin_layout Author", j)
1907 convert_TeX_brace_to_Argument(document, j, 1, 2, False, False, False)
1909 if i == -1 and j == -1:
1913 def revert_SIGGRAPH(document):
1914 " Reverts InsetArgument of Flex CRcat to TeX-code "
1915 if document.textclass == "acmsiggraph":
1918 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1921 revert_Argument_to_TeX_brace(document, i, 0, 1, 3, False, False)
1925 def convert_SIGGRAPH(document):
1926 " Converts ERT of Flex CRcat to InsetArgument "
1927 if document.textclass == "acmsiggraph":
1930 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1933 convert_TeX_brace_to_Argument(document, i, 1, 3, True, False, False)
1937 def revert_EuropeCV(document):
1938 " Reverts InsetArguments of europeCV to TeX-code "
1939 if document.textclass == "europecv":
1946 i = find_token(document.body, "\\begin_layout Item", i)
1948 revert_Argument_to_TeX_brace(document, i, 0, 2, 2, False, False)
1951 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1953 revert_Argument_to_TeX_brace(document, j, 0, 2, 2, False, False)
1956 k = find_token(document.body, "\\begin_layout Language", k)
1958 revert_Argument_to_TeX_brace(document, k, 0, 2, 6, False, False)
1961 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1963 revert_Argument_to_TeX_brace(document, m, 0, 2, 6, False, False)
1965 if i == -1 and j == -1 and k == -1 and m == -1:
1969 def convert_EuropeCV(document):
1970 " Converts ERT of europeCV to InsetArgument "
1971 if document.textclass == "europecv":
1978 i = find_token(document.body, "\\begin_layout Item", i)
1980 convert_TeX_brace_to_Argument(document, i, 2, 2, False, False, False)
1983 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1985 convert_TeX_brace_to_Argument(document, j, 2, 2, False, False, False)
1988 k = find_token(document.body, "\\begin_layout Language", k)
1990 convert_TeX_brace_to_Argument(document, k, 2, 6, False, False, False)
1993 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1995 convert_TeX_brace_to_Argument(document, m, 2, 6, False, False, False)
1997 if i == -1 and j == -1 and k == -1 and m == -1:
2001 def revert_ModernCV(document):
2002 " Reverts InsetArguments of modernCV to TeX-code "
2003 if document.textclass == "moderncv":
2011 j = find_token(document.body, "\\begin_layout Entry", j)
2013 revert_Argument_to_TeX_brace(document, j, 0, 1, 5, False, False)
2016 k = find_token(document.body, "\\begin_layout Item", k)
2018 revert_Argument_to_TeX_brace(document, k, 0, 1, 1, False, False)
2021 m = find_token(document.body, "\\begin_layout ItemWithComment", m)
2023 revert_Argument_to_TeX_brace(document, m, 0, 1, 2, False, False)
2024 document.body[m] = document.body[m].replace("\\begin_layout ItemWithComment", "\\begin_layout Language")
2027 o = find_token(document.body, "\\begin_layout DoubleItem", o)
2029 revert_Argument_to_TeX_brace(document, o, 0, 1, 3, False, False)
2030 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout Computer")
2033 p = find_token(document.body, "\\begin_layout Social", p)
2035 revert_Argument_to_TeX_brace(document, p, 0, 1, 1, False, True)
2037 if j == -1 and k == -1 and m == -1 and o == -1 and p == -1:
2041 def revert_ModernCV_2(document):
2042 " Reverts the Flex:Column inset of modernCV to TeX-code "
2043 if document.textclass == "moderncv":
2047 flex = find_token(document.body, "\\begin_inset Flex Column", flex)
2050 flexEnd = find_end_of_inset(document.body, flex)
2051 wasOpt = revert_Argument_to_TeX_brace(document, flex, flexEnd, 1, 1, False, True)
2052 revert_Argument_to_TeX_brace(document, flex, 0, 2, 2, False, False)
2053 flexEnd = find_end_of_inset(document.body, flex)
2055 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn")
2057 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn{")
2058 document.body[flexEnd + 4 : flexEnd + 7] = put_cmd_in_ert("}")
2062 def revert_ModernCV_3(document):
2063 " Reverts the Column style of modernCV to TeX-code "
2064 if document.textclass == "moderncv":
2065 # revert the layouts
2066 revert_ModernCV(document)
2068 # get the position of the end of the last column inset
2069 LastFlexEnd = revert_ModernCV_2(document)
2071 p = find_token(document.body, "\\begin_layout Columns", p)
2074 pEnd = find_end_of_layout(document.body, p)
2075 document.body[p] = document.body[p].replace("\\begin_layout Columns", "\\begin_layout Standard")
2076 if LastFlexEnd != -1:
2077 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\begin{cvcolumns}")
2078 document.body[LastFlexEnd + 24 : LastFlexEnd + 24] = put_cmd_in_ert("\\end{cvcolumns}")
2082 def revert_ModernCV_4(document):
2083 " Reverts the style Social to TeX-code "
2084 if document.textclass == "moderncv":
2085 # revert the layouts
2086 revert_ModernCV(document)
2089 p = find_token(document.body, "\\begin_layout Social", p)
2092 pEnd = find_end_of_layout(document.body, p)
2093 document.body[p] = document.body[p].replace("\\begin_layout Social", "\\begin_layout Standard")
2094 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\social")
2095 hasOpt = find_token(document.body, "[", p + 9)
2097 document.body[p + 30 : p + 30] = put_cmd_in_ert("{")
2098 document.body[p + 41 : p + 41] = put_cmd_in_ert("}")
2100 document.body[p + 11 : p + 11] = put_cmd_in_ert("{")
2101 document.body[p + 21 : p + 21] = put_cmd_in_ert("}")
2105 def convert_ModernCV(document):
2106 " Converts ERT of modernCV to InsetArgument "
2107 if document.textclass == "moderncv":
2115 i = find_token(document.body, "\\begin_layout DoubleItem", i)
2117 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
2118 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout DoubleListItem")
2121 j = find_token(document.body, "\\begin_layout Entry", j)
2123 convert_TeX_brace_to_Argument(document, j, 1, 5, False, False, False)
2126 k = find_token(document.body, "\\begin_layout Item", k)
2128 convert_TeX_brace_to_Argument(document, k, 1, 1, False, False, False)
2131 m = find_token(document.body, "\\begin_layout Language", m)
2133 convert_TeX_brace_to_Argument(document, m, 1, 2, False, False, False)
2135 if i == -1 and j == -1 and k == -1 and m == -1:
2139 def revert_Initials(document):
2140 " Reverts InsetArgument of Initial to TeX-code "
2143 i = find_token(document.body, "\\begin_layout Initial", i)
2146 # first arg (optional) and second arg (first mandatory) are supported in LyX 2.0.x
2147 revert_Argument_to_TeX_brace(document, i, 0, 3, 3, False, False)
2151 def convert_Initials(document):
2152 " Converts ERT of Initial to InsetArgument "
2155 i = find_token(document.body, "\\begin_layout Initial", i)
2158 convert_TeX_brace_to_Argument(document, i, 3, 3, False, False, False)
2162 def revert_literate(document):
2163 " Revert Literate document to old format "
2164 if del_token(document.header, "noweb", 0):
2165 document.textclass = "literate-" + document.textclass
2168 i = find_token(document.body, "\\begin_layout Chunk", i)
2171 document.body[i] = "\\begin_layout Scrap"
2175 def convert_literate(document):
2176 " Convert Literate document to new format"
2177 i = find_token(document.header, "\\textclass", 0)
2178 if (i != -1) and "literate-" in document.header[i]:
2179 document.textclass = document.header[i].replace("\\textclass literate-", "")
2180 j = find_token(document.header, "\\begin_modules", 0)
2182 document.header.insert(j + 1, "noweb")
2184 document.header.insert(i + 1, "\\end_modules")
2185 document.header.insert(i + 1, "noweb")
2186 document.header.insert(i + 1, "\\begin_modules")
2189 i = find_token(document.body, "\\begin_layout Scrap", i)
2192 document.body[i] = "\\begin_layout Chunk"
2196 def revert_itemargs(document):
2197 " Reverts \\item arguments to TeX-code "
2200 i = find_token(document.body, "\\begin_inset Argument item:", i)
2203 j = find_end_of_inset(document.body, i)
2204 # Find containing paragraph layout
2205 parent = get_containing_layout(document.body, i)
2207 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2211 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2212 endPlain = find_end_of_layout(document.body, beginPlain)
2213 content = document.body[beginPlain + 1 : endPlain]
2214 del document.body[i:j+1]
2215 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2216 document.body[parbeg : parbeg] = subst
2220 def revert_garamondx_newtxmath(document):
2221 " Revert native garamond newtxmath definition to LaTeX "
2223 i = find_token(document.header, "\\font_math", 0)
2226 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2227 val = get_value(document.header, "\\font_math", i)
2228 if val == "garamondx-ntxm":
2229 add_to_preamble(document, "\\usepackage[garamondx]{newtxmath}")
2230 document.header[i] = "\\font_math auto"
2233 def revert_garamondx(document):
2234 " Revert native garamond font definition to LaTeX "
2236 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2237 i = find_token(document.header, "\\font_roman garamondx", 0)
2240 j = find_token(document.header, "\\font_osf true", 0)
2243 preamble = "\\usepackage"
2245 preamble += "[osfI]"
2246 preamble += "{garamondx}"
2247 add_to_preamble(document, [preamble])
2248 document.header[i] = "\\font_roman default"
2251 def convert_beamerargs(document):
2252 " Converts beamer arguments to new layout "
2254 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2255 if document.textclass not in beamer_classes:
2258 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2259 list_layouts = ["Itemize", "Enumerate", "Description"]
2260 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
2264 i = find_token(document.body, "\\begin_inset Argument", i)
2267 # Find containing paragraph layout
2268 parent = get_containing_layout(document.body, i)
2270 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2275 layoutname = parent[0]
2276 for p in range(parbeg, parend):
2277 if layoutname in shifted_layouts:
2278 m = rx.match(document.body[p])
2280 argnr = int(m.group(1))
2282 document.body[p] = "\\begin_inset Argument %d" % argnr
2283 if layoutname == "AgainFrame":
2284 m = rx.match(document.body[p])
2286 document.body[p] = "\\begin_inset Argument 3"
2287 if document.body[p + 4] == "\\begin_inset ERT":
2288 if document.body[p + 9].startswith("<"):
2289 # This is an overlay specification
2291 document.body[p + 9] = document.body[p + 9][1:]
2292 if document.body[p + 9].endswith(">"):
2294 document.body[p + 9] = document.body[p + 9][:-1]
2296 document.body[p] = "\\begin_inset Argument 2"
2297 if layoutname in list_layouts:
2298 m = rx.match(document.body[p])
2300 if m.group(1) == "1":
2301 if document.body[p + 4] == "\\begin_inset ERT":
2302 if document.body[p + 9].startswith("<"):
2303 # This is an overlay specification
2305 document.body[p + 9] = document.body[p + 9][1:]
2306 if document.body[p + 9].endswith(">"):
2308 document.body[p + 9] = document.body[p + 9][:-1]
2309 elif document.body[p + 4].startswith("<"):
2310 # This is an overlay specification (without ERT)
2312 document.body[p + 4] = document.body[p + 4][1:]
2313 if document.body[p + 4].endswith(">"):
2315 document.body[p + 4] = document.body[p + 4][:-1]
2316 elif layoutname != "Itemize":
2318 document.body[p] = "\\begin_inset Argument 2"
2323 # Helper function for the frame conversion routines
2325 # FIXME: This method currently requires the arguments to be either
2326 # * In one (whole) ERT each: <ERT>[<arg1>]</ERT><ERT><arg2></ERT><ERT>[arg3]</ERT>
2327 # * Altogether in one whole ERT: <ERT>[<arg1>]<arg2>[arg3]</ERT>
2328 # If individual arguments mix ERT and non-ERT or are splitted
2329 # over several ERTs, the parsing fails.
2330 def convert_beamerframeargs(document, i, parbeg):
2333 if document.body[parbeg] != "\\begin_inset ERT":
2335 ertend = find_end_of_inset(document.body, parbeg)
2337 document.warning("Malformed LyX document: missing ERT \\end_inset")
2339 ertcont = parbeg + 5
2340 if document.body[ertcont].startswith("[<"):
2341 # This is a default overlay specification
2343 document.body[ertcont] = document.body[ertcont][2:]
2344 if document.body[ertcont].endswith(">]"):
2346 document.body[ertcont] = document.body[ertcont][:-2]
2347 elif document.body[ertcont].endswith("]"):
2349 tok = document.body[ertcont].find('>][')
2351 subst = [document.body[ertcont][:tok],
2352 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2353 'status collapsed', '', '\\begin_layout Plain Layout',
2354 document.body[ertcont][tok + 3:-1]]
2355 document.body[ertcont : ertcont + 1] = subst
2357 # Convert to ArgInset
2358 document.body[parbeg] = "\\begin_inset Argument 2"
2359 elif document.body[ertcont].startswith("<"):
2360 # This is an overlay specification
2362 document.body[ertcont] = document.body[ertcont][1:]
2363 if document.body[ertcont].endswith(">"):
2365 document.body[ertcont] = document.body[ertcont][:-1]
2366 # Convert to ArgInset
2367 document.body[parbeg] = "\\begin_inset Argument 1"
2368 elif document.body[ertcont].endswith(">]"):
2370 tok = document.body[ertcont].find('>[<')
2372 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2373 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2374 'status collapsed', '', '\\begin_layout Plain Layout',
2375 document.body[ertcont][tok + 3:-2]]
2376 # Convert to ArgInset
2377 document.body[parbeg] = "\\begin_inset Argument 1"
2379 elif document.body[ertcont].endswith("]"):
2381 tok = document.body[ertcont].find('>[<')
2384 tokk = document.body[ertcont].find('>][')
2386 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2387 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2388 'status collapsed', '', '\\begin_layout Plain Layout',
2389 document.body[ertcont][tok + 3:tokk],
2390 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2391 'status collapsed', '', '\\begin_layout Plain Layout',
2392 document.body[ertcont][tokk + 3:-1]]
2395 tokk = document.body[ertcont].find('>[')
2397 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tokk],
2398 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2399 'status collapsed', '', '\\begin_layout Plain Layout',
2400 document.body[ertcont][tokk + 2:-1]]
2402 # Convert to ArgInset
2403 document.body[parbeg] = "\\begin_inset Argument 1"
2404 elif document.body[ertcont].startswith("["):
2405 # This is an ERT option
2407 document.body[ertcont] = document.body[ertcont][1:]
2408 if document.body[ertcont].endswith("]"):
2410 document.body[ertcont] = document.body[ertcont][:-1]
2411 # Convert to ArgInset
2412 document.body[parbeg] = "\\begin_inset Argument 3"
2418 def convert_againframe_args(document):
2419 " Converts beamer AgainFrame to new layout "
2421 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2422 if document.textclass not in beamer_classes:
2427 i = find_token(document.body, "\\begin_layout AgainFrame", i)
2430 parent = get_containing_layout(document.body, i)
2432 document.warning("Wrong parent layout!")
2436 # Convert ERT arguments
2437 # FIXME: See restrictions in convert_beamerframeargs method
2438 ertend = convert_beamerframeargs(document, i, parbeg)
2444 def convert_corollary_args(document):
2445 " Converts beamer corrolary-style ERT arguments native InsetArgs "
2447 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2448 if document.textclass not in beamer_classes:
2451 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2452 for lay in corollary_layouts:
2455 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2458 parent = get_containing_layout(document.body, i)
2460 document.warning("Wrong parent layout!")
2464 if document.body[parbeg] == "\\begin_inset ERT":
2465 ertcontfirstline = parbeg + 5
2466 # Find the last ERT in this paragraph (which might also be the first)
2467 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
2468 if lastertbeg == -1:
2469 document.warning("Last ERT not found!")
2471 lastertend = find_end_of_inset(document.body, lastertbeg)
2472 if lastertend == -1:
2473 document.warning("End of last ERT not found!")
2475 ertcontlastline = lastertend - 3
2476 if document.body[ertcontfirstline].startswith("<"):
2477 # This is an overlay specification
2479 document.body[ertcontfirstline] = document.body[ertcontfirstline][1:]
2480 if document.body[ertcontlastline].endswith(">"):
2482 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
2483 if ertcontfirstline < ertcontlastline:
2484 # Multiline ERT. Might contain TeX code. Embrace in ERT.
2485 document.body[ertcontlastline : ertcontlastline + 1] = [
2486 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
2487 document.body[ertcontfirstline : ertcontfirstline + 1] = [
2488 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
2489 'status collapsed', '', '\\begin_layout Plain Layout',
2490 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
2491 document.body[ertcontfirstline]]
2493 # Convert to ArgInset
2494 document.body[parbeg] = "\\begin_inset Argument 1"
2495 elif document.body[ertcontlastline].endswith("]"):
2497 tok = document.body[ertcontfirstline].find('>[')
2499 if ertcontfirstline < ertcontlastline:
2500 # Multiline ERT. Might contain TeX code. Embrace in ERT.
2501 document.body[ertcontlastline : ertcontlastline + 1] = [
2502 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
2503 document.body[ertcontfirstline : ertcontfirstline + 1] = [document.body[ertcontfirstline][:tok],
2504 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2505 'status collapsed', '', '\\begin_layout Plain Layout',
2506 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
2507 document.body[ertcontfirstline][tok + 2:-1]]
2509 document.body[ertcontfirstline : ertcontfirstline + 1] = [document.body[ertcontfirstline][:tok],
2510 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2511 'status collapsed', '', '\\begin_layout Plain Layout',
2512 document.body[ertcontfirstline][tok + 2:-1]]
2513 # Convert to ArgInset
2514 document.body[parbeg] = "\\begin_inset Argument 1"
2517 elif document.body[ertcontlastline].startswith("["):
2518 if document.body[ertcontlastline].endswith("]"):
2519 # This is an ERT option
2521 document.body[ertcontlastline] = document.body[ertcontlastline][1:]
2523 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
2524 # Convert to ArgInset
2525 document.body[parbeg] = "\\begin_inset Argument 2"
2527 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, True)
2534 def convert_quote_args(document):
2535 " Converts beamer quote style ERT args to native InsetArgs "
2537 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2538 if document.textclass not in beamer_classes:
2541 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2542 for lay in quote_layouts:
2545 i = find_token(document.body, "\\begin_layout " + lay, i)
2548 parent = get_containing_layout(document.body, i)
2550 document.warning("Wrong parent layout!")
2554 if document.body[parbeg] == "\\begin_inset ERT":
2555 if document.body[i + 6].startswith("<"):
2556 # This is an overlay specification
2558 document.body[i + 6] = document.body[i + 6][1:]
2559 if document.body[i + 6].endswith(">"):
2561 document.body[i + 6] = document.body[i + 6][:-1]
2562 # Convert to ArgInset
2563 document.body[i + 1] = "\\begin_inset Argument 1"
2567 def cleanup_beamerargs(document):
2568 " Clean up empty ERTs (conversion artefacts) "
2570 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2571 if document.textclass not in beamer_classes:
2576 i = find_token(document.body, "\\begin_inset Argument", i)
2579 j = find_end_of_inset(document.body, i)
2581 document.warning("Malformed LyX document: Can't find end of Argument inset")
2585 ertbeg = find_token(document.body, "\\begin_inset ERT", i, j)
2588 ertend = find_end_of_inset(document.body, ertbeg)
2590 document.warning("Malformed LyX document: Can't find end of ERT inset")
2592 stripped = [line for line in document.body[ertbeg : ertend + 1] if line.strip()]
2593 if len(stripped) == 5:
2594 # This is an empty ERT
2595 offset = len(document.body[ertbeg : ertend + 1])
2596 del document.body[ertbeg : ertend + 1]
2603 def revert_beamerargs(document):
2604 " Reverts beamer arguments to old layout "
2606 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2607 if document.textclass not in beamer_classes:
2611 list_layouts = ["Itemize", "Enumerate", "Description"]
2612 headings = ["Part", "Section", "Section*", "Subsection", "Subsection*",
2613 "Subsubsection", "Subsubsection*", "FrameSubtitle", "NoteItem"]
2614 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2615 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2616 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2619 i = find_token(document.body, "\\begin_inset Argument", i)
2622 # Find containing paragraph layout
2623 parent = get_containing_layout(document.body, i)
2625 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2630 realparbeg = parent[3]
2631 layoutname = parent[0]
2633 for p in range(parbeg, parend):
2637 if layoutname in headings:
2638 m = rx.match(document.body[p])
2642 # Find containing paragraph layout
2643 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2644 endPlain = find_end_of_layout(document.body, beginPlain)
2645 endInset = find_end_of_inset(document.body, p)
2646 argcontent = document.body[beginPlain + 1 : endPlain]
2648 realparend = realparend - len(document.body[p : endInset + 1])
2650 del document.body[p : endInset + 1]
2651 if layoutname == "FrameSubtitle":
2652 pre = put_cmd_in_ert("\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2653 elif layoutname == "NoteItem":
2654 pre = put_cmd_in_ert("\\note<") + argcontent + put_cmd_in_ert(">[item]")
2655 elif layoutname.endswith('*'):
2656 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower()[:-1] + "<") + argcontent + put_cmd_in_ert(">*")
2658 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2659 secarg = find_token(document.body, "\\begin_inset Argument 2", parbeg, parend)
2661 # Find containing paragraph layout
2662 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", secarg)
2663 endPlain = find_end_of_layout(document.body, beginPlain)
2664 endInset = find_end_of_inset(document.body, secarg)
2665 argcontent = document.body[beginPlain + 1 : endPlain]
2667 realparend = realparend - len(document.body[secarg : endInset + 1])
2668 del document.body[secarg : endInset + 1]
2669 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2670 pre += put_cmd_in_ert("{")
2671 document.body[parbeg] = "\\begin_layout Standard"
2672 document.body[realparbeg : realparbeg] = pre
2673 pe = find_end_of_layout(document.body, parbeg)
2674 post = put_cmd_in_ert("}")
2675 document.body[pe : pe] = post
2676 realparend += len(pre) + len(post)
2677 if layoutname == "AgainFrame":
2678 m = rx.match(document.body[p])
2682 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2683 endPlain = find_end_of_layout(document.body, beginPlain)
2684 endInset = find_end_of_inset(document.body, p)
2685 content = document.body[beginPlain + 1 : endPlain]
2687 realparend = realparend - len(document.body[p : endInset + 1])
2689 del document.body[p : endInset + 1]
2690 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2691 document.body[realparbeg : realparbeg] = subst
2692 if layoutname == "Overprint":
2693 m = rx.match(document.body[p])
2697 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2698 endPlain = find_end_of_layout(document.body, beginPlain)
2699 endInset = find_end_of_inset(document.body, p)
2700 content = document.body[beginPlain + 1 : endPlain]
2702 realparend = realparend - len(document.body[p : endInset + 1])
2704 del document.body[p : endInset + 1]
2705 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2706 document.body[realparbeg : realparbeg] = subst
2707 if layoutname == "OverlayArea":
2708 m = rx.match(document.body[p])
2712 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2713 endPlain = find_end_of_layout(document.body, beginPlain)
2714 endInset = find_end_of_inset(document.body, p)
2715 content = document.body[beginPlain + 1 : endPlain]
2717 realparend = realparend - len(document.body[p : endInset + 1])
2719 del document.body[p : endInset + 1]
2720 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2721 document.body[realparbeg : realparbeg] = subst
2722 if layoutname in list_layouts:
2723 m = rx.match(document.body[p])
2727 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2728 endPlain = find_end_of_layout(document.body, beginPlain)
2729 endInset = find_end_of_inset(document.body, p)
2730 content = document.body[beginPlain + 1 : endPlain]
2731 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2732 realparend = realparend + len(subst) - len(content)
2733 document.body[beginPlain + 1 : endPlain] = subst
2734 elif argnr == "item:1":
2735 j = find_end_of_inset(document.body, i)
2736 # Find containing paragraph layout
2737 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2738 endPlain = find_end_of_layout(document.body, beginPlain)
2739 content = document.body[beginPlain + 1 : endPlain]
2740 del document.body[i:j+1]
2741 if layoutname == "Description":
2742 # Description only has one (overlay) item arg
2743 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2744 # This must be put after the first space (begin of decription body
2745 # in LyX's arkward description list syntax)
2746 # Try to find that place ...
2747 rxx = re.compile(r'^([^\\ ]+ )(.*)$')
2748 for q in range(parbeg, parend):
2749 m = rxx.match(document.body[q])
2751 # We found it. Now insert the ERT argument just there:
2752 document.body[q : q] = [m.group(1), ''] + subst + ['', m.group(2)]
2755 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2756 document.body[realparbeg : realparbeg] = subst
2757 elif argnr == "item:2":
2758 j = find_end_of_inset(document.body, i)
2759 # Find containing paragraph layout
2760 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2761 endPlain = find_end_of_layout(document.body, beginPlain)
2762 content = document.body[beginPlain + 1 : endPlain]
2763 del document.body[i:j+1]
2764 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2765 document.body[realparbeg : realparbeg] = subst
2766 if layoutname in quote_layouts:
2767 m = rx.match(document.body[p])
2771 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2772 endPlain = find_end_of_layout(document.body, beginPlain)
2773 endInset = find_end_of_inset(document.body, p)
2774 content = document.body[beginPlain + 1 : endPlain]
2776 realparend = realparend - len(document.body[p : endInset + 1])
2778 del document.body[p : endInset + 1]
2779 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2780 document.body[realparbeg : realparbeg] = subst
2781 if layoutname in corollary_layouts:
2782 m = rx.match(document.body[p])
2786 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2787 endPlain = find_end_of_layout(document.body, beginPlain)
2788 endInset = find_end_of_inset(document.body, p)
2789 content = document.body[beginPlain + 1 : endPlain]
2791 realparend = realparend - len(document.body[p : endInset + 1])
2793 del document.body[p : endInset + 1]
2794 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2795 document.body[realparbeg : realparbeg] = subst
2800 def revert_beamerargs2(document):
2801 " Reverts beamer arguments to old layout, step 2 "
2803 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2804 if document.textclass not in beamer_classes:
2808 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2809 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2810 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2813 i = find_token(document.body, "\\begin_inset Argument", i)
2816 # Find containing paragraph layout
2817 parent = get_containing_layout(document.body, i)
2819 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2824 realparbeg = parent[3]
2825 layoutname = parent[0]
2827 for p in range(parbeg, parend):
2831 if layoutname in shifted_layouts:
2832 m = rx.match(document.body[p])
2836 document.body[p] = "\\begin_inset Argument 1"
2837 if layoutname in corollary_layouts:
2838 m = rx.match(document.body[p])
2842 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2843 endPlain = find_end_of_layout(document.body, beginPlain)
2844 endInset = find_end_of_inset(document.body, p)
2845 content = document.body[beginPlain + 1 : endPlain]
2847 realparend = realparend - len(document.body[p : endInset + 1])
2849 del document.body[p : endInset + 1]
2850 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2851 document.body[realparbeg : realparbeg] = subst
2852 if layoutname == "OverlayArea":
2853 m = rx.match(document.body[p])
2857 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2858 endPlain = find_end_of_layout(document.body, beginPlain)
2859 endInset = find_end_of_inset(document.body, p)
2860 content = document.body[beginPlain + 1 : endPlain]
2862 realparend = realparend - len(document.body[p : endInset + 1])
2864 del document.body[p : endInset + 1]
2865 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2866 document.body[realparbeg : realparbeg] = subst
2867 if layoutname == "AgainFrame":
2868 m = rx.match(document.body[p])
2872 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2873 endPlain = find_end_of_layout(document.body, beginPlain)
2874 endInset = find_end_of_inset(document.body, p)
2875 content = document.body[beginPlain + 1 : endPlain]
2877 realparend = realparend - len(document.body[p : endInset + 1])
2879 del document.body[p : endInset + 1]
2880 subst = put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
2881 document.body[realparbeg : realparbeg] = subst
2885 def revert_beamerargs3(document):
2886 " Reverts beamer arguments to old layout, step 3 "
2888 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2889 if document.textclass not in beamer_classes:
2892 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2895 i = find_token(document.body, "\\begin_inset Argument", i)
2898 # Find containing paragraph layout
2899 parent = get_containing_layout(document.body, i)
2901 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2906 realparbeg = parent[3]
2907 layoutname = parent[0]
2909 for p in range(parbeg, parend):
2913 if layoutname == "AgainFrame":
2914 m = rx.match(document.body[p])
2918 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2919 endPlain = find_end_of_layout(document.body, beginPlain)
2920 endInset = find_end_of_inset(document.body, p)
2921 content = document.body[beginPlain + 1 : endPlain]
2923 realparend = realparend - len(document.body[p : endInset + 1])
2925 del document.body[p : endInset + 1]
2926 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2927 document.body[realparbeg : realparbeg] = subst
2931 def revert_beamerflex(document):
2932 " Reverts beamer Flex insets "
2934 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2935 if document.textclass not in beamer_classes:
2938 new_flexes = {"Bold" : "\\textbf", "Emphasize" : "\\emph", "Only" : "\\only",
2939 "Uncover" : "\\uncover", "Visible" : "\\visible",
2940 "Invisible" : "\\invisible", "Alternative" : "\\alt",
2941 "Beamer_Note" : "\\note"}
2942 old_flexes = {"Alert" : "\\alert", "Structure" : "\\structure"}
2943 rx = re.compile(r'^\\begin_inset Flex (.+)$')
2947 i = find_token(document.body, "\\begin_inset Flex", i)
2950 m = rx.match(document.body[i])
2952 flextype = m.group(1)
2953 z = find_end_of_inset(document.body, i)
2955 document.warning("Can't find end of Flex " + flextype + " inset.")
2958 if flextype in new_flexes:
2959 pre = put_cmd_in_ert(new_flexes[flextype])
2960 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2962 argend = find_end_of_inset(document.body, arg)
2964 document.warning("Can't find end of Argument!")
2967 # Find containing paragraph layout
2968 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2969 endPlain = find_end_of_layout(document.body, beginPlain)
2970 argcontent = document.body[beginPlain + 1 : endPlain]
2972 z = z - len(document.body[arg : argend + 1])
2974 del document.body[arg : argend + 1]
2975 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2976 arg = find_token(document.body, "\\begin_inset Argument 2", i, z)
2978 argend = find_end_of_inset(document.body, arg)
2980 document.warning("Can't find end of Argument!")
2983 # Find containing paragraph layout
2984 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2985 endPlain = find_end_of_layout(document.body, beginPlain)
2986 argcontent = document.body[beginPlain + 1 : endPlain]
2988 z = z - len(document.body[arg : argend + 1])
2990 del document.body[arg : argend + 1]
2991 if flextype == "Alternative":
2992 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
2994 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2995 pre += put_cmd_in_ert("{")
2996 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2997 endPlain = find_end_of_layout(document.body, beginPlain)
2999 z = z - len(document.body[i : beginPlain + 1])
3001 document.body[i : beginPlain + 1] = pre
3002 post = put_cmd_in_ert("}")
3003 document.body[z - 2 : z + 1] = post
3004 elif flextype in old_flexes:
3005 pre = put_cmd_in_ert(old_flexes[flextype])
3006 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
3010 argend = find_end_of_inset(document.body, arg)
3012 document.warning("Can't find end of Argument!")
3015 # Find containing paragraph layout
3016 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3017 endPlain = find_end_of_layout(document.body, beginPlain)
3018 argcontent = document.body[beginPlain + 1 : endPlain]
3020 z = z - len(document.body[arg : argend + 1])
3022 del document.body[arg : argend + 1]
3023 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
3024 pre += put_cmd_in_ert("{")
3025 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
3026 endPlain = find_end_of_layout(document.body, beginPlain)
3028 z = z - len(document.body[i : beginPlain + 1])
3030 document.body[i : beginPlain + 1] = pre
3031 post = put_cmd_in_ert("}")
3032 document.body[z - 2 : z + 1] = post
3037 def revert_beamerblocks(document):
3038 " Reverts beamer block arguments to ERT "
3040 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3041 if document.textclass not in beamer_classes:
3044 blocks = ["Block", "ExampleBlock", "AlertBlock"]
3046 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3049 i = find_token(document.body, "\\begin_inset Argument", i)
3052 # Find containing paragraph layout
3053 parent = get_containing_layout(document.body, i)
3055 document.warning("Malformed LyX document: Can't find parent paragraph layout")
3060 realparbeg = parent[3]
3061 layoutname = parent[0]
3063 for p in range(parbeg, parend):
3067 if layoutname in blocks:
3068 m = rx.match(document.body[p])
3072 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3073 endPlain = find_end_of_layout(document.body, beginPlain)
3074 endInset = find_end_of_inset(document.body, p)
3075 content = document.body[beginPlain + 1 : endPlain]
3077 realparend = realparend - len(document.body[p : endInset + 1])
3079 del document.body[p : endInset + 1]
3080 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3081 document.body[realparbeg : realparbeg] = subst
3083 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3084 endPlain = find_end_of_layout(document.body, beginPlain)
3085 endInset = find_end_of_inset(document.body, p)
3086 content = document.body[beginPlain + 1 : endPlain]
3088 realparend = realparend - len(document.body[p : endInset + 1])
3090 del document.body[p : endInset + 1]
3091 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3092 document.body[realparbeg : realparbeg] = subst
3097 def convert_beamerblocks(document):
3098 " Converts beamer block ERT args to native InsetArgs "
3100 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3101 if document.textclass not in beamer_classes:
3104 blocks = ["Block", "ExampleBlock", "AlertBlock"]
3108 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
3111 parent = get_containing_layout(document.body, i)
3112 if parent == False or parent[1] != i:
3113 document.warning("Wrong parent layout!")
3120 # If the paragraph starts with a language switch, adjust parbeg
3121 if len(document.body[parbeg]) == 0 and parbeg < parend \
3122 and document.body[parbeg + 1].startswith("\\lang"):
3124 if document.body[parbeg] == "\\begin_inset ERT":
3125 ertcontfirstline = parbeg + 5
3129 # Find the last ERT in this paragraph used for arguments
3130 # (which might also be the first)
3131 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
3132 if lastertbeg == -1:
3133 document.warning("Last ERT not found!")
3135 lastertend = find_end_of_inset(document.body, lastertbeg)
3136 if lastertend == -1:
3137 document.warning("End of last ERT not found!")
3139 # Is this ERT really used for an argument?
3140 # Note: This will fail when non-argument ERTs actually use brackets
3142 regexp = re.compile(r'.*[>\]\}]', re.IGNORECASE)
3143 cbracket = find_re(document.body, regexp, lastertbeg, lastertend)
3146 if lastertbeg == parbeg:
3149 if lastertbeg == -1 or lastertend == -1:
3151 ertcontlastline = lastertend - 3
3153 if document.body[ertcontfirstline].lstrip().startswith("<"):
3154 # This is an overlay specification
3156 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3157 if document.body[ertcontlastline].rstrip().endswith(">"):
3159 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3160 # Convert to ArgInset
3161 document.body[parbeg] = "\\begin_inset Argument 1"
3162 elif document.body[ertcontlastline].rstrip().endswith("}"):
3164 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3166 ertcontdivline = ertcontfirstline
3167 tok = document.body[ertcontdivline].find('>{')
3169 regexp = re.compile(r'.*>\{', re.IGNORECASE)
3170 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3171 tok = document.body[ertcontdivline].find('>{')
3173 if ertcontfirstline < ertcontlastline:
3174 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3175 document.body[ertcontlastline : ertcontlastline + 1] = [
3176 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3177 if ertcontdivline == ertcontfirstline:
3178 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3179 '\\end_layout', '', '\\end_inset', '',
3180 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3181 'status collapsed', '', '\\begin_layout Plain Layout',
3182 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3183 document.body[ertcontdivline][tok + 2:]]
3185 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3186 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3187 'status collapsed', '', '\\begin_layout Plain Layout',
3188 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3189 document.body[ertcontdivline][tok + 2:]]
3191 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3192 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3193 'status collapsed', '', '\\begin_layout Plain Layout',
3194 document.body[ertcontdivline][tok + 2:]]
3196 # check if have delimiters in two different ERTs
3197 tok = document.body[ertcontdivline].find('>')
3199 regexp = re.compile(r'.*>', re.IGNORECASE)
3200 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3201 tok = document.body[ertcontdivline].find('>')
3203 tokk = document.body[ertcontdivline].find('{')
3205 regexp = re.compile(r'.*\{', re.IGNORECASE)
3206 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, lastertend)
3207 tokk = document.body[ertcontdivlinetwo].find('{')
3209 if ertcontfirstline < ertcontlastline:
3210 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3211 document.body[ertcontlastline : ertcontlastline + 1] = [
3212 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3213 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3214 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3215 '\\end_inset', '', '', '\\begin_inset Argument 2',
3216 'status collapsed', '', '\\begin_layout Plain Layout',
3217 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3218 document.body[ertcontdivlinetwo][tokk + 1:]]
3220 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3221 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3222 'status collapsed', '', '\\begin_layout Plain Layout',
3223 document.body[ertcontdivlinetwo][tokk + 1:]]
3224 # Convert to ArgInset
3225 if ertcontfirstline < ertcontlastline:
3226 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3227 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 1',
3228 'status collapsed', '', '\\begin_layout Plain Layout',
3229 '\\begin_inset ERT', '']
3231 document.body[parbeg] = "\\begin_inset Argument 1"
3232 elif document.body[ertcontfirstline].lstrip().startswith("{"):
3233 # This is the block title
3234 if document.body[ertcontlastline].rstrip().endswith("}"):
3235 # strip off the braces
3236 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3237 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3238 if ertcontfirstline < ertcontlastline:
3239 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3240 document.body[parend : parend + 1] = [
3241 document.body[parend], '\\end_inset', '', '\\end_layout']
3242 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3243 'status collapsed', '', '\\begin_layout Plain Layout',
3244 '\\begin_inset ERT', '']
3246 # Convert to ArgInset
3247 document.body[parbeg] = "\\begin_inset Argument 2"
3248 # the overlay argument can also follow the title, so ...
3249 elif document.body[ertcontlastline].rstrip().endswith(">"):
3251 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3253 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3255 ertcontdivline = ertcontfirstline
3256 tok = document.body[ertcontdivline].find('}<')
3258 regexp = re.compile(r'.*\}<', re.IGNORECASE)
3259 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3260 tok = document.body[ertcontdivline].find('}<')
3262 if ertcontfirstline < ertcontlastline:
3263 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3264 document.body[ertcontlastline : ertcontlastline + 1] = [
3265 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3266 if ertcontdivline == ertcontfirstline:
3267 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3268 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3269 'status collapsed', '', '\\begin_layout Plain Layout',
3270 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3271 document.body[ertcontdivline][tok + 2:]]
3273 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3274 '\\end_layout', '', '\\end_inset', '',
3275 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3276 'status collapsed', '', '\\begin_layout Plain Layout',
3277 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3278 document.body[ertcontdivline][tok + 2:]]
3280 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3281 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3282 'status collapsed', '', '\\begin_layout Plain Layout',
3283 document.body[ertcontdivline][tok + 2:]]
3285 # check if have delimiters in two different ERTs
3286 tok = document.body[ertcontdivline].find('}')
3288 regexp = re.compile(r'.*\}', re.IGNORECASE)
3289 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3290 tok = document.body[ertcontdivline].find('}')
3292 tokk = document.body[ertcontdivline].find('<')
3294 regexp = re.compile(r'.*<', re.IGNORECASE)
3295 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, lastertend)
3296 tokk = document.body[ertcontdivlinetwo].find('<')
3298 if ertcontfirstline < ertcontlastline:
3299 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3300 document.body[ertcontlastline : ertcontlastline + 1] = [
3301 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3302 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3303 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3304 '\\end_inset', '', '', '\\begin_inset Argument 1',
3305 'status collapsed', '', '\\begin_layout Plain Layout',
3306 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3307 document.body[ertcontdivlinetwo][tokk + 1:]]
3309 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3310 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3311 'status collapsed', '', '\\begin_layout Plain Layout',
3312 document.body[ertcontdivlinetwo][tokk + 1:]]
3313 # Convert to ArgInset
3314 if ertcontfirstline < ertcontlastline:
3315 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3316 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3317 'status collapsed', '', '\\begin_layout Plain Layout',
3318 '\\begin_inset ERT', '']
3320 document.body[parbeg] = "\\begin_inset Argument 2"
3321 elif count_pars_in_inset(document.body, ertcontfirstline) > 1:
3322 # Multipar ERT. Skip this.
3325 # ERT has contents after the closing bracket. We cannot convert this.
3326 # convert_TeX_brace_to_Argument cannot either.
3327 #convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, False)
3331 j = find_end_of_layout(document.body, i)
3333 document.warning("end of layout not found!")
3334 k = find_token(document.body, "\\begin_inset Argument", i, j)
3336 document.warning("InsetArgument not found!")
3338 l = find_end_of_inset(document.body, k)
3339 m = find_token(document.body, "\\begin_inset ERT", l, j)
3342 ertcontfirstline = m + 5
3347 def convert_overprint(document):
3348 " Convert old beamer overprint layouts to ERT "
3350 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3351 if document.textclass not in beamer_classes:
3356 i = find_token(document.body, "\\begin_layout Overprint", i)
3359 # Find end of sequence
3360 j = find_end_of_sequence(document.body, i)
3362 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3366 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3368 if document.body[j] == "\\end_deeper":
3369 esubst = ["", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3371 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3372 endseq = endseq + len(esubst) - len(document.body[j : j])
3373 document.body[j : j] = esubst
3374 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3376 argend = find_end_of_layout(document.body, argbeg)
3378 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3381 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3382 endPlain = find_end_of_layout(document.body, beginPlain)
3383 content = document.body[beginPlain + 1 : endPlain]
3385 endseq = endseq - len(document.body[argbeg : argend + 1])
3387 del document.body[argbeg : argend + 1]
3388 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3390 endseq = endseq - len(document.body[i : i])
3391 document.body[i : i] = subst + ["\\end_layout"]
3392 endseq += len(subst)
3394 for p in range(i, endseq):
3395 if document.body[p] == "\\begin_layout Overprint":
3396 document.body[p] = "\\begin_layout Standard"
3401 def revert_overprint(document):
3402 " Revert old beamer overprint layouts to ERT "
3404 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3405 if document.textclass not in beamer_classes:
3410 i = find_token(document.body, "\\begin_layout Overprint", i)
3413 # Find end of sequence
3414 j = find_end_of_sequence(document.body, i)
3416 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3420 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3421 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}")
3422 endseq = endseq + len(esubst) - len(document.body[j : j])
3423 if document.body[j] == "\\end_deeper":
3424 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3426 document.body[j : j] = ["\\end_layout", ""] + esubst
3429 if document.body[r] == "\\begin_deeper":
3430 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3432 document.body[r] = ""
3433 document.body[s] = ""
3437 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3439 # Is this really our argument?
3440 nested = find_token(document.body, "\\begin_deeper", i, argbeg)
3442 argend = find_end_of_inset(document.body, argbeg)
3444 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3447 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3448 endPlain = find_end_of_layout(document.body, beginPlain)
3449 content = document.body[beginPlain + 1 : endPlain]
3451 endseq = endseq - len(document.body[argbeg : argend])
3453 del document.body[argbeg : argend + 1]
3454 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3456 endseq = endseq - len(document.body[i : i])
3457 document.body[i : i] = subst + ["\\end_layout"]
3458 endseq += len(subst)
3464 if document.body[p] == "\\begin_layout Overprint":
3465 q = find_end_of_layout(document.body, p)
3467 document.warning("Malformed LyX document. Cannot find end of Overprint layout!")
3470 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\onslide")
3471 argbeg = find_token(document.body, "\\begin_inset Argument item:1", p, q)
3473 argend = find_end_of_inset(document.body, argbeg)
3475 document.warning("Malformed LyX document. Cannot find end of Overprint item argument!")
3478 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3479 endPlain = find_end_of_layout(document.body, beginPlain)
3480 content = document.body[beginPlain + 1 : endPlain]
3482 endseq = endseq - len(document.body[argbeg : argend + 1])
3484 del document.body[argbeg : argend + 1]
3485 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3486 endseq = endseq - len(document.body[p : p + 1]) + len(subst)
3487 document.body[p : p + 1] = subst
3493 def revert_frametitle(document):
3494 " Reverts beamer frametitle layout to ERT "
3496 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3497 if document.textclass not in beamer_classes:
3500 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3503 i = find_token(document.body, "\\begin_layout FrameTitle", i)
3506 j = find_end_of_layout(document.body, i)
3508 document.warning("Malformed LyX document: Can't find end of FrameTitle layout")
3512 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
3513 endlay += len(put_cmd_in_ert("}"))
3514 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\frametitle")
3515 for p in range(i, j):
3518 m = rx.match(document.body[p])
3522 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3523 endPlain = find_end_of_layout(document.body, beginPlain)
3524 endInset = find_end_of_inset(document.body, p)
3525 content = document.body[beginPlain + 1 : endPlain]
3527 endlay = endlay - len(document.body[p : endInset + 1])
3529 del document.body[p : endInset + 1]
3530 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3532 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3533 endPlain = find_end_of_layout(document.body, beginPlain)
3534 endInset = find_end_of_inset(document.body, p)
3535 content = document.body[beginPlain + 1 : endPlain]
3537 endlay = endlay - len(document.body[p : endInset + 1])
3539 del document.body[p : endInset + 1]
3540 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3542 subst += put_cmd_in_ert("{")
3543 document.body[i : i + 1] = subst
3547 def convert_epigraph(document):
3548 " Converts memoir epigraph to new syntax "
3550 if document.textclass != "memoir":
3555 i = find_token(document.body, "\\begin_layout Epigraph", i)
3558 j = find_end_of_layout(document.body, i)
3560 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3565 ert = find_token(document.body, "\\begin_inset ERT", i, j)
3567 endInset = find_end_of_inset(document.body, ert)
3568 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", ert)
3569 endPlain = find_end_of_layout(document.body, beginPlain)
3570 ertcont = beginPlain + 2
3571 if document.body[ertcont] == "}{":
3573 # Convert to ArgInset
3574 endlay = endlay - 2 * len(document.body[j])
3575 begsubst = ['\\begin_inset Argument post:1', 'status collapsed', '',
3576 '\\begin_layout Plain Layout']
3577 endsubst = ['\\end_layout', '', '\\end_inset', '', document.body[j]]
3578 document.body[j : j + 1] = endsubst
3579 document.body[endInset + 1 : endInset + 1] = begsubst
3581 endlay += len(begsubst) + len(endsubst)
3582 endlay = endlay - len(document.body[ert : endInset + 1])
3583 del document.body[ert : endInset + 1]
3588 def revert_epigraph(document):
3589 " Reverts memoir epigraph argument to ERT "
3591 if document.textclass != "memoir":
3596 i = find_token(document.body, "\\begin_layout Epigraph", i)
3599 j = find_end_of_layout(document.body, i)
3601 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3606 p = find_token(document.body, "\\begin_layout Argument post:1", i, j)
3608 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3609 endPlain = find_end_of_layout(document.body, beginPlain)
3610 endInset = find_end_of_inset(document.body, p)
3611 content = document.body[beginPlain + 1 : endPlain]
3613 endlay = endlay - len(document.body[p : endInset + 1])
3615 del document.body[p : endInset + 1]
3616 subst += put_cmd_in_ert("}{") + content
3618 subst += put_cmd_in_ert("}{")
3620 document.body[j : j] = subst + document.body[j : j]
3624 def convert_captioninsets(document):
3625 " Converts caption insets to new syntax "
3629 i = find_token(document.body, "\\begin_inset Caption", i)
3632 document.body[i] = "\\begin_inset Caption Standard"
3636 def revert_captioninsets(document):
3637 " Reverts caption insets to old syntax "
3641 i = find_token(document.body, "\\begin_inset Caption Standard", i)
3644 document.body[i] = "\\begin_inset Caption"
3648 def convert_captionlayouts(document):
3649 " Convert caption layouts to caption insets. "
3652 "Captionabove": "Above",
3653 "Captionbelow": "Below",
3654 "FigCaption" : "FigCaption",
3655 "Table_Caption" : "Table",
3656 "CenteredCaption" : "Centered",
3657 "Bicaption" : "Bicaption",
3660 for captype in caption_dict.keys():
3663 i = find_token(document.body, "\\begin_layout " + captype, i)
3666 j = find_end_of_layout(document.body, i)
3668 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3671 document.body[j:j] = ["\\end_layout", "", "\\end_inset", "", ""]
3672 document.body[i:i+1] = ["\\begin_layout %s" % document.default_layout,
3673 "\\begin_inset Caption %s" % caption_dict[captype], "",
3674 "\\begin_layout %s" % document.default_layout]
3678 def revert_captionlayouts(document):
3679 " Revert caption insets to caption layouts. "
3682 "Above" : "Captionabove",
3683 "Below" : "Captionbelow",
3684 "FigCaption" : "FigCaption",
3685 "Table" : "Table_Caption",
3686 "Centered" : "CenteredCaption",
3687 "Bicaption" : "Bicaption",
3691 rx = re.compile(r'^\\begin_inset Caption (\S+)$')
3693 i = find_token(document.body, "\\begin_inset Caption", i)
3697 m = rx.match(document.body[i])
3701 if val not in list(caption_dict.keys()):
3705 # We either need to delete the previous \begin_layout line, or we
3706 # need to end the previous layout if this inset is not in the first
3707 # position of the paragraph.
3708 layout_before = find_token_backwards(document.body, "\\begin_layout", i)
3709 if layout_before == -1:
3710 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3712 layout_line = document.body[layout_before]
3713 del_layout_before = True
3714 l = layout_before + 1
3716 if document.body[l] != "":
3717 del_layout_before = False
3720 if del_layout_before:
3721 del document.body[layout_before:i]
3724 document.body[i:i] = ["\\end_layout", ""]
3727 # Find start of layout in the inset and end of inset
3728 j = find_token(document.body, "\\begin_layout", i)
3730 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3732 k = find_end_of_inset(document.body, i)
3734 document.warning("Malformed LyX document: Missing `\\end_inset'.")
3737 # We either need to delete the following \end_layout line, or we need
3738 # to restart the old layout if this inset is not at the paragraph end.
3739 layout_after = find_token(document.body, "\\end_layout", k)
3740 if layout_after == -1:
3741 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3743 del_layout_after = True
3745 while l < layout_after:
3746 if document.body[l] != "":
3747 del_layout_after = False
3750 if del_layout_after:
3751 del document.body[k+1:layout_after+1]
3753 document.body[k+1:k+1] = [layout_line, ""]
3755 # delete \begin_layout and \end_inset and replace \begin_inset with
3756 # "\begin_layout XXX". This works because we can only have one
3757 # paragraph in the caption inset: The old \end_layout will be recycled.
3758 del document.body[k]
3759 if document.body[k] == "":
3760 del document.body[k]
3761 del document.body[j]
3762 if document.body[j] == "":
3763 del document.body[j]
3764 document.body[i] = "\\begin_layout %s" % caption_dict[val]
3765 if document.body[i+1] == "":
3766 del document.body[i+1]
3770 def revert_fragileframe(document):
3771 " Reverts beamer FragileFrame layout to ERT "
3773 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3774 if document.textclass not in beamer_classes:
3779 i = find_token(document.body, "\\begin_layout FragileFrame", i)
3782 # Find end of sequence
3783 j = find_end_of_sequence(document.body, i)
3785 document.warning("Malformed LyX document. Cannot find end of FragileFrame sequence!")
3789 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{frame}")
3790 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{frame}")
3791 endseq = endseq + len(esubst) - len(document.body[j : j])
3792 if document.body[j] == "\\end_deeper":
3793 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3795 document.body[j : j] = esubst
3796 for q in range(i, j):
3797 if document.body[q] == "\\begin_layout FragileFrame":
3798 document.body[q] = "\\begin_layout %s" % document.default_layout
3801 if document.body[r] == "\\begin_deeper":
3802 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3804 document.body[r] = ""
3805 document.body[s] = ""
3809 for p in range(1, 5):
3810 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, j)
3813 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3814 endPlain = find_end_of_layout(document.body, beginPlain)
3815 endInset = find_end_of_inset(document.body, arg)
3816 content = document.body[beginPlain + 1 : endPlain]
3818 j = j - len(document.body[arg : endInset + 1])
3820 del document.body[arg : endInset + 1]
3821 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3823 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3824 endPlain = find_end_of_layout(document.body, beginPlain)
3825 endInset = find_end_of_inset(document.body, arg)
3826 content = document.body[beginPlain + 1 : endPlain]
3828 j = j - len(document.body[arg : endInset + 1])
3830 del document.body[arg : endInset + 1]
3831 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3833 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3834 endPlain = find_end_of_layout(document.body, beginPlain)
3835 endInset = find_end_of_inset(document.body, arg)
3836 content = document.body[beginPlain + 1 : endPlain]
3838 j = j - len(document.body[arg : endInset + 1])
3840 del document.body[arg : endInset + 1]
3841 subst += put_cmd_in_ert("[fragile,") + content + put_cmd_in_ert("]")
3843 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3844 endPlain = find_end_of_layout(document.body, beginPlain)
3845 endInset = find_end_of_inset(document.body, arg)
3846 content = document.body[beginPlain + 1 : endPlain]
3848 j = j - len(document.body[arg : endInset + 1])
3850 del document.body[arg : endInset + 1]
3851 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3853 subst += put_cmd_in_ert("[fragile]")
3855 document.body[i : i + 1] = subst
3859 def revert_newframes(document):
3860 " Reverts beamer Frame and PlainFrame layouts to old forms "
3862 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3863 if document.textclass not in beamer_classes:
3867 "Frame" : "BeginFrame",
3868 "PlainFrame" : "BeginPlainFrame",
3871 rx = re.compile(r'^\\begin_layout (\S+)$')
3874 i = find_token(document.body, "\\begin_layout", i)
3878 m = rx.match(document.body[i])
3882 if val not in list(frame_dict.keys()):
3885 # Find end of sequence
3886 j = find_end_of_sequence(document.body, i)
3888 document.warning("Malformed LyX document. Cannot find end of Frame sequence!")
3892 subst = ["\\begin_layout %s" % frame_dict[val]]
3893 esubst = ["", "\\begin_layout EndFrame", "", "\\end_layout"]
3894 endseq = endseq + len(esubst) - len(document.body[j : j])
3895 if document.body[j] == "\\end_deeper":
3896 document.body[j : j] = esubst
3898 document.body[j+1 : j+1] = esubst
3899 for q in range(i, j):
3900 if document.body[q] == "\\begin_layout %s" % val:
3901 document.body[q] = "\\begin_layout %s" % document.default_layout
3904 if document.body[r] == "\\begin_deeper":
3905 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3907 document.body[r] = ""
3908 document.body[s] = ""
3912 l = find_end_of_layout(document.body, i)
3913 for p in range(1, 5):
3914 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, l)
3917 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3918 endPlain = find_end_of_layout(document.body, beginPlain)
3919 endInset = find_end_of_inset(document.body, arg)
3920 content = document.body[beginPlain + 1 : endPlain]
3922 l = l - len(document.body[arg : endInset + 1])
3924 del document.body[arg : endInset + 1]
3925 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3927 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3928 endPlain = find_end_of_layout(document.body, beginPlain)
3929 endInset = find_end_of_inset(document.body, arg)
3930 content = document.body[beginPlain + 1 : endPlain]
3932 l = l - len(document.body[arg : endInset + 1])
3934 del document.body[arg : endInset + 1]
3935 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3937 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3938 endPlain = find_end_of_layout(document.body, beginPlain)
3939 endInset = find_end_of_inset(document.body, arg)
3940 content = document.body[beginPlain + 1 : endPlain]
3942 l = l - len(document.body[arg : endInset + 1])
3944 del document.body[arg : endInset + 1]
3945 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3947 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3948 endPlain = find_end_of_layout(document.body, beginPlain)
3949 endInset = find_end_of_inset(document.body, arg)
3950 content = document.body[beginPlain + 1 : endPlain]
3952 l = l - len(document.body[arg : endInset + 1])
3954 del document.body[arg : endInset + 1]
3957 document.body[i : i + 1] = subst
3960 # known encodings that do not change their names (same LyX and LaTeX names)
3961 known_enc_tuple = ("auto", "default", "ansinew", "applemac", "armscii8", "ascii",
3962 "cp437", "cp437de", "cp850", "cp852", "cp855", "cp858", "cp862", "cp865", "cp866",
3963 "cp1250", "cp1251", "cp1252", "cp1255", "cp1256", "cp1257", "koi8-r", "koi8-u",
3964 "pt154", "pt254", "tis620-0", "utf8", "utf8x", "utf8-plain")
3966 def convert_encodings(document):
3967 "Use the LyX names of the encodings instead of the LaTeX names."
3968 LaTeX2LyX_enc_dict = {
3969 "8859-6": "iso8859-6",
3970 "8859-8": "iso8859-8",
3972 "euc": "euc-jp-platex",
3977 "iso88595": "iso8859-5",
3978 "iso-8859-7": "iso8859-7",
3980 "jis": "jis-platex",
3982 "l7xenc": "iso8859-13",
3983 "latin1": "iso8859-1",
3984 "latin2": "iso8859-2",
3985 "latin3": "iso8859-3",
3986 "latin4": "iso8859-4",
3987 "latin5": "iso8859-9",
3988 "latin9": "iso8859-15",
3989 "latin10": "iso8859-16",
3990 "SJIS": "shift-jis",
3991 "sjis": "shift-jis-platex",
3994 i = find_token(document.header, "\\inputencoding" , 0)
3997 val = get_value(document.header, "\\inputencoding", i)
3998 if val in list(LaTeX2LyX_enc_dict.keys()):
3999 document.header[i] = "\\inputencoding %s" % LaTeX2LyX_enc_dict[val]
4000 elif val not in known_enc_tuple:
4001 document.warning("Ignoring unknown input encoding: `%s'" % val)
4004 def revert_encodings(document):
4005 """Revert to using the LaTeX names of the encodings instead of the LyX names.
4006 Also revert utf8-platex to sjis, the language default when using Japanese.
4008 LyX2LaTeX_enc_dict = {
4013 "euc-jp-platex": "euc",
4016 "iso8859-1": "latin1",
4017 "iso8859-2": "latin2",
4018 "iso8859-3": "latin3",
4019 "iso8859-4": "latin4",
4020 "iso8859-5": "iso88595",
4021 "iso8859-6": "8859-6",
4022 "iso8859-7": "iso-8859-7",
4023 "iso8859-8": "8859-8",
4024 "iso8859-9": "latin5",
4025 "iso8859-13": "l7xenc",
4026 "iso8859-15": "latin9",
4027 "iso8859-16": "latin10",
4029 "jis-platex": "jis",
4030 "shift-jis": "SJIS",
4031 "shift-jis-platex": "sjis",
4033 "utf8-platex": "sjis"
4035 i = find_token(document.header, "\\inputencoding" , 0)
4038 val = get_value(document.header, "\\inputencoding", i)
4039 if val in list(LyX2LaTeX_enc_dict.keys()):
4040 document.header[i] = "\\inputencoding %s" % LyX2LaTeX_enc_dict[val]
4041 elif val not in known_enc_tuple:
4042 document.warning("Ignoring unknown input encoding: `%s'" % val)
4045 def revert_IEEEtran_3(document):
4047 Reverts Flex Insets to TeX-code
4049 if document.textclass == "IEEEtran":
4055 h = find_token(document.body, "\\begin_inset Flex Author Mark", h)
4057 endh = find_end_of_inset(document.body, h)
4058 document.body[endh - 2 : endh + 1] = put_cmd_in_ert("}")
4059 document.body[h : h + 4] = put_cmd_in_ert("\\IEEEauthorrefmark{")
4062 i = find_token(document.body, "\\begin_inset Flex Author Name", i)
4064 endi = find_end_of_inset(document.body, i)
4065 document.body[endi - 2 : endi + 1] = put_cmd_in_ert("}")
4066 document.body[i : i + 4] = put_cmd_in_ert("\\IEEEauthorblockN{")
4069 j = find_token(document.body, "\\begin_inset Flex Author Affiliation", j)
4071 endj = find_end_of_inset(document.body, j)
4072 document.body[endj - 2 : endj + 1] = put_cmd_in_ert("}")
4073 document.body[j : j + 4] = put_cmd_in_ert("\\IEEEauthorblockA{")
4075 if i == -1 and j == -1 and h == -1:
4079 def revert_kurier_fonts(document):
4080 " Revert kurier font definition to LaTeX "
4082 i = find_token(document.header, "\\font_math", 0)
4084 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4085 val = get_value(document.header, "\\font_math", i)
4086 if val == "kurier-math":
4087 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
4088 "\\usepackage[math]{kurier}\n" \
4089 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
4090 document.header[i] = "\\font_math auto"
4092 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4093 kurier_fonts = ["kurier", "kurierc", "kurierl", "kurierlc"]
4094 k = find_token(document.header, "\\font_sans kurier", 0)
4096 sf = get_value(document.header, "\\font_sans", k)
4097 if sf in kurier_fonts:
4098 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4099 document.header[k] = "\\font_sans default"
4101 def revert_iwona_fonts(document):
4102 " Revert iwona font definition to LaTeX "
4104 i = find_token(document.header, "\\font_math", 0)
4106 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4107 val = get_value(document.header, "\\font_math", i)
4108 if val == "iwona-math":
4109 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
4110 "\\usepackage[math]{iwona}\n" \
4111 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
4112 document.header[i] = "\\font_math auto"
4114 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4115 iwona_fonts = ["iwona", "iwonac", "iwonal", "iwonalc"]
4116 k = find_token(document.header, "\\font_sans iwona", 0)
4118 sf = get_value(document.header, "\\font_sans", k)
4119 if sf in iwona_fonts:
4120 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4121 document.header[k] = "\\font_sans default"
4124 def revert_new_libertines(document):
4125 " Revert new libertine font definition to LaTeX "
4127 if find_token(document.header, "\\use_non_tex_fonts true", 0) != -1:
4130 i = find_token(document.header, "\\font_typewriter libertine-mono", 0)
4132 preamble = "\\usepackage"
4133 sc = find_token(document.header, "\\font_tt_scale", 0)
4135 scval = get_value(document.header, "\\font_tt_scale", sc)
4137 preamble += "[scale=%f]" % (float(scval) / 100)
4138 document.header[sc] = "\\font_tt_scale 100"
4139 preamble += "{libertineMono-type1}"
4140 add_to_preamble(document, [preamble])
4141 document.header[i] = "\\font_typewriter default"
4143 k = find_token(document.header, "\\font_sans biolinum", 0)
4145 preamble = "\\usepackage"
4147 j = find_token(document.header, "\\font_osf true", 0)
4152 sc = find_token(document.header, "\\font_sf_scale", 0)
4154 scval = get_value(document.header, "\\font_sf_scale", sc)
4156 options += ",scale=%f" % (float(scval) / 100)
4157 document.header[sc] = "\\font_sf_scale 100"
4159 preamble += "[" + options +"]"
4160 preamble += "{biolinum-type1}"
4161 add_to_preamble(document, [preamble])
4162 document.header[k] = "\\font_sans default"
4165 def convert_lyxframes(document):
4166 " Converts old beamer frames to new style "
4168 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4169 if document.textclass not in beamer_classes:
4172 framebeg = ["BeginFrame", "BeginPlainFrame"]
4173 frameend = ["Frame", "PlainFrame", "EndFrame", "BeginFrame", "BeginPlainFrame", "AgainFrame",
4174 "Section", "Section*", "Subsection", "Subsection*", "Subsubsection", "Subsubsection*"]
4175 for lay in framebeg:
4178 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
4181 parent = get_containing_layout(document.body, i)
4182 if parent == False or parent[1] != i:
4183 document.warning("Wrong parent layout!")
4186 frametype = parent[0]
4190 # Step I: Convert ERT arguments
4191 # FIXME: See restrictions in convert_beamerframeargs method
4192 ertend = convert_beamerframeargs(document, i, parbeg)
4195 # Step II: Now rename the layout and convert the title to an argument
4196 j = find_end_of_layout(document.body, i)
4197 document.body[j : j + 1] = ['\\end_layout', '', '\\end_inset', '', '\\end_layout']
4198 if lay == "BeginFrame":
4199 document.body[i] = "\\begin_layout Frame"
4201 document.body[i] = "\\begin_layout PlainFrame"
4202 document.body[ertend + 1 : ertend + 1] = ['\\begin_inset Argument 4',
4203 'status open', '', '\\begin_layout Plain Layout']
4204 # Step III: find real frame end
4207 inInset = get_containing_inset(document.body, i)
4209 fend = find_token(document.body, "\\begin_layout", jj)
4211 document.warning("Malformed LyX document: No real frame end!")
4213 val = get_value(document.body, "\\begin_layout", fend)
4214 if val not in frameend:
4217 # is this frame nested in an inset (e.g., Note)?
4218 if inInset != False:
4219 # if so, end the frame inside the inset
4220 if inInset[2] < fend:
4222 if val == frametype:
4223 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4224 # consider explicit EndFrames between two identical frame types
4225 elif val == "EndFrame":
4226 nextlayout = find_token(document.body, "\\begin_layout", fend + 1)
4227 if nextlayout != -1 and get_value(document.body, "\\begin_layout", nextlayout) == frametype:
4228 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4230 document.body[fend : fend] = ['\\end_deeper']
4232 document.body[fend : fend] = ['\\end_deeper']
4233 document.body[j + 1 : j + 1] = ['', '\\begin_deeper']
4238 def remove_endframes(document):
4239 " Remove deprecated beamer endframes "
4241 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4242 if document.textclass not in beamer_classes:
4247 i = find_token_exact(document.body, "\\begin_layout EndFrame", i)
4250 j = find_end_of_layout(document.body, i)
4252 document.warning("Malformed LyX document: Missing \\end_layout to EndFrame")
4255 del document.body[i : j + 1]
4258 def revert_powerdot_flexes(document):
4259 " Reverts powerdot flex insets "
4261 if document.textclass != "powerdot":
4264 flexes = {"Onslide" : "\\onslide",
4265 "Onslide*" : "\\onslide*",
4266 "Onslide+" : "\\onslide+"}
4267 rx = re.compile(r'^\\begin_inset Flex (.+)$')
4271 i = find_token(document.body, "\\begin_inset Flex", i)
4274 m = rx.match(document.body[i])
4276 flextype = m.group(1)
4277 z = find_end_of_inset(document.body, i)
4279 document.warning("Can't find end of Flex " + flextype + " inset.")
4282 if flextype in flexes:
4283 pre = put_cmd_in_ert(flexes[flextype])
4284 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
4286 argend = find_end_of_inset(document.body, arg)
4288 document.warning("Can't find end of Argument!")
4291 # Find containing paragraph layout
4292 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
4293 endPlain = find_end_of_layout(document.body, beginPlain)
4294 argcontent = document.body[beginPlain + 1 : endPlain]
4296 z = z - len(document.body[arg : argend + 1])
4298 del document.body[arg : argend + 1]
4299 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
4300 pre += put_cmd_in_ert("{")
4301 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4302 endPlain = find_end_of_layout(document.body, beginPlain)
4304 z = z - len(document.body[i : beginPlain + 1])
4306 document.body[i : beginPlain + 1] = pre
4307 post = put_cmd_in_ert("}")
4308 document.body[z - 2 : z + 1] = post
4312 def revert_powerdot_pause(document):
4313 " Reverts powerdot pause layout to ERT "
4315 if document.textclass != "powerdot":
4320 i = find_token(document.body, "\\begin_layout Pause", i)
4323 j = find_end_of_layout(document.body, i)
4325 document.warning("Malformed LyX document: Can't find end of Pause layout")
4329 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\pause")
4330 for p in range(i, j):
4333 arg = find_token(document.body, "\\begin_inset Argument 1", i, j)
4335 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4336 endPlain = find_end_of_layout(document.body, beginPlain)
4337 endInset = find_end_of_inset(document.body, p)
4338 content = document.body[beginPlain + 1 : endPlain]
4340 endlay = endlay - len(document.body[p : endInset + 1])
4342 del document.body[p : endInset + 1]
4343 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4345 document.body[i : i + 1] = subst
4349 def revert_powerdot_itemargs(document):
4350 " Reverts powerdot item arguments to ERT "
4352 if document.textclass != "powerdot":
4356 list_layouts = ["Itemize", "ItemizeType1", "Enumerate", "EnumerateType1"]
4357 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4360 i = find_token(document.body, "\\begin_inset Argument", i)
4363 # Find containing paragraph layout
4364 parent = get_containing_layout(document.body, i)
4366 document.warning("Malformed LyX document: Can't find parent paragraph layout")
4371 realparbeg = parent[3]
4372 layoutname = parent[0]
4374 for p in range(parbeg, parend):
4378 if layoutname in list_layouts:
4379 m = rx.match(document.body[p])
4382 if argnr == "item:1":
4383 j = find_end_of_inset(document.body, i)
4384 # Find containing paragraph layout
4385 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4386 endPlain = find_end_of_layout(document.body, beginPlain)
4387 content = document.body[beginPlain + 1 : endPlain]
4388 del document.body[i:j+1]
4389 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4390 document.body[realparbeg : realparbeg] = subst
4391 elif argnr == "item:2":
4392 j = find_end_of_inset(document.body, i)
4393 # Find containing paragraph layout
4394 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4395 endPlain = find_end_of_layout(document.body, beginPlain)
4396 content = document.body[beginPlain + 1 : endPlain]
4397 del document.body[i:j+1]
4398 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
4399 document.body[realparbeg : realparbeg] = subst
4404 def revert_powerdot_columns(document):
4405 " Reverts powerdot twocolumn to TeX-code "
4406 if document.textclass != "powerdot":
4409 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4412 i = find_token(document.body, "\\begin_layout Twocolumn", i)
4415 j = find_end_of_layout(document.body, i)
4417 document.warning("Malformed LyX document: Can't find end of Twocolumn layout")
4421 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
4422 endlay += len(put_cmd_in_ert("}"))
4423 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\twocolumn")
4424 for p in range(i, j):
4427 m = rx.match(document.body[p])
4431 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4432 endPlain = find_end_of_layout(document.body, beginPlain)
4433 endInset = find_end_of_inset(document.body, p)
4434 content = document.body[beginPlain + 1 : endPlain]
4436 endlay = endlay - len(document.body[p : endInset + 1])
4438 del document.body[p : endInset + 1]
4439 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4441 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4442 endPlain = find_end_of_layout(document.body, beginPlain)
4443 endInset = find_end_of_inset(document.body, p)
4444 content = document.body[beginPlain + 1 : endPlain]
4446 endlay = endlay - len(document.body[p : endInset + 1])
4448 del document.body[p : endInset + 1]
4449 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
4451 subst += put_cmd_in_ert("{")
4452 document.body[i : i + 1] = subst
4456 def revert_mbox_fbox(document):
4457 'Convert revert mbox/fbox boxes to TeX-code'
4460 i = find_token(document.body, "\\begin_inset Box", i)
4463 j = find_token(document.body, "width", i)
4465 document.warning("Malformed LyX document: Can't find box width")
4467 width = get_value(document.body, "width", j)
4468 k = find_end_of_inset(document.body, j)
4470 document.warning("Malformed LyX document: Can't find end of box inset")
4473 BeginLayout = find_token(document.body, "\\begin_layout Plain Layout", j)
4474 EndLayout = find_end_of_layout(document.body, BeginLayout)
4475 # replace if width is ""
4477 document.body[EndLayout:k + 1] = put_cmd_in_ert("}")
4478 if document.body[i] == "\\begin_inset Box Frameless":
4479 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\mbox{")
4480 if document.body[i] == "\\begin_inset Box Boxed":
4481 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\fbox{")
4485 def revert_starred_caption(document):
4486 " Reverts unnumbered longtable caption insets "
4490 i = find_token(document.body, "\\begin_inset Caption LongTableNoNumber", i)
4493 # This is not equivalent, but since the caption inset is a full blown
4494 # text inset a true conversion to ERT is too difficult.
4495 document.body[i] = "\\begin_inset Caption Standard"
4499 def revert_forced_local_layout(document):
4502 i = find_token(document.header, "\\begin_forced_local_layout", i)
4505 j = find_end_of(document.header, i, "\\begin_forced_local_layout", "\\end_forced_local_layout")
4507 # this should not happen
4509 regexp = re.compile(r'\s*forcelocal', re.IGNORECASE)
4510 k = find_re(document.header, regexp, i, j)
4512 del document.header[k]
4514 k = find_re(document.header, regexp, i, j)
4515 k = find_token(document.header, "\\begin_local_layout", 0)
4517 document.header[i] = "\\begin_local_layout"
4518 document.header[j] = "\\end_local_layout"
4520 l = find_end_of(document.header, k, "\\begin_local_layout", "\\end_local_layout")
4522 # this should not happen
4524 lines = document.header[i+1 : j]
4526 document.header[k+1 : k+1] = lines
4527 document.header[i : j ] = []
4529 document.header[i : j ] = []
4530 document.header[k+1 : k+1] = lines
4533 def revert_aa1(document):
4534 " Reverts InsetArguments of aa to TeX-code "
4535 if document.textclass == "aa":
4539 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4541 revert_Argument_to_TeX_brace(document, i, 0, 1, 4, False, False)
4547 def revert_aa2(document):
4548 " Reverts InsetArguments of aa to TeX-code "
4549 if document.textclass == "aa":
4553 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4555 document.body[i] = "\\begin_layout Abstract"
4561 def revert_tibetan(document):
4562 "Set the document language for Tibetan to English"
4564 if document.language == "tibetan":
4565 document.language = "english"
4566 i = find_token(document.header, "\\language", 0)
4568 document.header[i] = "\\language english"
4570 while j < len(document.body):
4571 j = find_token(document.body, "\\lang tibetan", j)
4573 document.body[j] = document.body[j].replace("\\lang tibetan", "\\lang english")
4576 j = len(document.body)
4585 # The idea here is that we will have a sequence of chunk paragraphs.
4586 # We want to convert them to paragraphs in one or several chunk insets.
4587 # Individual chunks are terminated by the character @ on the last line.
4588 # This line will be discarded, and following lines are treated as new
4589 # chunks, which go into their own insets.
4590 # The first line of a chunk should look like: <<CONTENT>>=
4591 # We will discard the delimiters, and put the CONTENT into the
4592 # optional argument of the inset, if the CONTENT is non-empty.
4593 def convert_chunks(document):
4594 first_re = re.compile(r'<<(.*)>>=(.*)')
4597 # find start of a block of chunks
4598 i = find_token(document.body, "\\begin_layout Chunk", file_pos)
4604 chunk_started = False
4607 # process the one we just found
4608 j = find_end_of_layout(document.body, i)
4610 document.warning("Malformed LyX documents. Can't find end of Chunk layout!")
4611 # there is no point continuing, as we will run into the same error again.
4613 this_chunk = "".join(document.body[i + 1:j])
4615 # there may be empty lines between chunks
4616 # we just skip them.
4617 if not chunk_started:
4618 if this_chunk != "":
4620 chunk_started = True
4623 contents.append(document.body[i + 1:j])
4625 # look for potential chunk terminator
4626 # on the last line of the chunk paragraph
4627 if document.body[j - 1] == "@":
4630 # look for subsequent chunk paragraph
4631 i = find_token(document.body, "\\begin_layout", j)
4635 if get_value(document.body, "\\begin_layout", i) != "Chunk":
4638 file_pos = end = j + 1
4640 # The last chunk should simply have an "@" in it
4641 # or at least end with "@" (can happen if @ is
4642 # preceded by a newline)
4644 if len(contents) > 0:
4645 lastpar = ''.join(contents[-1])
4646 if not lastpar.endswith("@"):
4647 document.warning("Unexpected chunk content: chunk not terminated by '@'!")
4648 if len(contents) == 0:
4649 # convert empty chunk layouts to Standard
4650 document.body[start] = "\\begin_layout Standard"
4654 # chunk par only contains "@". Just drop it.
4657 # chunk par contains more. Only drop the "@".
4660 # The first line should look like: <<CONTENT>>=
4661 # We want the CONTENT
4662 optarg = ' '.join(contents[0])
4664 # We can already have real chunk content in
4665 # the first par (separated from the options by a newline).
4666 # We collect such stuff to re-insert it later.
4669 match = first_re.search(optarg)
4671 optarg = match.groups()[0]
4672 if match.groups()[1] != "":
4674 for c in contents[0]:
4675 if c.endswith(">>="):
4679 postoptstuff.append(c)
4680 # We have stripped everything. This can be deleted.
4683 newstuff = ['\\begin_layout Standard']
4685 # Maintain paragraph parameters
4686 par_params = ["\\noindent", "\\indent", "\\indent-toggle", "\\leftindent",
4687 "\\start_of_appendix", "\\paragraph_spacing", "\\align",
4688 "\\labelwidthstring"]
4691 if document.body[parms].split(' ', 1)[0] not in par_params:
4693 newstuff.extend([document.body[parms]])
4697 ['\\begin_inset Flex Chunk',
4699 '\\begin_layout Plain Layout', ''])
4701 # If we have a non-empty optional argument, insert it.
4702 if match and optarg != "":
4704 ['\\begin_inset Argument 1',
4706 '\\begin_layout Plain Layout',
4711 # Since we already opened a Plain layout, the first paragraph
4712 # does not need to do that.
4715 # we need to replace newlines with new layouts
4717 started_text = False
4718 for lno in range(0,len(postoptstuff)):
4719 if postoptstuff[lno].startswith("\\begin_inset Newline newline"):
4721 elif start_newline != -1:
4722 if postoptstuff[lno].startswith("\\end_inset"):
4723 # replace that bit, but only if we already have some text
4724 # and we're not at the end except for a blank line
4725 if started_text and \
4726 (lno != len(postoptstuff) - 2 or postoptstuff[-1] != ""):
4727 newstuff.extend(['\\end_layout', '\n', '\\begin_layout Plain Layout', '\n'])
4731 newstuff.extend([postoptstuff[lno]])
4732 newstuff.append('\\end_layout')
4736 newstuff.extend(['', '\\begin_layout Plain Layout', ''])
4740 newstuff.append('\\end_layout')
4742 newstuff.extend(['', '\\end_inset', '', '\\end_layout', ''])
4744 document.body[start:end] = newstuff
4746 file_pos += len(newstuff) - (end - start)
4749 def revert_chunks(document):
4752 i = find_token(document.body, "\\begin_inset Flex Chunk", i)
4756 iend = find_end_of_inset(document.body, i)
4758 document.warning("Can't find end of Chunk!")
4762 # Look for optional argument
4764 ostart = find_token(document.body, "\\begin_inset Argument 1", i, iend)
4766 oend = find_end_of_inset(document.body, ostart)
4767 k = find_token(document.body, "\\begin_layout Plain Layout", ostart, oend)
4769 document.warning("Malformed LyX document: Can't find argument contents!")
4771 m = find_end_of_layout(document.body, k)
4772 optarg = "".join(document.body[k+1:m])
4774 # We now remove the optional argument, so we have something
4775 # uniform on which to work
4776 document.body[ostart : oend + 1] = []
4777 # iend is now invalid
4778 iend = find_end_of_inset(document.body, i)
4780 retval = get_containing_layout(document.body, i)
4782 document.warning("Can't find containing layout for Chunk!")
4785 (lname, lstart, lend, pstart) = retval
4786 # we now want to work through the various paragraphs, and collect their contents
4790 k = find_token(document.body, "\\begin_layout Plain Layout", k, lend)
4793 j = find_end_of_layout(document.body, k)
4795 document.warning("Can't find end of layout inside chunk!")
4797 parlist.append(document.body[k+1:j])
4799 # we now need to wrap all of these paragraphs in chunks
4801 newlines.extend(["\\begin_layout Chunk", "", "<<" + optarg + ">>=", "\\end_layout", ""])
4802 for stuff in parlist:
4803 newlines.extend(["\\begin_layout Chunk"] + stuff + ["\\end_layout", ""])
4804 newlines.extend(["\\begin_layout Chunk", "", "@", "\\end_layout", ""])
4805 # replace old content with new content
4806 document.body[lstart : lend + 1] = newlines
4807 i = lstart + len(newlines)
4814 supported_versions = ["2.1.0","2.1"]
4817 [415, [convert_undertilde]],
4819 [417, [convert_japanese_encodings]],
4820 [418, [convert_justification]],
4822 [420, [convert_biblio_style]],
4823 [421, [convert_longtable_captions]],
4824 [422, [convert_use_packages]],
4825 [423, [convert_use_mathtools]],
4826 [424, [convert_cite_engine_type]],
4827 # No convert_cancel, since cancel will be loaded automatically
4828 # in format 425 without any possibility to switch it off.
4829 # This has been fixed in format 464.
4833 [428, [convert_cell_rotation]],
4834 [429, [convert_table_rotation]],
4835 [430, [convert_listoflistings]],
4836 [431, [convert_use_amssymb]],
4838 [433, [convert_armenian]],
4845 [440, [convert_mathfonts]],
4846 [441, [convert_mdnomath]],
4851 [446, [convert_latexargs]],
4852 [447, [convert_IEEEtran, convert_AASTeX, convert_AGUTeX, convert_IJMP, convert_SIGPLAN, convert_SIGGRAPH, convert_EuropeCV, convert_Initials, convert_ModernCV]],
4853 [448, [convert_literate]],
4856 [451, [convert_beamerargs, convert_againframe_args, convert_corollary_args, convert_quote_args]],
4857 [452, [convert_beamerblocks]],
4858 [453, [convert_use_stmaryrd]],
4859 [454, [convert_overprint]],
4861 [456, [convert_epigraph]],
4862 [457, [convert_use_stackrel]],
4863 [458, [convert_captioninsets, convert_captionlayouts]],
4868 [463, [convert_encodings]],
4869 [464, [convert_use_cancel]],
4870 [465, [convert_lyxframes, remove_endframes]],
4876 [471, [convert_cite_engine_type_default]],
4879 [474, [convert_chunks, cleanup_beamerargs]],
4883 [473, [revert_chunks]],
4884 [472, [revert_tibetan]],
4885 [471, [revert_aa1,revert_aa2]],
4886 [470, [revert_cite_engine_type_default]],
4887 [469, [revert_forced_local_layout]],
4888 [468, [revert_starred_caption]],
4889 [467, [revert_mbox_fbox]],
4890 [466, [revert_iwona_fonts]],
4891 [465, [revert_powerdot_flexes, revert_powerdot_pause, revert_powerdot_itemargs, revert_powerdot_columns]],
4893 [463, [revert_use_cancel]],
4894 [462, [revert_encodings]],
4895 [461, [revert_new_libertines]],
4896 [460, [revert_kurier_fonts]],
4897 [459, [revert_IEEEtran_3]],
4898 [458, [revert_fragileframe, revert_newframes]],
4899 [457, [revert_captioninsets, revert_captionlayouts]],
4900 [456, [revert_use_stackrel]],
4901 [455, [revert_epigraph]],
4902 [454, [revert_frametitle]],
4903 [453, [revert_overprint]],
4904 [452, [revert_use_stmaryrd]],
4905 [451, [revert_beamerblocks]],
4906 [450, [revert_beamerargs, revert_beamerargs2, revert_beamerargs3, revert_beamerflex]],
4907 [449, [revert_garamondx, revert_garamondx_newtxmath]],
4908 [448, [revert_itemargs]],
4909 [447, [revert_literate]],
4910 [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]],
4911 [445, [revert_latexargs]],
4912 [444, [revert_uop]],
4913 [443, [revert_biolinum]],
4915 [441, [revert_newtxmath]],
4916 [440, [revert_mdnomath]],
4917 [439, [revert_mathfonts]],
4918 [438, [revert_minionpro]],
4919 [437, [revert_ipadeco, revert_ipachar]],
4920 [436, [revert_texgyre]],
4921 [435, [revert_mathdesign]],
4922 [434, [revert_txtt]],
4923 [433, [revert_libertine]],
4924 [432, [revert_armenian]],
4925 [431, [revert_languages, revert_ancientgreek]],
4926 [430, [revert_use_amssymb]],
4927 [429, [revert_listoflistings]],
4928 [428, [revert_table_rotation]],
4929 [427, [revert_cell_rotation]],
4930 [426, [revert_tipa]],
4931 [425, [revert_verbatim]],
4932 [424, [revert_cancel]],
4933 [423, [revert_cite_engine_type]],
4934 [422, [revert_use_mathtools]],
4935 [421, [revert_use_packages]],
4936 [420, [revert_longtable_captions]],
4937 [419, [revert_biblio_style]],
4938 [418, [revert_australian]],
4939 [417, [revert_justification]],
4940 [416, [revert_japanese_encodings]],
4941 [415, [revert_negative_space, revert_math_spaces]],
4942 [414, [revert_undertilde]],
4943 [413, [revert_visible_space]]
4947 if __name__ == "__main__":