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":
1706 i = find_token(document.body, "\\begin_layout Page headings", i)
1708 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1711 i2 = find_token(document.body, "\\begin_inset Flex Paragraph Start", i2)
1713 revert_Argument_to_TeX_brace(document, i2, 0, 1, 1, False, False)
1716 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1718 revert_Argument_to_TeX_brace(document, j, 0, 1, 1, True, False)
1721 k = find_token(document.body, "\\begin_layout Biography", k)
1722 kA = find_token(document.body, "\\begin_layout Biography without photo", k)
1723 if k == kA and k != -1:
1727 # start with the second argument, therefore 2
1728 revert_Argument_to_TeX_brace(document, k, 0, 2, 2, True, False)
1730 if i == -1 and i2 == -1 and j == -1 and k == -1:
1734 def revert_IEEEtran_2(document):
1736 Reverts Flex Paragraph Start to TeX-code
1738 if document.textclass == "IEEEtran":
1741 begin = find_token(document.body, "\\begin_inset Flex Paragraph Start", begin)
1744 end1 = find_end_of_inset(document.body, begin)
1745 document.body[end1 - 2 : end1 + 1] = put_cmd_in_ert("}")
1746 document.body[begin : begin + 4] = put_cmd_in_ert("\\IEEEPARstart{")
1750 def convert_IEEEtran(document):
1755 Biography without photo
1758 if document.textclass == "IEEEtran":
1764 i = find_token(document.body, "\\begin_layout Page headings", i)
1766 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1769 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1771 convert_TeX_brace_to_Argument(document, j, 1, 1, False, True, False)
1774 # assure that we don't handle Biography Biography without photo
1775 k = find_token(document.body, "\\begin_layout Biography", k)
1776 kA = find_token(document.body, "\\begin_layout Biography without photo", k - 1)
1777 if k == kA and k != -1:
1781 # the argument we want to convert is the second one
1782 convert_TeX_brace_to_Argument(document, k, 2, 2, False, True, False)
1784 if i == -1 and j == -1 and k == -1:
1788 def revert_AASTeX(document):
1789 " Reverts InsetArgument of Altaffilation to TeX-code "
1790 if document.textclass == "aastex":
1793 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1796 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1800 def convert_AASTeX(document):
1801 " Converts ERT of Altaffilation to InsetArgument "
1802 if document.textclass == "aastex":
1805 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1808 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1812 def revert_AGUTeX(document):
1813 " Reverts InsetArgument of Author affiliation to TeX-code "
1814 if document.textclass == "agutex":
1817 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1820 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1824 def convert_AGUTeX(document):
1825 " Converts ERT of Author affiliation to InsetArgument "
1826 if document.textclass == "agutex":
1829 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1832 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1836 def revert_IJMP(document):
1837 " Reverts InsetArgument of MarkBoth to TeX-code "
1838 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1841 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1844 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1848 def convert_IJMP(document):
1849 " Converts ERT of MarkBoth to InsetArgument "
1850 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1853 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1856 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1860 def revert_SIGPLAN(document):
1861 " Reverts InsetArguments of SIGPLAN to TeX-code "
1862 if document.textclass == "sigplanconf":
1867 i = find_token(document.body, "\\begin_layout Conference", i)
1869 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1872 j = find_token(document.body, "\\begin_layout Author", j)
1874 revert_Argument_to_TeX_brace(document, j, 0, 1, 2, False, False)
1876 if i == -1 and j == -1:
1880 def convert_SIGPLAN(document):
1881 " Converts ERT of SIGPLAN to InsetArgument "
1882 if document.textclass == "sigplanconf":
1887 i = find_token(document.body, "\\begin_layout Conference", i)
1889 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1892 j = find_token(document.body, "\\begin_layout Author", j)
1894 convert_TeX_brace_to_Argument(document, j, 1, 2, False, False, False)
1896 if i == -1 and j == -1:
1900 def revert_SIGGRAPH(document):
1901 " Reverts InsetArgument of Flex CRcat to TeX-code "
1902 if document.textclass == "acmsiggraph":
1905 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1908 revert_Argument_to_TeX_brace(document, i, 0, 1, 3, False, False)
1912 def convert_SIGGRAPH(document):
1913 " Converts ERT of Flex CRcat to InsetArgument "
1914 if document.textclass == "acmsiggraph":
1917 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1920 convert_TeX_brace_to_Argument(document, i, 1, 3, True, False, False)
1924 def revert_EuropeCV(document):
1925 " Reverts InsetArguments of europeCV to TeX-code "
1926 if document.textclass == "europecv":
1933 i = find_token(document.body, "\\begin_layout Item", i)
1935 revert_Argument_to_TeX_brace(document, i, 0, 2, 2, False, False)
1938 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1940 revert_Argument_to_TeX_brace(document, j, 0, 2, 2, False, False)
1943 k = find_token(document.body, "\\begin_layout Language", k)
1945 revert_Argument_to_TeX_brace(document, k, 0, 2, 6, False, False)
1948 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1950 revert_Argument_to_TeX_brace(document, m, 0, 2, 6, False, False)
1952 if i == -1 and j == -1 and k == -1 and m == -1:
1956 def convert_EuropeCV(document):
1957 " Converts ERT of europeCV to InsetArgument "
1958 if document.textclass == "europecv":
1965 i = find_token(document.body, "\\begin_layout Item", i)
1967 convert_TeX_brace_to_Argument(document, i, 2, 2, False, False, False)
1970 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1972 convert_TeX_brace_to_Argument(document, j, 2, 2, False, False, False)
1975 k = find_token(document.body, "\\begin_layout Language", k)
1977 convert_TeX_brace_to_Argument(document, k, 2, 6, False, False, False)
1980 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1982 convert_TeX_brace_to_Argument(document, m, 2, 6, False, False, False)
1984 if i == -1 and j == -1 and k == -1 and m == -1:
1988 def revert_ModernCV(document):
1989 " Reverts InsetArguments of modernCV to TeX-code "
1990 if document.textclass == "moderncv":
1998 j = find_token(document.body, "\\begin_layout Entry", j)
2000 revert_Argument_to_TeX_brace(document, j, 0, 1, 5, False, False)
2003 k = find_token(document.body, "\\begin_layout Item", k)
2005 revert_Argument_to_TeX_brace(document, k, 0, 1, 1, False, False)
2008 m = find_token(document.body, "\\begin_layout ItemWithComment", m)
2010 revert_Argument_to_TeX_brace(document, m, 0, 1, 2, False, False)
2011 document.body[m] = document.body[m].replace("\\begin_layout ItemWithComment", "\\begin_layout Language")
2014 o = find_token(document.body, "\\begin_layout DoubleItem", o)
2016 revert_Argument_to_TeX_brace(document, o, 0, 1, 3, False, False)
2017 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout Computer")
2020 p = find_token(document.body, "\\begin_layout Social", p)
2022 revert_Argument_to_TeX_brace(document, p, 0, 1, 1, False, True)
2024 if j == -1 and k == -1 and m == -1 and o == -1 and p == -1:
2028 def revert_ModernCV_2(document):
2029 " Reverts the Flex:Column inset of modernCV to TeX-code "
2030 if document.textclass == "moderncv":
2034 flex = find_token(document.body, "\\begin_inset Flex Column", flex)
2037 flexEnd = find_end_of_inset(document.body, flex)
2038 wasOpt = revert_Argument_to_TeX_brace(document, flex, flexEnd, 1, 1, False, True)
2039 revert_Argument_to_TeX_brace(document, flex, 0, 2, 2, False, False)
2040 flexEnd = find_end_of_inset(document.body, flex)
2042 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn")
2044 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn{")
2045 document.body[flexEnd + 4 : flexEnd + 7] = put_cmd_in_ert("}")
2049 def revert_ModernCV_3(document):
2050 " Reverts the Column style of modernCV to TeX-code "
2051 if document.textclass == "moderncv":
2052 # revert the layouts
2053 revert_ModernCV(document)
2055 # get the position of the end of the last column inset
2056 LastFlexEnd = revert_ModernCV_2(document)
2058 p = find_token(document.body, "\\begin_layout Columns", p)
2061 pEnd = find_end_of_layout(document.body, p)
2062 document.body[p] = document.body[p].replace("\\begin_layout Columns", "\\begin_layout Standard")
2063 if LastFlexEnd != -1:
2064 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\begin{cvcolumns}")
2065 document.body[LastFlexEnd + 24 : LastFlexEnd + 24] = put_cmd_in_ert("\\end{cvcolumns}")
2069 def revert_ModernCV_4(document):
2070 " Reverts the style Social to TeX-code "
2071 if document.textclass == "moderncv":
2072 # revert the layouts
2073 revert_ModernCV(document)
2076 p = find_token(document.body, "\\begin_layout Social", p)
2079 pEnd = find_end_of_layout(document.body, p)
2080 document.body[p] = document.body[p].replace("\\begin_layout Social", "\\begin_layout Standard")
2081 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\social")
2082 hasOpt = find_token(document.body, "[", p + 9)
2084 document.body[p + 30 : p + 30] = put_cmd_in_ert("{")
2085 document.body[p + 41 : p + 41] = put_cmd_in_ert("}")
2087 document.body[p + 11 : p + 11] = put_cmd_in_ert("{")
2088 document.body[p + 21 : p + 21] = put_cmd_in_ert("}")
2092 def convert_ModernCV(document):
2093 " Converts ERT of modernCV to InsetArgument "
2094 if document.textclass == "moderncv":
2102 i = find_token(document.body, "\\begin_layout DoubleItem", i)
2104 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
2105 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout DoubleListItem")
2108 j = find_token(document.body, "\\begin_layout Entry", j)
2110 convert_TeX_brace_to_Argument(document, j, 1, 5, False, False, False)
2113 k = find_token(document.body, "\\begin_layout Item", k)
2115 convert_TeX_brace_to_Argument(document, k, 1, 1, False, False, False)
2118 m = find_token(document.body, "\\begin_layout Language", m)
2120 convert_TeX_brace_to_Argument(document, m, 1, 2, False, False, False)
2122 if i == -1 and j == -1 and k == -1 and m == -1:
2126 def revert_Initials(document):
2127 " Reverts InsetArgument of Initial to TeX-code "
2130 i = find_token(document.body, "\\begin_layout Initial", i)
2133 # first arg (optional) and second arg (first mandatory) are supported in LyX 2.0.x
2134 revert_Argument_to_TeX_brace(document, i, 0, 3, 3, False, False)
2138 def convert_Initials(document):
2139 " Converts ERT of Initial to InsetArgument "
2142 i = find_token(document.body, "\\begin_layout Initial", i)
2145 convert_TeX_brace_to_Argument(document, i, 3, 3, False, False, False)
2149 def revert_literate(document):
2150 " Revert Literate document to old format "
2151 if del_token(document.header, "noweb", 0):
2152 document.textclass = "literate-" + document.textclass
2155 i = find_token(document.body, "\\begin_layout Chunk", i)
2158 document.body[i] = "\\begin_layout Scrap"
2162 def convert_literate(document):
2163 " Convert Literate document to new format"
2164 i = find_token(document.header, "\\textclass", 0)
2165 if (i != -1) and "literate-" in document.header[i]:
2166 document.textclass = document.header[i].replace("\\textclass literate-", "")
2167 j = find_token(document.header, "\\begin_modules", 0)
2169 document.header.insert(j + 1, "noweb")
2171 document.header.insert(i + 1, "\\end_modules")
2172 document.header.insert(i + 1, "noweb")
2173 document.header.insert(i + 1, "\\begin_modules")
2176 i = find_token(document.body, "\\begin_layout Scrap", i)
2179 document.body[i] = "\\begin_layout Chunk"
2183 def revert_itemargs(document):
2184 " Reverts \\item arguments to TeX-code "
2187 i = find_token(document.body, "\\begin_inset Argument item:", i)
2190 j = find_end_of_inset(document.body, i)
2191 # Find containing paragraph layout
2192 parent = get_containing_layout(document.body, i)
2194 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2198 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2199 endPlain = find_end_of_layout(document.body, beginPlain)
2200 content = document.body[beginPlain + 1 : endPlain]
2201 del document.body[i:j+1]
2202 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2203 document.body[parbeg : parbeg] = subst
2207 def revert_garamondx_newtxmath(document):
2208 " Revert native garamond newtxmath definition to LaTeX "
2210 i = find_token(document.header, "\\font_math", 0)
2213 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2214 val = get_value(document.header, "\\font_math", i)
2215 if val == "garamondx-ntxm":
2216 add_to_preamble(document, "\\usepackage[garamondx]{newtxmath}")
2217 document.header[i] = "\\font_math auto"
2220 def revert_garamondx(document):
2221 " Revert native garamond font definition to LaTeX "
2223 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2224 i = find_token(document.header, "\\font_roman garamondx", 0)
2227 j = find_token(document.header, "\\font_osf true", 0)
2230 preamble = "\\usepackage"
2232 preamble += "[osfI]"
2233 preamble += "{garamondx}"
2234 add_to_preamble(document, [preamble])
2235 document.header[i] = "\\font_roman default"
2238 def convert_beamerargs(document):
2239 " Converts beamer arguments to new layout "
2241 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2242 if document.textclass not in beamer_classes:
2245 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2246 list_layouts = ["Itemize", "Enumerate", "Description"]
2247 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
2251 i = find_token(document.body, "\\begin_inset Argument", i)
2254 # Find containing paragraph layout
2255 parent = get_containing_layout(document.body, i)
2257 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2262 layoutname = parent[0]
2263 for p in range(parbeg, parend):
2264 if layoutname in shifted_layouts:
2265 m = rx.match(document.body[p])
2267 argnr = int(m.group(1))
2269 document.body[p] = "\\begin_inset Argument %d" % argnr
2270 if layoutname == "AgainFrame":
2271 m = rx.match(document.body[p])
2273 document.body[p] = "\\begin_inset Argument 3"
2274 if document.body[p + 4] == "\\begin_inset ERT":
2275 if document.body[p + 9].startswith("<"):
2276 # This is an overlay specification
2278 document.body[p + 9] = document.body[p + 9][1:]
2279 if document.body[p + 9].endswith(">"):
2281 document.body[p + 9] = document.body[p + 9][:-1]
2283 document.body[p] = "\\begin_inset Argument 2"
2284 if layoutname in list_layouts:
2285 m = rx.match(document.body[p])
2287 if m.group(1) == "1":
2288 if document.body[p + 4] == "\\begin_inset ERT":
2289 if document.body[p + 9].startswith("<"):
2290 # This is an overlay specification
2292 document.body[p + 9] = document.body[p + 9][1:]
2293 if document.body[p + 9].endswith(">"):
2295 document.body[p + 9] = document.body[p + 9][:-1]
2296 elif document.body[p + 4].startswith("<"):
2297 # This is an overlay specification (without ERT)
2299 document.body[p + 4] = document.body[p + 4][1:]
2300 if document.body[p + 4].endswith(">"):
2302 document.body[p + 4] = document.body[p + 4][:-1]
2303 elif layoutname != "Itemize":
2305 document.body[p] = "\\begin_inset Argument 2"
2310 # Helper function for the frame conversion routines
2312 # FIXME: This method currently requires the arguments to be either
2313 # * In one (whole) ERT each: <ERT>[<arg1>]</ERT><ERT><arg2></ERT><ERT>[arg3]</ERT>
2314 # * Altogether in one whole ERT: <ERT>[<arg1>]<arg2>[arg3]</ERT>
2315 # If individual arguments mix ERT and non-ERT or are splitted
2316 # over several ERTs, the parsing fails.
2317 def convert_beamerframeargs(document, i, parbeg):
2320 if document.body[parbeg] != "\\begin_inset ERT":
2322 ertend = find_end_of_inset(document.body, parbeg)
2324 document.warning("Malformed LyX document: missing ERT \\end_inset")
2326 ertcont = parbeg + 5
2327 if document.body[ertcont].startswith("[<"):
2328 # This is a default overlay specification
2330 document.body[ertcont] = document.body[ertcont][2:]
2331 if document.body[ertcont].endswith(">]"):
2333 document.body[ertcont] = document.body[ertcont][:-2]
2334 elif document.body[ertcont].endswith("]"):
2336 tok = document.body[ertcont].find('>][')
2338 subst = [document.body[ertcont][:tok],
2339 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2340 'status collapsed', '', '\\begin_layout Plain Layout',
2341 document.body[ertcont][tok + 3:-1]]
2342 document.body[ertcont : ertcont + 1] = subst
2344 # Convert to ArgInset
2345 document.body[parbeg] = "\\begin_inset Argument 2"
2346 elif document.body[ertcont].startswith("<"):
2347 # This is an overlay specification
2349 document.body[ertcont] = document.body[ertcont][1:]
2350 if document.body[ertcont].endswith(">"):
2352 document.body[ertcont] = document.body[ertcont][:-1]
2353 # Convert to ArgInset
2354 document.body[parbeg] = "\\begin_inset Argument 1"
2355 elif document.body[ertcont].endswith(">]"):
2357 tok = document.body[ertcont].find('>[<')
2359 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2360 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2361 'status collapsed', '', '\\begin_layout Plain Layout',
2362 document.body[ertcont][tok + 3:-2]]
2363 # Convert to ArgInset
2364 document.body[parbeg] = "\\begin_inset Argument 1"
2366 elif document.body[ertcont].endswith("]"):
2368 tok = document.body[ertcont].find('>[<')
2371 tokk = document.body[ertcont].find('>][')
2373 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2374 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2375 'status collapsed', '', '\\begin_layout Plain Layout',
2376 document.body[ertcont][tok + 3:tokk],
2377 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2378 'status collapsed', '', '\\begin_layout Plain Layout',
2379 document.body[ertcont][tokk + 3:-1]]
2382 tokk = document.body[ertcont].find('>[')
2384 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tokk],
2385 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2386 'status collapsed', '', '\\begin_layout Plain Layout',
2387 document.body[ertcont][tokk + 2:-1]]
2389 # Convert to ArgInset
2390 document.body[parbeg] = "\\begin_inset Argument 1"
2391 elif document.body[ertcont].startswith("["):
2392 # This is an ERT option
2394 document.body[ertcont] = document.body[ertcont][1:]
2395 if document.body[ertcont].endswith("]"):
2397 document.body[ertcont] = document.body[ertcont][:-1]
2398 # Convert to ArgInset
2399 document.body[parbeg] = "\\begin_inset Argument 3"
2405 def convert_againframe_args(document):
2406 " Converts beamer AgainFrame to new layout "
2408 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2409 if document.textclass not in beamer_classes:
2414 i = find_token(document.body, "\\begin_layout AgainFrame", i)
2417 parent = get_containing_layout(document.body, i)
2419 document.warning("Wrong parent layout!")
2423 # Convert ERT arguments
2424 # FIXME: See restrictions in convert_beamerframeargs method
2425 ertend = convert_beamerframeargs(document, i, parbeg)
2431 def convert_corollary_args(document):
2432 " Converts beamer corrolary-style ERT arguments native InsetArgs "
2434 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2435 if document.textclass not in beamer_classes:
2438 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2439 for lay in corollary_layouts:
2442 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2445 parent = get_containing_layout(document.body, i)
2447 document.warning("Wrong parent layout!")
2451 if document.body[parbeg] == "\\begin_inset ERT":
2452 ertcontfirstline = parbeg + 5
2453 # Find the last ERT in this paragraph (which might also be the first)
2454 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
2455 if lastertbeg == -1:
2456 document.warning("Last ERT not found!")
2458 lastertend = find_end_of_inset(document.body, lastertbeg)
2459 if lastertend == -1:
2460 document.warning("End of last ERT not found!")
2462 ertcontlastline = lastertend - 3
2463 if document.body[ertcontfirstline].startswith("<"):
2464 # This is an overlay specification
2466 document.body[ertcontfirstline] = document.body[ertcontfirstline][1:]
2467 if document.body[ertcontlastline].endswith(">"):
2469 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
2470 if ertcontfirstline < ertcontlastline:
2471 # Multiline ERT. Might contain TeX code. Embrace in ERT.
2472 document.body[ertcontlastline : ertcontlastline + 1] = [
2473 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
2474 document.body[ertcontfirstline : ertcontfirstline + 1] = [
2475 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
2476 'status collapsed', '', '\\begin_layout Plain Layout',
2477 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
2478 document.body[ertcontfirstline]]
2480 # Convert to ArgInset
2481 document.body[parbeg] = "\\begin_inset Argument 1"
2482 elif document.body[ertcontlastline].endswith("]"):
2484 tok = document.body[ertcontfirstline].find('>[')
2486 if ertcontfirstline < ertcontlastline:
2487 # Multiline ERT. Might contain TeX code. Embrace in ERT.
2488 document.body[ertcontlastline : ertcontlastline + 1] = [
2489 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
2490 document.body[ertcontfirstline : ertcontfirstline + 1] = [document.body[ertcontfirstline][:tok],
2491 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2492 'status collapsed', '', '\\begin_layout Plain Layout',
2493 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
2494 document.body[ertcontfirstline][tok + 2:-1]]
2496 document.body[ertcontfirstline : ertcontfirstline + 1] = [document.body[ertcontfirstline][:tok],
2497 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2498 'status collapsed', '', '\\begin_layout Plain Layout',
2499 document.body[ertcontfirstline][tok + 2:-1]]
2500 # Convert to ArgInset
2501 document.body[parbeg] = "\\begin_inset Argument 1"
2504 elif document.body[ertcontlastline].startswith("["):
2505 if document.body[ertcontlastline].endswith("]"):
2506 # This is an ERT option
2508 document.body[ertcontlastline] = document.body[ertcontlastline][1:]
2510 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
2511 # Convert to ArgInset
2512 document.body[parbeg] = "\\begin_inset Argument 2"
2514 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, True)
2521 def convert_quote_args(document):
2522 " Converts beamer quote style ERT args to native InsetArgs "
2524 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2525 if document.textclass not in beamer_classes:
2528 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2529 for lay in quote_layouts:
2532 i = find_token(document.body, "\\begin_layout " + lay, i)
2535 parent = get_containing_layout(document.body, i)
2537 document.warning("Wrong parent layout!")
2541 if document.body[parbeg] == "\\begin_inset ERT":
2542 if document.body[i + 6].startswith("<"):
2543 # This is an overlay specification
2545 document.body[i + 6] = document.body[i + 6][1:]
2546 if document.body[i + 6].endswith(">"):
2548 document.body[i + 6] = document.body[i + 6][:-1]
2549 # Convert to ArgInset
2550 document.body[i + 1] = "\\begin_inset Argument 1"
2554 def cleanup_beamerargs(document):
2555 " Clean up empty ERTs (conversion artefacts) "
2557 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2558 if document.textclass not in beamer_classes:
2563 i = find_token(document.body, "\\begin_inset Argument", i)
2566 j = find_end_of_inset(document.body, i)
2568 document.warning("Malformed LyX document: Can't find end of Argument inset")
2572 ertbeg = find_token(document.body, "\\begin_inset ERT", i, j)
2575 ertend = find_end_of_inset(document.body, ertbeg)
2577 document.warning("Malformed LyX document: Can't find end of ERT inset")
2579 stripped = [line for line in document.body[ertbeg : ertend + 1] if line.strip()]
2580 if len(stripped) == 5:
2581 # This is an empty ERT
2582 offset = len(document.body[ertbeg : ertend + 1])
2583 del document.body[ertbeg : ertend + 1]
2590 def revert_beamerargs(document):
2591 " Reverts beamer arguments to old layout "
2593 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2594 if document.textclass not in beamer_classes:
2598 list_layouts = ["Itemize", "Enumerate", "Description"]
2599 headings = ["Part", "Section", "Section*", "Subsection", "Subsection*",
2600 "Subsubsection", "Subsubsection*", "FrameSubtitle", "NoteItem"]
2601 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2602 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2603 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2606 i = find_token(document.body, "\\begin_inset Argument", i)
2609 # Find containing paragraph layout
2610 parent = get_containing_layout(document.body, i)
2612 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2617 realparbeg = parent[3]
2618 layoutname = parent[0]
2620 for p in range(parbeg, parend):
2624 if layoutname in headings:
2625 m = rx.match(document.body[p])
2629 # Find containing paragraph layout
2630 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2631 endPlain = find_end_of_layout(document.body, beginPlain)
2632 endInset = find_end_of_inset(document.body, p)
2633 argcontent = document.body[beginPlain + 1 : endPlain]
2635 realparend = realparend - len(document.body[p : endInset + 1])
2637 del document.body[p : endInset + 1]
2638 if layoutname == "FrameSubtitle":
2639 pre = put_cmd_in_ert("\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2640 elif layoutname == "NoteItem":
2641 pre = put_cmd_in_ert("\\note<") + argcontent + put_cmd_in_ert(">[item]")
2642 elif layoutname.endswith('*'):
2643 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower()[:-1] + "<") + argcontent + put_cmd_in_ert(">*")
2645 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2646 secarg = find_token(document.body, "\\begin_inset Argument 2", parbeg, parend)
2648 # Find containing paragraph layout
2649 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", secarg)
2650 endPlain = find_end_of_layout(document.body, beginPlain)
2651 endInset = find_end_of_inset(document.body, secarg)
2652 argcontent = document.body[beginPlain + 1 : endPlain]
2654 realparend = realparend - len(document.body[secarg : endInset + 1])
2655 del document.body[secarg : endInset + 1]
2656 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2657 pre += put_cmd_in_ert("{")
2658 document.body[parbeg] = "\\begin_layout Standard"
2659 document.body[realparbeg : realparbeg] = pre
2660 pe = find_end_of_layout(document.body, parbeg)
2661 post = put_cmd_in_ert("}")
2662 document.body[pe : pe] = post
2663 realparend += len(pre) + len(post)
2664 if layoutname == "AgainFrame":
2665 m = rx.match(document.body[p])
2669 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2670 endPlain = find_end_of_layout(document.body, beginPlain)
2671 endInset = find_end_of_inset(document.body, p)
2672 content = document.body[beginPlain + 1 : endPlain]
2674 realparend = realparend - len(document.body[p : endInset + 1])
2676 del document.body[p : endInset + 1]
2677 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2678 document.body[realparbeg : realparbeg] = subst
2679 if layoutname == "Overprint":
2680 m = rx.match(document.body[p])
2684 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2685 endPlain = find_end_of_layout(document.body, beginPlain)
2686 endInset = find_end_of_inset(document.body, p)
2687 content = document.body[beginPlain + 1 : endPlain]
2689 realparend = realparend - len(document.body[p : endInset + 1])
2691 del document.body[p : endInset + 1]
2692 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2693 document.body[realparbeg : realparbeg] = subst
2694 if layoutname == "OverlayArea":
2695 m = rx.match(document.body[p])
2699 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2700 endPlain = find_end_of_layout(document.body, beginPlain)
2701 endInset = find_end_of_inset(document.body, p)
2702 content = document.body[beginPlain + 1 : endPlain]
2704 realparend = realparend - len(document.body[p : endInset + 1])
2706 del document.body[p : endInset + 1]
2707 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2708 document.body[realparbeg : realparbeg] = subst
2709 if layoutname in list_layouts:
2710 m = rx.match(document.body[p])
2714 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2715 endPlain = find_end_of_layout(document.body, beginPlain)
2716 endInset = find_end_of_inset(document.body, p)
2717 content = document.body[beginPlain + 1 : endPlain]
2718 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2719 realparend = realparend + len(subst) - len(content)
2720 document.body[beginPlain + 1 : endPlain] = subst
2721 elif argnr == "item:1":
2722 j = find_end_of_inset(document.body, i)
2723 # Find containing paragraph layout
2724 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2725 endPlain = find_end_of_layout(document.body, beginPlain)
2726 content = document.body[beginPlain + 1 : endPlain]
2727 del document.body[i:j+1]
2728 if layoutname == "Description":
2729 # Description only has one (overlay) item arg
2730 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2731 # This must be put after the first space (begin of decription body
2732 # in LyX's arkward description list syntax)
2733 # Try to find that place ...
2734 rxx = re.compile(r'^([^\\ ]+ )(.*)$')
2735 for q in range(parbeg, parend):
2736 m = rxx.match(document.body[q])
2738 # We found it. Now insert the ERT argument just there:
2739 document.body[q : q] = [m.group(1), ''] + subst + ['', m.group(2)]
2742 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2743 document.body[realparbeg : realparbeg] = subst
2744 elif argnr == "item:2":
2745 j = find_end_of_inset(document.body, i)
2746 # Find containing paragraph layout
2747 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2748 endPlain = find_end_of_layout(document.body, beginPlain)
2749 content = document.body[beginPlain + 1 : endPlain]
2750 del document.body[i:j+1]
2751 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2752 document.body[realparbeg : realparbeg] = subst
2753 if layoutname in quote_layouts:
2754 m = rx.match(document.body[p])
2758 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2759 endPlain = find_end_of_layout(document.body, beginPlain)
2760 endInset = find_end_of_inset(document.body, p)
2761 content = document.body[beginPlain + 1 : endPlain]
2763 realparend = realparend - len(document.body[p : endInset + 1])
2765 del document.body[p : endInset + 1]
2766 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2767 document.body[realparbeg : realparbeg] = subst
2768 if layoutname in corollary_layouts:
2769 m = rx.match(document.body[p])
2773 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2774 endPlain = find_end_of_layout(document.body, beginPlain)
2775 endInset = find_end_of_inset(document.body, p)
2776 content = document.body[beginPlain + 1 : endPlain]
2778 realparend = realparend - len(document.body[p : endInset + 1])
2780 del document.body[p : endInset + 1]
2781 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2782 document.body[realparbeg : realparbeg] = subst
2787 def revert_beamerargs2(document):
2788 " Reverts beamer arguments to old layout, step 2 "
2790 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2791 if document.textclass not in beamer_classes:
2795 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2796 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2797 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2800 i = find_token(document.body, "\\begin_inset Argument", i)
2803 # Find containing paragraph layout
2804 parent = get_containing_layout(document.body, i)
2806 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2811 realparbeg = parent[3]
2812 layoutname = parent[0]
2814 for p in range(parbeg, parend):
2818 if layoutname in shifted_layouts:
2819 m = rx.match(document.body[p])
2823 document.body[p] = "\\begin_inset Argument 1"
2824 if layoutname in corollary_layouts:
2825 m = rx.match(document.body[p])
2829 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2830 endPlain = find_end_of_layout(document.body, beginPlain)
2831 endInset = find_end_of_inset(document.body, p)
2832 content = document.body[beginPlain + 1 : endPlain]
2834 realparend = realparend - len(document.body[p : endInset + 1])
2836 del document.body[p : endInset + 1]
2837 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2838 document.body[realparbeg : realparbeg] = subst
2839 if layoutname == "OverlayArea":
2840 m = rx.match(document.body[p])
2844 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2845 endPlain = find_end_of_layout(document.body, beginPlain)
2846 endInset = find_end_of_inset(document.body, p)
2847 content = document.body[beginPlain + 1 : endPlain]
2849 realparend = realparend - len(document.body[p : endInset + 1])
2851 del document.body[p : endInset + 1]
2852 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2853 document.body[realparbeg : realparbeg] = subst
2854 if layoutname == "AgainFrame":
2855 m = rx.match(document.body[p])
2859 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2860 endPlain = find_end_of_layout(document.body, beginPlain)
2861 endInset = find_end_of_inset(document.body, p)
2862 content = document.body[beginPlain + 1 : endPlain]
2864 realparend = realparend - len(document.body[p : endInset + 1])
2866 del document.body[p : endInset + 1]
2867 subst = put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
2868 document.body[realparbeg : realparbeg] = subst
2872 def revert_beamerargs3(document):
2873 " Reverts beamer arguments to old layout, step 3 "
2875 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2876 if document.textclass not in beamer_classes:
2879 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2882 i = find_token(document.body, "\\begin_inset Argument", i)
2885 # Find containing paragraph layout
2886 parent = get_containing_layout(document.body, i)
2888 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2893 realparbeg = parent[3]
2894 layoutname = parent[0]
2896 for p in range(parbeg, parend):
2900 if layoutname == "AgainFrame":
2901 m = rx.match(document.body[p])
2905 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2906 endPlain = find_end_of_layout(document.body, beginPlain)
2907 endInset = find_end_of_inset(document.body, p)
2908 content = document.body[beginPlain + 1 : endPlain]
2910 realparend = realparend - len(document.body[p : endInset + 1])
2912 del document.body[p : endInset + 1]
2913 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2914 document.body[realparbeg : realparbeg] = subst
2918 def revert_beamerflex(document):
2919 " Reverts beamer Flex insets "
2921 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2922 if document.textclass not in beamer_classes:
2925 new_flexes = {"Bold" : "\\textbf", "Emphasize" : "\\emph", "Only" : "\\only",
2926 "Uncover" : "\\uncover", "Visible" : "\\visible",
2927 "Invisible" : "\\invisible", "Alternative" : "\\alt",
2928 "Beamer_Note" : "\\note"}
2929 old_flexes = {"Alert" : "\\alert", "Structure" : "\\structure"}
2930 rx = re.compile(r'^\\begin_inset Flex (.+)$')
2934 i = find_token(document.body, "\\begin_inset Flex", i)
2937 m = rx.match(document.body[i])
2939 flextype = m.group(1)
2940 z = find_end_of_inset(document.body, i)
2942 document.warning("Can't find end of Flex " + flextype + " inset.")
2945 if flextype in new_flexes:
2946 pre = put_cmd_in_ert(new_flexes[flextype])
2947 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2949 argend = find_end_of_inset(document.body, arg)
2951 document.warning("Can't find end of Argument!")
2954 # Find containing paragraph layout
2955 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2956 endPlain = find_end_of_layout(document.body, beginPlain)
2957 argcontent = document.body[beginPlain + 1 : endPlain]
2959 z = z - len(document.body[arg : argend + 1])
2961 del document.body[arg : argend + 1]
2962 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2963 arg = find_token(document.body, "\\begin_inset Argument 2", i, z)
2965 argend = find_end_of_inset(document.body, arg)
2967 document.warning("Can't find end of Argument!")
2970 # Find containing paragraph layout
2971 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2972 endPlain = find_end_of_layout(document.body, beginPlain)
2973 argcontent = document.body[beginPlain + 1 : endPlain]
2975 z = z - len(document.body[arg : argend + 1])
2977 del document.body[arg : argend + 1]
2978 if flextype == "Alternative":
2979 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
2981 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2982 pre += put_cmd_in_ert("{")
2983 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2984 endPlain = find_end_of_layout(document.body, beginPlain)
2986 z = z - len(document.body[i : beginPlain + 1])
2988 document.body[i : beginPlain + 1] = pre
2989 post = put_cmd_in_ert("}")
2990 document.body[z - 2 : z + 1] = post
2991 elif flextype in old_flexes:
2992 pre = put_cmd_in_ert(old_flexes[flextype])
2993 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2997 argend = find_end_of_inset(document.body, arg)
2999 document.warning("Can't find end of Argument!")
3002 # Find containing paragraph layout
3003 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3004 endPlain = find_end_of_layout(document.body, beginPlain)
3005 argcontent = document.body[beginPlain + 1 : endPlain]
3007 z = z - len(document.body[arg : argend + 1])
3009 del document.body[arg : argend + 1]
3010 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
3011 pre += put_cmd_in_ert("{")
3012 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
3013 endPlain = find_end_of_layout(document.body, beginPlain)
3015 z = z - len(document.body[i : beginPlain + 1])
3017 document.body[i : beginPlain + 1] = pre
3018 post = put_cmd_in_ert("}")
3019 document.body[z - 2 : z + 1] = post
3024 def revert_beamerblocks(document):
3025 " Reverts beamer block arguments to ERT "
3027 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3028 if document.textclass not in beamer_classes:
3031 blocks = ["Block", "ExampleBlock", "AlertBlock"]
3033 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3036 i = find_token(document.body, "\\begin_inset Argument", i)
3039 # Find containing paragraph layout
3040 parent = get_containing_layout(document.body, i)
3042 document.warning("Malformed LyX document: Can't find parent paragraph layout")
3047 realparbeg = parent[3]
3048 layoutname = parent[0]
3050 for p in range(parbeg, parend):
3054 if layoutname in blocks:
3055 m = rx.match(document.body[p])
3059 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3060 endPlain = find_end_of_layout(document.body, beginPlain)
3061 endInset = find_end_of_inset(document.body, p)
3062 content = document.body[beginPlain + 1 : endPlain]
3064 realparend = realparend - len(document.body[p : endInset + 1])
3066 del document.body[p : endInset + 1]
3067 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3068 document.body[realparbeg : realparbeg] = subst
3070 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3071 endPlain = find_end_of_layout(document.body, beginPlain)
3072 endInset = find_end_of_inset(document.body, p)
3073 content = document.body[beginPlain + 1 : endPlain]
3075 realparend = realparend - len(document.body[p : endInset + 1])
3077 del document.body[p : endInset + 1]
3078 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3079 document.body[realparbeg : realparbeg] = subst
3084 def convert_beamerblocks(document):
3085 " Converts beamer block ERT args to native InsetArgs "
3087 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3088 if document.textclass not in beamer_classes:
3091 blocks = ["Block", "ExampleBlock", "AlertBlock"]
3095 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
3098 parent = get_containing_layout(document.body, i)
3099 if parent == False or parent[1] != i:
3100 document.warning("Wrong parent layout!")
3107 # If the paragraph starts with a language switch, adjust parbeg
3108 if len(document.body[parbeg]) == 0 and parbeg < parend \
3109 and document.body[parbeg + 1].startswith("\\lang"):
3111 if document.body[parbeg] == "\\begin_inset ERT":
3112 ertcontfirstline = parbeg + 5
3116 # Find the last ERT in this paragraph used for arguments
3117 # (which might also be the first)
3118 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
3119 if lastertbeg == -1:
3120 document.warning("Last ERT not found!")
3122 lastertend = find_end_of_inset(document.body, lastertbeg)
3123 if lastertend == -1:
3124 document.warning("End of last ERT not found!")
3126 # Is this ERT really used for an argument?
3127 # Note: This will fail when non-argument ERTs actually use brackets
3129 regexp = re.compile(r'.*[>\]\}]', re.IGNORECASE)
3130 cbracket = find_re(document.body, regexp, lastertbeg, lastertend)
3133 if lastertbeg == parbeg:
3136 if lastertbeg == -1 or lastertend == -1:
3138 ertcontlastline = lastertend - 3
3140 if document.body[ertcontfirstline].lstrip().startswith("<"):
3141 # This is an overlay specification
3143 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3144 if document.body[ertcontlastline].rstrip().endswith(">"):
3146 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3147 # Convert to ArgInset
3148 document.body[parbeg] = "\\begin_inset Argument 1"
3149 elif document.body[ertcontlastline].rstrip().endswith("}"):
3151 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3153 ertcontdivline = ertcontfirstline
3154 tok = document.body[ertcontdivline].find('>{')
3156 regexp = re.compile(r'.*>\{', re.IGNORECASE)
3157 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3158 tok = document.body[ertcontdivline].find('>{')
3160 if ertcontfirstline < ertcontlastline:
3161 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3162 document.body[ertcontlastline : ertcontlastline + 1] = [
3163 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3164 if ertcontdivline == ertcontfirstline:
3165 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3166 '\\end_layout', '', '\\end_inset', '',
3167 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3168 'status collapsed', '', '\\begin_layout Plain Layout',
3169 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3170 document.body[ertcontdivline][tok + 2:]]
3172 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3173 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3174 'status collapsed', '', '\\begin_layout Plain Layout',
3175 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3176 document.body[ertcontdivline][tok + 2:]]
3178 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3179 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3180 'status collapsed', '', '\\begin_layout Plain Layout',
3181 document.body[ertcontdivline][tok + 2:]]
3183 # check if have delimiters in two different ERTs
3184 tok = document.body[ertcontdivline].find('>')
3186 regexp = re.compile(r'.*>', re.IGNORECASE)
3187 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3188 tok = document.body[ertcontdivline].find('>')
3190 tokk = document.body[ertcontdivline].find('{')
3192 regexp = re.compile(r'.*\{', re.IGNORECASE)
3193 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, lastertend)
3194 tokk = document.body[ertcontdivlinetwo].find('{')
3196 if ertcontfirstline < ertcontlastline:
3197 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3198 document.body[ertcontlastline : ertcontlastline + 1] = [
3199 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3200 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3201 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3202 '\\end_inset', '', '', '\\begin_inset Argument 2',
3203 'status collapsed', '', '\\begin_layout Plain Layout',
3204 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3205 document.body[ertcontdivlinetwo][tokk + 1:]]
3207 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3208 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3209 'status collapsed', '', '\\begin_layout Plain Layout',
3210 document.body[ertcontdivlinetwo][tokk + 1:]]
3211 # Convert to ArgInset
3212 if ertcontfirstline < ertcontlastline:
3213 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3214 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 1',
3215 'status collapsed', '', '\\begin_layout Plain Layout',
3216 '\\begin_inset ERT', '']
3218 document.body[parbeg] = "\\begin_inset Argument 1"
3219 elif document.body[ertcontfirstline].lstrip().startswith("{"):
3220 # This is the block title
3221 if document.body[ertcontlastline].rstrip().endswith("}"):
3222 # strip off the braces
3223 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3224 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3225 if ertcontfirstline < ertcontlastline:
3226 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3227 document.body[parend : parend + 1] = [
3228 document.body[parend], '\\end_inset', '', '\\end_layout']
3229 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3230 'status collapsed', '', '\\begin_layout Plain Layout',
3231 '\\begin_inset ERT', '']
3233 # Convert to ArgInset
3234 document.body[parbeg] = "\\begin_inset Argument 2"
3235 # the overlay argument can also follow the title, so ...
3236 elif document.body[ertcontlastline].rstrip().endswith(">"):
3238 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3240 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3242 ertcontdivline = ertcontfirstline
3243 tok = document.body[ertcontdivline].find('}<')
3245 regexp = re.compile(r'.*\}<', re.IGNORECASE)
3246 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3247 tok = document.body[ertcontdivline].find('}<')
3249 if ertcontfirstline < ertcontlastline:
3250 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3251 document.body[ertcontlastline : ertcontlastline + 1] = [
3252 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3253 if ertcontdivline == ertcontfirstline:
3254 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3255 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3256 'status collapsed', '', '\\begin_layout Plain Layout',
3257 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3258 document.body[ertcontdivline][tok + 2:]]
3260 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3261 '\\end_layout', '', '\\end_inset', '',
3262 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3263 'status collapsed', '', '\\begin_layout Plain Layout',
3264 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3265 document.body[ertcontdivline][tok + 2:]]
3267 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3268 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3269 'status collapsed', '', '\\begin_layout Plain Layout',
3270 document.body[ertcontdivline][tok + 2:]]
3272 # check if have delimiters in two different ERTs
3273 tok = document.body[ertcontdivline].find('}')
3275 regexp = re.compile(r'.*\}', re.IGNORECASE)
3276 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3277 tok = document.body[ertcontdivline].find('}')
3279 tokk = document.body[ertcontdivline].find('<')
3281 regexp = re.compile(r'.*<', re.IGNORECASE)
3282 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, lastertend)
3283 tokk = document.body[ertcontdivlinetwo].find('<')
3285 if ertcontfirstline < ertcontlastline:
3286 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3287 document.body[ertcontlastline : ertcontlastline + 1] = [
3288 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3289 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3290 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3291 '\\end_inset', '', '', '\\begin_inset Argument 1',
3292 'status collapsed', '', '\\begin_layout Plain Layout',
3293 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3294 document.body[ertcontdivlinetwo][tokk + 1:]]
3296 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3297 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3298 'status collapsed', '', '\\begin_layout Plain Layout',
3299 document.body[ertcontdivlinetwo][tokk + 1:]]
3300 # Convert to ArgInset
3301 if ertcontfirstline < ertcontlastline:
3302 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3303 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3304 'status collapsed', '', '\\begin_layout Plain Layout',
3305 '\\begin_inset ERT', '']
3307 document.body[parbeg] = "\\begin_inset Argument 2"
3308 elif count_pars_in_inset(document.body, ertcontfirstline) > 1:
3309 # Multipar ERT. Skip this.
3312 # ERT has contents after the closing bracket. We cannot convert this.
3313 # convert_TeX_brace_to_Argument cannot either.
3314 #convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, False)
3318 j = find_end_of_layout(document.body, i)
3320 document.warning("end of layout not found!")
3321 k = find_token(document.body, "\\begin_inset Argument", i, j)
3323 document.warning("InsetArgument not found!")
3325 l = find_end_of_inset(document.body, k)
3326 m = find_token(document.body, "\\begin_inset ERT", l, j)
3329 ertcontfirstline = m + 5
3334 def convert_overprint(document):
3335 " Convert old beamer overprint layouts to ERT "
3337 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3338 if document.textclass not in beamer_classes:
3343 i = find_token(document.body, "\\begin_layout Overprint", i)
3346 # Find end of sequence
3347 j = find_end_of_sequence(document.body, i)
3349 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3353 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3355 if document.body[j] == "\\end_deeper":
3356 esubst = ["", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3358 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3359 endseq = endseq + len(esubst) - len(document.body[j : j])
3360 document.body[j : j] = esubst
3361 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3363 argend = find_end_of_layout(document.body, argbeg)
3365 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3368 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3369 endPlain = find_end_of_layout(document.body, beginPlain)
3370 content = document.body[beginPlain + 1 : endPlain]
3372 endseq = endseq - len(document.body[argbeg : argend + 1])
3374 del document.body[argbeg : argend + 1]
3375 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3377 endseq = endseq - len(document.body[i : i])
3378 document.body[i : i] = subst + ["\\end_layout"]
3379 endseq += len(subst)
3381 for p in range(i, endseq):
3382 if document.body[p] == "\\begin_layout Overprint":
3383 document.body[p] = "\\begin_layout Standard"
3388 def revert_overprint(document):
3389 " Revert old beamer overprint layouts to ERT "
3391 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3392 if document.textclass not in beamer_classes:
3397 i = find_token(document.body, "\\begin_layout Overprint", i)
3400 # Find end of sequence
3401 j = find_end_of_sequence(document.body, i)
3403 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3407 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3408 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}")
3409 endseq = endseq + len(esubst) - len(document.body[j : j])
3410 if document.body[j] == "\\end_deeper":
3411 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3413 document.body[j : j] = ["\\end_layout", ""] + esubst
3416 if document.body[r] == "\\begin_deeper":
3417 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3419 document.body[r] = ""
3420 document.body[s] = ""
3424 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3426 # Is this really our argument?
3427 nested = find_token(document.body, "\\begin_deeper", i, argbeg)
3429 argend = find_end_of_inset(document.body, argbeg)
3431 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3434 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3435 endPlain = find_end_of_layout(document.body, beginPlain)
3436 content = document.body[beginPlain + 1 : endPlain]
3438 endseq = endseq - len(document.body[argbeg : argend])
3440 del document.body[argbeg : argend + 1]
3441 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3443 endseq = endseq - len(document.body[i : i])
3444 document.body[i : i] = subst + ["\\end_layout"]
3445 endseq += len(subst)
3451 if document.body[p] == "\\begin_layout Overprint":
3452 q = find_end_of_layout(document.body, p)
3454 document.warning("Malformed LyX document. Cannot find end of Overprint layout!")
3457 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\onslide")
3458 argbeg = find_token(document.body, "\\begin_inset Argument item:1", p, q)
3460 argend = find_end_of_inset(document.body, argbeg)
3462 document.warning("Malformed LyX document. Cannot find end of Overprint item argument!")
3465 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3466 endPlain = find_end_of_layout(document.body, beginPlain)
3467 content = document.body[beginPlain + 1 : endPlain]
3469 endseq = endseq - len(document.body[argbeg : argend + 1])
3471 del document.body[argbeg : argend + 1]
3472 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3473 endseq = endseq - len(document.body[p : p + 1]) + len(subst)
3474 document.body[p : p + 1] = subst
3480 def revert_frametitle(document):
3481 " Reverts beamer frametitle layout to ERT "
3483 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3484 if document.textclass not in beamer_classes:
3487 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3490 i = find_token(document.body, "\\begin_layout FrameTitle", i)
3493 j = find_end_of_layout(document.body, i)
3495 document.warning("Malformed LyX document: Can't find end of FrameTitle layout")
3499 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
3500 endlay += len(put_cmd_in_ert("}"))
3501 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\frametitle")
3502 for p in range(i, j):
3505 m = rx.match(document.body[p])
3509 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3510 endPlain = find_end_of_layout(document.body, beginPlain)
3511 endInset = find_end_of_inset(document.body, p)
3512 content = document.body[beginPlain + 1 : endPlain]
3514 endlay = endlay - len(document.body[p : endInset + 1])
3516 del document.body[p : endInset + 1]
3517 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3519 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3520 endPlain = find_end_of_layout(document.body, beginPlain)
3521 endInset = find_end_of_inset(document.body, p)
3522 content = document.body[beginPlain + 1 : endPlain]
3524 endlay = endlay - len(document.body[p : endInset + 1])
3526 del document.body[p : endInset + 1]
3527 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3529 subst += put_cmd_in_ert("{")
3530 document.body[i : i + 1] = subst
3534 def convert_epigraph(document):
3535 " Converts memoir epigraph to new syntax "
3537 if document.textclass != "memoir":
3542 i = find_token(document.body, "\\begin_layout Epigraph", i)
3545 j = find_end_of_layout(document.body, i)
3547 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3552 ert = find_token(document.body, "\\begin_inset ERT", i, j)
3554 endInset = find_end_of_inset(document.body, ert)
3555 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", ert)
3556 endPlain = find_end_of_layout(document.body, beginPlain)
3557 ertcont = beginPlain + 2
3558 if document.body[ertcont] == "}{":
3560 # Convert to ArgInset
3561 endlay = endlay - 2 * len(document.body[j])
3562 begsubst = ['\\begin_inset Argument post:1', 'status collapsed', '',
3563 '\\begin_layout Plain Layout']
3564 endsubst = ['\\end_layout', '', '\\end_inset', '', document.body[j]]
3565 document.body[j : j + 1] = endsubst
3566 document.body[endInset + 1 : endInset + 1] = begsubst
3568 endlay += len(begsubst) + len(endsubst)
3569 endlay = endlay - len(document.body[ert : endInset + 1])
3570 del document.body[ert : endInset + 1]
3575 def revert_epigraph(document):
3576 " Reverts memoir epigraph argument to ERT "
3578 if document.textclass != "memoir":
3583 i = find_token(document.body, "\\begin_layout Epigraph", i)
3586 j = find_end_of_layout(document.body, i)
3588 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3593 p = find_token(document.body, "\\begin_layout Argument post:1", i, j)
3595 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3596 endPlain = find_end_of_layout(document.body, beginPlain)
3597 endInset = find_end_of_inset(document.body, p)
3598 content = document.body[beginPlain + 1 : endPlain]
3600 endlay = endlay - len(document.body[p : endInset + 1])
3602 del document.body[p : endInset + 1]
3603 subst += put_cmd_in_ert("}{") + content
3605 subst += put_cmd_in_ert("}{")
3607 document.body[j : j] = subst + document.body[j : j]
3611 def convert_captioninsets(document):
3612 " Converts caption insets to new syntax "
3616 i = find_token(document.body, "\\begin_inset Caption", i)
3619 document.body[i] = "\\begin_inset Caption Standard"
3623 def revert_captioninsets(document):
3624 " Reverts caption insets to old syntax "
3628 i = find_token(document.body, "\\begin_inset Caption Standard", i)
3631 document.body[i] = "\\begin_inset Caption"
3635 def convert_captionlayouts(document):
3636 " Convert caption layouts to caption insets. "
3639 "Captionabove": "Above",
3640 "Captionbelow": "Below",
3641 "FigCaption" : "FigCaption",
3642 "Table_Caption" : "Table",
3643 "CenteredCaption" : "Centered",
3644 "Bicaption" : "Bicaption",
3649 i = find_token(document.body, "\\begin_layout", i)
3652 val = get_value(document.body, "\\begin_layout", i)
3653 if val in list(caption_dict.keys()):
3654 j = find_end_of_layout(document.body, i)
3656 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3659 document.body[j:j] = ["\\end_layout", "", "\\end_inset", "", ""]
3660 document.body[i:i+1] = ["\\begin_layout %s" % document.default_layout,
3661 "\\begin_inset Caption %s" % caption_dict[val], "",
3662 "\\begin_layout %s" % document.default_layout]
3666 def revert_captionlayouts(document):
3667 " Revert caption insets to caption layouts. "
3670 "Above" : "Captionabove",
3671 "Below" : "Captionbelow",
3672 "FigCaption" : "FigCaption",
3673 "Table" : "Table_Caption",
3674 "Centered" : "CenteredCaption",
3675 "Bicaption" : "Bicaption",
3679 rx = re.compile(r'^\\begin_inset Caption (\S+)$')
3681 i = find_token(document.body, "\\begin_inset Caption", i)
3685 m = rx.match(document.body[i])
3689 if val not in list(caption_dict.keys()):
3693 # We either need to delete the previous \begin_layout line, or we
3694 # need to end the previous layout if this inset is not in the first
3695 # position of the paragraph.
3696 layout_before = find_token_backwards(document.body, "\\begin_layout", i)
3697 if layout_before == -1:
3698 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3700 layout_line = document.body[layout_before]
3701 del_layout_before = True
3702 l = layout_before + 1
3704 if document.body[l] != "":
3705 del_layout_before = False
3708 if del_layout_before:
3709 del document.body[layout_before:i]
3712 document.body[i:i] = ["\\end_layout", ""]
3715 # Find start of layout in the inset and end of inset
3716 j = find_token(document.body, "\\begin_layout", i)
3718 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3720 k = find_end_of_inset(document.body, i)
3722 document.warning("Malformed LyX document: Missing `\\end_inset'.")
3725 # We either need to delete the following \end_layout line, or we need
3726 # to restart the old layout if this inset is not at the paragraph end.
3727 layout_after = find_token(document.body, "\\end_layout", k)
3728 if layout_after == -1:
3729 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3731 del_layout_after = True
3733 while l < layout_after:
3734 if document.body[l] != "":
3735 del_layout_after = False
3738 if del_layout_after:
3739 del document.body[k+1:layout_after+1]
3741 document.body[k+1:k+1] = [layout_line, ""]
3743 # delete \begin_layout and \end_inset and replace \begin_inset with
3744 # "\begin_layout XXX". This works because we can only have one
3745 # paragraph in the caption inset: The old \end_layout will be recycled.
3746 del document.body[k]
3747 if document.body[k] == "":
3748 del document.body[k]
3749 del document.body[j]
3750 if document.body[j] == "":
3751 del document.body[j]
3752 document.body[i] = "\\begin_layout %s" % caption_dict[val]
3753 if document.body[i+1] == "":
3754 del document.body[i+1]
3758 def revert_fragileframe(document):
3759 " Reverts beamer FragileFrame layout to ERT "
3761 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3762 if document.textclass not in beamer_classes:
3767 i = find_token(document.body, "\\begin_layout FragileFrame", i)
3770 # Find end of sequence
3771 j = find_end_of_sequence(document.body, i)
3773 document.warning("Malformed LyX document. Cannot find end of FragileFrame sequence!")
3777 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{frame}")
3778 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{frame}")
3779 endseq = endseq + len(esubst) - len(document.body[j : j])
3780 if document.body[j] == "\\end_deeper":
3781 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3783 document.body[j : j] = esubst
3784 for q in range(i, j):
3785 if document.body[q] == "\\begin_layout FragileFrame":
3786 document.body[q] = "\\begin_layout %s" % document.default_layout
3789 if document.body[r] == "\\begin_deeper":
3790 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3792 document.body[r] = ""
3793 document.body[s] = ""
3797 for p in range(1, 5):
3798 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, j)
3801 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3802 endPlain = find_end_of_layout(document.body, beginPlain)
3803 endInset = find_end_of_inset(document.body, arg)
3804 content = document.body[beginPlain + 1 : endPlain]
3806 j = j - len(document.body[arg : endInset + 1])
3808 del document.body[arg : endInset + 1]
3809 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3811 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3812 endPlain = find_end_of_layout(document.body, beginPlain)
3813 endInset = find_end_of_inset(document.body, arg)
3814 content = document.body[beginPlain + 1 : endPlain]
3816 j = j - len(document.body[arg : endInset + 1])
3818 del document.body[arg : endInset + 1]
3819 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3821 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3822 endPlain = find_end_of_layout(document.body, beginPlain)
3823 endInset = find_end_of_inset(document.body, arg)
3824 content = document.body[beginPlain + 1 : endPlain]
3826 j = j - len(document.body[arg : endInset + 1])
3828 del document.body[arg : endInset + 1]
3829 subst += put_cmd_in_ert("[fragile,") + content + put_cmd_in_ert("]")
3831 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3832 endPlain = find_end_of_layout(document.body, beginPlain)
3833 endInset = find_end_of_inset(document.body, arg)
3834 content = document.body[beginPlain + 1 : endPlain]
3836 j = j - len(document.body[arg : endInset + 1])
3838 del document.body[arg : endInset + 1]
3839 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3841 subst += put_cmd_in_ert("[fragile]")
3843 document.body[i : i + 1] = subst
3847 def revert_newframes(document):
3848 " Reverts beamer Frame and PlainFrame layouts to old forms "
3850 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3851 if document.textclass not in beamer_classes:
3855 "Frame" : "BeginFrame",
3856 "PlainFrame" : "BeginPlainFrame",
3859 rx = re.compile(r'^\\begin_layout (\S+)$')
3862 i = find_token(document.body, "\\begin_layout", i)
3866 m = rx.match(document.body[i])
3870 if val not in list(frame_dict.keys()):
3873 # Find end of sequence
3874 j = find_end_of_sequence(document.body, i)
3876 document.warning("Malformed LyX document. Cannot find end of Frame sequence!")
3880 subst = ["\\begin_layout %s" % frame_dict[val]]
3881 esubst = ["", "\\begin_layout EndFrame", "", "\\end_layout"]
3882 endseq = endseq + len(esubst) - len(document.body[j : j])
3883 if document.body[j] == "\\end_deeper":
3884 document.body[j : j] = esubst
3886 document.body[j+1 : j+1] = esubst
3887 for q in range(i, j):
3888 if document.body[q] == "\\begin_layout %s" % val:
3889 document.body[q] = "\\begin_layout %s" % document.default_layout
3892 if document.body[r] == "\\begin_deeper":
3893 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3895 document.body[r] = ""
3896 document.body[s] = ""
3900 l = find_end_of_layout(document.body, i)
3901 for p in range(1, 5):
3902 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, l)
3905 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3906 endPlain = find_end_of_layout(document.body, beginPlain)
3907 endInset = find_end_of_inset(document.body, arg)
3908 content = document.body[beginPlain + 1 : endPlain]
3910 l = l - len(document.body[arg : endInset + 1])
3912 del document.body[arg : endInset + 1]
3913 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3915 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3916 endPlain = find_end_of_layout(document.body, beginPlain)
3917 endInset = find_end_of_inset(document.body, arg)
3918 content = document.body[beginPlain + 1 : endPlain]
3920 l = l - len(document.body[arg : endInset + 1])
3922 del document.body[arg : endInset + 1]
3923 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3925 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3926 endPlain = find_end_of_layout(document.body, beginPlain)
3927 endInset = find_end_of_inset(document.body, arg)
3928 content = document.body[beginPlain + 1 : endPlain]
3930 l = l - len(document.body[arg : endInset + 1])
3932 del document.body[arg : endInset + 1]
3933 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3935 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3936 endPlain = find_end_of_layout(document.body, beginPlain)
3937 endInset = find_end_of_inset(document.body, arg)
3938 content = document.body[beginPlain + 1 : endPlain]
3940 l = l - len(document.body[arg : endInset + 1])
3942 del document.body[arg : endInset + 1]
3945 document.body[i : i + 1] = subst
3948 # known encodings that do not change their names (same LyX and LaTeX names)
3949 known_enc_tuple = ("auto", "default", "ansinew", "applemac", "armscii8", "ascii",
3950 "cp437", "cp437de", "cp850", "cp852", "cp855", "cp858", "cp862", "cp865", "cp866",
3951 "cp1250", "cp1251", "cp1252", "cp1255", "cp1256", "cp1257", "koi8-r", "koi8-u",
3952 "pt154", "pt254", "tis620-0", "utf8", "utf8x", "utf8-plain")
3954 def convert_encodings(document):
3955 "Use the LyX names of the encodings instead of the LaTeX names."
3956 LaTeX2LyX_enc_dict = {
3957 "8859-6": "iso8859-6",
3958 "8859-8": "iso8859-8",
3960 "euc": "euc-jp-platex",
3965 "iso88595": "iso8859-5",
3966 "iso-8859-7": "iso8859-7",
3968 "jis": "jis-platex",
3970 "l7xenc": "iso8859-13",
3971 "latin1": "iso8859-1",
3972 "latin2": "iso8859-2",
3973 "latin3": "iso8859-3",
3974 "latin4": "iso8859-4",
3975 "latin5": "iso8859-9",
3976 "latin9": "iso8859-15",
3977 "latin10": "iso8859-16",
3978 "SJIS": "shift-jis",
3979 "sjis": "shift-jis-platex",
3982 i = find_token(document.header, "\\inputencoding" , 0)
3985 val = get_value(document.header, "\\inputencoding", i)
3986 if val in list(LaTeX2LyX_enc_dict.keys()):
3987 document.header[i] = "\\inputencoding %s" % LaTeX2LyX_enc_dict[val]
3988 elif val not in known_enc_tuple:
3989 document.warning("Ignoring unknown input encoding: `%s'" % val)
3992 def revert_encodings(document):
3993 """Revert to using the LaTeX names of the encodings instead of the LyX names.
3994 Also revert utf8-platex to sjis, the language default when using Japanese.
3996 LyX2LaTeX_enc_dict = {
4001 "euc-jp-platex": "euc",
4004 "iso8859-1": "latin1",
4005 "iso8859-2": "latin2",
4006 "iso8859-3": "latin3",
4007 "iso8859-4": "latin4",
4008 "iso8859-5": "iso88595",
4009 "iso8859-6": "8859-6",
4010 "iso8859-7": "iso-8859-7",
4011 "iso8859-8": "8859-8",
4012 "iso8859-9": "latin5",
4013 "iso8859-13": "l7xenc",
4014 "iso8859-15": "latin9",
4015 "iso8859-16": "latin10",
4017 "jis-platex": "jis",
4018 "shift-jis": "SJIS",
4019 "shift-jis-platex": "sjis",
4021 "utf8-platex": "sjis"
4023 i = find_token(document.header, "\\inputencoding" , 0)
4026 val = get_value(document.header, "\\inputencoding", i)
4027 if val in list(LyX2LaTeX_enc_dict.keys()):
4028 document.header[i] = "\\inputencoding %s" % LyX2LaTeX_enc_dict[val]
4029 elif val not in known_enc_tuple:
4030 document.warning("Ignoring unknown input encoding: `%s'" % val)
4033 def revert_IEEEtran_3(document):
4035 Reverts Flex Insets to TeX-code
4037 if document.textclass == "IEEEtran":
4043 h = find_token(document.body, "\\begin_inset Flex Author Mark", h)
4045 endh = find_end_of_inset(document.body, h)
4046 document.body[endh - 2 : endh + 1] = put_cmd_in_ert("}")
4047 document.body[h : h + 4] = put_cmd_in_ert("\\IEEEauthorrefmark{")
4050 i = find_token(document.body, "\\begin_inset Flex Author Name", i)
4052 endi = find_end_of_inset(document.body, i)
4053 document.body[endi - 2 : endi + 1] = put_cmd_in_ert("}")
4054 document.body[i : i + 4] = put_cmd_in_ert("\\IEEEauthorblockN{")
4057 j = find_token(document.body, "\\begin_inset Flex Author Affiliation", j)
4059 endj = find_end_of_inset(document.body, j)
4060 document.body[endj - 2 : endj + 1] = put_cmd_in_ert("}")
4061 document.body[j : j + 4] = put_cmd_in_ert("\\IEEEauthorblockA{")
4063 if i == -1 and j == -1 and h == -1:
4067 def revert_kurier_fonts(document):
4068 " Revert kurier font definition to LaTeX "
4070 i = find_token(document.header, "\\font_math", 0)
4072 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4073 val = get_value(document.header, "\\font_math", i)
4074 if val == "kurier-math":
4075 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
4076 "\\usepackage[math]{kurier}\n" \
4077 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
4078 document.header[i] = "\\font_math auto"
4080 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4081 kurier_fonts = ["kurier", "kurierc", "kurierl", "kurierlc"]
4082 k = find_token(document.header, "\\font_sans kurier", 0)
4084 sf = get_value(document.header, "\\font_sans", k)
4085 if sf in kurier_fonts:
4086 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4087 document.header[k] = "\\font_sans default"
4089 def revert_iwona_fonts(document):
4090 " Revert iwona font definition to LaTeX "
4092 i = find_token(document.header, "\\font_math", 0)
4094 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4095 val = get_value(document.header, "\\font_math", i)
4096 if val == "iwona-math":
4097 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
4098 "\\usepackage[math]{iwona}\n" \
4099 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
4100 document.header[i] = "\\font_math auto"
4102 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4103 iwona_fonts = ["iwona", "iwonac", "iwonal", "iwonalc"]
4104 k = find_token(document.header, "\\font_sans iwona", 0)
4106 sf = get_value(document.header, "\\font_sans", k)
4107 if sf in iwona_fonts:
4108 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4109 document.header[k] = "\\font_sans default"
4112 def revert_new_libertines(document):
4113 " Revert new libertine font definition to LaTeX "
4115 if find_token(document.header, "\\use_non_tex_fonts true", 0) != -1:
4118 i = find_token(document.header, "\\font_typewriter libertine-mono", 0)
4120 preamble = "\\usepackage"
4121 sc = find_token(document.header, "\\font_tt_scale", 0)
4123 scval = get_value(document.header, "\\font_tt_scale", sc)
4125 preamble += "[scale=%f]" % (float(scval) / 100)
4126 document.header[sc] = "\\font_tt_scale 100"
4127 preamble += "{libertineMono-type1}"
4128 add_to_preamble(document, [preamble])
4129 document.header[i] = "\\font_typewriter default"
4131 k = find_token(document.header, "\\font_sans biolinum", 0)
4133 preamble = "\\usepackage"
4135 j = find_token(document.header, "\\font_osf true", 0)
4140 sc = find_token(document.header, "\\font_sf_scale", 0)
4142 scval = get_value(document.header, "\\font_sf_scale", sc)
4144 options += ",scale=%f" % (float(scval) / 100)
4145 document.header[sc] = "\\font_sf_scale 100"
4147 preamble += "[" + options +"]"
4148 preamble += "{biolinum-type1}"
4149 add_to_preamble(document, [preamble])
4150 document.header[k] = "\\font_sans default"
4153 def convert_lyxframes(document):
4154 " Converts old beamer frames to new style "
4156 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4157 if document.textclass not in beamer_classes:
4160 framebeg = ["BeginFrame", "BeginPlainFrame"]
4161 frameend = ["Frame", "PlainFrame", "EndFrame", "BeginFrame", "BeginPlainFrame", "AgainFrame",
4162 "Section", "Section*", "Subsection", "Subsection*", "Subsubsection", "Subsubsection*"]
4163 for lay in framebeg:
4166 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
4169 parent = get_containing_layout(document.body, i)
4170 if parent == False or parent[1] != i:
4171 document.warning("Wrong parent layout!")
4174 frametype = parent[0]
4178 # Step I: Convert ERT arguments
4179 # FIXME: See restrictions in convert_beamerframeargs method
4180 ertend = convert_beamerframeargs(document, i, parbeg)
4183 # Step II: Now rename the layout and convert the title to an argument
4184 j = find_end_of_layout(document.body, i)
4185 document.body[j : j + 1] = ['\\end_layout', '', '\\end_inset', '', '\\end_layout']
4186 if lay == "BeginFrame":
4187 document.body[i] = "\\begin_layout Frame"
4189 document.body[i] = "\\begin_layout PlainFrame"
4190 document.body[ertend + 1 : ertend + 1] = ['\\begin_inset Argument 4',
4191 'status open', '', '\\begin_layout Plain Layout']
4192 # Step III: find real frame end
4195 inInset = get_containing_inset(document.body, i)
4197 fend = find_token(document.body, "\\begin_layout", jj)
4199 document.warning("Malformed LyX document: No real frame end!")
4201 val = get_value(document.body, "\\begin_layout", fend)
4202 if val not in frameend:
4205 # is this frame nested in an inset (e.g., Note)?
4206 if inInset != False:
4207 # if so, end the frame inside the inset
4208 if inInset[2] < fend:
4210 if val == frametype:
4211 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4212 # consider explicit EndFrames between two identical frame types
4213 elif val == "EndFrame":
4214 nextlayout = find_token(document.body, "\\begin_layout", fend + 1)
4215 if nextlayout != -1 and get_value(document.body, "\\begin_layout", nextlayout) == frametype:
4216 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4218 document.body[fend : fend] = ['\\end_deeper']
4220 document.body[fend : fend] = ['\\end_deeper']
4221 document.body[j + 1 : j + 1] = ['', '\\begin_deeper']
4226 def remove_endframes(document):
4227 " Remove deprecated beamer endframes "
4229 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4230 if document.textclass not in beamer_classes:
4235 i = find_token_exact(document.body, "\\begin_layout EndFrame", i)
4238 j = find_end_of_layout(document.body, i)
4240 document.warning("Malformed LyX document: Missing \\end_layout to EndFrame")
4243 del document.body[i : j + 1]
4246 def revert_powerdot_flexes(document):
4247 " Reverts powerdot flex insets "
4249 if document.textclass != "powerdot":
4252 flexes = {"Onslide" : "\\onslide",
4253 "Onslide*" : "\\onslide*",
4254 "Onslide+" : "\\onslide+"}
4255 rx = re.compile(r'^\\begin_inset Flex (.+)$')
4259 i = find_token(document.body, "\\begin_inset Flex", i)
4262 m = rx.match(document.body[i])
4264 flextype = m.group(1)
4265 z = find_end_of_inset(document.body, i)
4267 document.warning("Can't find end of Flex " + flextype + " inset.")
4270 if flextype in flexes:
4271 pre = put_cmd_in_ert(flexes[flextype])
4272 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
4274 argend = find_end_of_inset(document.body, arg)
4276 document.warning("Can't find end of Argument!")
4279 # Find containing paragraph layout
4280 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
4281 endPlain = find_end_of_layout(document.body, beginPlain)
4282 argcontent = document.body[beginPlain + 1 : endPlain]
4284 z = z - len(document.body[arg : argend + 1])
4286 del document.body[arg : argend + 1]
4287 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
4288 pre += put_cmd_in_ert("{")
4289 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4290 endPlain = find_end_of_layout(document.body, beginPlain)
4292 z = z - len(document.body[i : beginPlain + 1])
4294 document.body[i : beginPlain + 1] = pre
4295 post = put_cmd_in_ert("}")
4296 document.body[z - 2 : z + 1] = post
4300 def revert_powerdot_pause(document):
4301 " Reverts powerdot pause layout to ERT "
4303 if document.textclass != "powerdot":
4308 i = find_token(document.body, "\\begin_layout Pause", i)
4311 j = find_end_of_layout(document.body, i)
4313 document.warning("Malformed LyX document: Can't find end of Pause layout")
4317 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\pause")
4318 for p in range(i, j):
4321 arg = find_token(document.body, "\\begin_inset Argument 1", i, j)
4323 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4324 endPlain = find_end_of_layout(document.body, beginPlain)
4325 endInset = find_end_of_inset(document.body, p)
4326 content = document.body[beginPlain + 1 : endPlain]
4328 endlay = endlay - len(document.body[p : endInset + 1])
4330 del document.body[p : endInset + 1]
4331 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4333 document.body[i : i + 1] = subst
4337 def revert_powerdot_itemargs(document):
4338 " Reverts powerdot item arguments to ERT "
4340 if document.textclass != "powerdot":
4344 list_layouts = ["Itemize", "ItemizeType1", "Enumerate", "EnumerateType1"]
4345 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4348 i = find_token(document.body, "\\begin_inset Argument", i)
4351 # Find containing paragraph layout
4352 parent = get_containing_layout(document.body, i)
4354 document.warning("Malformed LyX document: Can't find parent paragraph layout")
4359 realparbeg = parent[3]
4360 layoutname = parent[0]
4362 for p in range(parbeg, parend):
4366 if layoutname in list_layouts:
4367 m = rx.match(document.body[p])
4370 if argnr == "item:1":
4371 j = find_end_of_inset(document.body, i)
4372 # Find containing paragraph layout
4373 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4374 endPlain = find_end_of_layout(document.body, beginPlain)
4375 content = document.body[beginPlain + 1 : endPlain]
4376 del document.body[i:j+1]
4377 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4378 document.body[realparbeg : realparbeg] = subst
4379 elif argnr == "item:2":
4380 j = find_end_of_inset(document.body, i)
4381 # Find containing paragraph layout
4382 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4383 endPlain = find_end_of_layout(document.body, beginPlain)
4384 content = document.body[beginPlain + 1 : endPlain]
4385 del document.body[i:j+1]
4386 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
4387 document.body[realparbeg : realparbeg] = subst
4392 def revert_powerdot_columns(document):
4393 " Reverts powerdot twocolumn to TeX-code "
4394 if document.textclass != "powerdot":
4397 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4400 i = find_token(document.body, "\\begin_layout Twocolumn", i)
4403 j = find_end_of_layout(document.body, i)
4405 document.warning("Malformed LyX document: Can't find end of Twocolumn layout")
4409 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
4410 endlay += len(put_cmd_in_ert("}"))
4411 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\twocolumn")
4412 for p in range(i, j):
4415 m = rx.match(document.body[p])
4419 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4420 endPlain = find_end_of_layout(document.body, beginPlain)
4421 endInset = find_end_of_inset(document.body, p)
4422 content = document.body[beginPlain + 1 : endPlain]
4424 endlay = endlay - len(document.body[p : endInset + 1])
4426 del document.body[p : endInset + 1]
4427 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4429 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4430 endPlain = find_end_of_layout(document.body, beginPlain)
4431 endInset = find_end_of_inset(document.body, p)
4432 content = document.body[beginPlain + 1 : endPlain]
4434 endlay = endlay - len(document.body[p : endInset + 1])
4436 del document.body[p : endInset + 1]
4437 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
4439 subst += put_cmd_in_ert("{")
4440 document.body[i : i + 1] = subst
4444 def revert_mbox_fbox(document):
4445 'Convert revert mbox/fbox boxes to TeX-code'
4448 i = find_token(document.body, "\\begin_inset Box", i)
4451 j = find_token(document.body, "width", i)
4453 document.warning("Malformed LyX document: Can't find box width")
4455 width = get_value(document.body, "width", j)
4456 k = find_end_of_inset(document.body, j)
4458 document.warning("Malformed LyX document: Can't find end of box inset")
4461 BeginLayout = find_token(document.body, "\\begin_layout Plain Layout", j)
4462 EndLayout = find_end_of_layout(document.body, BeginLayout)
4463 # replace if width is ""
4465 document.body[EndLayout:k + 1] = put_cmd_in_ert("}")
4466 if document.body[i] == "\\begin_inset Box Frameless":
4467 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\mbox{")
4468 if document.body[i] == "\\begin_inset Box Boxed":
4469 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\fbox{")
4473 def revert_starred_caption(document):
4474 " Reverts unnumbered longtable caption insets "
4478 i = find_token(document.body, "\\begin_inset Caption LongTableNoNumber", i)
4481 # This is not equivalent, but since the caption inset is a full blown
4482 # text inset a true conversion to ERT is too difficult.
4483 document.body[i] = "\\begin_inset Caption Standard"
4487 def revert_forced_local_layout(document):
4490 i = find_token(document.header, "\\begin_forced_local_layout", i)
4493 j = find_end_of(document.header, i, "\\begin_forced_local_layout", "\\end_forced_local_layout")
4495 # this should not happen
4497 regexp = re.compile(r'\s*forcelocal', re.IGNORECASE)
4498 k = find_re(document.header, regexp, i, j)
4500 del document.header[k]
4502 k = find_re(document.header, regexp, i, j)
4503 k = find_token(document.header, "\\begin_local_layout", 0)
4505 document.header[i] = "\\begin_local_layout"
4506 document.header[j] = "\\end_local_layout"
4508 l = find_end_of(document.header, k, "\\begin_local_layout", "\\end_local_layout")
4510 # this should not happen
4512 lines = document.header[i+1 : j]
4514 document.header[k+1 : k+1] = lines
4515 document.header[i : j ] = []
4517 document.header[i : j ] = []
4518 document.header[k+1 : k+1] = lines
4521 def revert_aa1(document):
4522 " Reverts InsetArguments of aa to TeX-code "
4523 if document.textclass == "aa":
4527 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4529 revert_Argument_to_TeX_brace(document, i, 0, 1, 4, False, False)
4535 def revert_aa2(document):
4536 " Reverts InsetArguments of aa to TeX-code "
4537 if document.textclass == "aa":
4541 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4543 document.body[i] = "\\begin_layout Abstract"
4549 def revert_tibetan(document):
4550 "Set the document language for Tibetan to English"
4552 if document.language == "tibetan":
4553 document.language = "english"
4554 i = find_token(document.header, "\\language", 0)
4556 document.header[i] = "\\language english"
4558 while j < len(document.body):
4559 j = find_token(document.body, "\\lang tibetan", j)
4561 document.body[j] = document.body[j].replace("\\lang tibetan", "\\lang english")
4564 j = len(document.body)
4573 # The idea here is that we will have a sequence of chunk paragraphs.
4574 # We want to convert them to paragraphs in one or several chunk insets.
4575 # Individual chunks are terminated by the character @ on the last line.
4576 # This line will be discarded, and following lines are treated as new
4577 # chunks, which go into their own insets.
4578 # The first line of a chunk should look like: <<CONTENT>>=
4579 # We will discard the delimiters, and put the CONTENT into the
4580 # optional argument of the inset, if the CONTENT is non-empty.
4581 def convert_chunks(document):
4582 first_re = re.compile(r'<<(.*)>>=(.*)')
4585 # find start of a block of chunks
4586 i = find_token(document.body, "\\begin_layout Chunk", file_pos)
4592 chunk_started = False
4595 # process the one we just found
4596 j = find_end_of_layout(document.body, i)
4598 document.warning("Malformed LyX documents. Can't find end of Chunk layout!")
4599 # there is no point continuing, as we will run into the same error again.
4601 this_chunk = "".join(document.body[i + 1:j])
4603 # there may be empty lines between chunks
4604 # we just skip them.
4605 if not chunk_started:
4606 if this_chunk != "":
4608 chunk_started = True
4611 contents.append(document.body[i + 1:j])
4613 # look for potential chunk terminator
4614 # on the last line of the chunk paragraph
4615 if document.body[j - 1] == "@":
4618 # look for subsequent chunk paragraph
4619 i = find_token(document.body, "\\begin_layout", j)
4623 if get_value(document.body, "\\begin_layout", i) != "Chunk":
4626 file_pos = end = j + 1
4628 # The last chunk should simply have an "@" in it
4629 # or at least end with "@" (can happen if @ is
4630 # preceded by a newline)
4632 if len(contents) > 0:
4633 lastpar = ''.join(contents[-1])
4634 if not lastpar.endswith("@"):
4635 document.warning("Unexpected chunk content: chunk not terminated by '@'!")
4636 if len(contents) == 0:
4637 # convert empty chunk layouts to Standard
4638 document.body[start] = "\\begin_layout Standard"
4642 # chunk par only contains "@". Just drop it.
4645 # chunk par contains more. Only drop the "@".
4648 # The first line should look like: <<CONTENT>>=
4649 # We want the CONTENT
4650 optarg = ' '.join(contents[0])
4652 # We can already have real chunk content in
4653 # the first par (separated from the options by a newline).
4654 # We collect such stuff to re-insert it later.
4657 match = first_re.search(optarg)
4659 optarg = match.groups()[0]
4660 if match.groups()[1] != "":
4662 for c in contents[0]:
4663 if c.endswith(">>="):
4667 postoptstuff.append(c)
4668 # We have stripped everything. This can be deleted.
4671 newstuff = ['\\begin_layout Standard']
4673 # Maintain paragraph parameters
4674 par_params = ["\\noindent", "\\indent", "\\indent-toggle", "\\leftindent",
4675 "\\start_of_appendix", "\\paragraph_spacing", "\\align",
4676 "\\labelwidthstring"]
4679 if document.body[parms].split(' ', 1)[0] not in par_params:
4681 newstuff.extend([document.body[parms]])
4685 ['\\begin_inset Flex Chunk',
4687 '\\begin_layout Plain Layout', ''])
4689 # If we have a non-empty optional argument, insert it.
4690 if match and optarg != "":
4692 ['\\begin_inset Argument 1',
4694 '\\begin_layout Plain Layout',
4699 # Since we already opened a Plain layout, the first paragraph
4700 # does not need to do that.
4703 # we need to replace newlines with new layouts
4705 started_text = False
4706 for lno in range(0,len(postoptstuff)):
4707 if postoptstuff[lno].startswith("\\begin_inset Newline newline"):
4709 elif start_newline != -1:
4710 if postoptstuff[lno].startswith("\\end_inset"):
4711 # replace that bit, but only if we already have some text
4712 # and we're not at the end except for a blank line
4713 if started_text and \
4714 (lno != len(postoptstuff) - 2 or postoptstuff[-1] != ""):
4715 newstuff.extend(['\\end_layout', '\n', '\\begin_layout Plain Layout', '\n'])
4719 newstuff.extend([postoptstuff[lno]])
4720 newstuff.append('\\end_layout')
4724 newstuff.extend(['', '\\begin_layout Plain Layout', ''])
4728 newstuff.append('\\end_layout')
4730 newstuff.extend(['', '\\end_inset', '', '\\end_layout', ''])
4732 document.body[start:end] = newstuff
4734 file_pos += len(newstuff) - (end - start)
4737 def revert_chunks(document):
4740 i = find_token(document.body, "\\begin_inset Flex Chunk", i)
4744 iend = find_end_of_inset(document.body, i)
4746 document.warning("Can't find end of Chunk!")
4750 # Look for optional argument
4752 ostart = find_token(document.body, "\\begin_inset Argument 1", i, iend)
4754 oend = find_end_of_inset(document.body, ostart)
4755 k = find_token(document.body, "\\begin_layout Plain Layout", ostart, oend)
4757 document.warning("Malformed LyX document: Can't find argument contents!")
4759 m = find_end_of_layout(document.body, k)
4760 optarg = "".join(document.body[k+1:m])
4762 # We now remove the optional argument, so we have something
4763 # uniform on which to work
4764 document.body[ostart : oend + 1] = []
4765 # iend is now invalid
4766 iend = find_end_of_inset(document.body, i)
4768 retval = get_containing_layout(document.body, i)
4770 document.warning("Can't find containing layout for Chunk!")
4773 (lname, lstart, lend, pstart) = retval
4774 # we now want to work through the various paragraphs, and collect their contents
4778 k = find_token(document.body, "\\begin_layout Plain Layout", k, lend)
4781 j = find_end_of_layout(document.body, k)
4783 document.warning("Can't find end of layout inside chunk!")
4785 parlist.append(document.body[k+1:j])
4787 # we now need to wrap all of these paragraphs in chunks
4789 newlines.extend(["\\begin_layout Chunk", "", "<<" + optarg + ">>=", "\\end_layout", ""])
4790 for stuff in parlist:
4791 newlines.extend(["\\begin_layout Chunk"] + stuff + ["\\end_layout", ""])
4792 newlines.extend(["\\begin_layout Chunk", "", "@", "\\end_layout", ""])
4793 # replace old content with new content
4794 document.body[lstart : lend + 1] = newlines
4795 i = lstart + len(newlines)
4802 supported_versions = ["2.1.0","2.1"]
4805 [415, [convert_undertilde]],
4807 [417, [convert_japanese_encodings]],
4808 [418, [convert_justification]],
4810 [420, [convert_biblio_style]],
4811 [421, [convert_longtable_captions]],
4812 [422, [convert_use_packages]],
4813 [423, [convert_use_mathtools]],
4814 [424, [convert_cite_engine_type]],
4815 # No convert_cancel, since cancel will be loaded automatically
4816 # in format 425 without any possibility to switch it off.
4817 # This has been fixed in format 464.
4821 [428, [convert_cell_rotation]],
4822 [429, [convert_table_rotation]],
4823 [430, [convert_listoflistings]],
4824 [431, [convert_use_amssymb]],
4826 [433, [convert_armenian]],
4833 [440, [convert_mathfonts]],
4834 [441, [convert_mdnomath]],
4839 [446, [convert_latexargs]],
4840 [447, [convert_IEEEtran, convert_AASTeX, convert_AGUTeX, convert_IJMP, convert_SIGPLAN, convert_SIGGRAPH, convert_EuropeCV, convert_Initials, convert_ModernCV]],
4841 [448, [convert_literate]],
4844 [451, [convert_beamerargs, convert_againframe_args, convert_corollary_args, convert_quote_args]],
4845 [452, [convert_beamerblocks]],
4846 [453, [convert_use_stmaryrd]],
4847 [454, [convert_overprint]],
4849 [456, [convert_epigraph]],
4850 [457, [convert_use_stackrel]],
4851 [458, [convert_captioninsets, convert_captionlayouts]],
4856 [463, [convert_encodings]],
4857 [464, [convert_use_cancel]],
4858 [465, [convert_lyxframes, remove_endframes]],
4864 [471, [convert_cite_engine_type_default]],
4867 [474, [convert_chunks, cleanup_beamerargs]],
4871 [473, [revert_chunks]],
4872 [472, [revert_tibetan]],
4873 [471, [revert_aa1,revert_aa2]],
4874 [470, [revert_cite_engine_type_default]],
4875 [469, [revert_forced_local_layout]],
4876 [468, [revert_starred_caption]],
4877 [467, [revert_mbox_fbox]],
4878 [466, [revert_iwona_fonts]],
4879 [465, [revert_powerdot_flexes, revert_powerdot_pause, revert_powerdot_itemargs, revert_powerdot_columns]],
4881 [463, [revert_use_cancel]],
4882 [462, [revert_encodings]],
4883 [461, [revert_new_libertines]],
4884 [460, [revert_kurier_fonts]],
4885 [459, [revert_IEEEtran_3]],
4886 [458, [revert_fragileframe, revert_newframes]],
4887 [457, [revert_captioninsets, revert_captionlayouts]],
4888 [456, [revert_use_stackrel]],
4889 [455, [revert_epigraph]],
4890 [454, [revert_frametitle]],
4891 [453, [revert_overprint]],
4892 [452, [revert_use_stmaryrd]],
4893 [451, [revert_beamerblocks]],
4894 [450, [revert_beamerargs, revert_beamerargs2, revert_beamerargs3, revert_beamerflex]],
4895 [449, [revert_garamondx, revert_garamondx_newtxmath]],
4896 [448, [revert_itemargs]],
4897 [447, [revert_literate]],
4898 [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]],
4899 [445, [revert_latexargs]],
4900 [444, [revert_uop]],
4901 [443, [revert_biolinum]],
4903 [441, [revert_newtxmath]],
4904 [440, [revert_mdnomath]],
4905 [439, [revert_mathfonts]],
4906 [438, [revert_minionpro]],
4907 [437, [revert_ipadeco, revert_ipachar]],
4908 [436, [revert_texgyre]],
4909 [435, [revert_mathdesign]],
4910 [434, [revert_txtt]],
4911 [433, [revert_libertine]],
4912 [432, [revert_armenian]],
4913 [431, [revert_languages, revert_ancientgreek]],
4914 [430, [revert_use_amssymb]],
4915 [429, [revert_listoflistings]],
4916 [428, [revert_table_rotation]],
4917 [427, [revert_cell_rotation]],
4918 [426, [revert_tipa]],
4919 [425, [revert_verbatim]],
4920 [424, [revert_cancel]],
4921 [423, [revert_cite_engine_type]],
4922 [422, [revert_use_mathtools]],
4923 [421, [revert_use_packages]],
4924 [420, [revert_longtable_captions]],
4925 [419, [revert_biblio_style]],
4926 [418, [revert_australian]],
4927 [417, [revert_justification]],
4928 [416, [revert_japanese_encodings]],
4929 [415, [revert_negative_space, revert_math_spaces]],
4930 [414, [revert_undertilde]],
4931 [413, [revert_visible_space]]
4935 if __name__ == "__main__":