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. "
821 subst_end = ['\end_layout', '', '\\begin_layout Plain Layout',
823 '\\begin_layout Plain Layout', '', '',
826 '\\end_layout', '', '\\end_inset',
827 '', '', '\\end_layout']
828 subst_begin = ['\\begin_layout Standard', '\\noindent',
829 '\\begin_inset ERT', 'status open', '',
830 '\\begin_layout Plain Layout', '', '', '\\backslash',
832 '\\end_layout', '', '\\begin_layout Plain Layout', '']
834 subst_end = ['\end_layout', '', '\\begin_layout Plain Layout',
836 '\\begin_layout Plain Layout', '', '',
839 '\\end_layout', '', '\\end_inset',
840 '', '', '\\end_layout']
841 subst_begin = ['\\begin_layout Standard', '\\noindent',
842 '\\begin_inset ERT', 'status open', '',
843 '\\begin_layout Plain Layout', '', '', '\\backslash',
845 '\\end_layout', '', '\\begin_layout Plain Layout', '']
847 layout_name = "Verbatim"
849 layout_name = "Verbatim*"
852 i = find_token(document.body, "\\begin_layout %s" % (layout_name), i)
855 j = find_end_of_layout(document.body, i)
857 document.warning("Malformed LyX document: Can't find end of %s layout" \
861 # delete all line breaks insets (there are no other insets)
864 n = find_token(document.body, "\\begin_inset Newline newline", l, j)
866 n = find_token(document.body, "\\begin_inset Newline linebreak", l, j)
869 m = find_end_of_inset(document.body, n)
870 del(document.body[m:m+1])
871 document.body[n:n+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
873 # we deleted a line, so the end of the inset moved forward.
875 # consecutive verbatim environments need to be connected
876 k = find_token(document.body, "\\begin_layout Verbatim", j)
877 if k == j + 2 and consecutive == False:
879 document.body[j:j+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
880 document.body[i:i+1] = subst_begin
882 if k == j + 2 and consecutive == True:
883 document.body[j:j+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
884 del(document.body[i:i+1])
886 if k != j + 2 and consecutive == True:
887 document.body[j:j+1] = subst_end
888 # the next paragraph must not be indented
889 document.body[j+19:j+19] = ['\\noindent']
890 del(document.body[i:i+1])
894 document.body[j:j+1] = subst_end
895 # the next paragraph must not be indented
896 document.body[j+19:j+19] = ['\\noindent']
897 document.body[i:i+1] = subst_begin
900 def revert_tipa(document):
901 " Revert native TIPA insets to mathed or ERT. "
904 i = find_token(document.body, "\\begin_inset IPA", i)
907 j = find_end_of_inset(document.body, i)
909 document.warning("Malformed LyX document: Can't find end of IPA inset")
913 n = find_token(document.body, "\\begin_layout", i, j)
915 document.warning("Malformed LyX document: IPA inset has no embedded layout")
918 m = find_end_of_layout(document.body, n)
920 document.warning("Malformed LyX document: Can't find end of embedded layout")
923 content = document.body[n+1:m]
924 p = find_token(document.body, "\\begin_layout", m, j)
925 if p != -1 or len(content) > 1:
927 content = document.body[i+1:j]
929 # IPA insets with multiple pars need to be wrapped by \begin{IPA}...\end{IPA}
930 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}")
931 add_to_preamble(document, ["\\usepackage{tipa,tipx}"])
933 # single-par IPA insets can be reverted to mathed
934 document.body[i:j+1] = ["\\begin_inset Formula $\\text{\\textipa{" + content[0] + "}}$", "\\end_inset"]
938 def revert_cell_rotation(document):
939 "Revert cell rotations to TeX-code"
941 load_rotating = False
945 # first, let's find out if we need to do anything
946 i = find_token(document.body, '<cell ', i)
949 j = document.body[i].find('rotate="')
951 k = document.body[i].find('"', j + 8)
952 value = document.body[i][j + 8 : k]
954 rgx = re.compile(r' rotate="[^"]+?"')
955 # remove rotate option
956 document.body[i] = rgx.sub('', document.body[i])
958 rgx = re.compile(r' rotate="[^"]+?"')
959 document.body[i] = rgx.sub(' rotate="true"', document.body[i])
961 rgx = re.compile(r' rotate="[^"]+?"')
963 # remove rotate option
964 document.body[i] = rgx.sub('', document.body[i])
966 document.body[i + 5 : i + 5] = \
967 put_cmd_in_ert("\\end{turn}")
968 document.body[i + 4 : i + 4] = \
969 put_cmd_in_ert("\\begin{turn}{" + value + "}")
975 add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"])
978 def convert_cell_rotation(document):
979 'Convert cell rotation statements from "true" to "90"'
983 # first, let's find out if we need to do anything
984 i = find_token(document.body, '<cell ', i)
987 j = document.body[i].find('rotate="true"')
989 rgx = re.compile(r'rotate="[^"]+?"')
990 # convert "true" to "90"
991 document.body[i] = rgx.sub('rotate="90"', document.body[i])
996 def revert_table_rotation(document):
997 "Revert table rotations to TeX-code"
999 load_rotating = False
1003 # first, let's find out if we need to do anything
1004 i = find_token(document.body, '<features ', i)
1007 j = document.body[i].find('rotate="')
1009 end_table = find_token(document.body, '</lyxtabular>', j)
1010 k = document.body[i].find('"', j + 8)
1011 value = document.body[i][j + 8 : k]
1013 rgx = re.compile(r' rotate="[^"]+?"')
1014 # remove rotate option
1015 document.body[i] = rgx.sub('', document.body[i])
1017 rgx = re.compile(r'rotate="[^"]+?"')
1018 document.body[i] = rgx.sub('rotate="true"', document.body[i])
1020 rgx = re.compile(r' rotate="[^"]+?"')
1021 load_rotating = True
1022 # remove rotate option
1023 document.body[i] = rgx.sub('', document.body[i])
1025 document.body[end_table + 3 : end_table + 3] = \
1026 put_cmd_in_ert("\\end{turn}")
1027 document.body[i - 2 : i - 2] = \
1028 put_cmd_in_ert("\\begin{turn}{" + value + "}")
1034 add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"])
1037 def convert_table_rotation(document):
1038 'Convert table rotation statements from "true" to "90"'
1042 # first, let's find out if we need to do anything
1043 i = find_token(document.body, '<features ', i)
1046 j = document.body[i].find('rotate="true"')
1048 rgx = re.compile(r'rotate="[^"]+?"')
1049 # convert "true" to "90"
1050 document.body[i] = rgx.sub('rotate="90"', document.body[i])
1055 def convert_listoflistings(document):
1056 'Convert ERT \lstlistoflistings to TOC lstlistoflistings inset'
1057 # We can support roundtrip because the command is so simple
1060 i = find_token(document.body, "\\begin_inset ERT", i)
1063 j = find_end_of_inset(document.body, i)
1065 document.warning("Malformed LyX document: Can't find end of ERT inset")
1068 ert = get_ert(document.body, i)
1069 if ert == "\\lstlistoflistings{}":
1070 document.body[i:j] = ["\\begin_inset CommandInset toc", "LatexCommand lstlistoflistings", ""]
1076 def revert_listoflistings(document):
1077 'Convert TOC lstlistoflistings inset to ERT lstlistoflistings'
1080 i = find_token(document.body, "\\begin_inset CommandInset toc", i)
1083 if document.body[i+1] == "LatexCommand lstlistoflistings":
1084 j = find_end_of_inset(document.body, i)
1086 document.warning("Malformed LyX document: Can't find end of TOC inset")
1089 subst = put_cmd_in_ert("\\lstlistoflistings{}")
1090 document.body[i:j+1] = subst
1091 add_to_preamble(document, ["\\usepackage{listings}"])
1095 def convert_use_amssymb(document):
1096 "insert use_package amssymb"
1097 regexp = re.compile(r'(\\use_package\s+amsmath)')
1098 i = find_re(document.header, regexp, 0)
1100 document.warning("Malformed LyX document: Can't find \\use_package amsmath.")
1102 value = get_value(document.header, "\\use_package" , i).split()[1]
1105 useamsmath = int(value)
1107 document.warning("Invalid \\use_package amsmath: " + value + ". Assuming auto.")
1109 j = find_token(document.preamble, "\\usepackage{amssymb}", 0)
1111 document.header.insert(i + 1, "\\use_package amssymb %d" % useamsmath)
1113 document.header.insert(i + 1, "\\use_package amssymb 2")
1114 del document.preamble[j]
1117 def revert_use_amssymb(document):
1118 "remove use_package amssymb"
1119 regexp1 = re.compile(r'(\\use_package\s+amsmath)')
1120 regexp2 = re.compile(r'(\\use_package\s+amssymb)')
1121 i = find_re(document.header, regexp1, 0)
1122 j = find_re(document.header, regexp2, 0)
1123 value1 = "1" # default is auto
1124 value2 = "1" # default is auto
1126 value1 = get_value(document.header, "\\use_package" , i).split()[1]
1128 value2 = get_value(document.header, "\\use_package" , j).split()[1]
1129 del document.header[j]
1130 if value1 != value2 and value2 == "2": # on
1131 add_to_preamble(document, ["\\usepackage{amssymb}"])
1134 def convert_use_cancel(document):
1135 "insert use_package cancel"
1136 convert_use_package(document, "cancel", cancel_commands, True)
1139 def revert_use_cancel(document):
1140 "remove use_package cancel"
1141 revert_use_package(document, "cancel", cancel_commands, True)
1144 def revert_ancientgreek(document):
1145 "Set the document language for ancientgreek to greek"
1147 if document.language == "ancientgreek":
1148 document.language = "greek"
1149 i = find_token(document.header, "\\language", 0)
1151 document.header[i] = "\\language greek"
1154 j = find_token(document.body, "\\lang ancientgreek", j)
1158 document.body[j] = document.body[j].replace("\\lang ancientgreek", "\\lang greek")
1162 def revert_languages(document):
1163 "Set the document language for new supported languages to English"
1166 "coptic", "divehi", "hindi", "kurmanji", "lao", "marathi", "occitan", "sanskrit",
1167 "syriac", "tamil", "telugu", "urdu"
1169 for n in range(len(languages)):
1170 if document.language == languages[n]:
1171 document.language = "english"
1172 i = find_token(document.header, "\\language", 0)
1174 document.header[i] = "\\language english"
1176 while j < len(document.body):
1177 j = find_token(document.body, "\\lang " + languages[n], j)
1179 document.body[j] = document.body[j].replace("\\lang " + languages[n], "\\lang english")
1182 j = len(document.body)
1185 def convert_armenian(document):
1186 "Use polyglossia and thus non-TeX fonts for Armenian"
1188 if document.language == "armenian":
1189 i = find_token(document.header, "\\use_non_tex_fonts", 0)
1191 document.header[i] = "\\use_non_tex_fonts true"
1194 def revert_armenian(document):
1195 "Use ArmTeX and thus TeX fonts for Armenian"
1197 if document.language == "armenian":
1198 i = find_token(document.header, "\\use_non_tex_fonts", 0)
1200 document.header[i] = "\\use_non_tex_fonts false"
1203 def revert_libertine(document):
1204 " Revert native libertine font definition to LaTeX "
1206 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1207 i = find_token(document.header, "\\font_roman libertine", 0)
1210 j = find_token(document.header, "\\font_osf true", 0)
1213 preamble = "\\usepackage"
1215 document.header[j] = "\\font_osf false"
1218 preamble += "[lining]"
1219 preamble += "{libertine-type1}"
1220 add_to_preamble(document, [preamble])
1221 document.header[i] = "\\font_roman default"
1224 def revert_txtt(document):
1225 " Revert native txtt font definition to LaTeX "
1227 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1228 i = find_token(document.header, "\\font_typewriter txtt", 0)
1230 preamble = "\\renewcommand{\\ttdefault}{txtt}"
1231 add_to_preamble(document, [preamble])
1232 document.header[i] = "\\font_typewriter default"
1235 def revert_mathdesign(document):
1236 " Revert native mathdesign font definition to LaTeX "
1238 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1244 i = find_token(document.header, "\\font_roman", 0)
1247 val = get_value(document.header, "\\font_roman", i)
1248 if val in list(mathdesign_dict.keys()):
1249 preamble = "\\usepackage[%s" % mathdesign_dict[val]
1251 j = find_token(document.header, "\\font_osf true", 0)
1254 document.header[j] = "\\font_osf false"
1255 l = find_token(document.header, "\\font_sc true", 0)
1258 document.header[l] = "\\font_sc false"
1260 preamble += ",expert"
1261 preamble += "]{mathdesign}"
1262 add_to_preamble(document, [preamble])
1263 document.header[i] = "\\font_roman default"
1266 def revert_texgyre(document):
1267 " Revert native TeXGyre font definition to LaTeX "
1269 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1270 texgyre_fonts = ["tgadventor", "tgbonum", "tgchorus", "tgcursor", \
1271 "tgheros", "tgpagella", "tgschola", "tgtermes"]
1272 i = find_token(document.header, "\\font_roman", 0)
1274 val = get_value(document.header, "\\font_roman", i)
1275 if val in texgyre_fonts:
1276 preamble = "\\usepackage{%s}" % val
1277 add_to_preamble(document, [preamble])
1278 document.header[i] = "\\font_roman default"
1279 i = find_token(document.header, "\\font_sans", 0)
1281 val = get_value(document.header, "\\font_sans", i)
1282 if val in texgyre_fonts:
1283 preamble = "\\usepackage{%s}" % val
1284 add_to_preamble(document, [preamble])
1285 document.header[i] = "\\font_sans default"
1286 i = find_token(document.header, "\\font_typewriter", 0)
1288 val = get_value(document.header, "\\font_typewriter", i)
1289 if val in texgyre_fonts:
1290 preamble = "\\usepackage{%s}" % val
1291 add_to_preamble(document, [preamble])
1292 document.header[i] = "\\font_typewriter default"
1295 def revert_ipadeco(document):
1296 " Revert IPA decorations to ERT "
1299 i = find_token(document.body, "\\begin_inset IPADeco", i)
1302 end = find_end_of_inset(document.body, i)
1304 document.warning("Can't find end of inset at line " + str(i))
1307 line = document.body[i]
1308 rx = re.compile(r'\\begin_inset IPADeco (.*)$')
1310 decotype = m.group(1)
1311 if decotype != "toptiebar" and decotype != "bottomtiebar":
1312 document.warning("Invalid IPADeco type: " + decotype)
1315 blay = find_token(document.body, "\\begin_layout Plain Layout", i, end)
1317 document.warning("Can't find layout for inset at line " + str(i))
1320 bend = find_end_of_layout(document.body, blay)
1322 document.warning("Malformed LyX document: Could not find end of IPADeco inset's layout.")
1325 substi = ["\\begin_inset ERT", "status collapsed", "",
1326 "\\begin_layout Plain Layout", "", "", "\\backslash",
1327 decotype + "{", "\\end_layout", "", "\\end_inset"]
1328 substj = ["\\size default", "", "\\begin_inset ERT", "status collapsed", "",
1329 "\\begin_layout Plain Layout", "", "}", "\\end_layout", "", "\\end_inset"]
1330 # do the later one first so as not to mess up the numbering
1331 document.body[bend:end + 1] = substj
1332 document.body[i:blay + 1] = substi
1333 i = end + len(substi) + len(substj) - (end - bend) - (blay - i) - 2
1334 add_to_preamble(document, "\\usepackage{tipa}")
1337 def revert_ipachar(document):
1338 ' Revert \\IPAChar to ERT '
1341 while i < len(document.body):
1342 m = re.match(r'(.*)\\IPAChar \\(\w+\{\w+\})(.*)', document.body[i])
1346 ipachar = m.group(2)
1349 '\\begin_inset ERT',
1350 'status collapsed', '',
1351 '\\begin_layout Standard',
1352 '', '', '\\backslash',
1357 document.body[i: i+1] = subst
1362 add_to_preamble(document, "\\usepackage{tone}")
1365 def revert_minionpro(document):
1366 " Revert native MinionPro font definition to LaTeX "
1368 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1369 i = find_token(document.header, "\\font_roman minionpro", 0)
1372 j = find_token(document.header, "\\font_osf true", 0)
1375 preamble = "\\usepackage"
1377 document.header[j] = "\\font_osf false"
1380 preamble += "{MinionPro}"
1381 add_to_preamble(document, [preamble])
1382 document.header[i] = "\\font_roman default"
1385 def revert_mathfonts(document):
1386 " Revert native math font definitions to LaTeX "
1388 i = find_token(document.header, "\\font_math", 0)
1391 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1392 val = get_value(document.header, "\\font_math", i)
1393 if val == "eulervm":
1394 add_to_preamble(document, "\\usepackage{eulervm}")
1395 elif val == "default":
1397 "lmodern": "\\renewcommand{\\rmdefault}{lmr}",
1398 "minionpro": "\\usepackage[onlytext,lf]{MinionPro}",
1399 "minionpro-osf": "\\usepackage[onlytext]{MinionPro}",
1400 "palatino": "\\renewcommand{\\rmdefault}{ppl}",
1401 "palatino-osf": "\\renewcommand{\\rmdefault}{pplj}",
1402 "times": "\\renewcommand{\\rmdefault}{ptm}",
1403 "utopia": "\\renewcommand{\\rmdefault}{futs}",
1404 "utopia-osf": "\\renewcommand{\\rmdefault}{futj}",
1406 j = find_token(document.header, "\\font_roman", 0)
1408 rm = get_value(document.header, "\\font_roman", j)
1409 k = find_token(document.header, "\\font_osf true", 0)
1412 if rm in list(mathfont_dict.keys()):
1413 add_to_preamble(document, mathfont_dict[rm])
1414 document.header[j] = "\\font_roman default"
1416 document.header[k] = "\\font_osf false"
1417 del document.header[i]
1420 def revert_mdnomath(document):
1421 " Revert mathdesign and fourier without math "
1423 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1425 "md-charter": "mdbch",
1426 "md-utopia": "mdput",
1427 "md-garamond": "mdugm"
1429 i = find_token(document.header, "\\font_roman", 0)
1432 val = get_value(document.header, "\\font_roman", i)
1433 if val in list(mathdesign_dict.keys()):
1434 j = find_token(document.header, "\\font_math", 0)
1436 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1437 mval = get_value(document.header, "\\font_math", j)
1438 if mval == "default":
1439 document.header[i] = "\\font_roman default"
1440 add_to_preamble(document, "\\renewcommand{\\rmdefault}{%s}" % mathdesign_dict[val])
1442 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1445 def convert_mdnomath(document):
1446 " Change mathdesign font name "
1448 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1450 "mdbch": "md-charter",
1451 "mdput": "md-utopia",
1452 "mdugm": "md-garamond"
1454 i = find_token(document.header, "\\font_roman", 0)
1457 val = get_value(document.header, "\\font_roman", i)
1458 if val in list(mathdesign_dict.keys()):
1459 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1462 def revert_newtxmath(document):
1463 " Revert native newtxmath definitions to LaTeX "
1465 i = find_token(document.header, "\\font_math", 0)
1468 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1469 val = get_value(document.header, "\\font_math", i)
1471 "libertine-ntxm": "\\usepackage[libertine]{newtxmath}",
1472 "minion-ntxm": "\\usepackage[minion]{newtxmath}",
1473 "newtxmath": "\\usepackage{newtxmath}",
1475 if val in list(mathfont_dict.keys()):
1476 add_to_preamble(document, mathfont_dict[val])
1477 document.header[i] = "\\font_math auto"
1480 def revert_biolinum(document):
1481 " Revert native biolinum font definition to LaTeX "
1483 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1484 i = find_token(document.header, "\\font_sans biolinum", 0)
1487 j = find_token(document.header, "\\font_osf true", 0)
1490 preamble = "\\usepackage"
1493 preamble += "{biolinum-type1}"
1494 add_to_preamble(document, [preamble])
1495 document.header[i] = "\\font_sans default"
1498 def revert_uop(document):
1499 " Revert native URW Classico (Optima) font definition to LaTeX "
1501 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1502 i = find_token(document.header, "\\font_sans uop", 0)
1504 preamble = "\\renewcommand{\\sfdefault}{uop}"
1505 add_to_preamble(document, [preamble])
1506 document.header[i] = "\\font_sans default"
1509 def convert_latexargs(document):
1510 " Convert InsetArgument to new syntax "
1512 if find_token(document.body, "\\begin_inset Argument", 0) == -1:
1516 # A list of layouts (document classes) with only optional or no arguments.
1517 # These can be safely converted to the new syntax
1518 # (I took the liberty to add some of my personal layouts/modules here; JSP)
1519 safe_layouts = ["aa", "aapaper", "aastex", "achemso", "acmsiggraph", "AEA",
1520 "agu-dtd", "agums", "agutex", "amsart", "amsbook", "apa",
1521 "arab-article", "armenian-article", "article-beamer", "article",
1522 "beamer", "book", "broadway", "chess", "cl2emult", "ctex-article",
1523 "ctex-book", "ctex-report", "dinbrief", "docbook-book", "docbook-chapter",
1524 "docbook", "docbook-section", "doublecol-new", "dtk", "ectaart", "egs",
1525 "elsarticle", "elsart", "entcs", "europecv", "extarticle", "extbook",
1526 "extletter", "extreport", "foils", "frletter", "g-brief2", "g-brief",
1527 "heb-article", "heb-letter", "hollywood", "IEEEtran", "ijmpc", "ijmpd",
1528 "iopart", "isprs", "jarticle", "jasatex", "jbook", "jgrga", "jreport",
1529 "jsarticle", "jsbeamer", "jsbook", "jss", "kluwer", "latex8", "letter", "lettre",
1530 "literate-article", "literate-book", "literate-report", "llncs", "ltugboat",
1531 "memoir", "moderncv", "mwart", "mwbk", "mwrep", "paper", "powerdot",
1532 "recipebook", "report", "revtex4", "revtex", "scrartcl", "scrarticle-beamer",
1533 "scrbook", "scrlettr", "scrlttr2", "scrreprt", "seminar", "siamltex",
1534 "sigplanconf", "simplecv", "singlecol", "singlecol-new", "slides", "spie",
1535 "svglobal3", "svglobal", "svjog", "svmono", "svmult", "svprobth", "tarticle",
1536 "tbook", "treport", "tufte-book", "tufte-handout"]
1537 # A list of "safe" modules, same as above
1538 safe_modules = ["biblatex", "beameraddons", "beamer-resenumerate", "beamersession", "braille",
1539 "customHeadersFooters", "endnotes", "enumitem", "eqs-within-sections", "figs-within-sections",
1540 "fix-cm", "fixltx2e", "foottoend", "hanging", "jscharstyles", "knitr", "lilypond",
1541 "linguistics", "linguisticx", "logicalmkup", "minimalistic", "nomindex", "noweb",
1542 "pdfcomment", "sweave", "tabs-within-sections", "theorems-ams-bytype",
1543 "theorems-ams-extended-bytype", "theorems-ams-extended", "theorems-ams", "theorems-bytype",
1544 "theorems-chap-bytype", "theorems-chap", "theorems-named", "theorems-sec-bytype",
1545 "theorems-sec", "theorems-starred", "theorems-std", "todonotes"]
1546 # Modules we need to take care of
1547 caveat_modules = ["initials"]
1548 # information about the relevant styles in caveat_modules (number of opt and req args)
1549 # use this if we get more caveat_modules. For now, use hard coding (see below).
1550 # initials = [{'Layout' : 'Initial', 'opt' : 1, 'req' : 1}]
1552 # Is this a known safe layout?
1553 safe_layout = document.textclass in safe_layouts
1555 document.warning("Lyx2lyx knows nothing about textclass '%s'. "
1556 "Please check if short title insets have been converted correctly."
1557 % document.textclass)
1558 # Do we use unsafe or unknown modules
1559 mods = document.get_module_list()
1560 unknown_modules = False
1561 used_caveat_modules = list()
1563 if mod in safe_modules:
1565 if mod in caveat_modules:
1566 used_caveat_modules.append(mod)
1568 unknown_modules = True
1569 document.warning("Lyx2lyx knows nothing about module '%s'. "
1570 "Please check if short title insets have been converted correctly."
1575 i = find_token(document.body, "\\begin_inset Argument", i)
1579 if not safe_layout or unknown_modules:
1580 # We cannot do more here since we have no access to this layout.
1581 # InsetArgument itself will do the real work
1582 # (see InsetArgument::updateBuffer())
1583 document.body[i] = "\\begin_inset Argument 999"
1587 # Find containing paragraph layout
1588 parent = get_containing_layout(document.body, i)
1590 document.warning("Malformed LyX document: Can't find parent paragraph layout")
1597 if len(used_caveat_modules) > 0:
1598 # We know for now that this must be the initials module with the Initial layout
1599 # If we get more such modules, we need some automating.
1600 if parent[0] == "Initial":
1601 # Layout has 1 opt and 1 req arg.
1602 # Count the actual arguments
1604 for p in range(parbeg, parend):
1605 if document.body[p] == "\\begin_inset Argument":
1610 # Collect all arguments in this paragraph
1612 for p in range(parbeg, parend):
1613 if document.body[p] == "\\begin_inset Argument":
1615 if allowed_opts != -1:
1616 # We have less arguments than opt + required.
1617 # required must take precedence.
1618 if argnr > allowed_opts and argnr < first_req:
1620 document.body[p] = "\\begin_inset Argument %d" % argnr
1624 def revert_latexargs(document):
1625 " Revert InsetArgument to old syntax "
1628 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
1631 # Search for Argument insets
1632 i = find_token(document.body, "\\begin_inset Argument", i)
1635 m = rx.match(document.body[i])
1637 # No ID: inset already reverted
1640 # Find containing paragraph layout
1641 parent = get_containing_layout(document.body, i)
1643 document.warning("Malformed LyX document: Can't find parent paragraph layout")
1648 # Do not set realparbeg to parent[3], since this does not work if we
1649 # have another inset (e.g. label or index) before the first argument
1650 # inset (this is the case in the user guide of LyX 2.0.8)
1652 # Collect all arguments in this paragraph
1654 for p in range(parbeg, parend):
1655 m = rx.match(document.body[p])
1658 # This is the first argument inset
1660 val = int(m.group(1))
1661 j = find_end_of_inset(document.body, p)
1662 # Revert to old syntax
1663 document.body[p] = "\\begin_inset Argument"
1665 document.warning("Malformed LyX document: Can't find end of Argument inset")
1668 args[val] = document.body[p : j + 1]
1670 realparend = realparend - len(document.body[p : j + 1])
1671 # Remove arg inset at this position
1672 del document.body[p : j + 1]
1676 # No argument inset found
1677 realparbeg = parent[3]
1678 # Now sort the arg insets
1680 for f in sorted(args):
1683 # Insert the sorted arg insets at paragraph begin
1684 document.body[realparbeg : realparbeg] = subst
1686 i = realparbeg + 1 + len(subst)
1689 def revert_IEEEtran(document):
1691 Reverts InsetArgument of
1694 Biography without photo
1697 if document.textclass == "IEEEtran":
1704 i = find_token(document.body, "\\begin_layout Page headings", i)
1706 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1709 i2 = find_token(document.body, "\\begin_inset Flex Paragraph Start", i2)
1711 revert_Argument_to_TeX_brace(document, i2, 0, 1, 1, False, False)
1714 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1716 revert_Argument_to_TeX_brace(document, j, 0, 1, 1, True, False)
1719 k = find_token(document.body, "\\begin_layout Biography", k)
1720 kA = find_token(document.body, "\\begin_layout Biography without photo", k)
1721 if k == kA and k != -1:
1725 # start with the second argument, therefore 2
1726 revert_Argument_to_TeX_brace(document, k, 0, 2, 2, True, False)
1728 if i == -1 and i2 == -1 and j == -1 and k == -1:
1732 def revert_IEEEtran_2(document):
1734 Reverts Flex Paragraph Start to TeX-code
1736 if document.textclass == "IEEEtran":
1739 begin = find_token(document.body, "\\begin_inset Flex Paragraph Start", begin)
1742 end1 = find_end_of_inset(document.body, begin)
1743 document.body[end1 - 2 : end1 + 1] = put_cmd_in_ert("}")
1744 document.body[begin : begin + 4] = put_cmd_in_ert("\\IEEEPARstart{")
1748 def convert_IEEEtran(document):
1753 Biography without photo
1756 if document.textclass == "IEEEtran":
1762 i = find_token(document.body, "\\begin_layout Page headings", i)
1764 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1767 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1769 convert_TeX_brace_to_Argument(document, j, 1, 1, False, True, False)
1772 # assure that we don't handle Biography Biography without photo
1773 k = find_token(document.body, "\\begin_layout Biography", k)
1774 kA = find_token(document.body, "\\begin_layout Biography without photo", k - 1)
1775 if k == kA and k != -1:
1779 # the argument we want to convert is the second one
1780 convert_TeX_brace_to_Argument(document, k, 2, 2, False, True, False)
1782 if i == -1 and j == -1 and k == -1:
1786 def revert_AASTeX(document):
1787 " Reverts InsetArgument of Altaffilation to TeX-code "
1788 if document.textclass == "aastex":
1791 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1794 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1798 def convert_AASTeX(document):
1799 " Converts ERT of Altaffilation to InsetArgument "
1800 if document.textclass == "aastex":
1803 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1806 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1810 def revert_AGUTeX(document):
1811 " Reverts InsetArgument of Author affiliation to TeX-code "
1812 if document.textclass == "agutex":
1815 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1818 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1822 def convert_AGUTeX(document):
1823 " Converts ERT of Author affiliation to InsetArgument "
1824 if document.textclass == "agutex":
1827 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1830 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1834 def revert_IJMP(document):
1835 " Reverts InsetArgument of MarkBoth to TeX-code "
1836 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1839 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1842 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1846 def convert_IJMP(document):
1847 " Converts ERT of MarkBoth to InsetArgument "
1848 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1851 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1854 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1858 def revert_SIGPLAN(document):
1859 " Reverts InsetArguments of SIGPLAN to TeX-code "
1860 if document.textclass == "sigplanconf":
1865 i = find_token(document.body, "\\begin_layout Conference", i)
1867 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1870 j = find_token(document.body, "\\begin_layout Author", j)
1872 revert_Argument_to_TeX_brace(document, j, 0, 1, 2, False, False)
1874 if i == -1 and j == -1:
1878 def convert_SIGPLAN(document):
1879 " Converts ERT of SIGPLAN to InsetArgument "
1880 if document.textclass == "sigplanconf":
1885 i = find_token(document.body, "\\begin_layout Conference", i)
1887 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1890 j = find_token(document.body, "\\begin_layout Author", j)
1892 convert_TeX_brace_to_Argument(document, j, 1, 2, False, False, False)
1894 if i == -1 and j == -1:
1898 def revert_SIGGRAPH(document):
1899 " Reverts InsetArgument of Flex CRcat to TeX-code "
1900 if document.textclass == "acmsiggraph":
1903 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1906 revert_Argument_to_TeX_brace(document, i, 0, 1, 3, False, False)
1910 def convert_SIGGRAPH(document):
1911 " Converts ERT of Flex CRcat to InsetArgument "
1912 if document.textclass == "acmsiggraph":
1915 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1918 convert_TeX_brace_to_Argument(document, i, 1, 3, True, False, False)
1922 def revert_EuropeCV(document):
1923 " Reverts InsetArguments of europeCV to TeX-code "
1924 if document.textclass == "europecv":
1931 i = find_token(document.body, "\\begin_layout Item", i)
1933 revert_Argument_to_TeX_brace(document, i, 0, 2, 2, False, False)
1936 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1938 revert_Argument_to_TeX_brace(document, j, 0, 2, 2, False, False)
1941 k = find_token(document.body, "\\begin_layout Language", k)
1943 revert_Argument_to_TeX_brace(document, k, 0, 2, 6, False, False)
1946 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1948 revert_Argument_to_TeX_brace(document, m, 0, 2, 6, False, False)
1950 if i == -1 and j == -1 and k == -1 and m == -1:
1954 def convert_EuropeCV(document):
1955 " Converts ERT of europeCV to InsetArgument "
1956 if document.textclass == "europecv":
1963 i = find_token(document.body, "\\begin_layout Item", i)
1965 convert_TeX_brace_to_Argument(document, i, 2, 2, False, False, False)
1968 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1970 convert_TeX_brace_to_Argument(document, j, 2, 2, False, False, False)
1973 k = find_token(document.body, "\\begin_layout Language", k)
1975 convert_TeX_brace_to_Argument(document, k, 2, 6, False, False, False)
1978 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1980 convert_TeX_brace_to_Argument(document, m, 2, 6, False, False, False)
1982 if i == -1 and j == -1 and k == -1 and m == -1:
1986 def revert_ModernCV(document):
1987 " Reverts InsetArguments of modernCV to TeX-code "
1988 if document.textclass == "moderncv":
1996 j = find_token(document.body, "\\begin_layout Entry", j)
1998 revert_Argument_to_TeX_brace(document, j, 0, 1, 5, False, False)
2001 k = find_token(document.body, "\\begin_layout Item", k)
2003 revert_Argument_to_TeX_brace(document, k, 0, 1, 1, False, False)
2006 m = find_token(document.body, "\\begin_layout ItemWithComment", m)
2008 revert_Argument_to_TeX_brace(document, m, 0, 1, 2, False, False)
2009 document.body[m] = document.body[m].replace("\\begin_layout ItemWithComment", "\\begin_layout Language")
2012 o = find_token(document.body, "\\begin_layout DoubleItem", o)
2014 revert_Argument_to_TeX_brace(document, o, 0, 1, 3, False, False)
2015 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout Computer")
2018 p = find_token(document.body, "\\begin_layout Social", p)
2020 revert_Argument_to_TeX_brace(document, p, 0, 1, 1, False, True)
2022 if j == -1 and k == -1 and m == -1 and o == -1 and p == -1:
2026 def revert_ModernCV_2(document):
2027 " Reverts the Flex:Column inset of modernCV to TeX-code "
2028 if document.textclass == "moderncv":
2032 flex = find_token(document.body, "\\begin_inset Flex Column", flex)
2035 flexEnd = find_end_of_inset(document.body, flex)
2036 wasOpt = revert_Argument_to_TeX_brace(document, flex, flexEnd, 1, 1, False, True)
2037 revert_Argument_to_TeX_brace(document, flex, 0, 2, 2, False, False)
2038 flexEnd = find_end_of_inset(document.body, flex)
2040 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn")
2042 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn{")
2043 document.body[flexEnd + 4 : flexEnd + 7] = put_cmd_in_ert("}")
2047 def revert_ModernCV_3(document):
2048 " Reverts the Column style of modernCV to TeX-code "
2049 if document.textclass == "moderncv":
2050 # revert the layouts
2051 revert_ModernCV(document)
2053 # get the position of the end of the last column inset
2054 LastFlexEnd = revert_ModernCV_2(document)
2056 p = find_token(document.body, "\\begin_layout Columns", p)
2059 pEnd = find_end_of_layout(document.body, p)
2060 document.body[p] = document.body[p].replace("\\begin_layout Columns", "\\begin_layout Standard")
2061 if LastFlexEnd != -1:
2062 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\begin{cvcolumns}")
2063 document.body[LastFlexEnd + 24 : LastFlexEnd + 24] = put_cmd_in_ert("\\end{cvcolumns}")
2067 def revert_ModernCV_4(document):
2068 " Reverts the style Social to TeX-code "
2069 if document.textclass == "moderncv":
2070 # revert the layouts
2071 revert_ModernCV(document)
2074 p = find_token(document.body, "\\begin_layout Social", p)
2077 pEnd = find_end_of_layout(document.body, p)
2078 document.body[p] = document.body[p].replace("\\begin_layout Social", "\\begin_layout Standard")
2079 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\social")
2080 hasOpt = find_token(document.body, "[", p + 9)
2082 document.body[p + 30 : p + 30] = put_cmd_in_ert("{")
2083 document.body[p + 41 : p + 41] = put_cmd_in_ert("}")
2085 document.body[p + 11 : p + 11] = put_cmd_in_ert("{")
2086 document.body[p + 21 : p + 21] = put_cmd_in_ert("}")
2090 def convert_ModernCV(document):
2091 " Converts ERT of modernCV to InsetArgument "
2092 if document.textclass == "moderncv":
2100 i = find_token(document.body, "\\begin_layout DoubleItem", i)
2102 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
2103 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout DoubleListItem")
2106 j = find_token(document.body, "\\begin_layout Entry", j)
2108 convert_TeX_brace_to_Argument(document, j, 1, 5, False, False, False)
2111 k = find_token(document.body, "\\begin_layout Item", k)
2113 convert_TeX_brace_to_Argument(document, k, 1, 1, False, False, False)
2116 m = find_token(document.body, "\\begin_layout Language", m)
2118 convert_TeX_brace_to_Argument(document, m, 1, 2, False, False, False)
2120 if i == -1 and j == -1 and k == -1 and m == -1:
2124 def revert_Initials(document):
2125 " Reverts InsetArgument of Initial to TeX-code "
2128 i = find_token(document.body, "\\begin_layout Initial", i)
2131 # first arg (optional) and second arg (first mandatory) are supported in LyX 2.0.x
2132 revert_Argument_to_TeX_brace(document, i, 0, 3, 3, False, False)
2136 def convert_Initials(document):
2137 " Converts ERT of Initial to InsetArgument "
2140 i = find_token(document.body, "\\begin_layout Initial", i)
2143 convert_TeX_brace_to_Argument(document, i, 3, 3, False, False, False)
2147 def revert_literate(document):
2148 " Revert Literate document to old format "
2149 if del_token(document.header, "noweb", 0):
2150 document.textclass = "literate-" + document.textclass
2153 i = find_token(document.body, "\\begin_layout Chunk", i)
2156 document.body[i] = "\\begin_layout Scrap"
2160 def convert_literate(document):
2161 " Convert Literate document to new format"
2162 i = find_token(document.header, "\\textclass", 0)
2163 if (i != -1) and "literate-" in document.header[i]:
2164 document.textclass = document.header[i].replace("\\textclass literate-", "")
2165 j = find_token(document.header, "\\begin_modules", 0)
2167 document.header.insert(j + 1, "noweb")
2169 document.header.insert(i + 1, "\\end_modules")
2170 document.header.insert(i + 1, "noweb")
2171 document.header.insert(i + 1, "\\begin_modules")
2174 i = find_token(document.body, "\\begin_layout Scrap", i)
2177 document.body[i] = "\\begin_layout Chunk"
2181 def revert_itemargs(document):
2182 " Reverts \\item arguments to TeX-code "
2185 i = find_token(document.body, "\\begin_inset Argument item:", i)
2188 j = find_end_of_inset(document.body, i)
2189 # Find containing paragraph layout
2190 parent = get_containing_layout(document.body, i)
2192 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2196 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2197 endPlain = find_end_of_layout(document.body, beginPlain)
2198 content = document.body[beginPlain + 1 : endPlain]
2199 del document.body[i:j+1]
2200 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2201 document.body[parbeg : parbeg] = subst
2205 def revert_garamondx_newtxmath(document):
2206 " Revert native garamond newtxmath definition to LaTeX "
2208 i = find_token(document.header, "\\font_math", 0)
2211 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2212 val = get_value(document.header, "\\font_math", i)
2213 if val == "garamondx-ntxm":
2214 add_to_preamble(document, "\\usepackage[garamondx]{newtxmath}")
2215 document.header[i] = "\\font_math auto"
2218 def revert_garamondx(document):
2219 " Revert native garamond font definition to LaTeX "
2221 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2222 i = find_token(document.header, "\\font_roman garamondx", 0)
2225 j = find_token(document.header, "\\font_osf true", 0)
2228 preamble = "\\usepackage"
2230 preamble += "[osfI]"
2231 preamble += "{garamondx}"
2232 add_to_preamble(document, [preamble])
2233 document.header[i] = "\\font_roman default"
2236 def convert_beamerargs(document):
2237 " Converts beamer arguments to new layout "
2239 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2240 if document.textclass not in beamer_classes:
2243 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2244 list_layouts = ["Itemize", "Enumerate", "Description"]
2245 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
2249 i = find_token(document.body, "\\begin_inset Argument", i)
2252 # Find containing paragraph layout
2253 parent = get_containing_layout(document.body, i)
2255 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2260 layoutname = parent[0]
2261 for p in range(parbeg, parend):
2262 if layoutname in shifted_layouts:
2263 m = rx.match(document.body[p])
2265 argnr = int(m.group(1))
2267 document.body[p] = "\\begin_inset Argument %d" % argnr
2268 if layoutname == "AgainFrame":
2269 m = rx.match(document.body[p])
2271 document.body[p] = "\\begin_inset Argument 3"
2272 if document.body[p + 4] == "\\begin_inset ERT":
2273 if document.body[p + 9].startswith("<"):
2274 # This is an overlay specification
2276 document.body[p + 9] = document.body[p + 9][1:]
2277 if document.body[p + 9].endswith(">"):
2279 document.body[p + 9] = document.body[p + 9][:-1]
2281 document.body[p] = "\\begin_inset Argument 2"
2282 if layoutname in list_layouts:
2283 m = rx.match(document.body[p])
2285 if m.group(1) == "1":
2286 if document.body[p + 4] == "\\begin_inset ERT":
2287 if document.body[p + 9].startswith("<"):
2288 # This is an overlay specification
2290 document.body[p + 9] = document.body[p + 9][1:]
2291 if document.body[p + 9].endswith(">"):
2293 document.body[p + 9] = document.body[p + 9][:-1]
2294 elif document.body[p + 4].startswith("<"):
2295 # This is an overlay specification (without ERT)
2297 document.body[p + 4] = document.body[p + 4][1:]
2298 if document.body[p + 4].endswith(">"):
2300 document.body[p + 4] = document.body[p + 4][:-1]
2301 elif layoutname != "Itemize":
2303 document.body[p] = "\\begin_inset Argument 2"
2308 # Helper function for the frame conversion routines
2310 # FIXME: This method currently requires the arguments to be either
2311 # * In one (whole) ERT each: <ERT>[<arg1>]</ERT><ERT><arg2></ERT><ERT>[arg3]</ERT>
2312 # * Altogether in one whole ERT: <ERT>[<arg1>]<arg2>[arg3]</ERT>
2313 # If individual arguments mix ERT and non-ERT or are splitted
2314 # over several ERTs, the parsing fails.
2315 def convert_beamerframeargs(document, i, parbeg):
2318 if document.body[parbeg] != "\\begin_inset ERT":
2320 ertend = find_end_of_inset(document.body, parbeg)
2322 document.warning("Malformed LyX document: missing ERT \\end_inset")
2324 ertcont = parbeg + 5
2325 if document.body[ertcont].startswith("[<"):
2326 # This is a default overlay specification
2328 document.body[ertcont] = document.body[ertcont][2:]
2329 if document.body[ertcont].endswith(">]"):
2331 document.body[ertcont] = document.body[ertcont][:-2]
2332 elif document.body[ertcont].endswith("]"):
2334 tok = document.body[ertcont].find('>][')
2336 subst = [document.body[ertcont][:tok],
2337 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2338 'status collapsed', '', '\\begin_layout Plain Layout',
2339 document.body[ertcont][tok + 3:-1]]
2340 document.body[ertcont : ertcont + 1] = subst
2342 # Convert to ArgInset
2343 document.body[parbeg] = "\\begin_inset Argument 2"
2344 elif document.body[ertcont].startswith("<"):
2345 # This is an overlay specification
2347 document.body[ertcont] = document.body[ertcont][1:]
2348 if document.body[ertcont].endswith(">"):
2350 document.body[ertcont] = document.body[ertcont][:-1]
2351 # Convert to ArgInset
2352 document.body[parbeg] = "\\begin_inset Argument 1"
2353 elif document.body[ertcont].endswith(">]"):
2355 tok = document.body[ertcont].find('>[<')
2357 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2358 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2359 'status collapsed', '', '\\begin_layout Plain Layout',
2360 document.body[ertcont][tok + 3:-2]]
2361 # Convert to ArgInset
2362 document.body[parbeg] = "\\begin_inset Argument 1"
2364 elif document.body[ertcont].endswith("]"):
2366 tok = document.body[ertcont].find('>[<')
2369 tokk = document.body[ertcont].find('>][')
2371 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2372 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2373 'status collapsed', '', '\\begin_layout Plain Layout',
2374 document.body[ertcont][tok + 3:tokk],
2375 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2376 'status collapsed', '', '\\begin_layout Plain Layout',
2377 document.body[ertcont][tokk + 3:-1]]
2380 tokk = document.body[ertcont].find('>[')
2382 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tokk],
2383 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2384 'status collapsed', '', '\\begin_layout Plain Layout',
2385 document.body[ertcont][tokk + 2:-1]]
2387 # Convert to ArgInset
2388 document.body[parbeg] = "\\begin_inset Argument 1"
2389 elif document.body[ertcont].startswith("["):
2390 # This is an ERT option
2392 document.body[ertcont] = document.body[ertcont][1:]
2393 if document.body[ertcont].endswith("]"):
2395 document.body[ertcont] = document.body[ertcont][:-1]
2396 # Convert to ArgInset
2397 document.body[parbeg] = "\\begin_inset Argument 3"
2403 def convert_againframe_args(document):
2404 " Converts beamer AgainFrame to new layout "
2406 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2407 if document.textclass not in beamer_classes:
2412 i = find_token(document.body, "\\begin_layout AgainFrame", i)
2415 parent = get_containing_layout(document.body, i)
2417 document.warning("Wrong parent layout!")
2421 # Convert ERT arguments
2422 # FIXME: See restrictions in convert_beamerframeargs method
2423 ertend = convert_beamerframeargs(document, i, parbeg)
2429 def convert_corollary_args(document):
2430 " Converts beamer corrolary-style ERT arguments native InsetArgs "
2432 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2433 if document.textclass not in beamer_classes:
2436 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2437 for lay in corollary_layouts:
2440 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2443 parent = get_containing_layout(document.body, i)
2445 document.warning("Wrong parent layout!")
2449 if document.body[parbeg] == "\\begin_inset ERT":
2450 ertcontfirstline = parbeg + 5
2451 # Find the last ERT in this paragraph (which might also be the first)
2452 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
2453 if lastertbeg == -1:
2454 document.warning("Last ERT not found!")
2456 lastertend = find_end_of_inset(document.body, lastertbeg)
2457 if lastertend == -1:
2458 document.warning("End of last ERT not found!")
2460 ertcontlastline = lastertend - 3
2461 if document.body[ertcontfirstline].startswith("<"):
2462 # This is an overlay specification
2464 document.body[ertcontfirstline] = document.body[ertcontfirstline][1:]
2465 if document.body[ertcontlastline].endswith(">"):
2467 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
2468 if ertcontfirstline < ertcontlastline:
2469 # Multiline ERT. Might contain TeX code. Embrace in ERT.
2470 document.body[ertcontlastline : ertcontlastline + 1] = [
2471 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
2472 document.body[ertcontfirstline : ertcontfirstline + 1] = [
2473 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
2474 'status collapsed', '', '\\begin_layout Plain Layout',
2475 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
2476 document.body[ertcontfirstline]]
2478 # Convert to ArgInset
2479 document.body[parbeg] = "\\begin_inset Argument 1"
2480 elif document.body[ertcontlastline].endswith("]"):
2482 tok = document.body[ertcontfirstline].find('>[')
2484 if ertcontfirstline < ertcontlastline:
2485 # Multiline ERT. Might contain TeX code. Embrace in ERT.
2486 document.body[ertcontlastline : ertcontlastline + 1] = [
2487 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
2488 document.body[ertcontfirstline : ertcontfirstline + 1] = [document.body[ertcontfirstline][:tok],
2489 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2490 'status collapsed', '', '\\begin_layout Plain Layout',
2491 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
2492 document.body[ertcontfirstline][tok + 2:-1]]
2494 document.body[ertcontfirstline : ertcontfirstline + 1] = [document.body[ertcontfirstline][:tok],
2495 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2496 'status collapsed', '', '\\begin_layout Plain Layout',
2497 document.body[ertcontfirstline][tok + 2:-1]]
2498 # Convert to ArgInset
2499 document.body[parbeg] = "\\begin_inset Argument 1"
2502 elif document.body[ertcontlastline].startswith("["):
2503 if document.body[ertcontlastline].endswith("]"):
2504 # This is an ERT option
2506 document.body[ertcontlastline] = document.body[ertcontlastline][1:]
2508 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
2509 # Convert to ArgInset
2510 document.body[parbeg] = "\\begin_inset Argument 2"
2512 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, True)
2519 def convert_quote_args(document):
2520 " Converts beamer quote style ERT args to native InsetArgs "
2522 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2523 if document.textclass not in beamer_classes:
2526 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2527 for lay in quote_layouts:
2530 i = find_token(document.body, "\\begin_layout " + lay, i)
2533 parent = get_containing_layout(document.body, i)
2535 document.warning("Wrong parent layout!")
2539 if document.body[parbeg] == "\\begin_inset ERT":
2540 if document.body[i + 6].startswith("<"):
2541 # This is an overlay specification
2543 document.body[i + 6] = document.body[i + 6][1:]
2544 if document.body[i + 6].endswith(">"):
2546 document.body[i + 6] = document.body[i + 6][:-1]
2547 # Convert to ArgInset
2548 document.body[i + 1] = "\\begin_inset Argument 1"
2552 def cleanup_beamerargs(document):
2553 " Clean up empty ERTs (conversion artefacts) "
2555 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2556 if document.textclass not in beamer_classes:
2561 i = find_token(document.body, "\\begin_inset Argument", i)
2564 j = find_end_of_inset(document.body, i)
2566 document.warning("Malformed LyX document: Can't find end of Argument inset")
2570 ertbeg = find_token(document.body, "\\begin_inset ERT", i, j)
2573 ertend = find_end_of_inset(document.body, ertbeg)
2575 document.warning("Malformed LyX document: Can't find end of ERT inset")
2577 stripped = [line for line in document.body[ertbeg : ertend + 1] if line.strip()]
2578 if len(stripped) == 5:
2579 # This is an empty ERT
2580 offset = len(document.body[ertbeg : ertend + 1])
2581 del document.body[ertbeg : ertend + 1]
2588 def revert_beamerargs(document):
2589 " Reverts beamer arguments to old layout "
2591 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2592 if document.textclass not in beamer_classes:
2596 list_layouts = ["Itemize", "Enumerate", "Description"]
2597 headings = ["Part", "Section", "Section*", "Subsection", "Subsection*",
2598 "Subsubsection", "Subsubsection*", "FrameSubtitle", "NoteItem"]
2599 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2600 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2601 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2604 i = find_token(document.body, "\\begin_inset Argument", i)
2607 # Find containing paragraph layout
2608 parent = get_containing_layout(document.body, i)
2610 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2615 realparbeg = parent[3]
2616 layoutname = parent[0]
2618 for p in range(parbeg, parend):
2622 if layoutname in headings:
2623 m = rx.match(document.body[p])
2627 # Find containing paragraph layout
2628 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2629 endPlain = find_end_of_layout(document.body, beginPlain)
2630 endInset = find_end_of_inset(document.body, p)
2631 argcontent = document.body[beginPlain + 1 : endPlain]
2633 realparend = realparend - len(document.body[p : endInset + 1])
2635 del document.body[p : endInset + 1]
2636 if layoutname == "FrameSubtitle":
2637 pre = put_cmd_in_ert("\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2638 elif layoutname == "NoteItem":
2639 pre = put_cmd_in_ert("\\note<") + argcontent + put_cmd_in_ert(">[item]")
2640 elif layoutname.endswith('*'):
2641 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower()[:-1] + "<") + argcontent + put_cmd_in_ert(">*")
2643 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2644 secarg = find_token(document.body, "\\begin_inset Argument 2", parbeg, parend)
2646 # Find containing paragraph layout
2647 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", secarg)
2648 endPlain = find_end_of_layout(document.body, beginPlain)
2649 endInset = find_end_of_inset(document.body, secarg)
2650 argcontent = document.body[beginPlain + 1 : endPlain]
2652 realparend = realparend - len(document.body[secarg : endInset + 1])
2653 del document.body[secarg : endInset + 1]
2654 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2655 pre += put_cmd_in_ert("{")
2656 document.body[parbeg] = "\\begin_layout Standard"
2657 document.body[realparbeg : realparbeg] = pre
2658 pe = find_end_of_layout(document.body, parbeg)
2659 post = put_cmd_in_ert("}")
2660 document.body[pe : pe] = post
2661 realparend += len(pre) + len(post)
2662 if layoutname == "AgainFrame":
2663 m = rx.match(document.body[p])
2667 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2668 endPlain = find_end_of_layout(document.body, beginPlain)
2669 endInset = find_end_of_inset(document.body, p)
2670 content = document.body[beginPlain + 1 : endPlain]
2672 realparend = realparend - len(document.body[p : endInset + 1])
2674 del document.body[p : endInset + 1]
2675 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2676 document.body[realparbeg : realparbeg] = subst
2677 if layoutname == "Overprint":
2678 m = rx.match(document.body[p])
2682 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2683 endPlain = find_end_of_layout(document.body, beginPlain)
2684 endInset = find_end_of_inset(document.body, p)
2685 content = document.body[beginPlain + 1 : endPlain]
2687 realparend = realparend - len(document.body[p : endInset + 1])
2689 del document.body[p : endInset + 1]
2690 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2691 document.body[realparbeg : realparbeg] = subst
2692 if layoutname == "OverlayArea":
2693 m = rx.match(document.body[p])
2697 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2698 endPlain = find_end_of_layout(document.body, beginPlain)
2699 endInset = find_end_of_inset(document.body, p)
2700 content = document.body[beginPlain + 1 : endPlain]
2702 realparend = realparend - len(document.body[p : endInset + 1])
2704 del document.body[p : endInset + 1]
2705 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2706 document.body[realparbeg : realparbeg] = subst
2707 if layoutname in list_layouts:
2708 m = rx.match(document.body[p])
2712 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2713 endPlain = find_end_of_layout(document.body, beginPlain)
2714 endInset = find_end_of_inset(document.body, p)
2715 content = document.body[beginPlain + 1 : endPlain]
2716 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2717 realparend = realparend + len(subst) - len(content)
2718 document.body[beginPlain + 1 : endPlain] = subst
2719 elif argnr == "item:1":
2720 j = find_end_of_inset(document.body, i)
2721 # Find containing paragraph layout
2722 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2723 endPlain = find_end_of_layout(document.body, beginPlain)
2724 content = document.body[beginPlain + 1 : endPlain]
2725 del document.body[i:j+1]
2726 if layoutname == "Description":
2727 # Description only has one (overlay) item arg
2728 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2729 # This must be put after the first space (begin of decription body
2730 # in LyX's arkward description list syntax)
2731 # Try to find that place ...
2732 rxx = re.compile(r'^([^\\ ]+ )(.*)$')
2733 for q in range(parbeg, parend):
2734 m = rxx.match(document.body[q])
2736 # We found it. Now insert the ERT argument just there:
2737 document.body[q : q] = [m.group(1), ''] + subst + ['', m.group(2)]
2740 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2741 document.body[realparbeg : realparbeg] = subst
2742 elif argnr == "item:2":
2743 j = find_end_of_inset(document.body, i)
2744 # Find containing paragraph layout
2745 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2746 endPlain = find_end_of_layout(document.body, beginPlain)
2747 content = document.body[beginPlain + 1 : endPlain]
2748 del document.body[i:j+1]
2749 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2750 document.body[realparbeg : realparbeg] = subst
2751 if layoutname in quote_layouts:
2752 m = rx.match(document.body[p])
2756 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2757 endPlain = find_end_of_layout(document.body, beginPlain)
2758 endInset = find_end_of_inset(document.body, p)
2759 content = document.body[beginPlain + 1 : endPlain]
2761 realparend = realparend - len(document.body[p : endInset + 1])
2763 del document.body[p : endInset + 1]
2764 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2765 document.body[realparbeg : realparbeg] = subst
2766 if layoutname in corollary_layouts:
2767 m = rx.match(document.body[p])
2771 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2772 endPlain = find_end_of_layout(document.body, beginPlain)
2773 endInset = find_end_of_inset(document.body, p)
2774 content = document.body[beginPlain + 1 : endPlain]
2776 realparend = realparend - len(document.body[p : endInset + 1])
2778 del document.body[p : endInset + 1]
2779 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2780 document.body[realparbeg : realparbeg] = subst
2785 def revert_beamerargs2(document):
2786 " Reverts beamer arguments to old layout, step 2 "
2788 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2789 if document.textclass not in beamer_classes:
2793 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2794 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2795 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2798 i = find_token(document.body, "\\begin_inset Argument", i)
2801 # Find containing paragraph layout
2802 parent = get_containing_layout(document.body, i)
2804 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2809 realparbeg = parent[3]
2810 layoutname = parent[0]
2812 for p in range(parbeg, parend):
2816 if layoutname in shifted_layouts:
2817 m = rx.match(document.body[p])
2821 document.body[p] = "\\begin_inset Argument 1"
2822 if layoutname in corollary_layouts:
2823 m = rx.match(document.body[p])
2827 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2828 endPlain = find_end_of_layout(document.body, beginPlain)
2829 endInset = find_end_of_inset(document.body, p)
2830 content = document.body[beginPlain + 1 : endPlain]
2832 realparend = realparend - len(document.body[p : endInset + 1])
2834 del document.body[p : endInset + 1]
2835 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2836 document.body[realparbeg : realparbeg] = subst
2837 if layoutname == "OverlayArea":
2838 m = rx.match(document.body[p])
2842 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2843 endPlain = find_end_of_layout(document.body, beginPlain)
2844 endInset = find_end_of_inset(document.body, p)
2845 content = document.body[beginPlain + 1 : endPlain]
2847 realparend = realparend - len(document.body[p : endInset + 1])
2849 del document.body[p : endInset + 1]
2850 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2851 document.body[realparbeg : realparbeg] = subst
2852 if layoutname == "AgainFrame":
2853 m = rx.match(document.body[p])
2857 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2858 endPlain = find_end_of_layout(document.body, beginPlain)
2859 endInset = find_end_of_inset(document.body, p)
2860 content = document.body[beginPlain + 1 : endPlain]
2862 realparend = realparend - len(document.body[p : endInset + 1])
2864 del document.body[p : endInset + 1]
2865 subst = put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
2866 document.body[realparbeg : realparbeg] = subst
2870 def revert_beamerargs3(document):
2871 " Reverts beamer arguments to old layout, step 3 "
2873 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2874 if document.textclass not in beamer_classes:
2877 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2880 i = find_token(document.body, "\\begin_inset Argument", i)
2883 # Find containing paragraph layout
2884 parent = get_containing_layout(document.body, i)
2886 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2891 realparbeg = parent[3]
2892 layoutname = parent[0]
2894 for p in range(parbeg, parend):
2898 if layoutname == "AgainFrame":
2899 m = rx.match(document.body[p])
2903 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2904 endPlain = find_end_of_layout(document.body, beginPlain)
2905 endInset = find_end_of_inset(document.body, p)
2906 content = document.body[beginPlain + 1 : endPlain]
2908 realparend = realparend - len(document.body[p : endInset + 1])
2910 del document.body[p : endInset + 1]
2911 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2912 document.body[realparbeg : realparbeg] = subst
2916 def revert_beamerflex(document):
2917 " Reverts beamer Flex insets "
2919 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2920 if document.textclass not in beamer_classes:
2923 new_flexes = {"Bold" : "\\textbf", "Emphasize" : "\\emph", "Only" : "\\only",
2924 "Uncover" : "\\uncover", "Visible" : "\\visible",
2925 "Invisible" : "\\invisible", "Alternative" : "\\alt",
2926 "Beamer_Note" : "\\note"}
2927 old_flexes = {"Alert" : "\\alert", "Structure" : "\\structure"}
2928 rx = re.compile(r'^\\begin_inset Flex (.+)$')
2932 i = find_token(document.body, "\\begin_inset Flex", i)
2935 m = rx.match(document.body[i])
2937 flextype = m.group(1)
2938 z = find_end_of_inset(document.body, i)
2940 document.warning("Can't find end of Flex " + flextype + " inset.")
2943 if flextype in new_flexes:
2944 pre = put_cmd_in_ert(new_flexes[flextype])
2945 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2947 argend = find_end_of_inset(document.body, arg)
2949 document.warning("Can't find end of Argument!")
2952 # Find containing paragraph layout
2953 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2954 endPlain = find_end_of_layout(document.body, beginPlain)
2955 argcontent = document.body[beginPlain + 1 : endPlain]
2957 z = z - len(document.body[arg : argend + 1])
2959 del document.body[arg : argend + 1]
2960 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2961 arg = find_token(document.body, "\\begin_inset Argument 2", i, z)
2963 argend = find_end_of_inset(document.body, arg)
2965 document.warning("Can't find end of Argument!")
2968 # Find containing paragraph layout
2969 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2970 endPlain = find_end_of_layout(document.body, beginPlain)
2971 argcontent = document.body[beginPlain + 1 : endPlain]
2973 z = z - len(document.body[arg : argend + 1])
2975 del document.body[arg : argend + 1]
2976 if flextype == "Alternative":
2977 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
2979 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2980 pre += put_cmd_in_ert("{")
2981 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2982 endPlain = find_end_of_layout(document.body, beginPlain)
2984 z = z - len(document.body[i : beginPlain + 1])
2986 document.body[i : beginPlain + 1] = pre
2987 post = put_cmd_in_ert("}")
2988 document.body[z - 2 : z + 1] = post
2989 elif flextype in old_flexes:
2990 pre = put_cmd_in_ert(old_flexes[flextype])
2991 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2995 argend = find_end_of_inset(document.body, arg)
2997 document.warning("Can't find end of Argument!")
3000 # Find containing paragraph layout
3001 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3002 endPlain = find_end_of_layout(document.body, beginPlain)
3003 argcontent = document.body[beginPlain + 1 : endPlain]
3005 z = z - len(document.body[arg : argend + 1])
3007 del document.body[arg : argend + 1]
3008 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
3009 pre += put_cmd_in_ert("{")
3010 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
3011 endPlain = find_end_of_layout(document.body, beginPlain)
3013 z = z - len(document.body[i : beginPlain + 1])
3015 document.body[i : beginPlain + 1] = pre
3016 post = put_cmd_in_ert("}")
3017 document.body[z - 2 : z + 1] = post
3022 def revert_beamerblocks(document):
3023 " Reverts beamer block arguments to ERT "
3025 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3026 if document.textclass not in beamer_classes:
3029 blocks = ["Block", "ExampleBlock", "AlertBlock"]
3031 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3034 i = find_token(document.body, "\\begin_inset Argument", i)
3037 # Find containing paragraph layout
3038 parent = get_containing_layout(document.body, i)
3040 document.warning("Malformed LyX document: Can't find parent paragraph layout")
3045 realparbeg = parent[3]
3046 layoutname = parent[0]
3048 for p in range(parbeg, parend):
3052 if layoutname in blocks:
3053 m = rx.match(document.body[p])
3057 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3058 endPlain = find_end_of_layout(document.body, beginPlain)
3059 endInset = find_end_of_inset(document.body, p)
3060 content = document.body[beginPlain + 1 : endPlain]
3062 realparend = realparend - len(document.body[p : endInset + 1])
3064 del document.body[p : endInset + 1]
3065 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3066 document.body[realparbeg : realparbeg] = subst
3068 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3069 endPlain = find_end_of_layout(document.body, beginPlain)
3070 endInset = find_end_of_inset(document.body, p)
3071 content = document.body[beginPlain + 1 : endPlain]
3073 realparend = realparend - len(document.body[p : endInset + 1])
3075 del document.body[p : endInset + 1]
3076 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3077 document.body[realparbeg : realparbeg] = subst
3082 def convert_beamerblocks(document):
3083 " Converts beamer block ERT args to native InsetArgs "
3085 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3086 if document.textclass not in beamer_classes:
3089 blocks = ["Block", "ExampleBlock", "AlertBlock"]
3093 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
3096 parent = get_containing_layout(document.body, i)
3097 if parent == False or parent[1] != i:
3098 document.warning("Wrong parent layout!")
3105 # If the paragraph starts with a language switch, adjust parbeg
3106 if len(document.body[parbeg]) == 0 and parbeg < parend \
3107 and document.body[parbeg + 1].startswith("\\lang"):
3109 if document.body[parbeg] == "\\begin_inset ERT":
3110 ertcontfirstline = parbeg + 5
3114 # Find the last ERT in this paragraph used for arguments
3115 # (which might also be the first)
3116 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
3117 if lastertbeg == -1:
3118 document.warning("Last ERT not found!")
3120 lastertend = find_end_of_inset(document.body, lastertbeg)
3121 if lastertend == -1:
3122 document.warning("End of last ERT not found!")
3124 # Is this ERT really used for an argument?
3125 # Note: This will fail when non-argument ERTs actually use brackets
3127 regexp = re.compile(r'.*[>\]\}]', re.IGNORECASE)
3128 cbracket = find_re(document.body, regexp, lastertbeg, lastertend)
3131 if lastertbeg == parbeg:
3134 if lastertbeg == -1 or lastertend == -1:
3136 ertcontlastline = lastertend - 3
3138 if document.body[ertcontfirstline].lstrip().startswith("<"):
3139 # This is an overlay specification
3141 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3142 if document.body[ertcontlastline].rstrip().endswith(">"):
3144 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3145 # Convert to ArgInset
3146 document.body[parbeg] = "\\begin_inset Argument 1"
3147 elif document.body[ertcontlastline].rstrip().endswith("}"):
3149 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3151 ertcontdivline = ertcontfirstline
3152 tok = document.body[ertcontdivline].find('>{')
3154 regexp = re.compile(r'.*>\{', re.IGNORECASE)
3155 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3156 tok = document.body[ertcontdivline].find('>{')
3158 if ertcontfirstline < ertcontlastline:
3159 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3160 document.body[ertcontlastline : ertcontlastline + 1] = [
3161 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3162 if ertcontdivline == ertcontfirstline:
3163 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3164 '\\end_layout', '', '\\end_inset', '',
3165 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3166 'status collapsed', '', '\\begin_layout Plain Layout',
3167 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3168 document.body[ertcontdivline][tok + 2:]]
3170 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3171 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3172 'status collapsed', '', '\\begin_layout Plain Layout',
3173 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3174 document.body[ertcontdivline][tok + 2:]]
3176 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3177 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3178 'status collapsed', '', '\\begin_layout Plain Layout',
3179 document.body[ertcontdivline][tok + 2:]]
3181 # check if have delimiters in two different ERTs
3182 tok = document.body[ertcontdivline].find('>')
3184 regexp = re.compile(r'.*>', re.IGNORECASE)
3185 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3186 tok = document.body[ertcontdivline].find('>')
3188 tokk = document.body[ertcontdivline].find('{')
3190 regexp = re.compile(r'.*\{', re.IGNORECASE)
3191 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, lastertend)
3192 tokk = document.body[ertcontdivlinetwo].find('{')
3194 if ertcontfirstline < ertcontlastline:
3195 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3196 document.body[ertcontlastline : ertcontlastline + 1] = [
3197 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3198 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3199 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3200 '\\end_inset', '', '', '\\begin_inset Argument 2',
3201 'status collapsed', '', '\\begin_layout Plain Layout',
3202 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3203 document.body[ertcontdivlinetwo][tokk + 1:]]
3205 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3206 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3207 'status collapsed', '', '\\begin_layout Plain Layout',
3208 document.body[ertcontdivlinetwo][tokk + 1:]]
3209 # Convert to ArgInset
3210 if ertcontfirstline < ertcontlastline:
3211 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3212 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 1',
3213 'status collapsed', '', '\\begin_layout Plain Layout',
3214 '\\begin_inset ERT', '']
3216 document.body[parbeg] = "\\begin_inset Argument 1"
3217 elif document.body[ertcontfirstline].lstrip().startswith("{"):
3218 # This is the block title
3219 if document.body[ertcontlastline].rstrip().endswith("}"):
3220 # strip off the braces
3221 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3222 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3223 if ertcontfirstline < ertcontlastline:
3224 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3225 document.body[parend : parend + 1] = [
3226 document.body[parend], '\\end_inset', '', '\\end_layout']
3227 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3228 'status collapsed', '', '\\begin_layout Plain Layout',
3229 '\\begin_inset ERT', '']
3231 # Convert to ArgInset
3232 document.body[parbeg] = "\\begin_inset Argument 2"
3233 # the overlay argument can also follow the title, so ...
3234 elif document.body[ertcontlastline].rstrip().endswith(">"):
3236 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3238 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3240 ertcontdivline = ertcontfirstline
3241 tok = document.body[ertcontdivline].find('}<')
3243 regexp = re.compile(r'.*\}<', re.IGNORECASE)
3244 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3245 tok = document.body[ertcontdivline].find('}<')
3247 if ertcontfirstline < ertcontlastline:
3248 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3249 document.body[ertcontlastline : ertcontlastline + 1] = [
3250 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3251 if ertcontdivline == ertcontfirstline:
3252 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3253 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3254 'status collapsed', '', '\\begin_layout Plain Layout',
3255 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3256 document.body[ertcontdivline][tok + 2:]]
3258 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3259 '\\end_layout', '', '\\end_inset', '',
3260 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3261 'status collapsed', '', '\\begin_layout Plain Layout',
3262 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3263 document.body[ertcontdivline][tok + 2:]]
3265 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3266 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3267 'status collapsed', '', '\\begin_layout Plain Layout',
3268 document.body[ertcontdivline][tok + 2:]]
3270 # check if have delimiters in two different ERTs
3271 tok = document.body[ertcontdivline].find('}')
3273 regexp = re.compile(r'.*\}', re.IGNORECASE)
3274 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3275 tok = document.body[ertcontdivline].find('}')
3277 tokk = document.body[ertcontdivline].find('<')
3279 regexp = re.compile(r'.*<', re.IGNORECASE)
3280 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, lastertend)
3281 tokk = document.body[ertcontdivlinetwo].find('<')
3283 if ertcontfirstline < ertcontlastline:
3284 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3285 document.body[ertcontlastline : ertcontlastline + 1] = [
3286 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3287 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3288 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3289 '\\end_inset', '', '', '\\begin_inset Argument 1',
3290 'status collapsed', '', '\\begin_layout Plain Layout',
3291 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3292 document.body[ertcontdivlinetwo][tokk + 1:]]
3294 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3295 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3296 'status collapsed', '', '\\begin_layout Plain Layout',
3297 document.body[ertcontdivlinetwo][tokk + 1:]]
3298 # Convert to ArgInset
3299 if ertcontfirstline < ertcontlastline:
3300 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3301 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3302 'status collapsed', '', '\\begin_layout Plain Layout',
3303 '\\begin_inset ERT', '']
3305 document.body[parbeg] = "\\begin_inset Argument 2"
3306 elif count_pars_in_inset(document.body, ertcontfirstline) > 1:
3307 # Multipar ERT. Skip this.
3310 # ERT has contents after the closing bracket. We cannot convert this.
3311 # convert_TeX_brace_to_Argument cannot either.
3312 #convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, False)
3316 j = find_end_of_layout(document.body, i)
3318 document.warning("end of layout not found!")
3319 k = find_token(document.body, "\\begin_inset Argument", i, j)
3321 document.warning("InsetArgument not found!")
3323 l = find_end_of_inset(document.body, k)
3324 m = find_token(document.body, "\\begin_inset ERT", l, j)
3327 ertcontfirstline = m + 5
3332 def convert_overprint(document):
3333 " Convert old beamer overprint layouts to ERT "
3335 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3336 if document.textclass not in beamer_classes:
3341 i = find_token(document.body, "\\begin_layout Overprint", i)
3344 # Find end of sequence
3345 j = find_end_of_sequence(document.body, i)
3347 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3351 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3353 if document.body[j] == "\\end_deeper":
3354 esubst = ["", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3356 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3357 endseq = endseq + len(esubst) - len(document.body[j : j])
3358 document.body[j : j] = esubst
3359 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3361 argend = find_end_of_layout(document.body, argbeg)
3363 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3366 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3367 endPlain = find_end_of_layout(document.body, beginPlain)
3368 content = document.body[beginPlain + 1 : endPlain]
3370 endseq = endseq - len(document.body[argbeg : argend + 1])
3372 del document.body[argbeg : argend + 1]
3373 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3375 endseq = endseq - len(document.body[i : i])
3376 document.body[i : i] = subst + ["\\end_layout"]
3377 endseq += len(subst)
3379 for p in range(i, endseq):
3380 if document.body[p] == "\\begin_layout Overprint":
3381 document.body[p] = "\\begin_layout Standard"
3386 def revert_overprint(document):
3387 " Revert old beamer overprint layouts to ERT "
3389 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3390 if document.textclass not in beamer_classes:
3395 i = find_token(document.body, "\\begin_layout Overprint", i)
3398 # Find end of sequence
3399 j = find_end_of_sequence(document.body, i)
3401 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3405 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3406 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}")
3407 endseq = endseq + len(esubst) - len(document.body[j : j])
3408 if document.body[j] == "\\end_deeper":
3409 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3411 document.body[j : j] = ["\\end_layout", ""] + esubst
3414 if document.body[r] == "\\begin_deeper":
3415 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3417 document.body[r] = ""
3418 document.body[s] = ""
3422 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3424 # Is this really our argument?
3425 nested = find_token(document.body, "\\begin_deeper", i, argbeg)
3427 argend = find_end_of_inset(document.body, argbeg)
3429 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3432 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3433 endPlain = find_end_of_layout(document.body, beginPlain)
3434 content = document.body[beginPlain + 1 : endPlain]
3436 endseq = endseq - len(document.body[argbeg : argend])
3438 del document.body[argbeg : argend + 1]
3439 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3441 endseq = endseq - len(document.body[i : i])
3442 document.body[i : i] = subst + ["\\end_layout"]
3443 endseq += len(subst)
3449 if document.body[p] == "\\begin_layout Overprint":
3450 q = find_end_of_layout(document.body, p)
3452 document.warning("Malformed LyX document. Cannot find end of Overprint layout!")
3455 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\onslide")
3456 argbeg = find_token(document.body, "\\begin_inset Argument item:1", p, q)
3458 argend = find_end_of_inset(document.body, argbeg)
3460 document.warning("Malformed LyX document. Cannot find end of Overprint item argument!")
3463 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3464 endPlain = find_end_of_layout(document.body, beginPlain)
3465 content = document.body[beginPlain + 1 : endPlain]
3467 endseq = endseq - len(document.body[argbeg : argend + 1])
3469 del document.body[argbeg : argend + 1]
3470 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3471 endseq = endseq - len(document.body[p : p + 1]) + len(subst)
3472 document.body[p : p + 1] = subst
3478 def revert_frametitle(document):
3479 " Reverts beamer frametitle layout to ERT "
3481 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3482 if document.textclass not in beamer_classes:
3485 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3488 i = find_token(document.body, "\\begin_layout FrameTitle", i)
3491 j = find_end_of_layout(document.body, i)
3493 document.warning("Malformed LyX document: Can't find end of FrameTitle layout")
3497 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
3498 endlay += len(put_cmd_in_ert("}"))
3499 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\frametitle")
3500 for p in range(i, j):
3503 m = rx.match(document.body[p])
3507 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3508 endPlain = find_end_of_layout(document.body, beginPlain)
3509 endInset = find_end_of_inset(document.body, p)
3510 content = document.body[beginPlain + 1 : endPlain]
3512 endlay = endlay - len(document.body[p : endInset + 1])
3514 del document.body[p : endInset + 1]
3515 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3517 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3518 endPlain = find_end_of_layout(document.body, beginPlain)
3519 endInset = find_end_of_inset(document.body, p)
3520 content = document.body[beginPlain + 1 : endPlain]
3522 endlay = endlay - len(document.body[p : endInset + 1])
3524 del document.body[p : endInset + 1]
3525 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3527 subst += put_cmd_in_ert("{")
3528 document.body[i : i + 1] = subst
3532 def convert_epigraph(document):
3533 " Converts memoir epigraph to new syntax "
3535 if document.textclass != "memoir":
3540 i = find_token(document.body, "\\begin_layout Epigraph", i)
3543 j = find_end_of_layout(document.body, i)
3545 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3550 ert = find_token(document.body, "\\begin_inset ERT", i, j)
3552 endInset = find_end_of_inset(document.body, ert)
3553 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", ert)
3554 endPlain = find_end_of_layout(document.body, beginPlain)
3555 ertcont = beginPlain + 2
3556 if document.body[ertcont] == "}{":
3558 # Convert to ArgInset
3559 endlay = endlay - 2 * len(document.body[j])
3560 begsubst = ['\\begin_inset Argument post:1', 'status collapsed', '',
3561 '\\begin_layout Plain Layout']
3562 endsubst = ['\\end_layout', '', '\\end_inset', '', document.body[j]]
3563 document.body[j : j + 1] = endsubst
3564 document.body[endInset + 1 : endInset + 1] = begsubst
3566 endlay += len(begsubst) + len(endsubst)
3567 endlay = endlay - len(document.body[ert : endInset + 1])
3568 del document.body[ert : endInset + 1]
3573 def revert_epigraph(document):
3574 " Reverts memoir epigraph argument to ERT "
3576 if document.textclass != "memoir":
3581 i = find_token(document.body, "\\begin_layout Epigraph", i)
3584 j = find_end_of_layout(document.body, i)
3586 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3591 p = find_token(document.body, "\\begin_layout Argument post:1", i, j)
3593 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3594 endPlain = find_end_of_layout(document.body, beginPlain)
3595 endInset = find_end_of_inset(document.body, p)
3596 content = document.body[beginPlain + 1 : endPlain]
3598 endlay = endlay - len(document.body[p : endInset + 1])
3600 del document.body[p : endInset + 1]
3601 subst += put_cmd_in_ert("}{") + content
3603 subst += put_cmd_in_ert("}{")
3605 document.body[j : j] = subst + document.body[j : j]
3609 def convert_captioninsets(document):
3610 " Converts caption insets to new syntax "
3614 i = find_token(document.body, "\\begin_inset Caption", i)
3617 document.body[i] = "\\begin_inset Caption Standard"
3621 def revert_captioninsets(document):
3622 " Reverts caption insets to old syntax "
3626 i = find_token(document.body, "\\begin_inset Caption Standard", i)
3629 document.body[i] = "\\begin_inset Caption"
3633 def convert_captionlayouts(document):
3634 " Convert caption layouts to caption insets. "
3637 "Captionabove": "Above",
3638 "Captionbelow": "Below",
3639 "FigCaption" : "FigCaption",
3640 "Table_Caption" : "Table",
3641 "CenteredCaption" : "Centered",
3642 "Bicaption" : "Bicaption",
3647 i = find_token(document.body, "\\begin_layout", i)
3650 val = get_value(document.body, "\\begin_layout", i)
3651 if val in list(caption_dict.keys()):
3652 j = find_end_of_layout(document.body, i)
3654 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3657 document.body[j:j] = ["\\end_layout", "", "\\end_inset", "", ""]
3658 document.body[i:i+1] = ["\\begin_layout %s" % document.default_layout,
3659 "\\begin_inset Caption %s" % caption_dict[val], "",
3660 "\\begin_layout %s" % document.default_layout]
3664 def revert_captionlayouts(document):
3665 " Revert caption insets to caption layouts. "
3668 "Above" : "Captionabove",
3669 "Below" : "Captionbelow",
3670 "FigCaption" : "FigCaption",
3671 "Table" : "Table_Caption",
3672 "Centered" : "CenteredCaption",
3673 "Bicaption" : "Bicaption",
3677 rx = re.compile(r'^\\begin_inset Caption (\S+)$')
3679 i = find_token(document.body, "\\begin_inset Caption", i)
3683 m = rx.match(document.body[i])
3687 if val not in list(caption_dict.keys()):
3691 # We either need to delete the previous \begin_layout line, or we
3692 # need to end the previous layout if this inset is not in the first
3693 # position of the paragraph.
3694 layout_before = find_token_backwards(document.body, "\\begin_layout", i)
3695 if layout_before == -1:
3696 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3698 layout_line = document.body[layout_before]
3699 del_layout_before = True
3700 l = layout_before + 1
3702 if document.body[l] != "":
3703 del_layout_before = False
3706 if del_layout_before:
3707 del document.body[layout_before:i]
3710 document.body[i:i] = ["\\end_layout", ""]
3713 # Find start of layout in the inset and end of inset
3714 j = find_token(document.body, "\\begin_layout", i)
3716 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3718 k = find_end_of_inset(document.body, i)
3720 document.warning("Malformed LyX document: Missing `\\end_inset'.")
3723 # We either need to delete the following \end_layout line, or we need
3724 # to restart the old layout if this inset is not at the paragraph end.
3725 layout_after = find_token(document.body, "\\end_layout", k)
3726 if layout_after == -1:
3727 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3729 del_layout_after = True
3731 while l < layout_after:
3732 if document.body[l] != "":
3733 del_layout_after = False
3736 if del_layout_after:
3737 del document.body[k+1:layout_after+1]
3739 document.body[k+1:k+1] = [layout_line, ""]
3741 # delete \begin_layout and \end_inset and replace \begin_inset with
3742 # "\begin_layout XXX". This works because we can only have one
3743 # paragraph in the caption inset: The old \end_layout will be recycled.
3744 del document.body[k]
3745 if document.body[k] == "":
3746 del document.body[k]
3747 del document.body[j]
3748 if document.body[j] == "":
3749 del document.body[j]
3750 document.body[i] = "\\begin_layout %s" % caption_dict[val]
3751 if document.body[i+1] == "":
3752 del document.body[i+1]
3756 def revert_fragileframe(document):
3757 " Reverts beamer FragileFrame layout to ERT "
3759 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3760 if document.textclass not in beamer_classes:
3765 i = find_token(document.body, "\\begin_layout FragileFrame", i)
3768 # Find end of sequence
3769 j = find_end_of_sequence(document.body, i)
3771 document.warning("Malformed LyX document. Cannot find end of FragileFrame sequence!")
3775 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{frame}")
3776 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{frame}")
3777 endseq = endseq + len(esubst) - len(document.body[j : j])
3778 if document.body[j] == "\\end_deeper":
3779 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3781 document.body[j : j] = esubst
3782 for q in range(i, j):
3783 if document.body[q] == "\\begin_layout FragileFrame":
3784 document.body[q] = "\\begin_layout %s" % document.default_layout
3787 if document.body[r] == "\\begin_deeper":
3788 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3790 document.body[r] = ""
3791 document.body[s] = ""
3795 for p in range(1, 5):
3796 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, j)
3799 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3800 endPlain = find_end_of_layout(document.body, beginPlain)
3801 endInset = find_end_of_inset(document.body, arg)
3802 content = document.body[beginPlain + 1 : endPlain]
3804 j = j - len(document.body[arg : endInset + 1])
3806 del document.body[arg : endInset + 1]
3807 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3809 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3810 endPlain = find_end_of_layout(document.body, beginPlain)
3811 endInset = find_end_of_inset(document.body, arg)
3812 content = document.body[beginPlain + 1 : endPlain]
3814 j = j - len(document.body[arg : endInset + 1])
3816 del document.body[arg : endInset + 1]
3817 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3819 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3820 endPlain = find_end_of_layout(document.body, beginPlain)
3821 endInset = find_end_of_inset(document.body, arg)
3822 content = document.body[beginPlain + 1 : endPlain]
3824 j = j - len(document.body[arg : endInset + 1])
3826 del document.body[arg : endInset + 1]
3827 subst += put_cmd_in_ert("[fragile,") + content + put_cmd_in_ert("]")
3829 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3830 endPlain = find_end_of_layout(document.body, beginPlain)
3831 endInset = find_end_of_inset(document.body, arg)
3832 content = document.body[beginPlain + 1 : endPlain]
3834 j = j - len(document.body[arg : endInset + 1])
3836 del document.body[arg : endInset + 1]
3837 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3839 subst += put_cmd_in_ert("[fragile]")
3841 document.body[i : i + 1] = subst
3845 def revert_newframes(document):
3846 " Reverts beamer Frame and PlainFrame layouts to old forms "
3848 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3849 if document.textclass not in beamer_classes:
3853 "Frame" : "BeginFrame",
3854 "PlainFrame" : "BeginPlainFrame",
3857 rx = re.compile(r'^\\begin_layout (\S+)$')
3860 i = find_token(document.body, "\\begin_layout", i)
3864 m = rx.match(document.body[i])
3868 if val not in list(frame_dict.keys()):
3871 # Find end of sequence
3872 j = find_end_of_sequence(document.body, i)
3874 document.warning("Malformed LyX document. Cannot find end of Frame sequence!")
3878 subst = ["\\begin_layout %s" % frame_dict[val]]
3879 esubst = ["", "\\begin_layout EndFrame", "", "\\end_layout"]
3880 endseq = endseq + len(esubst) - len(document.body[j : j])
3881 if document.body[j] == "\\end_deeper":
3882 document.body[j : j] = esubst
3884 document.body[j+1 : j+1] = esubst
3885 for q in range(i, j):
3886 if document.body[q] == "\\begin_layout %s" % val:
3887 document.body[q] = "\\begin_layout %s" % document.default_layout
3890 if document.body[r] == "\\begin_deeper":
3891 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3893 document.body[r] = ""
3894 document.body[s] = ""
3898 l = find_end_of_layout(document.body, i)
3899 for p in range(1, 5):
3900 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, l)
3903 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3904 endPlain = find_end_of_layout(document.body, beginPlain)
3905 endInset = find_end_of_inset(document.body, arg)
3906 content = document.body[beginPlain + 1 : endPlain]
3908 l = l - len(document.body[arg : endInset + 1])
3910 del document.body[arg : endInset + 1]
3911 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3913 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3914 endPlain = find_end_of_layout(document.body, beginPlain)
3915 endInset = find_end_of_inset(document.body, arg)
3916 content = document.body[beginPlain + 1 : endPlain]
3918 l = l - len(document.body[arg : endInset + 1])
3920 del document.body[arg : endInset + 1]
3921 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3923 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3924 endPlain = find_end_of_layout(document.body, beginPlain)
3925 endInset = find_end_of_inset(document.body, arg)
3926 content = document.body[beginPlain + 1 : endPlain]
3928 l = l - len(document.body[arg : endInset + 1])
3930 del document.body[arg : endInset + 1]
3931 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3933 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3934 endPlain = find_end_of_layout(document.body, beginPlain)
3935 endInset = find_end_of_inset(document.body, arg)
3936 content = document.body[beginPlain + 1 : endPlain]
3938 l = l - len(document.body[arg : endInset + 1])
3940 del document.body[arg : endInset + 1]
3943 document.body[i : i + 1] = subst
3946 # known encodings that do not change their names (same LyX and LaTeX names)
3947 known_enc_tuple = ("auto", "default", "ansinew", "applemac", "armscii8", "ascii",
3948 "cp437", "cp437de", "cp850", "cp852", "cp855", "cp858", "cp862", "cp865", "cp866",
3949 "cp1250", "cp1251", "cp1252", "cp1255", "cp1256", "cp1257", "koi8-r", "koi8-u",
3950 "pt154", "pt254", "tis620-0", "utf8", "utf8x", "utf8-plain")
3952 def convert_encodings(document):
3953 "Use the LyX names of the encodings instead of the LaTeX names."
3954 LaTeX2LyX_enc_dict = {
3955 "8859-6": "iso8859-6",
3956 "8859-8": "iso8859-8",
3958 "euc": "euc-jp-platex",
3963 "iso88595": "iso8859-5",
3964 "iso-8859-7": "iso8859-7",
3966 "jis": "jis-platex",
3968 "l7xenc": "iso8859-13",
3969 "latin1": "iso8859-1",
3970 "latin2": "iso8859-2",
3971 "latin3": "iso8859-3",
3972 "latin4": "iso8859-4",
3973 "latin5": "iso8859-9",
3974 "latin9": "iso8859-15",
3975 "latin10": "iso8859-16",
3976 "SJIS": "shift-jis",
3977 "sjis": "shift-jis-platex",
3980 i = find_token(document.header, "\\inputencoding" , 0)
3983 val = get_value(document.header, "\\inputencoding", i)
3984 if val in list(LaTeX2LyX_enc_dict.keys()):
3985 document.header[i] = "\\inputencoding %s" % LaTeX2LyX_enc_dict[val]
3986 elif val not in known_enc_tuple:
3987 document.warning("Ignoring unknown input encoding: `%s'" % val)
3990 def revert_encodings(document):
3991 """Revert to using the LaTeX names of the encodings instead of the LyX names.
3992 Also revert utf8-platex to sjis, the language default when using Japanese.
3994 LyX2LaTeX_enc_dict = {
3999 "euc-jp-platex": "euc",
4002 "iso8859-1": "latin1",
4003 "iso8859-2": "latin2",
4004 "iso8859-3": "latin3",
4005 "iso8859-4": "latin4",
4006 "iso8859-5": "iso88595",
4007 "iso8859-6": "8859-6",
4008 "iso8859-7": "iso-8859-7",
4009 "iso8859-8": "8859-8",
4010 "iso8859-9": "latin5",
4011 "iso8859-13": "l7xenc",
4012 "iso8859-15": "latin9",
4013 "iso8859-16": "latin10",
4015 "jis-platex": "jis",
4016 "shift-jis": "SJIS",
4017 "shift-jis-platex": "sjis",
4019 "utf8-platex": "sjis"
4021 i = find_token(document.header, "\\inputencoding" , 0)
4024 val = get_value(document.header, "\\inputencoding", i)
4025 if val in list(LyX2LaTeX_enc_dict.keys()):
4026 document.header[i] = "\\inputencoding %s" % LyX2LaTeX_enc_dict[val]
4027 elif val not in known_enc_tuple:
4028 document.warning("Ignoring unknown input encoding: `%s'" % val)
4031 def revert_IEEEtran_3(document):
4033 Reverts Flex Insets to TeX-code
4035 if document.textclass == "IEEEtran":
4041 h = find_token(document.body, "\\begin_inset Flex Author Mark", h)
4043 endh = find_end_of_inset(document.body, h)
4044 document.body[endh - 2 : endh + 1] = put_cmd_in_ert("}")
4045 document.body[h : h + 4] = put_cmd_in_ert("\\IEEEauthorrefmark{")
4048 i = find_token(document.body, "\\begin_inset Flex Author Name", i)
4050 endi = find_end_of_inset(document.body, i)
4051 document.body[endi - 2 : endi + 1] = put_cmd_in_ert("}")
4052 document.body[i : i + 4] = put_cmd_in_ert("\\IEEEauthorblockN{")
4055 j = find_token(document.body, "\\begin_inset Flex Author Affiliation", j)
4057 endj = find_end_of_inset(document.body, j)
4058 document.body[endj - 2 : endj + 1] = put_cmd_in_ert("}")
4059 document.body[j : j + 4] = put_cmd_in_ert("\\IEEEauthorblockA{")
4061 if i == -1 and j == -1 and h == -1:
4065 def revert_kurier_fonts(document):
4066 " Revert kurier font definition to LaTeX "
4068 i = find_token(document.header, "\\font_math", 0)
4070 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4071 val = get_value(document.header, "\\font_math", i)
4072 if val == "kurier-math":
4073 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
4074 "\\usepackage[math]{kurier}\n" \
4075 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
4076 document.header[i] = "\\font_math auto"
4078 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4079 kurier_fonts = ["kurier", "kurierc", "kurierl", "kurierlc"]
4080 k = find_token(document.header, "\\font_sans kurier", 0)
4082 sf = get_value(document.header, "\\font_sans", k)
4083 if sf in kurier_fonts:
4084 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4085 document.header[k] = "\\font_sans default"
4087 def revert_iwona_fonts(document):
4088 " Revert iwona font definition to LaTeX "
4090 i = find_token(document.header, "\\font_math", 0)
4092 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4093 val = get_value(document.header, "\\font_math", i)
4094 if val == "iwona-math":
4095 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
4096 "\\usepackage[math]{iwona}\n" \
4097 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
4098 document.header[i] = "\\font_math auto"
4100 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4101 iwona_fonts = ["iwona", "iwonac", "iwonal", "iwonalc"]
4102 k = find_token(document.header, "\\font_sans iwona", 0)
4104 sf = get_value(document.header, "\\font_sans", k)
4105 if sf in iwona_fonts:
4106 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4107 document.header[k] = "\\font_sans default"
4110 def revert_new_libertines(document):
4111 " Revert new libertine font definition to LaTeX "
4113 if find_token(document.header, "\\use_non_tex_fonts true", 0) != -1:
4116 i = find_token(document.header, "\\font_typewriter libertine-mono", 0)
4118 preamble = "\\usepackage"
4119 sc = find_token(document.header, "\\font_tt_scale", 0)
4121 scval = get_value(document.header, "\\font_tt_scale", sc)
4123 preamble += "[scale=%f]" % (float(scval) / 100)
4124 document.header[sc] = "\\font_tt_scale 100"
4125 preamble += "{libertineMono-type1}"
4126 add_to_preamble(document, [preamble])
4127 document.header[i] = "\\font_typewriter default"
4129 k = find_token(document.header, "\\font_sans biolinum", 0)
4131 preamble = "\\usepackage"
4133 j = find_token(document.header, "\\font_osf true", 0)
4138 sc = find_token(document.header, "\\font_sf_scale", 0)
4140 scval = get_value(document.header, "\\font_sf_scale", sc)
4142 options += ",scale=%f" % (float(scval) / 100)
4143 document.header[sc] = "\\font_sf_scale 100"
4145 preamble += "[" + options +"]"
4146 preamble += "{biolinum-type1}"
4147 add_to_preamble(document, [preamble])
4148 document.header[k] = "\\font_sans default"
4151 def convert_lyxframes(document):
4152 " Converts old beamer frames to new style "
4154 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4155 if document.textclass not in beamer_classes:
4158 framebeg = ["BeginFrame", "BeginPlainFrame"]
4159 frameend = ["Frame", "PlainFrame", "EndFrame", "BeginFrame", "BeginPlainFrame", "AgainFrame",
4160 "Section", "Section*", "Subsection", "Subsection*", "Subsubsection", "Subsubsection*"]
4161 for lay in framebeg:
4164 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
4167 parent = get_containing_layout(document.body, i)
4168 if parent == False or parent[1] != i:
4169 document.warning("Wrong parent layout!")
4172 frametype = parent[0]
4176 # Step I: Convert ERT arguments
4177 # FIXME: See restrictions in convert_beamerframeargs method
4178 ertend = convert_beamerframeargs(document, i, parbeg)
4181 # Step II: Now rename the layout and convert the title to an argument
4182 j = find_end_of_layout(document.body, i)
4183 document.body[j : j + 1] = ['\\end_layout', '', '\\end_inset', '', '\\end_layout']
4184 if lay == "BeginFrame":
4185 document.body[i] = "\\begin_layout Frame"
4187 document.body[i] = "\\begin_layout PlainFrame"
4188 document.body[ertend + 1 : ertend + 1] = ['\\begin_inset Argument 4',
4189 'status open', '', '\\begin_layout Plain Layout']
4190 # Step III: find real frame end
4193 inInset = get_containing_inset(document.body, i)
4195 fend = find_token(document.body, "\\begin_layout", jj)
4197 document.warning("Malformed LyX document: No real frame end!")
4199 val = get_value(document.body, "\\begin_layout", fend)
4200 if val not in frameend:
4203 # is this frame nested in an inset (e.g., Note)?
4204 if inInset != False:
4205 # if so, end the frame inside the inset
4206 if inInset[2] < fend:
4208 if val == frametype:
4209 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4210 # consider explicit EndFrames between two identical frame types
4211 elif val == "EndFrame":
4212 nextlayout = find_token(document.body, "\\begin_layout", fend + 1)
4213 if nextlayout != -1 and get_value(document.body, "\\begin_layout", nextlayout) == frametype:
4214 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4216 document.body[fend : fend] = ['\\end_deeper']
4218 document.body[fend : fend] = ['\\end_deeper']
4219 document.body[j + 1 : j + 1] = ['', '\\begin_deeper']
4224 def remove_endframes(document):
4225 " Remove deprecated beamer endframes "
4227 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4228 if document.textclass not in beamer_classes:
4233 i = find_token_exact(document.body, "\\begin_layout EndFrame", i)
4236 j = find_end_of_layout(document.body, i)
4238 document.warning("Malformed LyX document: Missing \\end_layout to EndFrame")
4241 del document.body[i : j + 1]
4244 def revert_powerdot_flexes(document):
4245 " Reverts powerdot flex insets "
4247 if document.textclass != "powerdot":
4250 flexes = {"Onslide" : "\\onslide",
4251 "Onslide*" : "\\onslide*",
4252 "Onslide+" : "\\onslide+"}
4253 rx = re.compile(r'^\\begin_inset Flex (.+)$')
4257 i = find_token(document.body, "\\begin_inset Flex", i)
4260 m = rx.match(document.body[i])
4262 flextype = m.group(1)
4263 z = find_end_of_inset(document.body, i)
4265 document.warning("Can't find end of Flex " + flextype + " inset.")
4268 if flextype in flexes:
4269 pre = put_cmd_in_ert(flexes[flextype])
4270 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
4272 argend = find_end_of_inset(document.body, arg)
4274 document.warning("Can't find end of Argument!")
4277 # Find containing paragraph layout
4278 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
4279 endPlain = find_end_of_layout(document.body, beginPlain)
4280 argcontent = document.body[beginPlain + 1 : endPlain]
4282 z = z - len(document.body[arg : argend + 1])
4284 del document.body[arg : argend + 1]
4285 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
4286 pre += put_cmd_in_ert("{")
4287 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4288 endPlain = find_end_of_layout(document.body, beginPlain)
4290 z = z - len(document.body[i : beginPlain + 1])
4292 document.body[i : beginPlain + 1] = pre
4293 post = put_cmd_in_ert("}")
4294 document.body[z - 2 : z + 1] = post
4298 def revert_powerdot_pause(document):
4299 " Reverts powerdot pause layout to ERT "
4301 if document.textclass != "powerdot":
4306 i = find_token(document.body, "\\begin_layout Pause", i)
4309 j = find_end_of_layout(document.body, i)
4311 document.warning("Malformed LyX document: Can't find end of Pause layout")
4315 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\pause")
4316 for p in range(i, j):
4319 arg = find_token(document.body, "\\begin_inset Argument 1", i, j)
4321 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4322 endPlain = find_end_of_layout(document.body, beginPlain)
4323 endInset = find_end_of_inset(document.body, p)
4324 content = document.body[beginPlain + 1 : endPlain]
4326 endlay = endlay - len(document.body[p : endInset + 1])
4328 del document.body[p : endInset + 1]
4329 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4331 document.body[i : i + 1] = subst
4335 def revert_powerdot_itemargs(document):
4336 " Reverts powerdot item arguments to ERT "
4338 if document.textclass != "powerdot":
4342 list_layouts = ["Itemize", "ItemizeType1", "Enumerate", "EnumerateType1"]
4343 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4346 i = find_token(document.body, "\\begin_inset Argument", i)
4349 # Find containing paragraph layout
4350 parent = get_containing_layout(document.body, i)
4352 document.warning("Malformed LyX document: Can't find parent paragraph layout")
4357 realparbeg = parent[3]
4358 layoutname = parent[0]
4360 for p in range(parbeg, parend):
4364 if layoutname in list_layouts:
4365 m = rx.match(document.body[p])
4368 if argnr == "item:1":
4369 j = find_end_of_inset(document.body, i)
4370 # Find containing paragraph layout
4371 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4372 endPlain = find_end_of_layout(document.body, beginPlain)
4373 content = document.body[beginPlain + 1 : endPlain]
4374 del document.body[i:j+1]
4375 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4376 document.body[realparbeg : realparbeg] = subst
4377 elif argnr == "item:2":
4378 j = find_end_of_inset(document.body, i)
4379 # Find containing paragraph layout
4380 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4381 endPlain = find_end_of_layout(document.body, beginPlain)
4382 content = document.body[beginPlain + 1 : endPlain]
4383 del document.body[i:j+1]
4384 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
4385 document.body[realparbeg : realparbeg] = subst
4390 def revert_powerdot_columns(document):
4391 " Reverts powerdot twocolumn to TeX-code "
4392 if document.textclass != "powerdot":
4395 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4398 i = find_token(document.body, "\\begin_layout Twocolumn", i)
4401 j = find_end_of_layout(document.body, i)
4403 document.warning("Malformed LyX document: Can't find end of Twocolumn layout")
4407 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
4408 endlay += len(put_cmd_in_ert("}"))
4409 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\twocolumn")
4410 for p in range(i, j):
4413 m = rx.match(document.body[p])
4417 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4418 endPlain = find_end_of_layout(document.body, beginPlain)
4419 endInset = find_end_of_inset(document.body, p)
4420 content = document.body[beginPlain + 1 : endPlain]
4422 endlay = endlay - len(document.body[p : endInset + 1])
4424 del document.body[p : endInset + 1]
4425 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4427 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4428 endPlain = find_end_of_layout(document.body, beginPlain)
4429 endInset = find_end_of_inset(document.body, p)
4430 content = document.body[beginPlain + 1 : endPlain]
4432 endlay = endlay - len(document.body[p : endInset + 1])
4434 del document.body[p : endInset + 1]
4435 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
4437 subst += put_cmd_in_ert("{")
4438 document.body[i : i + 1] = subst
4442 def revert_mbox_fbox(document):
4443 'Convert revert mbox/fbox boxes to TeX-code'
4446 i = find_token(document.body, "\\begin_inset Box", i)
4449 j = find_token(document.body, "width", i)
4451 document.warning("Malformed LyX document: Can't find box width")
4453 width = get_value(document.body, "width", j)
4454 k = find_end_of_inset(document.body, j)
4456 document.warning("Malformed LyX document: Can't find end of box inset")
4459 BeginLayout = find_token(document.body, "\\begin_layout Plain Layout", j)
4460 EndLayout = find_end_of_layout(document.body, BeginLayout)
4461 # replace if width is ""
4463 document.body[EndLayout:k + 1] = put_cmd_in_ert("}")
4464 if document.body[i] == "\\begin_inset Box Frameless":
4465 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\mbox{")
4466 if document.body[i] == "\\begin_inset Box Boxed":
4467 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\fbox{")
4471 def revert_starred_caption(document):
4472 " Reverts unnumbered longtable caption insets "
4476 i = find_token(document.body, "\\begin_inset Caption LongTableNoNumber", i)
4479 # This is not equivalent, but since the caption inset is a full blown
4480 # text inset a true conversion to ERT is too difficult.
4481 document.body[i] = "\\begin_inset Caption Standard"
4485 def revert_forced_local_layout(document):
4488 i = find_token(document.header, "\\begin_forced_local_layout", i)
4491 j = find_end_of(document.header, i, "\\begin_forced_local_layout", "\\end_forced_local_layout")
4493 # this should not happen
4495 regexp = re.compile(r'\s*forcelocal', re.IGNORECASE)
4496 k = find_re(document.header, regexp, i, j)
4498 del document.header[k]
4500 k = find_re(document.header, regexp, i, j)
4501 k = find_token(document.header, "\\begin_local_layout", 0)
4503 document.header[i] = "\\begin_local_layout"
4504 document.header[j] = "\\end_local_layout"
4506 l = find_end_of(document.header, k, "\\begin_local_layout", "\\end_local_layout")
4508 # this should not happen
4510 lines = document.header[i+1 : j]
4512 document.header[k+1 : k+1] = lines
4513 document.header[i : j ] = []
4515 document.header[i : j ] = []
4516 document.header[k+1 : k+1] = lines
4519 def revert_aa1(document):
4520 " Reverts InsetArguments of aa to TeX-code "
4521 if document.textclass == "aa":
4525 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4527 revert_Argument_to_TeX_brace(document, i, 0, 1, 4, False, False)
4533 def revert_aa2(document):
4534 " Reverts InsetArguments of aa to TeX-code "
4535 if document.textclass == "aa":
4539 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4541 document.body[i] = "\\begin_layout Abstract"
4547 def revert_tibetan(document):
4548 "Set the document language for Tibetan to English"
4550 if document.language == "tibetan":
4551 document.language = "english"
4552 i = find_token(document.header, "\\language", 0)
4554 document.header[i] = "\\language english"
4556 while j < len(document.body):
4557 j = find_token(document.body, "\\lang tibetan", j)
4559 document.body[j] = document.body[j].replace("\\lang tibetan", "\\lang english")
4562 j = len(document.body)
4571 # The idea here is that we will have a sequence of chunk paragraphs.
4572 # We want to convert them to paragraphs in one or several chunk insets.
4573 # Individual chunks are terminated by the character @ on the last line.
4574 # This line will be discarded, and following lines are treated as new
4575 # chunks, which go into their own insets.
4576 # The first line of a chunk should look like: <<CONTENT>>=
4577 # We will discard the delimiters, and put the CONTENT into the
4578 # optional argument of the inset, if the CONTENT is non-empty.
4579 def convert_chunks(document):
4580 first_re = re.compile(r'<<(.*)>>=(.*)')
4583 # find start of a block of chunks
4584 i = find_token(document.body, "\\begin_layout Chunk", file_pos)
4590 chunk_started = False
4593 # process the one we just found
4594 j = find_end_of_layout(document.body, i)
4596 document.warning("Malformed LyX documents. Can't find end of Chunk layout!")
4597 # there is no point continuing, as we will run into the same error again.
4599 this_chunk = "".join(document.body[i + 1:j])
4601 # there may be empty lines between chunks
4602 # we just skip them.
4603 if not chunk_started:
4604 if this_chunk != "":
4606 chunk_started = True
4609 contents.append(document.body[i + 1:j])
4611 # look for potential chunk terminator
4612 # on the last line of the chunk paragraph
4613 if document.body[j - 1] == "@":
4616 # look for subsequent chunk paragraph
4617 i = find_token(document.body, "\\begin_layout", j)
4621 if get_value(document.body, "\\begin_layout", i) != "Chunk":
4624 file_pos = end = j + 1
4626 # The last chunk should simply have an "@" in it
4627 # or at least end with "@" (can happen if @ is
4628 # preceded by a newline)
4630 if len(contents) > 0:
4631 lastpar = ''.join(contents[-1])
4632 if not lastpar.endswith("@"):
4633 document.warning("Unexpected chunk content: chunk not terminated by '@'!")
4634 if len(contents) == 0:
4635 # convert empty chunk layouts to Standard
4636 document.body[start] = "\\begin_layout Standard"
4640 # chunk par only contains "@". Just drop it.
4643 # chunk par contains more. Only drop the "@".
4646 # The first line should look like: <<CONTENT>>=
4647 # We want the CONTENT
4648 optarg = ' '.join(contents[0])
4650 # We can already have real chunk content in
4651 # the first par (separated from the options by a newline).
4652 # We collect such stuff to re-insert it later.
4655 match = first_re.search(optarg)
4657 optarg = match.groups()[0]
4658 if match.groups()[1] != "":
4660 for c in contents[0]:
4661 if c.endswith(">>="):
4665 postoptstuff.append(c)
4666 # We have stripped everything. This can be deleted.
4669 newstuff = ['\\begin_layout Standard']
4671 # Maintain paragraph parameters
4672 par_params = ["\\noindent", "\\indent", "\\indent-toggle", "\\leftindent",
4673 "\\start_of_appendix", "\\paragraph_spacing", "\\align",
4674 "\\labelwidthstring"]
4677 if document.body[parms].split(' ', 1)[0] not in par_params:
4679 newstuff.extend([document.body[parms]])
4683 ['\\begin_inset Flex Chunk',
4685 '\\begin_layout Plain Layout', ''])
4687 # If we have a non-empty optional argument, insert it.
4688 if match and optarg != "":
4690 ['\\begin_inset Argument 1',
4692 '\\begin_layout Plain Layout',
4697 # Since we already opened a Plain layout, the first paragraph
4698 # does not need to do that.
4701 # we need to replace newlines with new layouts
4703 started_text = False
4704 for lno in range(0,len(postoptstuff)):
4705 if postoptstuff[lno].startswith("\\begin_inset Newline newline"):
4707 elif start_newline != -1:
4708 if postoptstuff[lno].startswith("\\end_inset"):
4709 # replace that bit, but only if we already have some text
4710 # and we're not at the end except for a blank line
4711 if started_text and \
4712 (lno != len(postoptstuff) - 2 or postoptstuff[-1] != ""):
4713 newstuff.extend(['\\end_layout', '\n', '\\begin_layout Plain Layout', '\n'])
4717 newstuff.extend([postoptstuff[lno]])
4718 newstuff.append('\\end_layout')
4722 newstuff.extend(['', '\\begin_layout Plain Layout', ''])
4726 newstuff.append('\\end_layout')
4728 newstuff.extend(['', '\\end_inset', '', '\\end_layout', ''])
4730 document.body[start:end] = newstuff
4732 file_pos += len(newstuff) - (end - start)
4735 def revert_chunks(document):
4738 i = find_token(document.body, "\\begin_inset Flex Chunk", i)
4742 iend = find_end_of_inset(document.body, i)
4744 document.warning("Can't find end of Chunk!")
4748 # Look for optional argument
4750 ostart = find_token(document.body, "\\begin_inset Argument 1", i, iend)
4752 oend = find_end_of_inset(document.body, ostart)
4753 k = find_token(document.body, "\\begin_layout Plain Layout", ostart, oend)
4755 document.warning("Malformed LyX document: Can't find argument contents!")
4757 m = find_end_of_layout(document.body, k)
4758 optarg = "".join(document.body[k+1:m])
4760 # We now remove the optional argument, so we have something
4761 # uniform on which to work
4762 document.body[ostart : oend + 1] = []
4763 # iend is now invalid
4764 iend = find_end_of_inset(document.body, i)
4766 retval = get_containing_layout(document.body, i)
4768 document.warning("Can't find containing layout for Chunk!")
4771 (lname, lstart, lend, pstart) = retval
4772 # we now want to work through the various paragraphs, and collect their contents
4776 k = find_token(document.body, "\\begin_layout Plain Layout", k, lend)
4779 j = find_end_of_layout(document.body, k)
4781 document.warning("Can't find end of layout inside chunk!")
4783 parlist.append(document.body[k+1:j])
4785 # we now need to wrap all of these paragraphs in chunks
4787 newlines.extend(["\\begin_layout Chunk", "", "<<" + optarg + ">>=", "\\end_layout", ""])
4788 for stuff in parlist:
4789 newlines.extend(["\\begin_layout Chunk"] + stuff + ["\\end_layout", ""])
4790 newlines.extend(["\\begin_layout Chunk", "", "@", "\\end_layout", ""])
4791 # replace old content with new content
4792 document.body[lstart : lend + 1] = newlines
4793 i = lstart + len(newlines)
4800 supported_versions = ["2.1.0","2.1"]
4803 [415, [convert_undertilde]],
4805 [417, [convert_japanese_encodings]],
4806 [418, [convert_justification]],
4808 [420, [convert_biblio_style]],
4809 [421, [convert_longtable_captions]],
4810 [422, [convert_use_packages]],
4811 [423, [convert_use_mathtools]],
4812 [424, [convert_cite_engine_type]],
4813 # No convert_cancel, since cancel will be loaded automatically
4814 # in format 425 without any possibility to switch it off.
4815 # This has been fixed in format 464.
4819 [428, [convert_cell_rotation]],
4820 [429, [convert_table_rotation]],
4821 [430, [convert_listoflistings]],
4822 [431, [convert_use_amssymb]],
4824 [433, [convert_armenian]],
4832 [441, [convert_mdnomath]],
4837 [446, [convert_latexargs]],
4838 [447, [convert_IEEEtran, convert_AASTeX, convert_AGUTeX, convert_IJMP, convert_SIGPLAN, convert_SIGGRAPH, convert_EuropeCV, convert_Initials, convert_ModernCV]],
4839 [448, [convert_literate]],
4842 [451, [convert_beamerargs, convert_againframe_args, convert_corollary_args, convert_quote_args]],
4843 [452, [convert_beamerblocks]],
4844 [453, [convert_use_stmaryrd]],
4845 [454, [convert_overprint]],
4847 [456, [convert_epigraph]],
4848 [457, [convert_use_stackrel]],
4849 [458, [convert_captioninsets, convert_captionlayouts]],
4854 [463, [convert_encodings]],
4855 [464, [convert_use_cancel]],
4856 [465, [convert_lyxframes, remove_endframes]],
4862 [471, [convert_cite_engine_type_default]],
4865 [474, [convert_chunks, cleanup_beamerargs]],
4869 [473, [revert_chunks]],
4870 [472, [revert_tibetan]],
4871 [471, [revert_aa1,revert_aa2]],
4872 [470, [revert_cite_engine_type_default]],
4873 [469, [revert_forced_local_layout]],
4874 [468, [revert_starred_caption]],
4875 [467, [revert_mbox_fbox]],
4876 [466, [revert_iwona_fonts]],
4877 [465, [revert_powerdot_flexes, revert_powerdot_pause, revert_powerdot_itemargs, revert_powerdot_columns]],
4879 [463, [revert_use_cancel]],
4880 [462, [revert_encodings]],
4881 [461, [revert_new_libertines]],
4882 [460, [revert_kurier_fonts]],
4883 [459, [revert_IEEEtran_3]],
4884 [458, [revert_fragileframe, revert_newframes]],
4885 [457, [revert_captioninsets, revert_captionlayouts]],
4886 [456, [revert_use_stackrel]],
4887 [455, [revert_epigraph]],
4888 [454, [revert_frametitle]],
4889 [453, [revert_overprint]],
4890 [452, [revert_use_stmaryrd]],
4891 [451, [revert_beamerblocks]],
4892 [450, [revert_beamerargs, revert_beamerargs2, revert_beamerargs3, revert_beamerflex]],
4893 [449, [revert_garamondx, revert_garamondx_newtxmath]],
4894 [448, [revert_itemargs]],
4895 [447, [revert_literate]],
4896 [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]],
4897 [445, [revert_latexargs]],
4898 [444, [revert_uop]],
4899 [443, [revert_biolinum]],
4901 [441, [revert_newtxmath]],
4902 [440, [revert_mdnomath]],
4903 [439, [revert_mathfonts]],
4904 [438, [revert_minionpro]],
4905 [437, [revert_ipadeco, revert_ipachar]],
4906 [436, [revert_texgyre]],
4907 [435, [revert_mathdesign]],
4908 [434, [revert_txtt]],
4909 [433, [revert_libertine]],
4910 [432, [revert_armenian]],
4911 [431, [revert_languages, revert_ancientgreek]],
4912 [430, [revert_use_amssymb]],
4913 [429, [revert_listoflistings]],
4914 [428, [revert_table_rotation]],
4915 [427, [revert_cell_rotation]],
4916 [426, [revert_tipa]],
4917 [425, [revert_verbatim]],
4918 [424, [revert_cancel]],
4919 [423, [revert_cite_engine_type]],
4920 [422, [revert_use_mathtools]],
4921 [421, [revert_use_packages]],
4922 [420, [revert_longtable_captions]],
4923 [419, [revert_biblio_style]],
4924 [418, [revert_australian]],
4925 [417, [revert_justification]],
4926 [416, [revert_japanese_encodings]],
4927 [415, [revert_negative_space, revert_math_spaces]],
4928 [414, [revert_undertilde]],
4929 [413, [revert_visible_space]]
4933 if __name__ == "__main__":