1 # -*- coding: utf-8 -*-
2 # This file is part of lyx2lyx
3 # -*- coding: utf-8 -*-
4 # Copyright (C) 2011 The LyX team
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 """ Convert files to the file format generated by LyX 2.1"""
26 # Uncomment only what you need to import, please.
28 from parser_tools import count_pars_in_inset, del_token, find_token, find_token_exact, \
29 find_token_backwards, find_end_of, find_end_of_inset, find_end_of_layout, \
30 find_end_of_sequence, find_re, get_option_value, get_containing_layout, \
31 get_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 beginBrace == endBrace + 11 or beginBrace == endBrace + 12:
185 end = find_token(document.body, "\\end_inset", beginBrace)
186 document.body[lineERT : end + 1] = ["\\end_layout", "", "\\end_inset"]
188 # in the case that n > 1 we have optional arguments before
189 # therefore detect them if any
191 # first check if there is an argument
192 lineArg = find_token(document.body, "\\begin_inset Argument", line)
193 if lineArg < lineERT and lineArg != -1:
194 # we have an argument, so now search backwards for its end
195 # we must now assure that we don't find other insets like e.g. a newline
196 endInsetArg = lineERT
197 endLayoutArg = endInsetArg
198 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
199 endInsetArg = endInsetArg - 1
200 endLayoutArg = endInsetArg
201 endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
202 endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
203 line = endInsetArg + 1
205 document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
207 document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
209 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
212 # set the line where the next argument will be inserted
213 if beginBrace == endBrace + 11:
221 if environment == True:
222 end_ERT = find_end_of_inset(document.body, lineERT)
224 document.warning("Can't find end of ERT!!")
226 # Note that this only checks for [ or { at the beginning of a line
228 opening = find_token(document.body, "[", lineERT, end_ERT)
230 opening = find_token(document.body, "{", lineERT, end_ERT)
232 lineERT2 = find_token(document.body, "\\begin_inset ERT", end_ERT, end_layout)
234 # argument in a single ERT
235 # strip off the opening bracket
236 document.body[opening] = document.body[opening][1:]
237 ertcontlastline = end_ERT - 3
238 if (opt and document.body[ertcontlastline].endswith("]")) or document.body[ertcontlastline].endswith("}"):
239 # strip off the closing bracket
240 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
241 end2 = find_token(document.body, "\\end_inset", ertcontlastline)
242 document.body[lineERT : lineERT + 1] = ["\\begin_inset Argument " + str(n)]
244 end_ERT2 = find_end_of_inset(document.body, lineERT2)
246 document.warning("Can't find end of second ERT!!")
249 closing = find_token(document.body, "]", lineERT2, end_ERT2)
251 closing = find_token(document.body, "}", lineERT2, end_ERT2)
252 if closing != -1: # assure that the "}" is in this ERT
253 end2 = find_token(document.body, "\\end_inset", closing)
254 document.body[lineERT2 : end2 + 1] = ["\\end_layout", "", "\\end_inset"]
255 document.body[lineERT : end_ERT + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
259 ###############################################################################
261 ### Conversion and reversion routines
263 ###############################################################################
265 def revert_visible_space(document):
266 "Revert InsetSpace visible into its ERT counterpart"
269 i = find_token(document.body, "\\begin_inset space \\textvisiblespace{}", i)
272 end = find_end_of_inset(document.body, i)
273 subst = put_cmd_in_ert("\\textvisiblespace{}")
274 document.body[i:end + 1] = subst
277 undertilde_commands = ["utilde"]
278 def convert_undertilde(document):
279 " Load undertilde automatically "
280 i = find_token(document.header, "\\use_mathdots" , 0)
282 i = find_token(document.header, "\\use_mhchem" , 0)
284 i = find_token(document.header, "\\use_esint" , 0)
286 document.warning("Malformed LyX document: Can't find \\use_mathdots.")
288 j = find_token(document.preamble, "\\usepackage{undertilde}", 0)
290 # package was loaded in the preamble, convert this to header setting for round trip
291 document.header.insert(i + 1, "\\use_undertilde 2") # on
292 del document.preamble[j]
296 j = find_token(document.body, '\\begin_inset Formula', j)
299 k = find_end_of_inset(document.body, j)
301 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(j))
304 code = "\n".join(document.body[j:k])
305 for c in undertilde_commands:
306 if code.find("\\%s" % c) != -1:
307 # at least one of the commands was found - need to switch package off
308 document.header.insert(i + 1, "\\use_undertilde 0") # off
311 # no command was found - set to auto (bug 9069)
312 document.header.insert(i + 1, "\\use_undertilde 1") # auto
316 def revert_undertilde(document):
317 " Load undertilde if used in the document "
318 regexp = re.compile(r'(\\use_undertilde)')
319 i = find_re(document.header, regexp, 0)
320 value = "1" # default is auto
322 value = get_value(document.header, "\\use_undertilde" , i).split()[0]
323 del document.header[i]
324 if value == "2": # on
325 add_to_preamble(document, ["\\usepackage{undertilde}"])
326 elif value == "1": # auto
329 i = find_token(document.body, '\\begin_inset Formula', i)
332 j = find_end_of_inset(document.body, i)
334 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
337 code = "\n".join(document.body[i:j])
338 for c in undertilde_commands:
339 if code.find("\\%s" % c) != -1:
340 add_to_preamble(document, ["\\usepackage{undertilde}"])
345 def revert_negative_space(document):
346 "Revert InsetSpace negmedspace and negthickspace into its TeX-code counterpart"
351 i = find_token(document.body, "\\begin_inset space \\negmedspace{}", i)
353 j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
355 # load amsmath in the preamble if not already loaded if we are at the end of checking
357 i = find_token(document.header, "\\use_amsmath 2", 0)
359 add_to_preamble(document, ["\\@ifundefined{negthickspace}{\\usepackage{amsmath}}"])
363 end = find_end_of_inset(document.body, i)
364 subst = put_cmd_in_ert("\\negmedspace{}")
365 document.body[i:end + 1] = subst
366 j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
369 end = find_end_of_inset(document.body, j)
370 subst = put_cmd_in_ert("\\negthickspace{}")
371 document.body[j:end + 1] = subst
375 def revert_math_spaces(document):
376 "Revert formulas with protected custom space and protected hfills to TeX-code"
379 i = find_token(document.body, "\\begin_inset Formula", i)
382 j = document.body[i].find("\\hspace*")
384 end = find_end_of_inset(document.body, i)
385 subst = put_cmd_in_ert(document.body[i][21:])
386 document.body[i:end + 1] = subst
390 def convert_japanese_encodings(document):
391 " Rename the japanese encodings to names understood by platex "
393 "EUC-JP-pLaTeX": "euc",
395 "SJIS-pLaTeX": "sjis"
397 i = find_token(document.header, "\\inputencoding" , 0)
400 val = get_value(document.header, "\\inputencoding", i)
401 if val in list(jap_enc_dict.keys()):
402 document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
405 def revert_japanese_encodings(document):
406 " Revert the japanese encodings name changes "
408 "euc": "EUC-JP-pLaTeX",
410 "sjis": "SJIS-pLaTeX"
412 i = find_token(document.header, "\\inputencoding" , 0)
415 val = get_value(document.header, "\\inputencoding", i)
416 if val in list(jap_enc_dict.keys()):
417 document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
420 def convert_justification(document):
421 " Add the \\justification buffer param"
422 i = find_token(document.header, "\\suppress_date" , 0)
424 i = find_token(document.header, "\\paperorientation" , 0)
426 i = find_token(document.header, "\\use_indices" , 0)
428 i = find_token(document.header, "\\use_bibtopic" , 0)
430 document.warning("Malformed LyX document: Missing \\suppress_date.")
432 document.header.insert(i + 1, "\\justification true")
435 def revert_justification(document):
436 " Revert the \\justification buffer param"
437 if not del_token(document.header, '\\justification', 0):
438 document.warning("Malformed LyX document: Missing \\justification.")
441 def revert_australian(document):
442 "Set English language variants Australian and Newzealand to English"
444 if document.language == "australian" or document.language == "newzealand":
445 document.language = "english"
446 i = find_token(document.header, "\\language", 0)
448 document.header[i] = "\\language english"
451 j = find_token(document.body, "\\lang australian", j)
453 j = find_token(document.body, "\\lang newzealand", 0)
457 document.body[j] = document.body[j].replace("\\lang newzealand", "\\lang english")
459 document.body[j] = document.body[j].replace("\\lang australian", "\\lang english")
463 def convert_biblio_style(document):
464 "Add a sensible default for \\biblio_style based on the citation engine."
465 i = find_token(document.header, "\\cite_engine", 0)
467 engine = get_value(document.header, "\\cite_engine", i).split("_")[0]
468 style = {"basic": "plain", "natbib": "plainnat", "jurabib": "jurabib"}
469 document.header.insert(i + 1, "\\biblio_style " + style[engine])
472 def revert_biblio_style(document):
473 "BibTeX insets with default option use the style defined by \\biblio_style."
474 i = find_token(document.header, "\\biblio_style" , 0)
476 document.warning("No \\biblio_style line. Nothing to do.")
479 default_style = get_value(document.header, "\\biblio_style", i)
480 del document.header[i]
482 # We are looking for bibtex insets having the default option
485 i = find_token(document.body, "\\begin_inset CommandInset bibtex", i)
488 j = find_end_of_inset(document.body, i)
490 document.warning("Malformed LyX document: Can't find end of bibtex inset at line " + str(i))
493 k = find_token(document.body, "options", i, j)
495 options = get_quoted_value(document.body, "options", k)
496 if "default" in options.split(","):
497 document.body[k] = 'options "%s"' \
498 % options.replace("default", default_style)
502 def handle_longtable_captions(document, forward):
505 begin_table = find_token(document.body, '<lyxtabular version=', begin_table)
506 if begin_table == -1:
508 end_table = find_end_of(document.body, begin_table, '<lyxtabular', '</lyxtabular>')
510 document.warning("Malformed LyX document: Could not find end of table.")
513 fline = find_token(document.body, "<features", begin_table, end_table)
515 document.warning("Can't find features for inset at line " + str(begin_table))
518 p = document.body[fline].find("islongtable")
523 numrows = get_option_value(document.body[begin_table], "rows")
525 numrows = int(numrows)
527 document.warning(document.body[begin_table])
528 document.warning("Unable to determine rows!")
529 begin_table = end_table
531 begin_row = begin_table
532 for row in range(numrows):
533 begin_row = find_token(document.body, '<row', begin_row, end_table)
535 document.warning("Can't find row " + str(row + 1))
537 end_row = find_end_of(document.body, begin_row, '<row', '</row>')
539 document.warning("Can't find end of row " + str(row + 1))
542 if (get_option_value(document.body[begin_row], 'caption') == 'true' and
543 get_option_value(document.body[begin_row], 'endfirsthead') != 'true' and
544 get_option_value(document.body[begin_row], 'endhead') != 'true' and
545 get_option_value(document.body[begin_row], 'endfoot') != 'true' and
546 get_option_value(document.body[begin_row], 'endlastfoot') != 'true'):
547 document.body[begin_row] = set_option_value(document.body[begin_row], 'caption', 'true", endfirsthead="true')
548 elif get_option_value(document.body[begin_row], 'caption') == 'true':
549 if get_option_value(document.body[begin_row], 'endfirsthead') == 'true':
550 document.body[begin_row] = set_option_value(document.body[begin_row], 'endfirsthead', 'false')
551 if get_option_value(document.body[begin_row], 'endhead') == 'true':
552 document.body[begin_row] = set_option_value(document.body[begin_row], 'endhead', 'false')
553 if get_option_value(document.body[begin_row], 'endfoot') == 'true':
554 document.body[begin_row] = set_option_value(document.body[begin_row], 'endfoot', 'false')
555 if get_option_value(document.body[begin_row], 'endlastfoot') == 'true':
556 document.body[begin_row] = set_option_value(document.body[begin_row], 'endlastfoot', 'false')
558 # since there could be a tabular inside this one, we
559 # cannot jump to end.
563 def convert_longtable_captions(document):
564 "Add a firsthead flag to caption rows"
565 handle_longtable_captions(document, True)
568 def revert_longtable_captions(document):
569 "remove head/foot flag from caption rows"
570 handle_longtable_captions(document, False)
573 def convert_use_packages(document):
574 "use_xxx yyy => use_package xxx yyy"
575 packages = ["amsmath", "esint", "mathdots", "mhchem", "undertilde"]
577 i = find_token(document.header, "\\use_%s" % p, 0)
579 value = get_value(document.header, "\\use_%s" % p, i)
580 document.header[i] = "\\use_package %s %s" % (p, value)
583 def revert_use_packages(document):
584 "use_package xxx yyy => use_xxx yyy"
585 packages = ["amsmath", "esint", "mhchem", "mathdots", "undertilde"]
586 # the order is arbitrary for the use_package version, and not all packages need to be given.
587 # Ensure a complete list and correct order (important for older LyX versions and especially lyx2lyx)
588 # first loop: find line with first package
591 regexp = re.compile(r'(\\use_package\s+%s)' % p)
592 i = find_re(document.header, regexp, 0)
593 if i != -1 and (j < 0 or i < j):
595 # second loop: replace or insert packages in front of all existing ones
597 regexp = re.compile(r'(\\use_package\s+%s)' % p)
598 i = find_re(document.header, regexp, 0)
600 value = get_value(document.header, "\\use_package %s" % p, i).split()[1]
601 del document.header[i]
602 document.header.insert(j, "\\use_%s %s" % (p, value))
604 document.header.insert(j, "\\use_%s 1" % p)
608 def convert_use_package(document, pkg, commands, oldauto):
609 # oldauto defines how the version we are converting from behaves:
610 # if it is true, the old version uses the package automatically.
611 # if it is false, the old version never uses the package.
612 i = find_token(document.header, "\\use_package", 0)
614 document.warning("Malformed LyX document: Can't find \\use_package.")
616 j = find_token(document.preamble, "\\usepackage{" + pkg + "}", 0)
618 # package was loaded in the preamble, convert this to header setting for round trip
619 document.header.insert(i + 1, "\\use_package " + pkg + " 2") # on
620 del document.preamble[j]
621 # If oldauto is true we have two options:
622 # We can either set the package to auto - this is correct for files in
623 # format 425 to 463, and may create a conflict for older files which use
624 # any command in commands with a different definition.
625 # Or we can look whether any command in commands is used, and set it to
626 # auto if not and to off if yes. This will not create a conflict, but will
627 # create uncompilable documents for files in format 425 to 463, which use
628 # any command in commands.
629 # We choose the first option since its error is less likely.
631 document.header.insert(i + 1, "\\use_package " + pkg + " 1") # auto
635 j = find_token(document.body, '\\begin_inset Formula', j)
638 k = find_end_of_inset(document.body, j)
640 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(j))
643 code = "\n".join(document.body[j:k])
645 if code.find("\\%s" % c) != -1:
646 # at least one of the commands was found - need to switch package off
647 document.header.insert(i + 1, "\\use_package " + pkg + " 0") # off
650 # no command was found - set to auto (bug 9069)
651 document.header.insert(i + 1, "\\use_package " + pkg + " 1") # auto
654 def revert_use_package(document, pkg, commands, oldauto):
655 # oldauto defines how the version we are reverting to behaves:
656 # if it is true, the old version uses the package automatically.
657 # if it is false, the old version never uses the package.
658 regexp = re.compile(r'(\\use_package\s+%s)' % pkg)
659 i = find_re(document.header, regexp, 0)
660 value = "1" # default is auto
662 value = get_value(document.header, "\\use_package" , i).split()[1]
663 del document.header[i]
664 if value == "2": # on
665 add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
666 elif value == "1" and not oldauto: # auto
669 i = find_token(document.body, '\\begin_inset Formula', i)
672 j = find_end_of_inset(document.body, i)
674 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
677 code = "\n".join(document.body[i:j])
679 if code.find("\\%s" % c) != -1:
680 add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
685 mathtools_commands = ["mathclap", "mathllap", "mathrlap", \
686 "lgathered", "rgathered", "vcentcolon", "dblcolon", \
687 "coloneqq", "Coloneqq", "coloneq", "Coloneq", "eqqcolon", \
688 "Eqqcolon", "eqcolon", "Eqcolon", "colonapprox", \
689 "Colonapprox", "colonsim", "Colonsim"]
690 def convert_use_mathtools(document):
691 "insert use_package mathtools"
692 convert_use_package(document, "mathtools", mathtools_commands, False)
695 def revert_use_mathtools(document):
696 "remove use_package mathtools"
697 revert_use_package(document, "mathtools", mathtools_commands, False)
700 # commands provided by stmaryrd.sty but LyX uses other packages:
701 # boxdot lightning, bigtriangledown, bigtriangleup
702 stmaryrd_commands = ["shortleftarrow", "shortrightarrow", "shortuparrow", \
703 "shortdownarrow", "Yup", "Ydown", "Yleft", "Yright", \
704 "varcurlyvee", "varcurlywedge", "minuso", "baro", \
705 "sslash", "bbslash", "moo", "varotimes", "varoast", \
706 "varobar", "varodot", "varoslash", "varobslash", \
707 "varocircle", "varoplus", "varominus", "boxast", \
708 "boxbar", "boxslash", "boxbslash", "boxcircle", \
709 "boxbox", "boxempty", "merge", "vartimes", \
710 "fatsemi", "sswarrow", "ssearrow", "curlywedgeuparrow", \
711 "curlywedgedownarrow", "fatslash", "fatbslash", "lbag", \
712 "rbag", "varbigcirc", "leftrightarroweq", \
713 "curlyveedownarrow", "curlyveeuparrow", "nnwarrow", \
714 "nnearrow", "leftslice", "rightslice", "varolessthan", \
715 "varogreaterthan", "varovee", "varowedge", "talloblong", \
716 "interleave", "obar", "obslash", "olessthan", \
717 "ogreaterthan", "ovee", "owedge", "oblong", "inplus", \
718 "niplus", "nplus", "subsetplus", "supsetplus", \
719 "subsetpluseq", "supsetpluseq", "Lbag", "Rbag", \
720 "llbracket", "rrbracket", "llparenthesis", \
721 "rrparenthesis", "binampersand", "bindnasrepma", \
722 "trianglelefteqslant", "trianglerighteqslant", \
723 "ntrianglelefteqslant", "ntrianglerighteqslant", \
724 "llfloor", "rrfloor", "llceil", "rrceil", "arrownot", \
725 "Arrownot", "Mapstochar", "mapsfromchar", "Mapsfromchar", \
726 "leftrightarrowtriangle", "leftarrowtriangle", \
727 "rightarrowtriangle", \
728 "bigcurlyvee", "bigcurlywedge", "bigsqcap", "bigbox", \
729 "bigparallel", "biginterleave", "bignplus", \
730 "varcopyright", "longarrownot", "Longarrownot", \
731 "Mapsto", "mapsfrom", "Mapsfrom" "Longmapsto", \
732 "longmapsfrom", "Longmapsfrom"]
733 def convert_use_stmaryrd(document):
734 "insert use_package stmaryrd"
735 convert_use_package(document, "stmaryrd", stmaryrd_commands, False)
738 def revert_use_stmaryrd(document):
739 "remove use_package stmaryrd"
740 revert_use_package(document, "stmaryrd", stmaryrd_commands, False)
743 stackrel_commands = ["stackrel"]
744 def convert_use_stackrel(document):
745 "insert use_package stackrel"
746 convert_use_package(document, "stackrel", stackrel_commands, False)
749 def revert_use_stackrel(document):
750 "remove use_package stackrel"
751 revert_use_package(document, "stackrel", stackrel_commands, False)
754 def convert_cite_engine_type(document):
755 "Determine the \\cite_engine_type from the citation engine."
756 i = find_token(document.header, "\\cite_engine", 0)
759 engine = get_value(document.header, "\\cite_engine", i)
761 engine, type = engine.split("_")
763 type = {"basic": "numerical", "jurabib": "authoryear"}[engine]
764 document.header[i] = "\\cite_engine " + engine
765 document.header.insert(i + 1, "\\cite_engine_type " + type)
768 def revert_cite_engine_type(document):
769 "Natbib had the type appended with an underscore."
770 engine_type = "numerical"
771 i = find_token(document.header, "\\cite_engine_type" , 0)
773 document.warning("No \\cite_engine_type line. Assuming numerical.")
775 engine_type = get_value(document.header, "\\cite_engine_type", i)
776 del document.header[i]
778 # We are looking for the natbib citation engine
779 i = find_token(document.header, "\\cite_engine natbib", 0)
782 document.header[i] = "\\cite_engine natbib_" + engine_type
785 def convert_cite_engine_type_default(document):
786 "Convert \\cite_engine_type to default for the basic citation engine."
787 i = find_token(document.header, "\\cite_engine basic", 0)
790 i = find_token(document.header, "\\cite_engine_type" , 0)
793 document.header[i] = "\\cite_engine_type default"
796 def revert_cite_engine_type_default(document):
797 """Revert \\cite_engine_type default.
799 Revert to numerical for the basic cite engine, otherwise to authoryear."""
800 engine_type = "authoryear"
801 i = find_token(document.header, "\\cite_engine_type default" , 0)
804 j = find_token(document.header, "\\cite_engine basic", 0)
806 engine_type = "numerical"
807 document.header[i] = "\\cite_engine_type " + engine_type
810 cancel_commands = ["cancel", "bcancel", "xcancel", "cancelto"]
811 # this is the same, as revert_use_cancel() except for the default
812 def revert_cancel(document):
813 "add cancel to the preamble if necessary"
814 revert_use_package(document, "cancel", cancel_commands, False)
817 def revert_verbatim(document, starred = False):
818 " Revert verbatim environments completely to TeX-code. "
822 layout_name = "Verbatim"
823 latex_name = "verbatim"
825 layout_name = "Verbatim*"
826 latex_name = "verbatim*"
828 subst_end = ['\\end_layout', '', '\\begin_layout Plain Layout',
830 '\\begin_layout Plain Layout', '', '',
832 'end{%s}' % (latex_name),
833 '\\end_layout', '', '\\end_inset',
834 '', '', '\\end_layout']
835 subst_begin = ['\\begin_layout Standard', '\\noindent',
836 '\\begin_inset ERT', 'status open', '',
837 '\\begin_layout Plain Layout', '', '', '\\backslash',
838 'begin{%s}' % (latex_name),
839 '\\end_layout', '', '\\begin_layout Plain Layout', '']
842 i = find_token(document.body, "\\begin_layout %s" % (layout_name), i)
845 j = find_end_of_layout(document.body, i)
847 document.warning("Malformed LyX document: Can't find end of %s layout" \
851 # delete all line breaks insets (there are no other insets)
854 n = find_token(document.body, "\\begin_inset Newline newline", l, j)
856 n = find_token(document.body, "\\begin_inset Newline linebreak", l, j)
859 m = find_end_of_inset(document.body, n)
860 del(document.body[m:m+1])
861 document.body[n:n+1] = ['\\end_layout', '', '\\begin_layout Plain Layout']
863 # we deleted a line, so the end of the inset moved forward.
864 # FIXME But we also added some lines, didn't we? I think this
867 # consecutive verbatim environments need to be connected
868 k = find_token(document.body, "\\begin_layout %s" % (layout_name), j)
869 if k == j + 2 and consecutive == False:
871 document.body[j:j+1] = ['\\end_layout', '', '\\begin_layout Plain Layout']
872 document.body[i:i+1] = subst_begin
874 if k == j + 2 and consecutive == True:
875 document.body[j:j+1] = ['\\end_layout', '', '\\begin_layout Plain Layout']
876 del(document.body[i:i+1])
878 if k != j + 2 and consecutive == True:
879 document.body[j:j+1] = subst_end
880 # the next paragraph must not be indented
881 # FIXME This seems to be causing problems, because of the
882 # hardcoded use of 19. We should figure out exactly where
883 # this needs to go by searching for the right tag.
884 document.body[j+19:j+19] = ['\\noindent']
885 del(document.body[i:i+1])
889 document.body[j:j+1] = subst_end
890 # the next paragraph must not be indented
891 # FIXME This seems to be causing problems, because of the
892 # hardcoded use of 19. We should figure out exactly where
893 # this needs to go by searching for the right tag.
894 document.body[j+19:j+19] = ['\\noindent']
895 document.body[i:i+1] = subst_begin
898 def revert_tipa(document):
899 " Revert native TIPA insets to mathed or ERT. "
902 i = find_token(document.body, "\\begin_inset IPA", i)
905 j = find_end_of_inset(document.body, i)
907 document.warning("Malformed LyX document: Can't find end of IPA inset")
911 n = find_token(document.body, "\\begin_layout", i, j)
913 document.warning("Malformed LyX document: IPA inset has no embedded layout")
916 m = find_end_of_layout(document.body, n)
918 document.warning("Malformed LyX document: Can't find end of embedded layout")
921 content = document.body[n+1:m]
922 p = find_token(document.body, "\\begin_layout", m, j)
923 if p != -1 or len(content) > 1:
925 content = document.body[i+1:j]
927 # IPA insets with multiple pars need to be wrapped by \begin{IPA}...\end{IPA}
928 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}")
929 add_to_preamble(document, ["\\usepackage{tipa,tipx}"])
931 # single-par IPA insets can be reverted to mathed
932 document.body[i:j+1] = ["\\begin_inset Formula $\\text{\\textipa{" + content[0] + "}}$", "\\end_inset"]
936 def revert_cell_rotation(document):
937 "Revert cell rotations to TeX-code"
939 load_rotating = False
943 # first, let's find out if we need to do anything
944 i = find_token(document.body, '<cell ', i)
947 j = document.body[i].find('rotate="')
949 k = document.body[i].find('"', j + 8)
950 value = document.body[i][j + 8 : k]
952 rgx = re.compile(r' rotate="[^"]+?"')
953 # remove rotate option
954 document.body[i] = rgx.sub('', document.body[i])
956 rgx = re.compile(r' rotate="[^"]+?"')
957 document.body[i] = rgx.sub(' rotate="true"', document.body[i])
959 rgx = re.compile(r' rotate="[^"]+?"')
961 # remove rotate option
962 document.body[i] = rgx.sub('', document.body[i])
964 document.body[i + 5 : i + 5] = \
965 put_cmd_in_ert("\\end{turn}")
966 document.body[i + 4 : i + 4] = \
967 put_cmd_in_ert("\\begin{turn}{" + value + "}")
973 add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"])
976 def convert_cell_rotation(document):
977 'Convert cell rotation statements from "true" to "90"'
981 # first, let's find out if we need to do anything
982 i = find_token(document.body, '<cell ', i)
985 j = document.body[i].find('rotate="true"')
987 rgx = re.compile(r'rotate="[^"]+?"')
988 # convert "true" to "90"
989 document.body[i] = rgx.sub('rotate="90"', document.body[i])
994 def revert_table_rotation(document):
995 "Revert table rotations to TeX-code"
997 load_rotating = False
1001 # first, let's find out if we need to do anything
1002 i = find_token(document.body, '<features ', i)
1005 j = document.body[i].find('rotate="')
1007 end_table = find_token(document.body, '</lyxtabular>', j)
1008 k = document.body[i].find('"', j + 8)
1009 value = document.body[i][j + 8 : k]
1011 rgx = re.compile(r' rotate="[^"]+?"')
1012 # remove rotate option
1013 document.body[i] = rgx.sub('', document.body[i])
1015 rgx = re.compile(r'rotate="[^"]+?"')
1016 document.body[i] = rgx.sub('rotate="true"', document.body[i])
1018 rgx = re.compile(r' rotate="[^"]+?"')
1019 load_rotating = True
1020 # remove rotate option
1021 document.body[i] = rgx.sub('', document.body[i])
1023 document.body[end_table + 3 : end_table + 3] = \
1024 put_cmd_in_ert("\\end{turn}")
1025 document.body[i - 2 : i - 2] = \
1026 put_cmd_in_ert("\\begin{turn}{" + value + "}")
1032 add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"])
1035 def convert_table_rotation(document):
1036 'Convert table rotation statements from "true" to "90"'
1040 # first, let's find out if we need to do anything
1041 i = find_token(document.body, '<features ', i)
1044 j = document.body[i].find('rotate="true"')
1046 rgx = re.compile(r'rotate="[^"]+?"')
1047 # convert "true" to "90"
1048 document.body[i] = rgx.sub('rotate="90"', document.body[i])
1053 def convert_listoflistings(document):
1054 'Convert ERT \lstlistoflistings to TOC lstlistoflistings inset'
1055 # We can support roundtrip because the command is so simple
1058 i = find_token(document.body, "\\begin_inset ERT", i)
1061 j = find_end_of_inset(document.body, i)
1063 document.warning("Malformed LyX document: Can't find end of ERT inset")
1066 ert = get_ert(document.body, i)
1067 if ert == "\\lstlistoflistings{}":
1068 document.body[i:j] = ["\\begin_inset CommandInset toc", "LatexCommand lstlistoflistings", ""]
1074 def revert_listoflistings(document):
1075 'Convert TOC lstlistoflistings inset to ERT lstlistoflistings'
1078 i = find_token(document.body, "\\begin_inset CommandInset toc", i)
1081 if document.body[i+1] == "LatexCommand lstlistoflistings":
1082 j = find_end_of_inset(document.body, i)
1084 document.warning("Malformed LyX document: Can't find end of TOC inset")
1087 subst = put_cmd_in_ert("\\lstlistoflistings{}")
1088 document.body[i:j+1] = subst
1089 add_to_preamble(document, ["\\usepackage{listings}"])
1093 def convert_use_amssymb(document):
1094 "insert use_package amssymb"
1095 regexp = re.compile(r'(\\use_package\s+amsmath)')
1096 i = find_re(document.header, regexp, 0)
1098 document.warning("Malformed LyX document: Can't find \\use_package amsmath.")
1100 value = get_value(document.header, "\\use_package" , i).split()[1]
1103 useamsmath = int(value)
1105 document.warning("Invalid \\use_package amsmath: " + value + ". Assuming auto.")
1107 j = find_token(document.preamble, "\\usepackage{amssymb}", 0)
1109 document.header.insert(i + 1, "\\use_package amssymb %d" % useamsmath)
1111 document.header.insert(i + 1, "\\use_package amssymb 2")
1112 del document.preamble[j]
1115 def revert_use_amssymb(document):
1116 "remove use_package amssymb"
1117 regexp1 = re.compile(r'(\\use_package\s+amsmath)')
1118 regexp2 = re.compile(r'(\\use_package\s+amssymb)')
1119 i = find_re(document.header, regexp1, 0)
1120 j = find_re(document.header, regexp2, 0)
1121 value1 = "1" # default is auto
1122 value2 = "1" # default is auto
1124 value1 = get_value(document.header, "\\use_package" , i).split()[1]
1126 value2 = get_value(document.header, "\\use_package" , j).split()[1]
1127 del document.header[j]
1128 if value1 != value2 and value2 == "2": # on
1129 add_to_preamble(document, ["\\usepackage{amssymb}"])
1132 def convert_use_cancel(document):
1133 "insert use_package cancel"
1134 convert_use_package(document, "cancel", cancel_commands, True)
1137 def revert_use_cancel(document):
1138 "remove use_package cancel"
1139 revert_use_package(document, "cancel", cancel_commands, True)
1142 def revert_ancientgreek(document):
1143 "Set the document language for ancientgreek to greek"
1145 if document.language == "ancientgreek":
1146 document.language = "greek"
1147 i = find_token(document.header, "\\language", 0)
1149 document.header[i] = "\\language greek"
1152 j = find_token(document.body, "\\lang ancientgreek", j)
1156 document.body[j] = document.body[j].replace("\\lang ancientgreek", "\\lang greek")
1160 def revert_languages(document):
1161 "Set the document language for new supported languages to English"
1164 "coptic", "divehi", "hindi", "kurmanji", "lao", "marathi", "occitan", "sanskrit",
1165 "syriac", "tamil", "telugu", "urdu"
1167 for n in range(len(languages)):
1168 if document.language == languages[n]:
1169 document.language = "english"
1170 i = find_token(document.header, "\\language", 0)
1172 document.header[i] = "\\language english"
1174 while j < len(document.body):
1175 j = find_token(document.body, "\\lang " + languages[n], j)
1177 document.body[j] = document.body[j].replace("\\lang " + languages[n], "\\lang english")
1180 j = len(document.body)
1183 def convert_armenian(document):
1184 "Use polyglossia and thus non-TeX fonts for Armenian"
1186 if document.language == "armenian":
1187 i = find_token(document.header, "\\use_non_tex_fonts", 0)
1189 document.header[i] = "\\use_non_tex_fonts true"
1192 def revert_armenian(document):
1193 "Use ArmTeX and thus 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 false"
1201 def revert_libertine(document):
1202 " Revert native libertine font definition to LaTeX "
1204 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1205 i = find_token(document.header, "\\font_roman libertine", 0)
1208 j = find_token(document.header, "\\font_osf true", 0)
1211 preamble = "\\usepackage"
1213 document.header[j] = "\\font_osf false"
1216 preamble += "[lining]"
1217 preamble += "{libertine-type1}"
1218 add_to_preamble(document, [preamble])
1219 document.header[i] = "\\font_roman default"
1222 def revert_txtt(document):
1223 " Revert native txtt font definition to LaTeX "
1225 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1226 i = find_token(document.header, "\\font_typewriter txtt", 0)
1228 preamble = "\\renewcommand{\\ttdefault}{txtt}"
1229 add_to_preamble(document, [preamble])
1230 document.header[i] = "\\font_typewriter default"
1233 def revert_mathdesign(document):
1234 " Revert native mathdesign font definition to LaTeX "
1236 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1242 i = find_token(document.header, "\\font_roman", 0)
1245 val = get_value(document.header, "\\font_roman", i)
1246 if val in list(mathdesign_dict.keys()):
1247 preamble = "\\usepackage[%s" % mathdesign_dict[val]
1249 j = find_token(document.header, "\\font_osf true", 0)
1252 document.header[j] = "\\font_osf false"
1253 l = find_token(document.header, "\\font_sc true", 0)
1256 document.header[l] = "\\font_sc false"
1258 preamble += ",expert"
1259 preamble += "]{mathdesign}"
1260 add_to_preamble(document, [preamble])
1261 document.header[i] = "\\font_roman default"
1264 def revert_texgyre(document):
1265 " Revert native TeXGyre font definition to LaTeX "
1267 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1268 texgyre_fonts = ["tgadventor", "tgbonum", "tgchorus", "tgcursor", \
1269 "tgheros", "tgpagella", "tgschola", "tgtermes"]
1270 i = find_token(document.header, "\\font_roman", 0)
1272 val = get_value(document.header, "\\font_roman", i)
1273 if val in texgyre_fonts:
1274 preamble = "\\usepackage{%s}" % val
1275 add_to_preamble(document, [preamble])
1276 document.header[i] = "\\font_roman default"
1277 i = find_token(document.header, "\\font_sans", 0)
1279 val = get_value(document.header, "\\font_sans", i)
1280 if val in texgyre_fonts:
1281 preamble = "\\usepackage{%s}" % val
1282 add_to_preamble(document, [preamble])
1283 document.header[i] = "\\font_sans default"
1284 i = find_token(document.header, "\\font_typewriter", 0)
1286 val = get_value(document.header, "\\font_typewriter", i)
1287 if val in texgyre_fonts:
1288 preamble = "\\usepackage{%s}" % val
1289 add_to_preamble(document, [preamble])
1290 document.header[i] = "\\font_typewriter default"
1293 def revert_ipadeco(document):
1294 " Revert IPA decorations to ERT "
1297 i = find_token(document.body, "\\begin_inset IPADeco", i)
1300 end = find_end_of_inset(document.body, i)
1302 document.warning("Can't find end of inset at line " + str(i))
1305 line = document.body[i]
1306 rx = re.compile(r'\\begin_inset IPADeco (.*)$')
1308 decotype = m.group(1)
1309 if decotype != "toptiebar" and decotype != "bottomtiebar":
1310 document.warning("Invalid IPADeco type: " + decotype)
1313 blay = find_token(document.body, "\\begin_layout Plain Layout", i, end)
1315 document.warning("Can't find layout for inset at line " + str(i))
1318 bend = find_end_of_layout(document.body, blay)
1320 document.warning("Malformed LyX document: Could not find end of IPADeco inset's layout.")
1323 substi = ["\\begin_inset ERT", "status collapsed", "",
1324 "\\begin_layout Plain Layout", "", "", "\\backslash",
1325 decotype + "{", "\\end_layout", "", "\\end_inset"]
1326 substj = ["\\size default", "", "\\begin_inset ERT", "status collapsed", "",
1327 "\\begin_layout Plain Layout", "", "}", "\\end_layout", "", "\\end_inset"]
1328 # do the later one first so as not to mess up the numbering
1329 document.body[bend:end + 1] = substj
1330 document.body[i:blay + 1] = substi
1331 i = end + len(substi) + len(substj) - (end - bend) - (blay - i) - 2
1332 add_to_preamble(document, "\\usepackage{tipa}")
1335 def revert_ipachar(document):
1336 ' Revert \\IPAChar to ERT '
1339 while i < len(document.body):
1340 m = re.match(r'(.*)\\IPAChar \\(\w+\{\w+\})(.*)', document.body[i])
1344 ipachar = m.group(2)
1347 '\\begin_inset ERT',
1348 'status collapsed', '',
1349 '\\begin_layout Standard',
1350 '', '', '\\backslash',
1355 document.body[i: i+1] = subst
1360 add_to_preamble(document, "\\usepackage{tone}")
1363 def revert_minionpro(document):
1364 " Revert native MinionPro font definition to LaTeX "
1366 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1367 i = find_token(document.header, "\\font_roman minionpro", 0)
1370 j = find_token(document.header, "\\font_osf true", 0)
1373 preamble = "\\usepackage"
1375 document.header[j] = "\\font_osf false"
1378 preamble += "{MinionPro}"
1379 add_to_preamble(document, [preamble])
1380 document.header[i] = "\\font_roman default"
1383 def revert_mathfonts(document):
1384 " Revert native math font definitions to LaTeX "
1386 i = find_token(document.header, "\\font_math", 0)
1389 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1390 val = get_value(document.header, "\\font_math", i)
1391 if val == "eulervm":
1392 add_to_preamble(document, "\\usepackage{eulervm}")
1393 elif val == "default":
1395 "lmodern": "\\renewcommand{\\rmdefault}{lmr}",
1396 "minionpro": "\\usepackage[onlytext,lf]{MinionPro}",
1397 "minionpro-osf": "\\usepackage[onlytext]{MinionPro}",
1398 "palatino": "\\renewcommand{\\rmdefault}{ppl}",
1399 "palatino-osf": "\\renewcommand{\\rmdefault}{pplj}",
1400 "times": "\\renewcommand{\\rmdefault}{ptm}",
1401 "utopia": "\\renewcommand{\\rmdefault}{futs}",
1402 "utopia-osf": "\\renewcommand{\\rmdefault}{futj}",
1404 j = find_token(document.header, "\\font_roman", 0)
1406 rm = get_value(document.header, "\\font_roman", j)
1407 k = find_token(document.header, "\\font_osf true", 0)
1410 if rm in list(mathfont_dict.keys()):
1411 add_to_preamble(document, mathfont_dict[rm])
1412 document.header[j] = "\\font_roman default"
1414 document.header[k] = "\\font_osf false"
1415 del document.header[i]
1418 def revert_mdnomath(document):
1419 " Revert mathdesign and fourier without math "
1421 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1423 "md-charter": "mdbch",
1424 "md-utopia": "mdput",
1425 "md-garamond": "mdugm"
1427 i = find_token(document.header, "\\font_roman", 0)
1430 val = get_value(document.header, "\\font_roman", i)
1431 if val in list(mathdesign_dict.keys()):
1432 j = find_token(document.header, "\\font_math", 0)
1434 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1435 mval = get_value(document.header, "\\font_math", j)
1436 if mval == "default":
1437 document.header[i] = "\\font_roman default"
1438 add_to_preamble(document, "\\renewcommand{\\rmdefault}{%s}" % mathdesign_dict[val])
1440 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1443 def convert_mathfonts(document):
1444 document.header.insert(-1, "\\font_math auto")
1447 def convert_mdnomath(document):
1448 " Change mathdesign font name "
1450 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1452 "mdbch": "md-charter",
1453 "mdput": "md-utopia",
1454 "mdugm": "md-garamond"
1456 i = find_token(document.header, "\\font_roman", 0)
1459 val = get_value(document.header, "\\font_roman", i)
1460 if val in list(mathdesign_dict.keys()):
1461 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1464 def revert_newtxmath(document):
1465 " Revert native newtxmath definitions to LaTeX "
1467 i = find_token(document.header, "\\font_math", 0)
1470 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1471 val = get_value(document.header, "\\font_math", i)
1473 "libertine-ntxm": "\\usepackage[libertine]{newtxmath}",
1474 "minion-ntxm": "\\usepackage[minion]{newtxmath}",
1475 "newtxmath": "\\usepackage{newtxmath}",
1477 if val in list(mathfont_dict.keys()):
1478 add_to_preamble(document, mathfont_dict[val])
1479 document.header[i] = "\\font_math auto"
1482 def revert_biolinum(document):
1483 " Revert native biolinum font definition to LaTeX "
1485 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1486 i = find_token(document.header, "\\font_sans biolinum", 0)
1489 j = find_token(document.header, "\\font_osf true", 0)
1492 preamble = "\\usepackage"
1495 preamble += "{biolinum-type1}"
1496 add_to_preamble(document, [preamble])
1497 document.header[i] = "\\font_sans default"
1500 def revert_uop(document):
1501 " Revert native URW Classico (Optima) font definition to LaTeX "
1503 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1504 i = find_token(document.header, "\\font_sans uop", 0)
1506 preamble = "\\renewcommand{\\sfdefault}{uop}"
1507 add_to_preamble(document, [preamble])
1508 document.header[i] = "\\font_sans default"
1511 def convert_latexargs(document):
1512 " Convert InsetArgument to new syntax "
1514 if find_token(document.body, "\\begin_inset Argument", 0) == -1:
1518 # A list of layouts (document classes) with only optional or no arguments.
1519 # These can be safely converted to the new syntax
1520 # (I took the liberty to add some of my personal layouts/modules here; JSP)
1521 safe_layouts = ["aa", "aapaper", "aastex", "achemso", "acmsiggraph", "AEA",
1522 "agu-dtd", "agums", "agutex", "amsart", "amsbook", "apa",
1523 "arab-article", "armenian-article", "article-beamer", "article",
1524 "beamer", "book", "broadway", "chess", "cl2emult", "ctex-article",
1525 "ctex-book", "ctex-report", "dinbrief", "docbook-book", "docbook-chapter",
1526 "docbook", "docbook-section", "doublecol-new", "dtk", "ectaart", "egs",
1527 "elsarticle", "elsart", "entcs", "europecv", "extarticle", "extbook",
1528 "extletter", "extreport", "foils", "frletter", "g-brief2", "g-brief",
1529 "heb-article", "heb-letter", "hollywood", "IEEEtran", "ijmpc", "ijmpd",
1530 "iopart", "isprs", "jarticle", "jasatex", "jbook", "jgrga", "jreport",
1531 "jsarticle", "jsbeamer", "jsbook", "jss", "kluwer", "latex8", "letter", "lettre",
1532 "literate-article", "literate-book", "literate-report", "llncs", "ltugboat",
1533 "memoir", "moderncv", "mwart", "mwbk", "mwrep", "paper", "powerdot",
1534 "recipebook", "report", "revtex4", "revtex", "scrartcl", "scrarticle-beamer",
1535 "scrbook", "scrlettr", "scrlttr2", "scrreprt", "seminar", "siamltex",
1536 "sigplanconf", "simplecv", "singlecol", "singlecol-new", "slides", "spie",
1537 "svglobal3", "svglobal", "svjog", "svmono", "svmult", "svprobth", "tarticle",
1538 "tbook", "treport", "tufte-book", "tufte-handout"]
1539 # A list of "safe" modules, same as above
1540 safe_modules = ["biblatex", "beameraddons", "beamer-resenumerate", "beamersession", "braille",
1541 "customHeadersFooters", "endnotes", "enumitem", "eqs-within-sections", "figs-within-sections",
1542 "fix-cm", "fixltx2e", "foottoend", "hanging", "jscharstyles", "knitr", "lilypond",
1543 "linguistics", "linguisticx", "logicalmkup", "minimalistic", "nomindex", "noweb",
1544 "pdfcomment", "sweave", "tabs-within-sections", "theorems-ams-bytype",
1545 "theorems-ams-extended-bytype", "theorems-ams-extended", "theorems-ams", "theorems-bytype",
1546 "theorems-chap-bytype", "theorems-chap", "theorems-named", "theorems-sec-bytype",
1547 "theorems-sec", "theorems-starred", "theorems-std", "todonotes"]
1548 # Modules we need to take care of
1549 caveat_modules = ["initials"]
1550 # information about the relevant styles in caveat_modules (number of opt and req args)
1551 # use this if we get more caveat_modules. For now, use hard coding (see below).
1552 # initials = [{'Layout' : 'Initial', 'opt' : 1, 'req' : 1}]
1554 # Is this a known safe layout?
1555 safe_layout = document.textclass in safe_layouts
1557 document.warning("Lyx2lyx knows nothing about textclass '%s'. "
1558 "Please check if short title insets have been converted correctly."
1559 % document.textclass)
1560 # Do we use unsafe or unknown modules
1561 mods = document.get_module_list()
1562 unknown_modules = False
1563 used_caveat_modules = list()
1565 if mod in safe_modules:
1567 if mod in caveat_modules:
1568 used_caveat_modules.append(mod)
1570 unknown_modules = True
1571 document.warning("Lyx2lyx knows nothing about module '%s'. "
1572 "Please check if short title insets have been converted correctly."
1577 i = find_token(document.body, "\\begin_inset Argument", i)
1581 if not safe_layout or unknown_modules:
1582 # We cannot do more here since we have no access to this layout.
1583 # InsetArgument itself will do the real work
1584 # (see InsetArgument::updateBuffer())
1585 document.body[i] = "\\begin_inset Argument 999"
1589 # Find containing paragraph layout
1590 parent = get_containing_layout(document.body, i)
1592 document.warning("Malformed LyX document: Can't find parent paragraph layout")
1599 if len(used_caveat_modules) > 0:
1600 # We know for now that this must be the initials module with the Initial layout
1601 # If we get more such modules, we need some automating.
1602 if parent[0] == "Initial":
1603 # Layout has 1 opt and 1 req arg.
1604 # Count the actual arguments
1606 for p in range(parbeg, parend):
1607 if document.body[p] == "\\begin_inset Argument":
1612 # Collect all arguments in this paragraph
1614 for p in range(parbeg, parend):
1615 if document.body[p] == "\\begin_inset Argument":
1617 if allowed_opts != -1:
1618 # We have less arguments than opt + required.
1619 # required must take precedence.
1620 if argnr > allowed_opts and argnr < first_req:
1622 document.body[p] = "\\begin_inset Argument %d" % argnr
1626 def revert_latexargs(document):
1627 " Revert InsetArgument to old syntax "
1630 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
1633 # Search for Argument insets
1634 i = find_token(document.body, "\\begin_inset Argument", i)
1637 m = rx.match(document.body[i])
1639 # No ID: inset already reverted
1642 # Find containing paragraph layout
1643 parent = get_containing_layout(document.body, i)
1645 document.warning("Malformed LyX document: Can't find parent paragraph layout")
1650 # Do not set realparbeg to parent[3], since this does not work if we
1651 # have another inset (e.g. label or index) before the first argument
1652 # inset (this is the case in the user guide of LyX 2.0.8)
1654 # Collect all arguments in this paragraph
1656 for p in range(parbeg, parend):
1657 m = rx.match(document.body[p])
1660 # This is the first argument inset
1662 val = int(m.group(1))
1663 j = find_end_of_inset(document.body, p)
1664 # Revert to old syntax
1665 document.body[p] = "\\begin_inset Argument"
1667 document.warning("Malformed LyX document: Can't find end of Argument inset")
1670 args[val] = document.body[p : j + 1]
1672 realparend = realparend - len(document.body[p : j + 1])
1673 # Remove arg inset at this position
1674 del document.body[p : j + 1]
1678 # No argument inset found
1679 realparbeg = parent[3]
1680 # Now sort the arg insets
1682 for f in sorted(args):
1685 # Insert the sorted arg insets at paragraph begin
1686 document.body[realparbeg : realparbeg] = subst
1688 i = realparbeg + 1 + len(subst)
1691 def revert_IEEEtran(document):
1693 Reverts InsetArgument of
1696 Biography without photo
1699 if document.textclass != "IEEEtran":
1708 i = find_token(document.body, "\\begin_layout Page headings", i)
1710 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1713 i2 = find_token(document.body, "\\begin_inset Flex Paragraph Start", i2)
1715 revert_Argument_to_TeX_brace(document, i2, 0, 1, 1, False, False)
1718 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1720 revert_Argument_to_TeX_brace(document, j, 0, 1, 1, True, False)
1723 k = find_token(document.body, "\\begin_layout Biography", k)
1724 kA = find_token(document.body, "\\begin_layout Biography without photo", k)
1725 if k == kA and k != -1:
1729 # start with the second argument, therefore 2
1730 revert_Argument_to_TeX_brace(document, k, 0, 2, 2, True, False)
1732 if i == -1 and i2 == -1 and j == -1 and k == -1:
1736 def revert_IEEEtran_2(document):
1738 Reverts Flex Paragraph Start to TeX-code
1740 if document.textclass == "IEEEtran":
1743 begin = find_token(document.body, "\\begin_inset Flex Paragraph Start", begin)
1746 end1 = find_end_of_inset(document.body, begin)
1747 document.body[end1 - 2 : end1 + 1] = put_cmd_in_ert("}")
1748 document.body[begin : begin + 4] = put_cmd_in_ert("\\IEEEPARstart{")
1752 def convert_IEEEtran(document):
1757 Biography without photo
1760 if document.textclass != "IEEEtran":
1768 i = find_token(document.body, "\\begin_layout Page headings", i)
1770 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1773 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1775 convert_TeX_brace_to_Argument(document, j, 1, 1, False, True, False)
1778 # assure that we don't handle Biography Biography without photo
1779 k = find_token(document.body, "\\begin_layout Biography", k)
1780 kA = find_token(document.body, "\\begin_layout Biography without photo", k - 1)
1781 if k == kA and k != -1:
1785 # the argument we want to convert is the second one
1786 convert_TeX_brace_to_Argument(document, k, 2, 2, False, True, False)
1788 if i == -1 and j == -1 and k == -1:
1792 def revert_AASTeX(document):
1793 " Reverts InsetArgument of Altaffilation to TeX-code "
1794 if document.textclass == "aastex":
1797 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1800 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1804 def convert_AASTeX(document):
1805 " Converts ERT of Altaffilation to InsetArgument "
1806 if document.textclass == "aastex":
1809 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1812 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1816 def revert_AGUTeX(document):
1817 " Reverts InsetArgument of Author affiliation to TeX-code "
1818 if document.textclass == "agutex":
1821 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1824 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1828 def convert_AGUTeX(document):
1829 " Converts ERT of Author affiliation to InsetArgument "
1830 if document.textclass == "agutex":
1833 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1836 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1840 def revert_IJMP(document):
1841 " Reverts InsetArgument of MarkBoth to TeX-code "
1842 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1845 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1848 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1852 def convert_IJMP(document):
1853 " Converts ERT of MarkBoth to InsetArgument "
1854 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1857 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1860 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1864 def revert_SIGPLAN(document):
1865 " Reverts InsetArguments of SIGPLAN to TeX-code "
1866 if document.textclass == "sigplanconf":
1871 i = find_token(document.body, "\\begin_layout Conference", i)
1873 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1876 j = find_token(document.body, "\\begin_layout Author", j)
1878 revert_Argument_to_TeX_brace(document, j, 0, 1, 2, False, False)
1880 if i == -1 and j == -1:
1884 def convert_SIGPLAN(document):
1885 " Converts ERT of SIGPLAN to InsetArgument "
1886 if document.textclass == "sigplanconf":
1891 i = find_token(document.body, "\\begin_layout Conference", i)
1893 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1896 j = find_token(document.body, "\\begin_layout Author", j)
1898 convert_TeX_brace_to_Argument(document, j, 1, 2, False, False, False)
1900 if i == -1 and j == -1:
1904 def revert_SIGGRAPH(document):
1905 " Reverts InsetArgument of Flex CRcat to TeX-code "
1906 if document.textclass == "acmsiggraph":
1909 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1912 revert_Argument_to_TeX_brace(document, i, 0, 1, 3, False, False)
1916 def convert_SIGGRAPH(document):
1917 " Converts ERT of Flex CRcat to InsetArgument "
1918 if document.textclass == "acmsiggraph":
1921 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1924 convert_TeX_brace_to_Argument(document, i, 1, 3, True, False, False)
1928 def revert_EuropeCV(document):
1929 " Reverts InsetArguments of europeCV to TeX-code "
1930 if document.textclass == "europecv":
1937 i = find_token(document.body, "\\begin_layout Item", i)
1939 revert_Argument_to_TeX_brace(document, i, 0, 2, 2, False, False)
1942 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1944 revert_Argument_to_TeX_brace(document, j, 0, 2, 2, False, False)
1947 k = find_token(document.body, "\\begin_layout Language", k)
1949 revert_Argument_to_TeX_brace(document, k, 0, 2, 6, False, False)
1952 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1954 revert_Argument_to_TeX_brace(document, m, 0, 2, 6, False, False)
1956 if i == -1 and j == -1 and k == -1 and m == -1:
1960 def convert_EuropeCV(document):
1961 " Converts ERT of europeCV to InsetArgument "
1962 if document.textclass == "europecv":
1969 i = find_token(document.body, "\\begin_layout Item", i)
1971 convert_TeX_brace_to_Argument(document, i, 2, 2, False, False, False)
1974 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1976 convert_TeX_brace_to_Argument(document, j, 2, 2, False, False, False)
1979 k = find_token(document.body, "\\begin_layout Language", k)
1981 convert_TeX_brace_to_Argument(document, k, 2, 6, False, False, False)
1984 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1986 convert_TeX_brace_to_Argument(document, m, 2, 6, False, False, False)
1988 if i == -1 and j == -1 and k == -1 and m == -1:
1992 def revert_ModernCV(document):
1993 " Reverts InsetArguments of modernCV to TeX-code "
1994 if document.textclass == "moderncv":
2002 j = find_token(document.body, "\\begin_layout Entry", j)
2004 revert_Argument_to_TeX_brace(document, j, 0, 1, 5, False, False)
2007 k = find_token(document.body, "\\begin_layout Item", k)
2009 revert_Argument_to_TeX_brace(document, k, 0, 1, 1, False, False)
2012 m = find_token(document.body, "\\begin_layout ItemWithComment", m)
2014 revert_Argument_to_TeX_brace(document, m, 0, 1, 2, False, False)
2015 document.body[m] = document.body[m].replace("\\begin_layout ItemWithComment", "\\begin_layout Language")
2018 o = find_token(document.body, "\\begin_layout DoubleItem", o)
2020 revert_Argument_to_TeX_brace(document, o, 0, 1, 3, False, False)
2021 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout Computer")
2024 p = find_token(document.body, "\\begin_layout Social", p)
2026 revert_Argument_to_TeX_brace(document, p, 0, 1, 1, False, True)
2028 if j == -1 and k == -1 and m == -1 and o == -1 and p == -1:
2032 def revert_ModernCV_2(document):
2033 " Reverts the Flex:Column inset of modernCV to TeX-code "
2034 if document.textclass == "moderncv":
2038 flex = find_token(document.body, "\\begin_inset Flex Column", flex)
2041 flexEnd = find_end_of_inset(document.body, flex)
2042 wasOpt = revert_Argument_to_TeX_brace(document, flex, flexEnd, 1, 1, False, True)
2043 revert_Argument_to_TeX_brace(document, flex, 0, 2, 2, False, False)
2044 flexEnd = find_end_of_inset(document.body, flex)
2046 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn")
2048 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn{")
2049 document.body[flexEnd + 4 : flexEnd + 7] = put_cmd_in_ert("}")
2053 def revert_ModernCV_3(document):
2054 " Reverts the Column style of modernCV to TeX-code "
2055 if document.textclass == "moderncv":
2056 # revert the layouts
2057 revert_ModernCV(document)
2059 # get the position of the end of the last column inset
2060 LastFlexEnd = revert_ModernCV_2(document)
2062 p = find_token(document.body, "\\begin_layout Columns", p)
2065 pEnd = find_end_of_layout(document.body, p)
2066 document.body[p] = document.body[p].replace("\\begin_layout Columns", "\\begin_layout Standard")
2067 if LastFlexEnd != -1:
2068 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\begin{cvcolumns}")
2069 document.body[LastFlexEnd + 24 : LastFlexEnd + 24] = put_cmd_in_ert("\\end{cvcolumns}")
2073 def revert_ModernCV_4(document):
2074 " Reverts the style Social to TeX-code "
2075 if document.textclass == "moderncv":
2076 # revert the layouts
2077 revert_ModernCV(document)
2080 p = find_token(document.body, "\\begin_layout Social", p)
2083 pEnd = find_end_of_layout(document.body, p)
2084 document.body[p] = document.body[p].replace("\\begin_layout Social", "\\begin_layout Standard")
2085 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\social")
2086 hasOpt = find_token(document.body, "[", p + 9)
2088 document.body[p + 30 : p + 30] = put_cmd_in_ert("{")
2089 document.body[p + 41 : p + 41] = put_cmd_in_ert("}")
2091 document.body[p + 11 : p + 11] = put_cmd_in_ert("{")
2092 document.body[p + 21 : p + 21] = put_cmd_in_ert("}")
2096 def convert_ModernCV(document):
2097 " Converts ERT of modernCV to InsetArgument "
2098 if document.textclass == "moderncv":
2106 i = find_token(document.body, "\\begin_layout DoubleItem", i)
2108 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
2109 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout DoubleListItem")
2112 j = find_token(document.body, "\\begin_layout Entry", j)
2114 convert_TeX_brace_to_Argument(document, j, 1, 5, False, False, False)
2117 k = find_token(document.body, "\\begin_layout Item", k)
2119 convert_TeX_brace_to_Argument(document, k, 1, 1, False, False, False)
2122 m = find_token(document.body, "\\begin_layout Language", m)
2124 convert_TeX_brace_to_Argument(document, m, 1, 2, False, False, False)
2126 if i == -1 and j == -1 and k == -1 and m == -1:
2130 def revert_Initials(document):
2131 " Reverts InsetArgument of Initial to TeX-code "
2134 i = find_token(document.body, "\\begin_layout Initial", i)
2137 # first arg (optional) and second arg (first mandatory) are supported in LyX 2.0.x
2138 revert_Argument_to_TeX_brace(document, i, 0, 3, 3, False, False)
2142 def convert_Initials(document):
2143 " Converts ERT of Initial to InsetArgument "
2146 i = find_token(document.body, "\\begin_layout Initial", i)
2149 convert_TeX_brace_to_Argument(document, i, 3, 3, False, False, False)
2153 def revert_literate(document):
2154 " Revert Literate document to old format "
2155 if del_token(document.header, "noweb", 0):
2156 document.textclass = "literate-" + document.textclass
2159 i = find_token(document.body, "\\begin_layout Chunk", i)
2162 document.body[i] = "\\begin_layout Scrap"
2166 def convert_literate(document):
2167 " Convert Literate document to new format"
2168 i = find_token(document.header, "\\textclass", 0)
2169 if (i != -1) and "literate-" in document.header[i]:
2170 document.textclass = document.header[i].replace("\\textclass literate-", "")
2171 j = find_token(document.header, "\\begin_modules", 0)
2173 document.header.insert(j + 1, "noweb")
2175 document.header.insert(i + 1, "\\end_modules")
2176 document.header.insert(i + 1, "noweb")
2177 document.header.insert(i + 1, "\\begin_modules")
2180 i = find_token(document.body, "\\begin_layout Scrap", i)
2183 document.body[i] = "\\begin_layout Chunk"
2187 def revert_itemargs(document):
2188 " Reverts \\item arguments to TeX-code "
2191 i = find_token(document.body, "\\begin_inset Argument item:", i)
2194 j = find_end_of_inset(document.body, i)
2195 # Find containing paragraph layout
2196 parent = get_containing_layout(document.body, i)
2198 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2202 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2203 endPlain = find_end_of_layout(document.body, beginPlain)
2204 content = document.body[beginPlain + 1 : endPlain]
2205 del document.body[i:j+1]
2206 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2207 document.body[parbeg : parbeg] = subst
2211 def revert_garamondx_newtxmath(document):
2212 " Revert native garamond newtxmath definition to LaTeX "
2214 i = find_token(document.header, "\\font_math", 0)
2217 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2218 val = get_value(document.header, "\\font_math", i)
2219 if val == "garamondx-ntxm":
2220 add_to_preamble(document, "\\usepackage[garamondx]{newtxmath}")
2221 document.header[i] = "\\font_math auto"
2224 def revert_garamondx(document):
2225 " Revert native garamond font definition to LaTeX "
2227 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2228 i = find_token(document.header, "\\font_roman garamondx", 0)
2231 j = find_token(document.header, "\\font_osf true", 0)
2234 preamble = "\\usepackage"
2236 preamble += "[osfI]"
2237 preamble += "{garamondx}"
2238 add_to_preamble(document, [preamble])
2239 document.header[i] = "\\font_roman default"
2242 def convert_beamerargs(document):
2243 " Converts beamer arguments to new layout "
2245 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2246 if document.textclass not in beamer_classes:
2249 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2250 list_layouts = ["Itemize", "Enumerate", "Description"]
2251 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
2255 i = find_token(document.body, "\\begin_inset Argument", i)
2258 # Find containing paragraph layout
2259 parent = get_containing_layout(document.body, i)
2261 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2266 layoutname = parent[0]
2267 for p in range(parbeg, parend):
2268 if layoutname in shifted_layouts:
2269 m = rx.match(document.body[p])
2271 argnr = int(m.group(1))
2273 document.body[p] = "\\begin_inset Argument %d" % argnr
2274 if layoutname == "AgainFrame":
2275 m = rx.match(document.body[p])
2277 document.body[p] = "\\begin_inset Argument 3"
2278 if document.body[p + 4] == "\\begin_inset ERT":
2279 if document.body[p + 9].startswith("<"):
2280 # This is an overlay specification
2282 document.body[p + 9] = document.body[p + 9][1:]
2283 if document.body[p + 9].endswith(">"):
2285 document.body[p + 9] = document.body[p + 9][:-1]
2287 document.body[p] = "\\begin_inset Argument 2"
2288 if layoutname in list_layouts:
2289 m = rx.match(document.body[p])
2291 if m.group(1) == "1":
2292 if document.body[p + 4] == "\\begin_inset ERT":
2293 if document.body[p + 9].startswith("<"):
2294 # This is an overlay specification
2296 document.body[p + 9] = document.body[p + 9][1:]
2297 if document.body[p + 9].endswith(">"):
2299 document.body[p + 9] = document.body[p + 9][:-1]
2300 elif document.body[p + 4].startswith("<"):
2301 # This is an overlay specification (without ERT)
2303 document.body[p + 4] = document.body[p + 4][1:]
2304 if document.body[p + 4].endswith(">"):
2306 document.body[p + 4] = document.body[p + 4][:-1]
2307 elif layoutname != "Itemize":
2309 document.body[p] = "\\begin_inset Argument 2"
2314 # Helper function for the frame conversion routines
2316 # FIXME: This method currently requires the arguments to be either
2317 # * In one (whole) ERT each: <ERT>[<arg1>]</ERT><ERT><arg2></ERT><ERT>[arg3]</ERT>
2318 # * Altogether in one whole ERT: <ERT>[<arg1>]<arg2>[arg3]</ERT>
2319 # If individual arguments mix ERT and non-ERT or are splitted
2320 # over several ERTs, the parsing fails.
2321 def convert_beamerframeargs(document, i, parbeg):
2324 if document.body[parbeg] != "\\begin_inset ERT":
2326 ertend = find_end_of_inset(document.body, parbeg)
2328 document.warning("Malformed LyX document: missing ERT \\end_inset")
2330 ertcont = parbeg + 5
2331 if document.body[ertcont].startswith("[<"):
2332 # This is a default overlay specification
2334 document.body[ertcont] = document.body[ertcont][2:]
2335 if document.body[ertcont].endswith(">]"):
2337 document.body[ertcont] = document.body[ertcont][:-2]
2338 elif document.body[ertcont].endswith("]"):
2340 tok = document.body[ertcont].find('>][')
2342 subst = [document.body[ertcont][:tok],
2343 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2344 'status collapsed', '', '\\begin_layout Plain Layout',
2345 document.body[ertcont][tok + 3:-1]]
2346 document.body[ertcont : ertcont + 1] = subst
2348 # Convert to ArgInset
2349 document.body[parbeg] = "\\begin_inset Argument 2"
2350 elif document.body[ertcont].startswith("<"):
2351 # This is an overlay specification
2353 document.body[ertcont] = document.body[ertcont][1:]
2354 if document.body[ertcont].endswith(">"):
2356 document.body[ertcont] = document.body[ertcont][:-1]
2357 # Convert to ArgInset
2358 document.body[parbeg] = "\\begin_inset Argument 1"
2359 elif document.body[ertcont].endswith(">]"):
2361 tok = document.body[ertcont].find('>[<')
2363 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2364 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2365 'status collapsed', '', '\\begin_layout Plain Layout',
2366 document.body[ertcont][tok + 3:-2]]
2367 # Convert to ArgInset
2368 document.body[parbeg] = "\\begin_inset Argument 1"
2370 elif document.body[ertcont].endswith("]"):
2372 tok = document.body[ertcont].find('>[<')
2375 tokk = document.body[ertcont].find('>][')
2377 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2378 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2379 'status collapsed', '', '\\begin_layout Plain Layout',
2380 document.body[ertcont][tok + 3:tokk],
2381 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2382 'status collapsed', '', '\\begin_layout Plain Layout',
2383 document.body[ertcont][tokk + 3:-1]]
2386 tokk = document.body[ertcont].find('>[')
2388 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tokk],
2389 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2390 'status collapsed', '', '\\begin_layout Plain Layout',
2391 document.body[ertcont][tokk + 2:-1]]
2393 # Convert to ArgInset
2394 document.body[parbeg] = "\\begin_inset Argument 1"
2395 elif document.body[ertcont].startswith("["):
2396 # This is an ERT option
2398 document.body[ertcont] = document.body[ertcont][1:]
2399 if document.body[ertcont].endswith("]"):
2401 document.body[ertcont] = document.body[ertcont][:-1]
2402 # Convert to ArgInset
2403 document.body[parbeg] = "\\begin_inset Argument 3"
2409 def convert_againframe_args(document):
2410 " Converts beamer AgainFrame to new layout "
2412 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2413 if document.textclass not in beamer_classes:
2418 i = find_token(document.body, "\\begin_layout AgainFrame", i)
2421 parent = get_containing_layout(document.body, i)
2423 document.warning("Wrong parent layout!")
2427 # Convert ERT arguments
2428 # FIXME: See restrictions in convert_beamerframeargs method
2429 ertend = convert_beamerframeargs(document, i, parbeg)
2435 def convert_corollary_args(document):
2436 " Converts beamer corrolary-style ERT arguments native InsetArgs "
2438 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2439 if document.textclass not in beamer_classes:
2442 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2443 for lay in corollary_layouts:
2446 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2449 parent = get_containing_layout(document.body, i)
2451 document.warning("Wrong parent layout!")
2455 if document.body[parbeg] == "\\begin_inset ERT":
2456 ertcontfirstline = parbeg + 5
2457 # Find the last ERT in this paragraph (which might also be the first)
2458 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
2459 if lastertbeg == -1:
2460 document.warning("Last ERT not found!")
2462 lastertend = find_end_of_inset(document.body, lastertbeg)
2463 if lastertend == -1:
2464 document.warning("End of last ERT not found!")
2466 ertcontlastline = lastertend - 3
2467 if document.body[ertcontfirstline].startswith("<"):
2468 # This is an overlay specification
2470 document.body[ertcontfirstline] = document.body[ertcontfirstline][1:]
2471 if document.body[ertcontlastline].endswith(">"):
2473 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
2474 if ertcontfirstline < ertcontlastline:
2475 # Multiline ERT. Might contain TeX code. Embrace in ERT.
2476 document.body[ertcontlastline : ertcontlastline + 1] = [
2477 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
2478 document.body[ertcontfirstline : ertcontfirstline + 1] = [
2479 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
2480 'status collapsed', '', '\\begin_layout Plain Layout',
2481 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
2482 document.body[ertcontfirstline]]
2484 # Convert to ArgInset
2485 document.body[parbeg] = "\\begin_inset Argument 1"
2486 elif document.body[ertcontlastline].endswith("]"):
2488 tok = document.body[ertcontfirstline].find('>[')
2490 if ertcontfirstline < ertcontlastline:
2491 # Multiline ERT. Might contain TeX code. Embrace in ERT.
2492 document.body[ertcontlastline : ertcontlastline + 1] = [
2493 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
2494 document.body[ertcontfirstline : ertcontfirstline + 1] = [document.body[ertcontfirstline][:tok],
2495 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2496 'status collapsed', '', '\\begin_layout Plain Layout',
2497 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
2498 document.body[ertcontfirstline][tok + 2:-1]]
2500 document.body[ertcontfirstline : ertcontfirstline + 1] = [document.body[ertcontfirstline][:tok],
2501 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2502 'status collapsed', '', '\\begin_layout Plain Layout',
2503 document.body[ertcontfirstline][tok + 2:-1]]
2504 # Convert to ArgInset
2505 document.body[parbeg] = "\\begin_inset Argument 1"
2508 elif document.body[ertcontlastline].startswith("["):
2509 if document.body[ertcontlastline].endswith("]"):
2510 # This is an ERT option
2512 document.body[ertcontlastline] = document.body[ertcontlastline][1:]
2514 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
2515 # Convert to ArgInset
2516 document.body[parbeg] = "\\begin_inset Argument 2"
2518 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, True)
2525 def convert_quote_args(document):
2526 " Converts beamer quote style ERT args to native InsetArgs "
2528 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2529 if document.textclass not in beamer_classes:
2532 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2533 for lay in quote_layouts:
2536 i = find_token(document.body, "\\begin_layout " + lay, i)
2539 parent = get_containing_layout(document.body, i)
2541 document.warning("Wrong parent layout!")
2545 if document.body[parbeg] == "\\begin_inset ERT":
2546 if document.body[i + 6].startswith("<"):
2547 # This is an overlay specification
2549 document.body[i + 6] = document.body[i + 6][1:]
2550 if document.body[i + 6].endswith(">"):
2552 document.body[i + 6] = document.body[i + 6][:-1]
2553 # Convert to ArgInset
2554 document.body[i + 1] = "\\begin_inset Argument 1"
2558 def cleanup_beamerargs(document):
2559 " Clean up empty ERTs (conversion artefacts) "
2561 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2562 if document.textclass not in beamer_classes:
2567 i = find_token(document.body, "\\begin_inset Argument", i)
2570 j = find_end_of_inset(document.body, i)
2572 document.warning("Malformed LyX document: Can't find end of Argument inset")
2576 ertbeg = find_token(document.body, "\\begin_inset ERT", i, j)
2579 ertend = find_end_of_inset(document.body, ertbeg)
2581 document.warning("Malformed LyX document: Can't find end of ERT inset")
2583 stripped = [line for line in document.body[ertbeg : ertend + 1] if line.strip()]
2584 if len(stripped) == 5:
2585 # This is an empty ERT
2586 offset = len(document.body[ertbeg : ertend + 1])
2587 del document.body[ertbeg : ertend + 1]
2594 def revert_beamerargs(document):
2595 " Reverts beamer arguments to old layout "
2597 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2598 if document.textclass not in beamer_classes:
2602 list_layouts = ["Itemize", "Enumerate", "Description"]
2603 headings = ["Part", "Section", "Section*", "Subsection", "Subsection*",
2604 "Subsubsection", "Subsubsection*", "FrameSubtitle", "NoteItem"]
2605 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2606 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2607 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2610 i = find_token(document.body, "\\begin_inset Argument", i)
2613 # Find containing paragraph layout
2614 parent = get_containing_layout(document.body, i)
2616 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2621 realparbeg = parent[3]
2622 layoutname = parent[0]
2624 for p in range(parbeg, parend):
2628 if layoutname in headings:
2629 m = rx.match(document.body[p])
2633 # Find containing paragraph layout
2634 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2635 endPlain = find_end_of_layout(document.body, beginPlain)
2636 endInset = find_end_of_inset(document.body, p)
2637 argcontent = document.body[beginPlain + 1 : endPlain]
2639 realparend = realparend - len(document.body[p : endInset + 1])
2641 del document.body[p : endInset + 1]
2642 if layoutname == "FrameSubtitle":
2643 pre = put_cmd_in_ert("\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2644 elif layoutname == "NoteItem":
2645 pre = put_cmd_in_ert("\\note<") + argcontent + put_cmd_in_ert(">[item]")
2646 elif layoutname.endswith('*'):
2647 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower()[:-1] + "<") + argcontent + put_cmd_in_ert(">*")
2649 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2650 secarg = find_token(document.body, "\\begin_inset Argument 2", parbeg, parend)
2652 # Find containing paragraph layout
2653 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", secarg)
2654 endPlain = find_end_of_layout(document.body, beginPlain)
2655 endInset = find_end_of_inset(document.body, secarg)
2656 argcontent = document.body[beginPlain + 1 : endPlain]
2658 realparend = realparend - len(document.body[secarg : endInset + 1])
2659 del document.body[secarg : endInset + 1]
2660 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2661 pre += put_cmd_in_ert("{")
2662 document.body[parbeg] = "\\begin_layout Standard"
2663 document.body[realparbeg : realparbeg] = pre
2664 pe = find_end_of_layout(document.body, parbeg)
2665 post = put_cmd_in_ert("}")
2666 document.body[pe : pe] = post
2667 realparend += len(pre) + len(post)
2668 if layoutname == "AgainFrame":
2669 m = rx.match(document.body[p])
2673 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2674 endPlain = find_end_of_layout(document.body, beginPlain)
2675 endInset = find_end_of_inset(document.body, p)
2676 content = document.body[beginPlain + 1 : endPlain]
2678 realparend = realparend - len(document.body[p : endInset + 1])
2680 del document.body[p : endInset + 1]
2681 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2682 document.body[realparbeg : realparbeg] = subst
2683 if layoutname == "Overprint":
2684 m = rx.match(document.body[p])
2688 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2689 endPlain = find_end_of_layout(document.body, beginPlain)
2690 endInset = find_end_of_inset(document.body, p)
2691 content = document.body[beginPlain + 1 : endPlain]
2693 realparend = realparend - len(document.body[p : endInset + 1])
2695 del document.body[p : endInset + 1]
2696 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2697 document.body[realparbeg : realparbeg] = subst
2698 if layoutname == "OverlayArea":
2699 m = rx.match(document.body[p])
2703 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2704 endPlain = find_end_of_layout(document.body, beginPlain)
2705 endInset = find_end_of_inset(document.body, p)
2706 content = document.body[beginPlain + 1 : endPlain]
2708 realparend = realparend - len(document.body[p : endInset + 1])
2710 del document.body[p : endInset + 1]
2711 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2712 document.body[realparbeg : realparbeg] = subst
2713 if layoutname in list_layouts:
2714 m = rx.match(document.body[p])
2718 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2719 endPlain = find_end_of_layout(document.body, beginPlain)
2720 endInset = find_end_of_inset(document.body, p)
2721 content = document.body[beginPlain + 1 : endPlain]
2722 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2723 realparend = realparend + len(subst) - len(content)
2724 document.body[beginPlain + 1 : endPlain] = subst
2725 elif argnr == "item:1":
2726 j = find_end_of_inset(document.body, i)
2727 # Find containing paragraph layout
2728 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2729 endPlain = find_end_of_layout(document.body, beginPlain)
2730 content = document.body[beginPlain + 1 : endPlain]
2731 del document.body[i:j+1]
2732 if layoutname == "Description":
2733 # Description only has one (overlay) item arg
2734 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2735 # This must be put after the first space (begin of decription body
2736 # in LyX's arkward description list syntax)
2737 # Try to find that place ...
2738 rxx = re.compile(r'^([^\\ ]+ )(.*)$')
2739 for q in range(parbeg, parend):
2740 m = rxx.match(document.body[q])
2742 # We found it. Now insert the ERT argument just there:
2743 document.body[q : q] = [m.group(1), ''] + subst + ['', m.group(2)]
2746 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2747 document.body[realparbeg : realparbeg] = subst
2748 elif argnr == "item:2":
2749 j = find_end_of_inset(document.body, i)
2750 # Find containing paragraph layout
2751 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2752 endPlain = find_end_of_layout(document.body, beginPlain)
2753 content = document.body[beginPlain + 1 : endPlain]
2754 del document.body[i:j+1]
2755 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2756 document.body[realparbeg : realparbeg] = subst
2757 if layoutname in quote_layouts:
2758 m = rx.match(document.body[p])
2762 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2763 endPlain = find_end_of_layout(document.body, beginPlain)
2764 endInset = find_end_of_inset(document.body, p)
2765 content = document.body[beginPlain + 1 : endPlain]
2767 realparend = realparend - len(document.body[p : endInset + 1])
2769 del document.body[p : endInset + 1]
2770 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2771 document.body[realparbeg : realparbeg] = subst
2772 if layoutname in corollary_layouts:
2773 m = rx.match(document.body[p])
2777 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2778 endPlain = find_end_of_layout(document.body, beginPlain)
2779 endInset = find_end_of_inset(document.body, p)
2780 content = document.body[beginPlain + 1 : endPlain]
2782 realparend = realparend - len(document.body[p : endInset + 1])
2784 del document.body[p : endInset + 1]
2785 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2786 document.body[realparbeg : realparbeg] = subst
2791 def revert_beamerargs2(document):
2792 " Reverts beamer arguments to old layout, step 2 "
2794 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2795 if document.textclass not in beamer_classes:
2799 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2800 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2801 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2804 i = find_token(document.body, "\\begin_inset Argument", i)
2807 # Find containing paragraph layout
2808 parent = get_containing_layout(document.body, i)
2810 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2815 realparbeg = parent[3]
2816 layoutname = parent[0]
2818 for p in range(parbeg, parend):
2822 if layoutname in shifted_layouts:
2823 m = rx.match(document.body[p])
2827 document.body[p] = "\\begin_inset Argument 1"
2828 if layoutname in corollary_layouts:
2829 m = rx.match(document.body[p])
2833 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2834 endPlain = find_end_of_layout(document.body, beginPlain)
2835 endInset = find_end_of_inset(document.body, p)
2836 content = document.body[beginPlain + 1 : endPlain]
2838 realparend = realparend - len(document.body[p : endInset + 1])
2840 del document.body[p : endInset + 1]
2841 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2842 document.body[realparbeg : realparbeg] = subst
2843 if layoutname == "OverlayArea":
2844 m = rx.match(document.body[p])
2848 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2849 endPlain = find_end_of_layout(document.body, beginPlain)
2850 endInset = find_end_of_inset(document.body, p)
2851 content = document.body[beginPlain + 1 : endPlain]
2853 realparend = realparend - len(document.body[p : endInset + 1])
2855 del document.body[p : endInset + 1]
2856 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2857 document.body[realparbeg : realparbeg] = subst
2858 if layoutname == "AgainFrame":
2859 m = rx.match(document.body[p])
2863 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2864 endPlain = find_end_of_layout(document.body, beginPlain)
2865 endInset = find_end_of_inset(document.body, p)
2866 content = document.body[beginPlain + 1 : endPlain]
2868 realparend = realparend - len(document.body[p : endInset + 1])
2870 del document.body[p : endInset + 1]
2871 subst = put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
2872 document.body[realparbeg : realparbeg] = subst
2876 def revert_beamerargs3(document):
2877 " Reverts beamer arguments to old layout, step 3 "
2879 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2880 if document.textclass not in beamer_classes:
2883 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2886 i = find_token(document.body, "\\begin_inset Argument", i)
2889 # Find containing paragraph layout
2890 parent = get_containing_layout(document.body, i)
2892 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2897 realparbeg = parent[3]
2898 layoutname = parent[0]
2900 for p in range(parbeg, parend):
2904 if layoutname == "AgainFrame":
2905 m = rx.match(document.body[p])
2909 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2910 endPlain = find_end_of_layout(document.body, beginPlain)
2911 endInset = find_end_of_inset(document.body, p)
2912 content = document.body[beginPlain + 1 : endPlain]
2914 realparend = realparend - len(document.body[p : endInset + 1])
2916 del document.body[p : endInset + 1]
2917 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2918 document.body[realparbeg : realparbeg] = subst
2922 def revert_beamerflex(document):
2923 " Reverts beamer Flex insets "
2925 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2926 if document.textclass not in beamer_classes:
2929 new_flexes = {"Bold" : "\\textbf", "Emphasize" : "\\emph", "Only" : "\\only",
2930 "Uncover" : "\\uncover", "Visible" : "\\visible",
2931 "Invisible" : "\\invisible", "Alternative" : "\\alt",
2932 "Beamer_Note" : "\\note"}
2933 old_flexes = {"Alert" : "\\alert", "Structure" : "\\structure"}
2934 rx = re.compile(r'^\\begin_inset Flex (.+)$')
2938 i = find_token(document.body, "\\begin_inset Flex", i)
2941 m = rx.match(document.body[i])
2943 flextype = m.group(1)
2944 z = find_end_of_inset(document.body, i)
2946 document.warning("Can't find end of Flex " + flextype + " inset.")
2949 if flextype in new_flexes:
2950 pre = put_cmd_in_ert(new_flexes[flextype])
2951 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2953 argend = find_end_of_inset(document.body, arg)
2955 document.warning("Can't find end of Argument!")
2958 # Find containing paragraph layout
2959 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2960 endPlain = find_end_of_layout(document.body, beginPlain)
2961 argcontent = document.body[beginPlain + 1 : endPlain]
2963 z = z - len(document.body[arg : argend + 1])
2965 del document.body[arg : argend + 1]
2966 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2967 arg = find_token(document.body, "\\begin_inset Argument 2", i, z)
2969 argend = find_end_of_inset(document.body, arg)
2971 document.warning("Can't find end of Argument!")
2974 # Find containing paragraph layout
2975 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2976 endPlain = find_end_of_layout(document.body, beginPlain)
2977 argcontent = document.body[beginPlain + 1 : endPlain]
2979 z = z - len(document.body[arg : argend + 1])
2981 del document.body[arg : argend + 1]
2982 if flextype == "Alternative":
2983 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
2985 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2986 pre += put_cmd_in_ert("{")
2987 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2988 endPlain = find_end_of_layout(document.body, beginPlain)
2990 z = z - len(document.body[i : beginPlain + 1])
2992 document.body[i : beginPlain + 1] = pre
2993 post = put_cmd_in_ert("}")
2994 document.body[z - 2 : z + 1] = post
2995 elif flextype in old_flexes:
2996 pre = put_cmd_in_ert(old_flexes[flextype])
2997 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
3001 argend = find_end_of_inset(document.body, arg)
3003 document.warning("Can't find end of Argument!")
3006 # Find containing paragraph layout
3007 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3008 endPlain = find_end_of_layout(document.body, beginPlain)
3009 argcontent = document.body[beginPlain + 1 : endPlain]
3011 z = z - len(document.body[arg : argend + 1])
3013 del document.body[arg : argend + 1]
3014 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
3015 pre += put_cmd_in_ert("{")
3016 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
3017 endPlain = find_end_of_layout(document.body, beginPlain)
3019 z = z - len(document.body[i : beginPlain + 1])
3021 document.body[i : beginPlain + 1] = pre
3022 post = put_cmd_in_ert("}")
3023 document.body[z - 2 : z + 1] = post
3028 def revert_beamerblocks(document):
3029 " Reverts beamer block arguments to ERT "
3031 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3032 if document.textclass not in beamer_classes:
3035 blocks = ["Block", "ExampleBlock", "AlertBlock"]
3037 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3040 i = find_token(document.body, "\\begin_inset Argument", i)
3043 # Find containing paragraph layout
3044 parent = get_containing_layout(document.body, i)
3046 document.warning("Malformed LyX document: Can't find parent paragraph layout")
3051 realparbeg = parent[3]
3052 layoutname = parent[0]
3054 for p in range(parbeg, parend):
3058 if layoutname in blocks:
3059 m = rx.match(document.body[p])
3063 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3064 endPlain = find_end_of_layout(document.body, beginPlain)
3065 endInset = find_end_of_inset(document.body, p)
3066 content = document.body[beginPlain + 1 : endPlain]
3068 realparend = realparend - len(document.body[p : endInset + 1])
3070 del document.body[p : endInset + 1]
3071 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3072 document.body[realparbeg : realparbeg] = subst
3074 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3075 endPlain = find_end_of_layout(document.body, beginPlain)
3076 endInset = find_end_of_inset(document.body, p)
3077 content = document.body[beginPlain + 1 : endPlain]
3079 realparend = realparend - len(document.body[p : endInset + 1])
3081 del document.body[p : endInset + 1]
3082 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3083 document.body[realparbeg : realparbeg] = subst
3088 def convert_beamerblocks(document):
3089 " Converts beamer block ERT args to native InsetArgs "
3091 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3092 if document.textclass not in beamer_classes:
3095 blocks = ["Block", "ExampleBlock", "AlertBlock"]
3099 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
3102 parent = get_containing_layout(document.body, i)
3103 if parent == False or parent[1] != i:
3104 document.warning("Wrong parent layout!")
3111 # If the paragraph starts with a language switch, adjust parbeg
3112 if len(document.body[parbeg]) == 0 and parbeg < parend \
3113 and document.body[parbeg + 1].startswith("\\lang"):
3115 if document.body[parbeg] == "\\begin_inset ERT":
3116 ertcontfirstline = parbeg + 5
3120 # Find the last ERT in this paragraph used for arguments
3121 # (which might also be the first)
3122 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
3123 if lastertbeg == -1:
3124 document.warning("Last ERT not found!")
3126 lastertend = find_end_of_inset(document.body, lastertbeg)
3127 if lastertend == -1:
3128 document.warning("End of last ERT not found!")
3130 # Is this ERT really used for an argument?
3131 # Note: This will fail when non-argument ERTs actually use brackets
3133 regexp = re.compile(r'.*[>\]\}]', re.IGNORECASE)
3134 cbracket = find_re(document.body, regexp, lastertbeg, lastertend)
3137 if lastertbeg == parbeg:
3140 if lastertbeg == -1 or lastertend == -1:
3142 ertcontlastline = lastertend - 3
3144 if document.body[ertcontfirstline].lstrip().startswith("<"):
3145 # This is an overlay specification
3147 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3148 if document.body[ertcontlastline].rstrip().endswith(">"):
3150 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3151 # Convert to ArgInset
3152 document.body[parbeg] = "\\begin_inset Argument 1"
3153 elif document.body[ertcontlastline].rstrip().endswith("}"):
3155 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3157 ertcontdivline = ertcontfirstline
3158 tok = document.body[ertcontdivline].find('>{')
3160 regexp = re.compile(r'.*>\{', re.IGNORECASE)
3161 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3162 tok = document.body[ertcontdivline].find('>{')
3164 if ertcontfirstline < ertcontlastline:
3165 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3166 document.body[ertcontlastline : ertcontlastline + 1] = [
3167 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3168 if ertcontdivline == ertcontfirstline:
3169 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3170 '\\end_layout', '', '\\end_inset', '',
3171 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3172 'status collapsed', '', '\\begin_layout Plain Layout',
3173 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3174 document.body[ertcontdivline][tok + 2:]]
3176 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3177 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3178 'status collapsed', '', '\\begin_layout Plain Layout',
3179 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3180 document.body[ertcontdivline][tok + 2:]]
3182 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3183 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3184 'status collapsed', '', '\\begin_layout Plain Layout',
3185 document.body[ertcontdivline][tok + 2:]]
3187 # check if have delimiters in two different ERTs
3188 tok = document.body[ertcontdivline].find('>')
3190 regexp = re.compile(r'.*>', re.IGNORECASE)
3191 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3192 tok = document.body[ertcontdivline].find('>')
3194 tokk = document.body[ertcontdivline].find('{')
3196 regexp = re.compile(r'.*\{', re.IGNORECASE)
3197 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, lastertend)
3198 tokk = document.body[ertcontdivlinetwo].find('{')
3200 if ertcontfirstline < ertcontlastline:
3201 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3202 document.body[ertcontlastline : ertcontlastline + 1] = [
3203 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3204 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3205 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3206 '\\end_inset', '', '', '\\begin_inset Argument 2',
3207 'status collapsed', '', '\\begin_layout Plain Layout',
3208 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3209 document.body[ertcontdivlinetwo][tokk + 1:]]
3211 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3212 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3213 'status collapsed', '', '\\begin_layout Plain Layout',
3214 document.body[ertcontdivlinetwo][tokk + 1:]]
3215 # Convert to ArgInset
3216 if ertcontfirstline < ertcontlastline:
3217 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3218 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 1',
3219 'status collapsed', '', '\\begin_layout Plain Layout',
3220 '\\begin_inset ERT', '']
3222 document.body[parbeg] = "\\begin_inset Argument 1"
3223 elif document.body[ertcontfirstline].lstrip().startswith("{"):
3224 # This is the block title
3225 if document.body[ertcontlastline].rstrip().endswith("}"):
3226 # strip off the braces
3227 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3228 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3229 if ertcontfirstline < ertcontlastline:
3230 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3231 document.body[parend : parend + 1] = [
3232 document.body[parend], '\\end_inset', '', '\\end_layout']
3233 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3234 'status collapsed', '', '\\begin_layout Plain Layout',
3235 '\\begin_inset ERT', '']
3237 # Convert to ArgInset
3238 document.body[parbeg] = "\\begin_inset Argument 2"
3239 # the overlay argument can also follow the title, so ...
3240 elif document.body[ertcontlastline].rstrip().endswith(">"):
3242 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3244 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3246 ertcontdivline = ertcontfirstline
3247 tok = document.body[ertcontdivline].find('}<')
3249 regexp = re.compile(r'.*\}<', re.IGNORECASE)
3250 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3251 tok = document.body[ertcontdivline].find('}<')
3253 if ertcontfirstline < ertcontlastline:
3254 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3255 document.body[ertcontlastline : ertcontlastline + 1] = [
3256 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3257 if ertcontdivline == ertcontfirstline:
3258 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3259 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3260 'status collapsed', '', '\\begin_layout Plain Layout',
3261 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3262 document.body[ertcontdivline][tok + 2:]]
3264 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3265 '\\end_layout', '', '\\end_inset', '',
3266 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3267 'status collapsed', '', '\\begin_layout Plain Layout',
3268 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3269 document.body[ertcontdivline][tok + 2:]]
3271 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3272 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3273 'status collapsed', '', '\\begin_layout Plain Layout',
3274 document.body[ertcontdivline][tok + 2:]]
3276 # check if have delimiters in two different ERTs
3277 tok = document.body[ertcontdivline].find('}')
3279 regexp = re.compile(r'.*\}', re.IGNORECASE)
3280 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3281 tok = document.body[ertcontdivline].find('}')
3283 tokk = document.body[ertcontdivline].find('<')
3285 regexp = re.compile(r'.*<', re.IGNORECASE)
3286 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, lastertend)
3287 tokk = document.body[ertcontdivlinetwo].find('<')
3289 if ertcontfirstline < ertcontlastline:
3290 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3291 document.body[ertcontlastline : ertcontlastline + 1] = [
3292 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3293 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3294 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3295 '\\end_inset', '', '', '\\begin_inset Argument 1',
3296 'status collapsed', '', '\\begin_layout Plain Layout',
3297 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3298 document.body[ertcontdivlinetwo][tokk + 1:]]
3300 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3301 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3302 'status collapsed', '', '\\begin_layout Plain Layout',
3303 document.body[ertcontdivlinetwo][tokk + 1:]]
3304 # Convert to ArgInset
3305 if ertcontfirstline < ertcontlastline:
3306 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3307 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3308 'status collapsed', '', '\\begin_layout Plain Layout',
3309 '\\begin_inset ERT', '']
3311 document.body[parbeg] = "\\begin_inset Argument 2"
3312 elif count_pars_in_inset(document.body, ertcontfirstline) > 1:
3313 # Multipar ERT. Skip this.
3316 # ERT has contents after the closing bracket. We cannot convert this.
3317 # convert_TeX_brace_to_Argument cannot either.
3318 #convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, False)
3322 j = find_end_of_layout(document.body, i)
3324 document.warning("end of layout not found!")
3325 k = find_token(document.body, "\\begin_inset Argument", i, j)
3327 document.warning("InsetArgument not found!")
3329 l = find_end_of_inset(document.body, k)
3330 m = find_token(document.body, "\\begin_inset ERT", l, j)
3333 ertcontfirstline = m + 5
3338 def convert_overprint(document):
3339 " Convert old beamer overprint layouts to ERT "
3341 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3342 if document.textclass not in beamer_classes:
3347 i = find_token(document.body, "\\begin_layout Overprint", i)
3350 # Find end of sequence
3351 j = find_end_of_sequence(document.body, i)
3353 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3357 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3359 if document.body[j] == "\\end_deeper":
3360 esubst = ["", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3362 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3363 endseq = endseq + len(esubst) - len(document.body[j : j])
3364 document.body[j : j] = esubst
3365 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3367 argend = find_end_of_layout(document.body, argbeg)
3369 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3372 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3373 endPlain = find_end_of_layout(document.body, beginPlain)
3374 content = document.body[beginPlain + 1 : endPlain]
3376 endseq = endseq - len(document.body[argbeg : argend + 1])
3378 del document.body[argbeg : argend + 1]
3379 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3381 endseq = endseq - len(document.body[i : i])
3382 document.body[i : i] = subst + ["\\end_layout"]
3383 endseq += len(subst)
3385 for p in range(i, endseq):
3386 if document.body[p] == "\\begin_layout Overprint":
3387 document.body[p] = "\\begin_layout Standard"
3392 def revert_overprint(document):
3393 " Revert old beamer overprint layouts to ERT "
3395 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3396 if document.textclass not in beamer_classes:
3401 i = find_token(document.body, "\\begin_layout Overprint", i)
3404 # Find end of sequence
3405 j = find_end_of_sequence(document.body, i)
3407 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3411 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3412 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}")
3413 endseq = endseq + len(esubst) - len(document.body[j : j])
3414 if document.body[j] == "\\end_deeper":
3415 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3417 document.body[j : j] = ["\\end_layout", ""] + esubst
3420 if document.body[r] == "\\begin_deeper":
3421 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3423 document.body[r] = ""
3424 document.body[s] = ""
3428 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3430 # Is this really our argument?
3431 nested = find_token(document.body, "\\begin_deeper", i, argbeg)
3433 argend = find_end_of_inset(document.body, argbeg)
3435 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3438 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3439 endPlain = find_end_of_layout(document.body, beginPlain)
3440 content = document.body[beginPlain + 1 : endPlain]
3442 endseq = endseq - len(document.body[argbeg : argend])
3444 del document.body[argbeg : argend + 1]
3445 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3447 endseq = endseq - len(document.body[i : i])
3448 document.body[i : i] = subst + ["\\end_layout"]
3449 endseq += len(subst)
3455 if document.body[p] == "\\begin_layout Overprint":
3456 q = find_end_of_layout(document.body, p)
3458 document.warning("Malformed LyX document. Cannot find end of Overprint layout!")
3461 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\onslide")
3462 argbeg = find_token(document.body, "\\begin_inset Argument item:1", p, q)
3464 argend = find_end_of_inset(document.body, argbeg)
3466 document.warning("Malformed LyX document. Cannot find end of Overprint item argument!")
3469 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3470 endPlain = find_end_of_layout(document.body, beginPlain)
3471 content = document.body[beginPlain + 1 : endPlain]
3473 endseq = endseq - len(document.body[argbeg : argend + 1])
3475 del document.body[argbeg : argend + 1]
3476 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3477 endseq = endseq - len(document.body[p : p + 1]) + len(subst)
3478 document.body[p : p + 1] = subst
3484 def revert_frametitle(document):
3485 " Reverts beamer frametitle layout to ERT "
3487 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3488 if document.textclass not in beamer_classes:
3491 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3494 i = find_token(document.body, "\\begin_layout FrameTitle", i)
3497 j = find_end_of_layout(document.body, i)
3499 document.warning("Malformed LyX document: Can't find end of FrameTitle layout")
3503 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
3504 endlay += len(put_cmd_in_ert("}"))
3505 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\frametitle")
3506 for p in range(i, j):
3509 m = rx.match(document.body[p])
3513 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3514 endPlain = find_end_of_layout(document.body, beginPlain)
3515 endInset = find_end_of_inset(document.body, p)
3516 content = document.body[beginPlain + 1 : endPlain]
3518 endlay = endlay - len(document.body[p : endInset + 1])
3520 del document.body[p : endInset + 1]
3521 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3523 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3524 endPlain = find_end_of_layout(document.body, beginPlain)
3525 endInset = find_end_of_inset(document.body, p)
3526 content = document.body[beginPlain + 1 : endPlain]
3528 endlay = endlay - len(document.body[p : endInset + 1])
3530 del document.body[p : endInset + 1]
3531 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3533 subst += put_cmd_in_ert("{")
3534 document.body[i : i + 1] = subst
3538 def convert_epigraph(document):
3539 " Converts memoir epigraph to new syntax "
3541 if document.textclass != "memoir":
3546 i = find_token(document.body, "\\begin_layout Epigraph", i)
3549 j = find_end_of_layout(document.body, i)
3551 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3556 ert = find_token(document.body, "\\begin_inset ERT", i, j)
3558 endInset = find_end_of_inset(document.body, ert)
3559 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", ert)
3560 endPlain = find_end_of_layout(document.body, beginPlain)
3561 ertcont = beginPlain + 2
3562 if document.body[ertcont] == "}{":
3564 # Convert to ArgInset
3565 endlay = endlay - 2 * len(document.body[j])
3566 begsubst = ['\\begin_inset Argument post:1', 'status collapsed', '',
3567 '\\begin_layout Plain Layout']
3568 endsubst = ['\\end_layout', '', '\\end_inset', '', document.body[j]]
3569 document.body[j : j + 1] = endsubst
3570 document.body[endInset + 1 : endInset + 1] = begsubst
3572 endlay += len(begsubst) + len(endsubst)
3573 endlay = endlay - len(document.body[ert : endInset + 1])
3574 del document.body[ert : endInset + 1]
3579 def revert_epigraph(document):
3580 " Reverts memoir epigraph argument to ERT "
3582 if document.textclass != "memoir":
3587 i = find_token(document.body, "\\begin_layout Epigraph", i)
3590 j = find_end_of_layout(document.body, i)
3592 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3597 p = find_token(document.body, "\\begin_layout Argument post:1", i, j)
3599 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3600 endPlain = find_end_of_layout(document.body, beginPlain)
3601 endInset = find_end_of_inset(document.body, p)
3602 content = document.body[beginPlain + 1 : endPlain]
3604 endlay = endlay - len(document.body[p : endInset + 1])
3606 del document.body[p : endInset + 1]
3607 subst += put_cmd_in_ert("}{") + content
3609 subst += put_cmd_in_ert("}{")
3611 document.body[j : j] = subst + document.body[j : j]
3615 def convert_captioninsets(document):
3616 " Converts caption insets to new syntax "
3620 i = find_token(document.body, "\\begin_inset Caption", i)
3623 document.body[i] = "\\begin_inset Caption Standard"
3627 def revert_captioninsets(document):
3628 " Reverts caption insets to old syntax "
3632 i = find_token(document.body, "\\begin_inset Caption Standard", i)
3635 document.body[i] = "\\begin_inset Caption"
3639 def convert_captionlayouts(document):
3640 " Convert caption layouts to caption insets. "
3643 "Captionabove": "Above",
3644 "Captionbelow": "Below",
3645 "FigCaption" : "FigCaption",
3646 "Table_Caption" : "Table",
3647 "CenteredCaption" : "Centered",
3648 "Bicaption" : "Bicaption",
3653 i = find_token(document.body, "\\begin_layout", i)
3656 val = get_value(document.body, "\\begin_layout", i)
3657 if val in list(caption_dict.keys()):
3658 j = find_end_of_layout(document.body, i)
3660 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3663 document.body[j:j] = ["\\end_layout", "", "\\end_inset", "", ""]
3664 document.body[i:i+1] = ["\\begin_layout %s" % document.default_layout,
3665 "\\begin_inset Caption %s" % caption_dict[val], "",
3666 "\\begin_layout %s" % document.default_layout]
3670 def revert_captionlayouts(document):
3671 " Revert caption insets to caption layouts. "
3674 "Above" : "Captionabove",
3675 "Below" : "Captionbelow",
3676 "FigCaption" : "FigCaption",
3677 "Table" : "Table_Caption",
3678 "Centered" : "CenteredCaption",
3679 "Bicaption" : "Bicaption",
3683 rx = re.compile(r'^\\begin_inset Caption (\S+)$')
3685 i = find_token(document.body, "\\begin_inset Caption", i)
3689 m = rx.match(document.body[i])
3693 if val not in list(caption_dict.keys()):
3697 # We either need to delete the previous \begin_layout line, or we
3698 # need to end the previous layout if this inset is not in the first
3699 # position of the paragraph.
3700 layout_before = find_token_backwards(document.body, "\\begin_layout", i)
3701 if layout_before == -1:
3702 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3704 layout_line = document.body[layout_before]
3705 del_layout_before = True
3706 l = layout_before + 1
3708 if document.body[l] != "":
3709 del_layout_before = False
3712 if del_layout_before:
3713 del document.body[layout_before:i]
3716 document.body[i:i] = ["\\end_layout", ""]
3719 # Find start of layout in the inset and end of inset
3720 j = find_token(document.body, "\\begin_layout", i)
3722 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3724 k = find_end_of_inset(document.body, i)
3726 document.warning("Malformed LyX document: Missing `\\end_inset'.")
3729 # We either need to delete the following \end_layout line, or we need
3730 # to restart the old layout if this inset is not at the paragraph end.
3731 layout_after = find_token(document.body, "\\end_layout", k)
3732 if layout_after == -1:
3733 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3735 del_layout_after = True
3737 while l < layout_after:
3738 if document.body[l] != "":
3739 del_layout_after = False
3742 if del_layout_after:
3743 del document.body[k+1:layout_after+1]
3745 document.body[k+1:k+1] = [layout_line, ""]
3747 # delete \begin_layout and \end_inset and replace \begin_inset with
3748 # "\begin_layout XXX". This works because we can only have one
3749 # paragraph in the caption inset: The old \end_layout will be recycled.
3750 del document.body[k]
3751 if document.body[k] == "":
3752 del document.body[k]
3753 del document.body[j]
3754 if document.body[j] == "":
3755 del document.body[j]
3756 document.body[i] = "\\begin_layout %s" % caption_dict[val]
3757 if document.body[i+1] == "":
3758 del document.body[i+1]
3762 def revert_fragileframe(document):
3763 " Reverts beamer FragileFrame layout to ERT "
3765 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3766 if document.textclass not in beamer_classes:
3771 i = find_token(document.body, "\\begin_layout FragileFrame", i)
3774 # Find end of sequence
3775 j = find_end_of_sequence(document.body, i)
3777 document.warning("Malformed LyX document. Cannot find end of FragileFrame sequence!")
3781 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{frame}")
3782 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{frame}")
3783 endseq = endseq + len(esubst) - len(document.body[j : j])
3784 if document.body[j] == "\\end_deeper":
3785 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3787 document.body[j : j] = esubst
3788 for q in range(i, j):
3789 if document.body[q] == "\\begin_layout FragileFrame":
3790 document.body[q] = "\\begin_layout %s" % document.default_layout
3793 if document.body[r] == "\\begin_deeper":
3794 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3796 document.body[r] = ""
3797 document.body[s] = ""
3801 for p in range(1, 5):
3802 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, j)
3805 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3806 endPlain = find_end_of_layout(document.body, beginPlain)
3807 endInset = find_end_of_inset(document.body, arg)
3808 content = document.body[beginPlain + 1 : endPlain]
3810 j = j - len(document.body[arg : endInset + 1])
3812 del document.body[arg : endInset + 1]
3813 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3815 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3816 endPlain = find_end_of_layout(document.body, beginPlain)
3817 endInset = find_end_of_inset(document.body, arg)
3818 content = document.body[beginPlain + 1 : endPlain]
3820 j = j - len(document.body[arg : endInset + 1])
3822 del document.body[arg : endInset + 1]
3823 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3825 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3826 endPlain = find_end_of_layout(document.body, beginPlain)
3827 endInset = find_end_of_inset(document.body, arg)
3828 content = document.body[beginPlain + 1 : endPlain]
3830 j = j - len(document.body[arg : endInset + 1])
3832 del document.body[arg : endInset + 1]
3833 subst += put_cmd_in_ert("[fragile,") + content + put_cmd_in_ert("]")
3835 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3836 endPlain = find_end_of_layout(document.body, beginPlain)
3837 endInset = find_end_of_inset(document.body, arg)
3838 content = document.body[beginPlain + 1 : endPlain]
3840 j = j - len(document.body[arg : endInset + 1])
3842 del document.body[arg : endInset + 1]
3843 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3845 subst += put_cmd_in_ert("[fragile]")
3847 document.body[i : i + 1] = subst
3851 def revert_newframes(document):
3852 " Reverts beamer Frame and PlainFrame layouts to old forms "
3854 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3855 if document.textclass not in beamer_classes:
3859 "Frame" : "BeginFrame",
3860 "PlainFrame" : "BeginPlainFrame",
3863 rx = re.compile(r'^\\begin_layout (\S+)$')
3866 i = find_token(document.body, "\\begin_layout", i)
3870 m = rx.match(document.body[i])
3874 if val not in list(frame_dict.keys()):
3877 # Find end of sequence
3878 j = find_end_of_sequence(document.body, i)
3880 document.warning("Malformed LyX document. Cannot find end of Frame sequence!")
3884 subst = ["\\begin_layout %s" % frame_dict[val]]
3885 esubst = ["", "\\begin_layout EndFrame", "", "\\end_layout"]
3886 endseq = endseq + len(esubst) - len(document.body[j : j])
3887 if document.body[j] == "\\end_deeper":
3888 document.body[j : j] = esubst
3890 document.body[j+1 : j+1] = esubst
3891 for q in range(i, j):
3892 if document.body[q] == "\\begin_layout %s" % val:
3893 document.body[q] = "\\begin_layout %s" % document.default_layout
3896 if document.body[r] == "\\begin_deeper":
3897 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3899 document.body[r] = ""
3900 document.body[s] = ""
3904 l = find_end_of_layout(document.body, i)
3905 for p in range(1, 5):
3906 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, l)
3909 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3910 endPlain = find_end_of_layout(document.body, beginPlain)
3911 endInset = find_end_of_inset(document.body, arg)
3912 content = document.body[beginPlain + 1 : endPlain]
3914 l = l - len(document.body[arg : endInset + 1])
3916 del document.body[arg : endInset + 1]
3917 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3919 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3920 endPlain = find_end_of_layout(document.body, beginPlain)
3921 endInset = find_end_of_inset(document.body, arg)
3922 content = document.body[beginPlain + 1 : endPlain]
3924 l = l - len(document.body[arg : endInset + 1])
3926 del document.body[arg : endInset + 1]
3927 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3929 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3930 endPlain = find_end_of_layout(document.body, beginPlain)
3931 endInset = find_end_of_inset(document.body, arg)
3932 content = document.body[beginPlain + 1 : endPlain]
3934 l = l - len(document.body[arg : endInset + 1])
3936 del document.body[arg : endInset + 1]
3937 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3939 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3940 endPlain = find_end_of_layout(document.body, beginPlain)
3941 endInset = find_end_of_inset(document.body, arg)
3942 content = document.body[beginPlain + 1 : endPlain]
3944 l = l - len(document.body[arg : endInset + 1])
3946 del document.body[arg : endInset + 1]
3949 document.body[i : i + 1] = subst
3952 # known encodings that do not change their names (same LyX and LaTeX names)
3953 known_enc_tuple = ("auto", "default", "ansinew", "applemac", "armscii8", "ascii",
3954 "cp437", "cp437de", "cp850", "cp852", "cp855", "cp858", "cp862", "cp865", "cp866",
3955 "cp1250", "cp1251", "cp1252", "cp1255", "cp1256", "cp1257", "koi8-r", "koi8-u",
3956 "pt154", "pt254", "tis620-0", "utf8", "utf8x", "utf8-plain")
3958 def convert_encodings(document):
3959 "Use the LyX names of the encodings instead of the LaTeX names."
3960 LaTeX2LyX_enc_dict = {
3961 "8859-6": "iso8859-6",
3962 "8859-8": "iso8859-8",
3964 "euc": "euc-jp-platex",
3969 "iso88595": "iso8859-5",
3970 "iso-8859-7": "iso8859-7",
3972 "jis": "jis-platex",
3974 "l7xenc": "iso8859-13",
3975 "latin1": "iso8859-1",
3976 "latin2": "iso8859-2",
3977 "latin3": "iso8859-3",
3978 "latin4": "iso8859-4",
3979 "latin5": "iso8859-9",
3980 "latin9": "iso8859-15",
3981 "latin10": "iso8859-16",
3982 "SJIS": "shift-jis",
3983 "sjis": "shift-jis-platex",
3986 i = find_token(document.header, "\\inputencoding" , 0)
3989 val = get_value(document.header, "\\inputencoding", i)
3990 if val in list(LaTeX2LyX_enc_dict.keys()):
3991 document.header[i] = "\\inputencoding %s" % LaTeX2LyX_enc_dict[val]
3992 elif val not in known_enc_tuple:
3993 document.warning("Ignoring unknown input encoding: `%s'" % val)
3996 def revert_encodings(document):
3997 """Revert to using the LaTeX names of the encodings instead of the LyX names.
3998 Also revert utf8-platex to sjis, the language default when using Japanese.
4000 LyX2LaTeX_enc_dict = {
4005 "euc-jp-platex": "euc",
4008 "iso8859-1": "latin1",
4009 "iso8859-2": "latin2",
4010 "iso8859-3": "latin3",
4011 "iso8859-4": "latin4",
4012 "iso8859-5": "iso88595",
4013 "iso8859-6": "8859-6",
4014 "iso8859-7": "iso-8859-7",
4015 "iso8859-8": "8859-8",
4016 "iso8859-9": "latin5",
4017 "iso8859-13": "l7xenc",
4018 "iso8859-15": "latin9",
4019 "iso8859-16": "latin10",
4021 "jis-platex": "jis",
4022 "shift-jis": "SJIS",
4023 "shift-jis-platex": "sjis",
4025 "utf8-platex": "sjis"
4027 i = find_token(document.header, "\\inputencoding" , 0)
4030 val = get_value(document.header, "\\inputencoding", i)
4031 if val in list(LyX2LaTeX_enc_dict.keys()):
4032 document.header[i] = "\\inputencoding %s" % LyX2LaTeX_enc_dict[val]
4033 elif val not in known_enc_tuple:
4034 document.warning("Ignoring unknown input encoding: `%s'" % val)
4037 def revert_IEEEtran_3(document):
4039 Reverts Flex Insets to TeX-code
4041 if document.textclass == "IEEEtran":
4047 h = find_token(document.body, "\\begin_inset Flex Author Mark", h)
4049 endh = find_end_of_inset(document.body, h)
4050 document.body[endh - 2 : endh + 1] = put_cmd_in_ert("}")
4051 document.body[h : h + 4] = put_cmd_in_ert("\\IEEEauthorrefmark{")
4054 i = find_token(document.body, "\\begin_inset Flex Author Name", i)
4056 endi = find_end_of_inset(document.body, i)
4057 document.body[endi - 2 : endi + 1] = put_cmd_in_ert("}")
4058 document.body[i : i + 4] = put_cmd_in_ert("\\IEEEauthorblockN{")
4061 j = find_token(document.body, "\\begin_inset Flex Author Affiliation", j)
4063 endj = find_end_of_inset(document.body, j)
4064 document.body[endj - 2 : endj + 1] = put_cmd_in_ert("}")
4065 document.body[j : j + 4] = put_cmd_in_ert("\\IEEEauthorblockA{")
4067 if i == -1 and j == -1 and h == -1:
4071 def revert_kurier_fonts(document):
4072 " Revert kurier font definition to LaTeX "
4074 i = find_token(document.header, "\\font_math", 0)
4076 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4077 val = get_value(document.header, "\\font_math", i)
4078 if val == "kurier-math":
4079 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
4080 "\\usepackage[math]{kurier}\n" \
4081 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
4082 document.header[i] = "\\font_math auto"
4084 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4085 kurier_fonts = ["kurier", "kurierc", "kurierl", "kurierlc"]
4086 k = find_token(document.header, "\\font_sans kurier", 0)
4088 sf = get_value(document.header, "\\font_sans", k)
4089 if sf in kurier_fonts:
4090 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4091 document.header[k] = "\\font_sans default"
4093 def revert_iwona_fonts(document):
4094 " Revert iwona font definition to LaTeX "
4096 i = find_token(document.header, "\\font_math", 0)
4098 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4099 val = get_value(document.header, "\\font_math", i)
4100 if val == "iwona-math":
4101 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
4102 "\\usepackage[math]{iwona}\n" \
4103 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
4104 document.header[i] = "\\font_math auto"
4106 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4107 iwona_fonts = ["iwona", "iwonac", "iwonal", "iwonalc"]
4108 k = find_token(document.header, "\\font_sans iwona", 0)
4110 sf = get_value(document.header, "\\font_sans", k)
4111 if sf in iwona_fonts:
4112 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4113 document.header[k] = "\\font_sans default"
4116 def revert_new_libertines(document):
4117 " Revert new libertine font definition to LaTeX "
4119 if find_token(document.header, "\\use_non_tex_fonts true", 0) != -1:
4122 i = find_token(document.header, "\\font_typewriter libertine-mono", 0)
4124 preamble = "\\usepackage"
4125 sc = find_token(document.header, "\\font_tt_scale", 0)
4127 scval = get_value(document.header, "\\font_tt_scale", sc)
4129 preamble += "[scale=%f]" % (float(scval) / 100)
4130 document.header[sc] = "\\font_tt_scale 100"
4131 preamble += "{libertineMono-type1}"
4132 add_to_preamble(document, [preamble])
4133 document.header[i] = "\\font_typewriter default"
4135 k = find_token(document.header, "\\font_sans biolinum", 0)
4137 preamble = "\\usepackage"
4139 j = find_token(document.header, "\\font_osf true", 0)
4144 sc = find_token(document.header, "\\font_sf_scale", 0)
4146 scval = get_value(document.header, "\\font_sf_scale", sc)
4148 options += ",scale=%f" % (float(scval) / 100)
4149 document.header[sc] = "\\font_sf_scale 100"
4151 preamble += "[" + options +"]"
4152 preamble += "{biolinum-type1}"
4153 add_to_preamble(document, [preamble])
4154 document.header[k] = "\\font_sans default"
4157 def convert_lyxframes(document):
4158 " Converts old beamer frames to new style "
4160 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4161 if document.textclass not in beamer_classes:
4164 framebeg = ["BeginFrame", "BeginPlainFrame"]
4165 frameend = ["Frame", "PlainFrame", "EndFrame", "BeginFrame", "BeginPlainFrame", "AgainFrame",
4166 "Section", "Section*", "Subsection", "Subsection*", "Subsubsection", "Subsubsection*"]
4167 for lay in framebeg:
4170 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
4173 parent = get_containing_layout(document.body, i)
4174 if parent == False or parent[1] != i:
4175 document.warning("Wrong parent layout!")
4178 frametype = parent[0]
4182 # Step I: Convert ERT arguments
4183 # FIXME: See restrictions in convert_beamerframeargs method
4184 ertend = convert_beamerframeargs(document, i, parbeg)
4187 # Step II: Now rename the layout and convert the title to an argument
4188 j = find_end_of_layout(document.body, i)
4189 document.body[j : j + 1] = ['\\end_layout', '', '\\end_inset', '', '\\end_layout']
4190 if lay == "BeginFrame":
4191 document.body[i] = "\\begin_layout Frame"
4193 document.body[i] = "\\begin_layout PlainFrame"
4194 document.body[ertend + 1 : ertend + 1] = ['\\begin_inset Argument 4',
4195 'status open', '', '\\begin_layout Plain Layout']
4196 # Step III: find real frame end
4199 inInset = get_containing_inset(document.body, i)
4201 fend = find_token(document.body, "\\begin_layout", jj)
4203 document.warning("Malformed LyX document: No real frame end!")
4205 val = get_value(document.body, "\\begin_layout", fend)
4206 if val not in frameend:
4209 # is this frame nested in an inset (e.g., Note)?
4210 if inInset != False:
4211 # if so, end the frame inside the inset
4212 if inInset[2] < fend:
4214 if val == frametype:
4215 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4216 # consider explicit EndFrames between two identical frame types
4217 elif val == "EndFrame":
4218 nextlayout = find_token(document.body, "\\begin_layout", fend + 1)
4219 if nextlayout != -1 and get_value(document.body, "\\begin_layout", nextlayout) == frametype:
4220 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4222 document.body[fend : fend] = ['\\end_deeper']
4224 document.body[fend : fend] = ['\\end_deeper']
4225 document.body[j + 1 : j + 1] = ['', '\\begin_deeper']
4230 def remove_endframes(document):
4231 " Remove deprecated beamer endframes "
4233 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4234 if document.textclass not in beamer_classes:
4239 i = find_token_exact(document.body, "\\begin_layout EndFrame", i)
4242 j = find_end_of_layout(document.body, i)
4244 document.warning("Malformed LyX document: Missing \\end_layout to EndFrame")
4247 del document.body[i : j + 1]
4250 def revert_powerdot_flexes(document):
4251 " Reverts powerdot flex insets "
4253 if document.textclass != "powerdot":
4256 flexes = {"Onslide" : "\\onslide",
4257 "Onslide*" : "\\onslide*",
4258 "Onslide+" : "\\onslide+"}
4259 rx = re.compile(r'^\\begin_inset Flex (.+)$')
4263 i = find_token(document.body, "\\begin_inset Flex", i)
4266 m = rx.match(document.body[i])
4268 flextype = m.group(1)
4269 z = find_end_of_inset(document.body, i)
4271 document.warning("Can't find end of Flex " + flextype + " inset.")
4274 if flextype in flexes:
4275 pre = put_cmd_in_ert(flexes[flextype])
4276 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
4278 argend = find_end_of_inset(document.body, arg)
4280 document.warning("Can't find end of Argument!")
4283 # Find containing paragraph layout
4284 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
4285 endPlain = find_end_of_layout(document.body, beginPlain)
4286 argcontent = document.body[beginPlain + 1 : endPlain]
4288 z = z - len(document.body[arg : argend + 1])
4290 del document.body[arg : argend + 1]
4291 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
4292 pre += put_cmd_in_ert("{")
4293 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4294 endPlain = find_end_of_layout(document.body, beginPlain)
4296 z = z - len(document.body[i : beginPlain + 1])
4298 document.body[i : beginPlain + 1] = pre
4299 post = put_cmd_in_ert("}")
4300 document.body[z - 2 : z + 1] = post
4304 def revert_powerdot_pause(document):
4305 " Reverts powerdot pause layout to ERT "
4307 if document.textclass != "powerdot":
4312 i = find_token(document.body, "\\begin_layout Pause", i)
4315 j = find_end_of_layout(document.body, i)
4317 document.warning("Malformed LyX document: Can't find end of Pause layout")
4321 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\pause")
4322 for p in range(i, j):
4325 arg = find_token(document.body, "\\begin_inset Argument 1", i, j)
4327 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4328 endPlain = find_end_of_layout(document.body, beginPlain)
4329 endInset = find_end_of_inset(document.body, p)
4330 content = document.body[beginPlain + 1 : endPlain]
4332 endlay = endlay - len(document.body[p : endInset + 1])
4334 del document.body[p : endInset + 1]
4335 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4337 document.body[i : i + 1] = subst
4341 def revert_powerdot_itemargs(document):
4342 " Reverts powerdot item arguments to ERT "
4344 if document.textclass != "powerdot":
4348 list_layouts = ["Itemize", "ItemizeType1", "Enumerate", "EnumerateType1"]
4349 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4352 i = find_token(document.body, "\\begin_inset Argument", i)
4355 # Find containing paragraph layout
4356 parent = get_containing_layout(document.body, i)
4358 document.warning("Malformed LyX document: Can't find parent paragraph layout")
4363 realparbeg = parent[3]
4364 layoutname = parent[0]
4366 for p in range(parbeg, parend):
4370 if layoutname in list_layouts:
4371 m = rx.match(document.body[p])
4374 if argnr == "item:1":
4375 j = find_end_of_inset(document.body, i)
4376 # Find containing paragraph layout
4377 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4378 endPlain = find_end_of_layout(document.body, beginPlain)
4379 content = document.body[beginPlain + 1 : endPlain]
4380 del document.body[i:j+1]
4381 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4382 document.body[realparbeg : realparbeg] = subst
4383 elif argnr == "item:2":
4384 j = find_end_of_inset(document.body, i)
4385 # Find containing paragraph layout
4386 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4387 endPlain = find_end_of_layout(document.body, beginPlain)
4388 content = document.body[beginPlain + 1 : endPlain]
4389 del document.body[i:j+1]
4390 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
4391 document.body[realparbeg : realparbeg] = subst
4396 def revert_powerdot_columns(document):
4397 " Reverts powerdot twocolumn to TeX-code "
4398 if document.textclass != "powerdot":
4401 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4404 i = find_token(document.body, "\\begin_layout Twocolumn", i)
4407 j = find_end_of_layout(document.body, i)
4409 document.warning("Malformed LyX document: Can't find end of Twocolumn layout")
4413 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
4414 endlay += len(put_cmd_in_ert("}"))
4415 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\twocolumn")
4416 for p in range(i, j):
4419 m = rx.match(document.body[p])
4423 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4424 endPlain = find_end_of_layout(document.body, beginPlain)
4425 endInset = find_end_of_inset(document.body, p)
4426 content = document.body[beginPlain + 1 : endPlain]
4428 endlay = endlay - len(document.body[p : endInset + 1])
4430 del document.body[p : endInset + 1]
4431 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4433 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4434 endPlain = find_end_of_layout(document.body, beginPlain)
4435 endInset = find_end_of_inset(document.body, p)
4436 content = document.body[beginPlain + 1 : endPlain]
4438 endlay = endlay - len(document.body[p : endInset + 1])
4440 del document.body[p : endInset + 1]
4441 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
4443 subst += put_cmd_in_ert("{")
4444 document.body[i : i + 1] = subst
4448 def revert_mbox_fbox(document):
4449 'Convert revert mbox/fbox boxes to TeX-code'
4452 i = find_token(document.body, "\\begin_inset Box", i)
4455 j = find_token(document.body, "width", i)
4457 document.warning("Malformed LyX document: Can't find box width")
4459 width = get_value(document.body, "width", j)
4460 k = find_end_of_inset(document.body, j)
4462 document.warning("Malformed LyX document: Can't find end of box inset")
4465 BeginLayout = find_token(document.body, "\\begin_layout Plain Layout", j)
4466 EndLayout = find_end_of_layout(document.body, BeginLayout)
4467 # replace if width is ""
4469 document.body[EndLayout:k + 1] = put_cmd_in_ert("}")
4470 if document.body[i] == "\\begin_inset Box Frameless":
4471 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\mbox{")
4472 if document.body[i] == "\\begin_inset Box Boxed":
4473 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\fbox{")
4477 def revert_starred_caption(document):
4478 " Reverts unnumbered longtable caption insets "
4482 i = find_token(document.body, "\\begin_inset Caption LongTableNoNumber", i)
4485 # This is not equivalent, but since the caption inset is a full blown
4486 # text inset a true conversion to ERT is too difficult.
4487 document.body[i] = "\\begin_inset Caption Standard"
4491 def revert_forced_local_layout(document):
4494 i = find_token(document.header, "\\begin_forced_local_layout", i)
4497 j = find_end_of(document.header, i, "\\begin_forced_local_layout", "\\end_forced_local_layout")
4499 # this should not happen
4501 regexp = re.compile(r'\s*forcelocal', re.IGNORECASE)
4502 k = find_re(document.header, regexp, i, j)
4504 del document.header[k]
4506 k = find_re(document.header, regexp, i, j)
4507 k = find_token(document.header, "\\begin_local_layout", 0)
4509 document.header[i] = "\\begin_local_layout"
4510 document.header[j] = "\\end_local_layout"
4512 l = find_end_of(document.header, k, "\\begin_local_layout", "\\end_local_layout")
4514 # this should not happen
4516 lines = document.header[i+1 : j]
4518 document.header[k+1 : k+1] = lines
4519 document.header[i : j ] = []
4521 document.header[i : j ] = []
4522 document.header[k+1 : k+1] = lines
4525 def revert_aa1(document):
4526 " Reverts InsetArguments of aa to TeX-code "
4527 if document.textclass == "aa":
4531 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4533 revert_Argument_to_TeX_brace(document, i, 0, 1, 4, False, False)
4539 def revert_aa2(document):
4540 " Reverts InsetArguments of aa to TeX-code "
4541 if document.textclass == "aa":
4545 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4547 document.body[i] = "\\begin_layout Abstract"
4553 def revert_tibetan(document):
4554 "Set the document language for Tibetan to English"
4556 if document.language == "tibetan":
4557 document.language = "english"
4558 i = find_token(document.header, "\\language", 0)
4560 document.header[i] = "\\language english"
4562 while j < len(document.body):
4563 j = find_token(document.body, "\\lang tibetan", j)
4565 document.body[j] = document.body[j].replace("\\lang tibetan", "\\lang english")
4568 j = len(document.body)
4577 # The idea here is that we will have a sequence of chunk paragraphs.
4578 # We want to convert them to paragraphs in one or several chunk insets.
4579 # Individual chunks are terminated by the character @ on the last line.
4580 # This line will be discarded, and following lines are treated as new
4581 # chunks, which go into their own insets.
4582 # The first line of a chunk should look like: <<CONTENT>>=
4583 # We will discard the delimiters, and put the CONTENT into the
4584 # optional argument of the inset, if the CONTENT is non-empty.
4585 def convert_chunks(document):
4586 first_re = re.compile(r'<<(.*)>>=(.*)')
4589 # find start of a block of chunks
4590 i = find_token(document.body, "\\begin_layout Chunk", file_pos)
4596 chunk_started = False
4599 # process the one we just found
4600 j = find_end_of_layout(document.body, i)
4602 document.warning("Malformed LyX documents. Can't find end of Chunk layout!")
4603 # there is no point continuing, as we will run into the same error again.
4605 this_chunk = "".join(document.body[i + 1:j])
4607 # there may be empty lines between chunks
4608 # we just skip them.
4609 if not chunk_started:
4610 if this_chunk != "":
4612 chunk_started = True
4615 contents.append(document.body[i + 1:j])
4617 # look for potential chunk terminator
4618 # on the last line of the chunk paragraph
4619 if document.body[j - 1] == "@":
4622 # look for subsequent chunk paragraph
4623 i = find_token(document.body, "\\begin_layout", j)
4627 if get_value(document.body, "\\begin_layout", i) != "Chunk":
4630 file_pos = end = j + 1
4632 # The last chunk should simply have an "@" in it
4633 # or at least end with "@" (can happen if @ is
4634 # preceded by a newline)
4636 if len(contents) > 0:
4637 lastpar = ''.join(contents[-1])
4638 if not lastpar.endswith("@"):
4639 document.warning("Unexpected chunk content: chunk not terminated by '@'!")
4640 if len(contents) == 0:
4641 # convert empty chunk layouts to Standard
4642 document.body[start] = "\\begin_layout Standard"
4646 # chunk par only contains "@". Just drop it.
4649 # chunk par contains more. Only drop the "@".
4652 # The first line should look like: <<CONTENT>>=
4653 # We want the CONTENT
4654 optarg = ' '.join(contents[0])
4656 # We can already have real chunk content in
4657 # the first par (separated from the options by a newline).
4658 # We collect such stuff to re-insert it later.
4661 match = first_re.search(optarg)
4663 optarg = match.groups()[0]
4664 if match.groups()[1] != "":
4666 for c in contents[0]:
4667 if c.endswith(">>="):
4671 postoptstuff.append(c)
4672 # We have stripped everything. This can be deleted.
4675 newstuff = ['\\begin_layout Standard']
4677 # Maintain paragraph parameters
4678 par_params = ["\\noindent", "\\indent", "\\indent-toggle", "\\leftindent",
4679 "\\start_of_appendix", "\\paragraph_spacing", "\\align",
4680 "\\labelwidthstring"]
4683 if document.body[parms].split(' ', 1)[0] not in par_params:
4685 newstuff.extend([document.body[parms]])
4689 ['\\begin_inset Flex Chunk',
4691 '\\begin_layout Plain Layout', ''])
4693 # If we have a non-empty optional argument, insert it.
4694 if match and optarg != "":
4696 ['\\begin_inset Argument 1',
4698 '\\begin_layout Plain Layout',
4703 # Since we already opened a Plain layout, the first paragraph
4704 # does not need to do that.
4707 # we need to replace newlines with new layouts
4709 started_text = False
4710 for lno in range(0,len(postoptstuff)):
4711 if postoptstuff[lno].startswith("\\begin_inset Newline newline"):
4713 elif start_newline != -1:
4714 if postoptstuff[lno].startswith("\\end_inset"):
4715 # replace that bit, but only if we already have some text
4716 # and we're not at the end except for a blank line
4717 if started_text and \
4718 (lno != len(postoptstuff) - 2 or postoptstuff[-1] != ""):
4719 newstuff.extend(['\\end_layout', '\n', '\\begin_layout Plain Layout', '\n'])
4723 newstuff.extend([postoptstuff[lno]])
4724 newstuff.append('\\end_layout')
4728 newstuff.extend(['', '\\begin_layout Plain Layout', ''])
4732 newstuff.append('\\end_layout')
4734 newstuff.extend(['', '\\end_inset', '', '\\end_layout', ''])
4736 document.body[start:end] = newstuff
4738 file_pos += len(newstuff) - (end - start)
4741 def revert_chunks(document):
4744 i = find_token(document.body, "\\begin_inset Flex Chunk", i)
4748 iend = find_end_of_inset(document.body, i)
4750 document.warning("Can't find end of Chunk!")
4754 # Look for optional argument
4756 ostart = find_token(document.body, "\\begin_inset Argument 1", i, iend)
4758 oend = find_end_of_inset(document.body, ostart)
4759 k = find_token(document.body, "\\begin_layout Plain Layout", ostart, oend)
4761 document.warning("Malformed LyX document: Can't find argument contents!")
4763 m = find_end_of_layout(document.body, k)
4764 optarg = "".join(document.body[k+1:m])
4766 # We now remove the optional argument, so we have something
4767 # uniform on which to work
4768 document.body[ostart : oend + 1] = []
4769 # iend is now invalid
4770 iend = find_end_of_inset(document.body, i)
4772 retval = get_containing_layout(document.body, i)
4774 document.warning("Can't find containing layout for Chunk!")
4777 (lname, lstart, lend, pstart) = retval
4778 # we now want to work through the various paragraphs, and collect their contents
4782 k = find_token(document.body, "\\begin_layout Plain Layout", k, lend)
4785 j = find_end_of_layout(document.body, k)
4787 document.warning("Can't find end of layout inside chunk!")
4789 parlist.append(document.body[k+1:j])
4791 # we now need to wrap all of these paragraphs in chunks
4793 newlines.extend(["\\begin_layout Chunk", "", "<<" + optarg + ">>=", "\\end_layout", ""])
4794 for stuff in parlist:
4795 newlines.extend(["\\begin_layout Chunk"] + stuff + ["\\end_layout", ""])
4796 newlines.extend(["\\begin_layout Chunk", "", "@", "\\end_layout", ""])
4797 # replace old content with new content
4798 document.body[lstart : lend + 1] = newlines
4799 i = lstart + len(newlines)
4806 supported_versions = ["2.1.0","2.1"]
4809 [415, [convert_undertilde]],
4811 [417, [convert_japanese_encodings]],
4812 [418, [convert_justification]],
4814 [420, [convert_biblio_style]],
4815 [421, [convert_longtable_captions]],
4816 [422, [convert_use_packages]],
4817 [423, [convert_use_mathtools]],
4818 [424, [convert_cite_engine_type]],
4819 # No convert_cancel, since cancel will be loaded automatically
4820 # in format 425 without any possibility to switch it off.
4821 # This has been fixed in format 464.
4825 [428, [convert_cell_rotation]],
4826 [429, [convert_table_rotation]],
4827 [430, [convert_listoflistings]],
4828 [431, [convert_use_amssymb]],
4830 [433, [convert_armenian]],
4837 [440, [convert_mathfonts]],
4838 [441, [convert_mdnomath]],
4843 [446, [convert_latexargs]],
4844 [447, [convert_IEEEtran, convert_AASTeX, convert_AGUTeX, convert_IJMP, convert_SIGPLAN, convert_SIGGRAPH, convert_EuropeCV, convert_Initials, convert_ModernCV]],
4845 [448, [convert_literate]],
4848 [451, [convert_beamerargs, convert_againframe_args, convert_corollary_args, convert_quote_args]],
4849 [452, [convert_beamerblocks]],
4850 [453, [convert_use_stmaryrd]],
4851 [454, [convert_overprint]],
4853 [456, [convert_epigraph]],
4854 [457, [convert_use_stackrel]],
4855 [458, [convert_captioninsets, convert_captionlayouts]],
4860 [463, [convert_encodings]],
4861 [464, [convert_use_cancel]],
4862 [465, [convert_lyxframes, remove_endframes]],
4868 [471, [convert_cite_engine_type_default]],
4871 [474, [convert_chunks, cleanup_beamerargs]],
4875 [473, [revert_chunks]],
4876 [472, [revert_tibetan]],
4877 [471, [revert_aa1,revert_aa2]],
4878 [470, [revert_cite_engine_type_default]],
4879 [469, [revert_forced_local_layout]],
4880 [468, [revert_starred_caption]],
4881 [467, [revert_mbox_fbox]],
4882 [466, [revert_iwona_fonts]],
4883 [465, [revert_powerdot_flexes, revert_powerdot_pause, revert_powerdot_itemargs, revert_powerdot_columns]],
4885 [463, [revert_use_cancel]],
4886 [462, [revert_encodings]],
4887 [461, [revert_new_libertines]],
4888 [460, [revert_kurier_fonts]],
4889 [459, [revert_IEEEtran_3]],
4890 [458, [revert_fragileframe, revert_newframes]],
4891 [457, [revert_captioninsets, revert_captionlayouts]],
4892 [456, [revert_use_stackrel]],
4893 [455, [revert_epigraph]],
4894 [454, [revert_frametitle]],
4895 [453, [revert_overprint]],
4896 [452, [revert_use_stmaryrd]],
4897 [451, [revert_beamerblocks]],
4898 [450, [revert_beamerargs, revert_beamerargs2, revert_beamerargs3, revert_beamerflex]],
4899 [449, [revert_garamondx, revert_garamondx_newtxmath]],
4900 [448, [revert_itemargs]],
4901 [447, [revert_literate]],
4902 [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]],
4903 [445, [revert_latexargs]],
4904 [444, [revert_uop]],
4905 [443, [revert_biolinum]],
4907 [441, [revert_newtxmath]],
4908 [440, [revert_mdnomath]],
4909 [439, [revert_mathfonts]],
4910 [438, [revert_minionpro]],
4911 [437, [revert_ipadeco, revert_ipachar]],
4912 [436, [revert_texgyre]],
4913 [435, [revert_mathdesign]],
4914 [434, [revert_txtt]],
4915 [433, [revert_libertine]],
4916 [432, [revert_armenian]],
4917 [431, [revert_languages, revert_ancientgreek]],
4918 [430, [revert_use_amssymb]],
4919 [429, [revert_listoflistings]],
4920 [428, [revert_table_rotation]],
4921 [427, [revert_cell_rotation]],
4922 [426, [revert_tipa]],
4923 [425, [revert_verbatim]],
4924 [424, [revert_cancel]],
4925 [423, [revert_cite_engine_type]],
4926 [422, [revert_use_mathtools]],
4927 [421, [revert_use_packages]],
4928 [420, [revert_longtable_captions]],
4929 [419, [revert_biblio_style]],
4930 [418, [revert_australian]],
4931 [417, [revert_justification]],
4932 [416, [revert_japanese_encodings]],
4933 [415, [revert_negative_space, revert_math_spaces]],
4934 [414, [revert_undertilde]],
4935 [413, [revert_visible_space]]
4939 if __name__ == "__main__":