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):
818 " Revert verbatim einvironments 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', '']
835 i = find_token(document.body, "\\begin_layout Verbatim", i)
838 j = find_end_of_layout(document.body, i)
840 document.warning("Malformed LyX document: Can't find end of Verbatim layout")
843 # delete all line breaks insets (there are no other insets)
846 n = find_token(document.body, "\\begin_inset Newline newline", l, j)
848 n = find_token(document.body, "\\begin_inset Newline linebreak", l, j)
851 m = find_end_of_inset(document.body, n)
852 del(document.body[m:m+1])
853 document.body[n:n+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
855 # we deleted a line, so the end of the inset moved forward.
857 # consecutive verbatim environments need to be connected
858 k = find_token(document.body, "\\begin_layout Verbatim", j)
859 if k == j + 2 and consecutive == False:
861 document.body[j:j+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
862 document.body[i:i+1] = subst_begin
864 if k == j + 2 and consecutive == True:
865 document.body[j:j+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
866 del(document.body[i:i+1])
868 if k != j + 2 and consecutive == True:
869 document.body[j:j+1] = subst_end
870 # the next paragraph must not be indented
871 document.body[j+19:j+19] = ['\\noindent']
872 del(document.body[i:i+1])
876 document.body[j:j+1] = subst_end
877 # the next paragraph must not be indented
878 document.body[j+19:j+19] = ['\\noindent']
879 document.body[i:i+1] = subst_begin
882 def revert_tipa(document):
883 " Revert native TIPA insets to mathed or ERT. "
886 i = find_token(document.body, "\\begin_inset IPA", i)
889 j = find_end_of_inset(document.body, i)
891 document.warning("Malformed LyX document: Can't find end of IPA inset")
895 n = find_token(document.body, "\\begin_layout", i, j)
897 document.warning("Malformed LyX document: IPA inset has no embedded layout")
900 m = find_end_of_layout(document.body, n)
902 document.warning("Malformed LyX document: Can't find end of embedded layout")
905 content = document.body[n+1:m]
906 p = find_token(document.body, "\\begin_layout", m, j)
907 if p != -1 or len(content) > 1:
909 content = document.body[i+1:j]
911 # IPA insets with multiple pars need to be wrapped by \begin{IPA}...\end{IPA}
912 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}")
913 add_to_preamble(document, ["\\usepackage{tipa,tipx}"])
915 # single-par IPA insets can be reverted to mathed
916 document.body[i:j+1] = ["\\begin_inset Formula $\\text{\\textipa{" + content[0] + "}}$", "\\end_inset"]
920 def revert_cell_rotation(document):
921 "Revert cell rotations to TeX-code"
923 load_rotating = False
927 # first, let's find out if we need to do anything
928 i = find_token(document.body, '<cell ', i)
931 j = document.body[i].find('rotate="')
933 k = document.body[i].find('"', j + 8)
934 value = document.body[i][j + 8 : k]
936 rgx = re.compile(r' rotate="[^"]+?"')
937 # remove rotate option
938 document.body[i] = rgx.sub('', document.body[i])
940 rgx = re.compile(r' rotate="[^"]+?"')
941 document.body[i] = rgx.sub(' rotate="true"', document.body[i])
943 rgx = re.compile(r' rotate="[^"]+?"')
945 # remove rotate option
946 document.body[i] = rgx.sub('', document.body[i])
948 document.body[i + 5 : i + 5] = \
949 put_cmd_in_ert("\\end{turn}")
950 document.body[i + 4 : i + 4] = \
951 put_cmd_in_ert("\\begin{turn}{" + value + "}")
957 add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"])
960 def convert_cell_rotation(document):
961 'Convert cell rotation statements from "true" to "90"'
965 # first, let's find out if we need to do anything
966 i = find_token(document.body, '<cell ', i)
969 j = document.body[i].find('rotate="true"')
971 rgx = re.compile(r'rotate="[^"]+?"')
972 # convert "true" to "90"
973 document.body[i] = rgx.sub('rotate="90"', document.body[i])
978 def revert_table_rotation(document):
979 "Revert table rotations to TeX-code"
981 load_rotating = False
985 # first, let's find out if we need to do anything
986 i = find_token(document.body, '<features ', i)
989 j = document.body[i].find('rotate="')
991 end_table = find_token(document.body, '</lyxtabular>', j)
992 k = document.body[i].find('"', j + 8)
993 value = document.body[i][j + 8 : k]
995 rgx = re.compile(r' rotate="[^"]+?"')
996 # remove rotate option
997 document.body[i] = rgx.sub('', document.body[i])
999 rgx = re.compile(r'rotate="[^"]+?"')
1000 document.body[i] = rgx.sub('rotate="true"', document.body[i])
1002 rgx = re.compile(r' rotate="[^"]+?"')
1003 load_rotating = True
1004 # remove rotate option
1005 document.body[i] = rgx.sub('', document.body[i])
1007 document.body[end_table + 3 : end_table + 3] = \
1008 put_cmd_in_ert("\\end{turn}")
1009 document.body[i - 2 : i - 2] = \
1010 put_cmd_in_ert("\\begin{turn}{" + value + "}")
1016 add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"])
1019 def convert_table_rotation(document):
1020 'Convert table rotation statements from "true" to "90"'
1024 # first, let's find out if we need to do anything
1025 i = find_token(document.body, '<features ', i)
1028 j = document.body[i].find('rotate="true"')
1030 rgx = re.compile(r'rotate="[^"]+?"')
1031 # convert "true" to "90"
1032 document.body[i] = rgx.sub('rotate="90"', document.body[i])
1037 def convert_listoflistings(document):
1038 'Convert ERT \lstlistoflistings to TOC lstlistoflistings inset'
1039 # We can support roundtrip because the command is so simple
1042 i = find_token(document.body, "\\begin_inset ERT", i)
1045 j = find_end_of_inset(document.body, i)
1047 document.warning("Malformed LyX document: Can't find end of ERT inset")
1050 ert = get_ert(document.body, i)
1051 if ert == "\\lstlistoflistings{}":
1052 document.body[i:j] = ["\\begin_inset CommandInset toc", "LatexCommand lstlistoflistings", ""]
1058 def revert_listoflistings(document):
1059 'Convert TOC lstlistoflistings inset to ERT lstlistoflistings'
1062 i = find_token(document.body, "\\begin_inset CommandInset toc", i)
1065 if document.body[i+1] == "LatexCommand lstlistoflistings":
1066 j = find_end_of_inset(document.body, i)
1068 document.warning("Malformed LyX document: Can't find end of TOC inset")
1071 subst = put_cmd_in_ert("\\lstlistoflistings{}")
1072 document.body[i:j+1] = subst
1073 add_to_preamble(document, ["\\usepackage{listings}"])
1077 def convert_use_amssymb(document):
1078 "insert use_package amssymb"
1079 regexp = re.compile(r'(\\use_package\s+amsmath)')
1080 i = find_re(document.header, regexp, 0)
1082 document.warning("Malformed LyX document: Can't find \\use_package amsmath.")
1084 value = get_value(document.header, "\\use_package" , i).split()[1]
1087 useamsmath = int(value)
1089 document.warning("Invalid \\use_package amsmath: " + value + ". Assuming auto.")
1091 j = find_token(document.preamble, "\\usepackage{amssymb}", 0)
1093 document.header.insert(i + 1, "\\use_package amssymb %d" % useamsmath)
1095 document.header.insert(i + 1, "\\use_package amssymb 2")
1096 del document.preamble[j]
1099 def revert_use_amssymb(document):
1100 "remove use_package amssymb"
1101 regexp1 = re.compile(r'(\\use_package\s+amsmath)')
1102 regexp2 = re.compile(r'(\\use_package\s+amssymb)')
1103 i = find_re(document.header, regexp1, 0)
1104 j = find_re(document.header, regexp2, 0)
1105 value1 = "1" # default is auto
1106 value2 = "1" # default is auto
1108 value1 = get_value(document.header, "\\use_package" , i).split()[1]
1110 value2 = get_value(document.header, "\\use_package" , j).split()[1]
1111 del document.header[j]
1112 if value1 != value2 and value2 == "2": # on
1113 add_to_preamble(document, ["\\usepackage{amssymb}"])
1116 def convert_use_cancel(document):
1117 "insert use_package cancel"
1118 convert_use_package(document, "cancel", cancel_commands, True)
1121 def revert_use_cancel(document):
1122 "remove use_package cancel"
1123 revert_use_package(document, "cancel", cancel_commands, True)
1126 def revert_ancientgreek(document):
1127 "Set the document language for ancientgreek to greek"
1129 if document.language == "ancientgreek":
1130 document.language = "greek"
1131 i = find_token(document.header, "\\language", 0)
1133 document.header[i] = "\\language greek"
1136 j = find_token(document.body, "\\lang ancientgreek", j)
1140 document.body[j] = document.body[j].replace("\\lang ancientgreek", "\\lang greek")
1144 def revert_languages(document):
1145 "Set the document language for new supported languages to English"
1148 "coptic", "divehi", "hindi", "kurmanji", "lao", "marathi", "occitan", "sanskrit",
1149 "syriac", "tamil", "telugu", "urdu"
1151 for n in range(len(languages)):
1152 if document.language == languages[n]:
1153 document.language = "english"
1154 i = find_token(document.header, "\\language", 0)
1156 document.header[i] = "\\language english"
1158 while j < len(document.body):
1159 j = find_token(document.body, "\\lang " + languages[n], j)
1161 document.body[j] = document.body[j].replace("\\lang " + languages[n], "\\lang english")
1164 j = len(document.body)
1167 def convert_armenian(document):
1168 "Use polyglossia and thus non-TeX fonts for Armenian"
1170 if document.language == "armenian":
1171 i = find_token(document.header, "\\use_non_tex_fonts", 0)
1173 document.header[i] = "\\use_non_tex_fonts true"
1176 def revert_armenian(document):
1177 "Use ArmTeX and thus TeX fonts for Armenian"
1179 if document.language == "armenian":
1180 i = find_token(document.header, "\\use_non_tex_fonts", 0)
1182 document.header[i] = "\\use_non_tex_fonts false"
1185 def revert_libertine(document):
1186 " Revert native libertine font definition to LaTeX "
1188 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1189 i = find_token(document.header, "\\font_roman libertine", 0)
1192 j = find_token(document.header, "\\font_osf true", 0)
1195 preamble = "\\usepackage"
1197 document.header[j] = "\\font_osf false"
1200 preamble += "[lining]"
1201 preamble += "{libertine-type1}"
1202 add_to_preamble(document, [preamble])
1203 document.header[i] = "\\font_roman default"
1206 def revert_txtt(document):
1207 " Revert native txtt font definition to LaTeX "
1209 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1210 i = find_token(document.header, "\\font_typewriter txtt", 0)
1212 preamble = "\\renewcommand{\\ttdefault}{txtt}"
1213 add_to_preamble(document, [preamble])
1214 document.header[i] = "\\font_typewriter default"
1217 def revert_mathdesign(document):
1218 " Revert native mathdesign font definition to LaTeX "
1220 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1226 i = find_token(document.header, "\\font_roman", 0)
1229 val = get_value(document.header, "\\font_roman", i)
1230 if val in list(mathdesign_dict.keys()):
1231 preamble = "\\usepackage[%s" % mathdesign_dict[val]
1233 j = find_token(document.header, "\\font_osf true", 0)
1236 document.header[j] = "\\font_osf false"
1237 l = find_token(document.header, "\\font_sc true", 0)
1240 document.header[l] = "\\font_sc false"
1242 preamble += ",expert"
1243 preamble += "]{mathdesign}"
1244 add_to_preamble(document, [preamble])
1245 document.header[i] = "\\font_roman default"
1248 def revert_texgyre(document):
1249 " Revert native TeXGyre font definition to LaTeX "
1251 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1252 texgyre_fonts = ["tgadventor", "tgbonum", "tgchorus", "tgcursor", \
1253 "tgheros", "tgpagella", "tgschola", "tgtermes"]
1254 i = find_token(document.header, "\\font_roman", 0)
1256 val = get_value(document.header, "\\font_roman", i)
1257 if val in texgyre_fonts:
1258 preamble = "\\usepackage{%s}" % val
1259 add_to_preamble(document, [preamble])
1260 document.header[i] = "\\font_roman default"
1261 i = find_token(document.header, "\\font_sans", 0)
1263 val = get_value(document.header, "\\font_sans", i)
1264 if val in texgyre_fonts:
1265 preamble = "\\usepackage{%s}" % val
1266 add_to_preamble(document, [preamble])
1267 document.header[i] = "\\font_sans default"
1268 i = find_token(document.header, "\\font_typewriter", 0)
1270 val = get_value(document.header, "\\font_typewriter", i)
1271 if val in texgyre_fonts:
1272 preamble = "\\usepackage{%s}" % val
1273 add_to_preamble(document, [preamble])
1274 document.header[i] = "\\font_typewriter default"
1277 def revert_ipadeco(document):
1278 " Revert IPA decorations to ERT "
1281 i = find_token(document.body, "\\begin_inset IPADeco", i)
1284 end = find_end_of_inset(document.body, i)
1286 document.warning("Can't find end of inset at line " + str(i))
1289 line = document.body[i]
1290 rx = re.compile(r'\\begin_inset IPADeco (.*)$')
1292 decotype = m.group(1)
1293 if decotype != "toptiebar" and decotype != "bottomtiebar":
1294 document.warning("Invalid IPADeco type: " + decotype)
1297 blay = find_token(document.body, "\\begin_layout Plain Layout", i, end)
1299 document.warning("Can't find layout for inset at line " + str(i))
1302 bend = find_end_of_layout(document.body, blay)
1304 document.warning("Malformed LyX document: Could not find end of IPADeco inset's layout.")
1307 substi = ["\\begin_inset ERT", "status collapsed", "",
1308 "\\begin_layout Plain Layout", "", "", "\\backslash",
1309 decotype + "{", "\\end_layout", "", "\\end_inset"]
1310 substj = ["\\size default", "", "\\begin_inset ERT", "status collapsed", "",
1311 "\\begin_layout Plain Layout", "", "}", "\\end_layout", "", "\\end_inset"]
1312 # do the later one first so as not to mess up the numbering
1313 document.body[bend:end + 1] = substj
1314 document.body[i:blay + 1] = substi
1315 i = end + len(substi) + len(substj) - (end - bend) - (blay - i) - 2
1316 add_to_preamble(document, "\\usepackage{tipa}")
1319 def revert_ipachar(document):
1320 ' Revert \\IPAChar to ERT '
1323 while i < len(document.body):
1324 m = re.match(r'(.*)\\IPAChar \\(\w+\{\w+\})(.*)', document.body[i])
1328 ipachar = m.group(2)
1331 '\\begin_inset ERT',
1332 'status collapsed', '',
1333 '\\begin_layout Standard',
1334 '', '', '\\backslash',
1339 document.body[i: i+1] = subst
1344 add_to_preamble(document, "\\usepackage{tone}")
1347 def revert_minionpro(document):
1348 " Revert native MinionPro font definition to LaTeX "
1350 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1351 i = find_token(document.header, "\\font_roman minionpro", 0)
1354 j = find_token(document.header, "\\font_osf true", 0)
1357 preamble = "\\usepackage"
1359 document.header[j] = "\\font_osf false"
1362 preamble += "{MinionPro}"
1363 add_to_preamble(document, [preamble])
1364 document.header[i] = "\\font_roman default"
1367 def revert_mathfonts(document):
1368 " Revert native math font definitions to LaTeX "
1370 i = find_token(document.header, "\\font_math", 0)
1373 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1374 val = get_value(document.header, "\\font_math", i)
1375 if val == "eulervm":
1376 add_to_preamble(document, "\\usepackage{eulervm}")
1377 elif val == "default":
1379 "lmodern": "\\renewcommand{\\rmdefault}{lmr}",
1380 "minionpro": "\\usepackage[onlytext,lf]{MinionPro}",
1381 "minionpro-osf": "\\usepackage[onlytext]{MinionPro}",
1382 "palatino": "\\renewcommand{\\rmdefault}{ppl}",
1383 "palatino-osf": "\\renewcommand{\\rmdefault}{pplj}",
1384 "times": "\\renewcommand{\\rmdefault}{ptm}",
1385 "utopia": "\\renewcommand{\\rmdefault}{futs}",
1386 "utopia-osf": "\\renewcommand{\\rmdefault}{futj}",
1388 j = find_token(document.header, "\\font_roman", 0)
1390 rm = get_value(document.header, "\\font_roman", j)
1391 k = find_token(document.header, "\\font_osf true", 0)
1394 if rm in list(mathfont_dict.keys()):
1395 add_to_preamble(document, mathfont_dict[rm])
1396 document.header[j] = "\\font_roman default"
1398 document.header[k] = "\\font_osf false"
1399 del document.header[i]
1402 def revert_mdnomath(document):
1403 " Revert mathdesign and fourier without math "
1405 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1407 "md-charter": "mdbch",
1408 "md-utopia": "mdput",
1409 "md-garamond": "mdugm"
1411 i = find_token(document.header, "\\font_roman", 0)
1414 val = get_value(document.header, "\\font_roman", i)
1415 if val in list(mathdesign_dict.keys()):
1416 j = find_token(document.header, "\\font_math", 0)
1418 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1419 mval = get_value(document.header, "\\font_math", j)
1420 if mval == "default":
1421 document.header[i] = "\\font_roman default"
1422 add_to_preamble(document, "\\renewcommand{\\rmdefault}{%s}" % mathdesign_dict[val])
1424 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1427 def convert_mdnomath(document):
1428 " Change mathdesign font name "
1430 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1432 "mdbch": "md-charter",
1433 "mdput": "md-utopia",
1434 "mdugm": "md-garamond"
1436 i = find_token(document.header, "\\font_roman", 0)
1439 val = get_value(document.header, "\\font_roman", i)
1440 if val in list(mathdesign_dict.keys()):
1441 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1444 def revert_newtxmath(document):
1445 " Revert native newtxmath definitions to LaTeX "
1447 i = find_token(document.header, "\\font_math", 0)
1450 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1451 val = get_value(document.header, "\\font_math", i)
1453 "libertine-ntxm": "\\usepackage[libertine]{newtxmath}",
1454 "minion-ntxm": "\\usepackage[minion]{newtxmath}",
1455 "newtxmath": "\\usepackage{newtxmath}",
1457 if val in list(mathfont_dict.keys()):
1458 add_to_preamble(document, mathfont_dict[val])
1459 document.header[i] = "\\font_math auto"
1462 def revert_biolinum(document):
1463 " Revert native biolinum font definition to LaTeX "
1465 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1466 i = find_token(document.header, "\\font_sans biolinum", 0)
1469 j = find_token(document.header, "\\font_osf true", 0)
1472 preamble = "\\usepackage"
1475 preamble += "{biolinum-type1}"
1476 add_to_preamble(document, [preamble])
1477 document.header[i] = "\\font_sans default"
1480 def revert_uop(document):
1481 " Revert native URW Classico (Optima) 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 uop", 0)
1486 preamble = "\\renewcommand{\\sfdefault}{uop}"
1487 add_to_preamble(document, [preamble])
1488 document.header[i] = "\\font_sans default"
1491 def convert_latexargs(document):
1492 " Convert InsetArgument to new syntax "
1494 if find_token(document.body, "\\begin_inset Argument", 0) == -1:
1498 # A list of layouts (document classes) with only optional or no arguments.
1499 # These can be safely converted to the new syntax
1500 # (I took the liberty to add some of my personal layouts/modules here; JSP)
1501 safe_layouts = ["aa", "aapaper", "aastex", "achemso", "acmsiggraph", "AEA",
1502 "agu-dtd", "agums", "agutex", "amsart", "amsbook", "apa",
1503 "arab-article", "armenian-article", "article-beamer", "article",
1504 "beamer", "book", "broadway", "chess", "cl2emult", "ctex-article",
1505 "ctex-book", "ctex-report", "dinbrief", "docbook-book", "docbook-chapter",
1506 "docbook", "docbook-section", "doublecol-new", "dtk", "ectaart", "egs",
1507 "elsarticle", "elsart", "entcs", "europecv", "extarticle", "extbook",
1508 "extletter", "extreport", "foils", "frletter", "g-brief2", "g-brief",
1509 "heb-article", "heb-letter", "hollywood", "IEEEtran", "ijmpc", "ijmpd",
1510 "iopart", "isprs", "jarticle", "jasatex", "jbook", "jgrga", "jreport",
1511 "jsarticle", "jsbeamer", "jsbook", "jss", "kluwer", "latex8", "letter", "lettre",
1512 "literate-article", "literate-book", "literate-report", "llncs", "ltugboat",
1513 "memoir", "moderncv", "mwart", "mwbk", "mwrep", "paper", "powerdot",
1514 "recipebook", "report", "revtex4", "revtex", "scrartcl", "scrarticle-beamer",
1515 "scrbook", "scrlettr", "scrlttr2", "scrreprt", "seminar", "siamltex",
1516 "sigplanconf", "simplecv", "singlecol", "singlecol-new", "slides", "spie",
1517 "svglobal3", "svglobal", "svjog", "svmono", "svmult", "svprobth", "tarticle",
1518 "tbook", "treport", "tufte-book", "tufte-handout"]
1519 # A list of "safe" modules, same as above
1520 safe_modules = ["biblatex", "beameraddons", "beamer-resenumerate", "beamersession", "braille",
1521 "customHeadersFooters", "endnotes", "enumitem", "eqs-within-sections", "figs-within-sections",
1522 "fix-cm", "fixltx2e", "foottoend", "hanging", "jscharstyles", "knitr", "lilypond",
1523 "linguistics", "linguisticx", "logicalmkup", "minimalistic", "nomindex", "noweb",
1524 "pdfcomment", "sweave", "tabs-within-sections", "theorems-ams-bytype",
1525 "theorems-ams-extended-bytype", "theorems-ams-extended", "theorems-ams", "theorems-bytype",
1526 "theorems-chap-bytype", "theorems-chap", "theorems-named", "theorems-sec-bytype",
1527 "theorems-sec", "theorems-starred", "theorems-std", "todonotes"]
1528 # Modules we need to take care of
1529 caveat_modules = ["initials"]
1530 # information about the relevant styles in caveat_modules (number of opt and req args)
1531 # use this if we get more caveat_modules. For now, use hard coding (see below).
1532 # initials = [{'Layout' : 'Initial', 'opt' : 1, 'req' : 1}]
1534 # Is this a known safe layout?
1535 safe_layout = document.textclass in safe_layouts
1537 document.warning("Lyx2lyx knows nothing about textclass '%s'. "
1538 "Please check if short title insets have been converted correctly."
1539 % document.textclass)
1540 # Do we use unsafe or unknown modules
1541 mods = document.get_module_list()
1542 unknown_modules = False
1543 used_caveat_modules = list()
1545 if mod in safe_modules:
1547 if mod in caveat_modules:
1548 used_caveat_modules.append(mod)
1550 unknown_modules = True
1551 document.warning("Lyx2lyx knows nothing about module '%s'. "
1552 "Please check if short title insets have been converted correctly."
1557 i = find_token(document.body, "\\begin_inset Argument", i)
1561 if not safe_layout or unknown_modules:
1562 # We cannot do more here since we have no access to this layout.
1563 # InsetArgument itself will do the real work
1564 # (see InsetArgument::updateBuffer())
1565 document.body[i] = "\\begin_inset Argument 999"
1569 # Find containing paragraph layout
1570 parent = get_containing_layout(document.body, i)
1572 document.warning("Malformed LyX document: Can't find parent paragraph layout")
1579 if len(used_caveat_modules) > 0:
1580 # We know for now that this must be the initials module with the Initial layout
1581 # If we get more such modules, we need some automating.
1582 if parent[0] == "Initial":
1583 # Layout has 1 opt and 1 req arg.
1584 # Count the actual arguments
1586 for p in range(parbeg, parend):
1587 if document.body[p] == "\\begin_inset Argument":
1592 # Collect all arguments in this paragraph
1594 for p in range(parbeg, parend):
1595 if document.body[p] == "\\begin_inset Argument":
1597 if allowed_opts != -1:
1598 # We have less arguments than opt + required.
1599 # required must take precedence.
1600 if argnr > allowed_opts and argnr < first_req:
1602 document.body[p] = "\\begin_inset Argument %d" % argnr
1606 def revert_latexargs(document):
1607 " Revert InsetArgument to old syntax "
1610 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
1613 # Search for Argument insets
1614 i = find_token(document.body, "\\begin_inset Argument", i)
1617 m = rx.match(document.body[i])
1619 # No ID: inset already reverted
1622 # Find containing paragraph layout
1623 parent = get_containing_layout(document.body, i)
1625 document.warning("Malformed LyX document: Can't find parent paragraph layout")
1630 # Do not set realparbeg to parent[3], since this does not work if we
1631 # have another inset (e.g. label or index) before the first argument
1632 # inset (this is the case in the user guide of LyX 2.0.8)
1634 # Collect all arguments in this paragraph
1636 for p in range(parbeg, parend):
1637 m = rx.match(document.body[p])
1640 # This is the first argument inset
1642 val = int(m.group(1))
1643 j = find_end_of_inset(document.body, p)
1644 # Revert to old syntax
1645 document.body[p] = "\\begin_inset Argument"
1647 document.warning("Malformed LyX document: Can't find end of Argument inset")
1650 args[val] = document.body[p : j + 1]
1652 realparend = realparend - len(document.body[p : j + 1])
1653 # Remove arg inset at this position
1654 del document.body[p : j + 1]
1658 # No argument inset found
1659 realparbeg = parent[3]
1660 # Now sort the arg insets
1662 for f in sorted(args):
1665 # Insert the sorted arg insets at paragraph begin
1666 document.body[realparbeg : realparbeg] = subst
1668 i = realparbeg + 1 + len(subst)
1671 def revert_IEEEtran(document):
1673 Reverts InsetArgument of
1676 Biography without photo
1679 if document.textclass == "IEEEtran":
1686 i = find_token(document.body, "\\begin_layout Page headings", i)
1688 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1691 i2 = find_token(document.body, "\\begin_inset Flex Paragraph Start", i2)
1693 revert_Argument_to_TeX_brace(document, i2, 0, 1, 1, False, False)
1696 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1698 revert_Argument_to_TeX_brace(document, j, 0, 1, 1, True, False)
1701 k = find_token(document.body, "\\begin_layout Biography", k)
1702 kA = find_token(document.body, "\\begin_layout Biography without photo", k)
1703 if k == kA and k != -1:
1707 # start with the second argument, therefore 2
1708 revert_Argument_to_TeX_brace(document, k, 0, 2, 2, True, False)
1710 if i == -1 and i2 == -1 and j == -1 and k == -1:
1714 def revert_IEEEtran_2(document):
1716 Reverts Flex Paragraph Start to TeX-code
1718 if document.textclass == "IEEEtran":
1721 begin = find_token(document.body, "\\begin_inset Flex Paragraph Start", begin)
1724 end1 = find_end_of_inset(document.body, begin)
1725 document.body[end1 - 2 : end1 + 1] = put_cmd_in_ert("}")
1726 document.body[begin : begin + 4] = put_cmd_in_ert("\\IEEEPARstart{")
1730 def convert_IEEEtran(document):
1735 Biography without photo
1738 if document.textclass == "IEEEtran":
1744 i = find_token(document.body, "\\begin_layout Page headings", i)
1746 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1749 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1751 convert_TeX_brace_to_Argument(document, j, 1, 1, False, True, False)
1754 # assure that we don't handle Biography Biography without photo
1755 k = find_token(document.body, "\\begin_layout Biography", k)
1756 kA = find_token(document.body, "\\begin_layout Biography without photo", k - 1)
1757 if k == kA and k != -1:
1761 # the argument we want to convert is the second one
1762 convert_TeX_brace_to_Argument(document, k, 2, 2, False, True, False)
1764 if i == -1 and j == -1 and k == -1:
1768 def revert_AASTeX(document):
1769 " Reverts InsetArgument of Altaffilation to TeX-code "
1770 if document.textclass == "aastex":
1773 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1776 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1780 def convert_AASTeX(document):
1781 " Converts ERT of Altaffilation to InsetArgument "
1782 if document.textclass == "aastex":
1785 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1788 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1792 def revert_AGUTeX(document):
1793 " Reverts InsetArgument of Author affiliation to TeX-code "
1794 if document.textclass == "agutex":
1797 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1800 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1804 def convert_AGUTeX(document):
1805 " Converts ERT of Author affiliation to InsetArgument "
1806 if document.textclass == "agutex":
1809 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1812 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1816 def revert_IJMP(document):
1817 " Reverts InsetArgument of MarkBoth to TeX-code "
1818 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1821 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1824 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1828 def convert_IJMP(document):
1829 " Converts ERT of MarkBoth to InsetArgument "
1830 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1833 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1836 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1840 def revert_SIGPLAN(document):
1841 " Reverts InsetArguments of SIGPLAN to TeX-code "
1842 if document.textclass == "sigplanconf":
1847 i = find_token(document.body, "\\begin_layout Conference", i)
1849 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1852 j = find_token(document.body, "\\begin_layout Author", j)
1854 revert_Argument_to_TeX_brace(document, j, 0, 1, 2, False, False)
1856 if i == -1 and j == -1:
1860 def convert_SIGPLAN(document):
1861 " Converts ERT of SIGPLAN to InsetArgument "
1862 if document.textclass == "sigplanconf":
1867 i = find_token(document.body, "\\begin_layout Conference", i)
1869 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1872 j = find_token(document.body, "\\begin_layout Author", j)
1874 convert_TeX_brace_to_Argument(document, j, 1, 2, False, False, False)
1876 if i == -1 and j == -1:
1880 def revert_SIGGRAPH(document):
1881 " Reverts InsetArgument of Flex CRcat to TeX-code "
1882 if document.textclass == "acmsiggraph":
1885 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1888 revert_Argument_to_TeX_brace(document, i, 0, 1, 3, False, False)
1892 def convert_SIGGRAPH(document):
1893 " Converts ERT of Flex CRcat to InsetArgument "
1894 if document.textclass == "acmsiggraph":
1897 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1900 convert_TeX_brace_to_Argument(document, i, 1, 3, True, False, False)
1904 def revert_EuropeCV(document):
1905 " Reverts InsetArguments of europeCV to TeX-code "
1906 if document.textclass == "europecv":
1913 i = find_token(document.body, "\\begin_layout Item", i)
1915 revert_Argument_to_TeX_brace(document, i, 0, 2, 2, False, False)
1918 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1920 revert_Argument_to_TeX_brace(document, j, 0, 2, 2, False, False)
1923 k = find_token(document.body, "\\begin_layout Language", k)
1925 revert_Argument_to_TeX_brace(document, k, 0, 2, 6, False, False)
1928 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1930 revert_Argument_to_TeX_brace(document, m, 0, 2, 6, False, False)
1932 if i == -1 and j == -1 and k == -1 and m == -1:
1936 def convert_EuropeCV(document):
1937 " Converts ERT of europeCV to InsetArgument "
1938 if document.textclass == "europecv":
1945 i = find_token(document.body, "\\begin_layout Item", i)
1947 convert_TeX_brace_to_Argument(document, i, 2, 2, False, False, False)
1950 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1952 convert_TeX_brace_to_Argument(document, j, 2, 2, False, False, False)
1955 k = find_token(document.body, "\\begin_layout Language", k)
1957 convert_TeX_brace_to_Argument(document, k, 2, 6, False, False, False)
1960 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1962 convert_TeX_brace_to_Argument(document, m, 2, 6, False, False, False)
1964 if i == -1 and j == -1 and k == -1 and m == -1:
1968 def revert_ModernCV(document):
1969 " Reverts InsetArguments of modernCV to TeX-code "
1970 if document.textclass == "moderncv":
1978 j = find_token(document.body, "\\begin_layout Entry", j)
1980 revert_Argument_to_TeX_brace(document, j, 0, 1, 5, False, False)
1983 k = find_token(document.body, "\\begin_layout Item", k)
1985 revert_Argument_to_TeX_brace(document, k, 0, 1, 1, False, False)
1988 m = find_token(document.body, "\\begin_layout ItemWithComment", m)
1990 revert_Argument_to_TeX_brace(document, m, 0, 1, 2, False, False)
1991 document.body[m] = document.body[m].replace("\\begin_layout ItemWithComment", "\\begin_layout Language")
1994 o = find_token(document.body, "\\begin_layout DoubleItem", o)
1996 revert_Argument_to_TeX_brace(document, o, 0, 1, 3, False, False)
1997 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout Computer")
2000 p = find_token(document.body, "\\begin_layout Social", p)
2002 revert_Argument_to_TeX_brace(document, p, 0, 1, 1, False, True)
2004 if j == -1 and k == -1 and m == -1 and o == -1 and p == -1:
2008 def revert_ModernCV_2(document):
2009 " Reverts the Flex:Column inset of modernCV to TeX-code "
2010 if document.textclass == "moderncv":
2014 flex = find_token(document.body, "\\begin_inset Flex Column", flex)
2017 flexEnd = find_end_of_inset(document.body, flex)
2018 wasOpt = revert_Argument_to_TeX_brace(document, flex, flexEnd, 1, 1, False, True)
2019 revert_Argument_to_TeX_brace(document, flex, 0, 2, 2, False, False)
2020 flexEnd = find_end_of_inset(document.body, flex)
2022 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn")
2024 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn{")
2025 document.body[flexEnd + 4 : flexEnd + 7] = put_cmd_in_ert("}")
2029 def revert_ModernCV_3(document):
2030 " Reverts the Column style of modernCV to TeX-code "
2031 if document.textclass == "moderncv":
2032 # revert the layouts
2033 revert_ModernCV(document)
2035 # get the position of the end of the last column inset
2036 LastFlexEnd = revert_ModernCV_2(document)
2038 p = find_token(document.body, "\\begin_layout Columns", p)
2041 pEnd = find_end_of_layout(document.body, p)
2042 document.body[p] = document.body[p].replace("\\begin_layout Columns", "\\begin_layout Standard")
2043 if LastFlexEnd != -1:
2044 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\begin{cvcolumns}")
2045 document.body[LastFlexEnd + 24 : LastFlexEnd + 24] = put_cmd_in_ert("\\end{cvcolumns}")
2049 def revert_ModernCV_4(document):
2050 " Reverts the style Social to TeX-code "
2051 if document.textclass == "moderncv":
2052 # revert the layouts
2053 revert_ModernCV(document)
2056 p = find_token(document.body, "\\begin_layout Social", p)
2059 pEnd = find_end_of_layout(document.body, p)
2060 document.body[p] = document.body[p].replace("\\begin_layout Social", "\\begin_layout Standard")
2061 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\social")
2062 hasOpt = find_token(document.body, "[", p + 9)
2064 document.body[p + 30 : p + 30] = put_cmd_in_ert("{")
2065 document.body[p + 41 : p + 41] = put_cmd_in_ert("}")
2067 document.body[p + 11 : p + 11] = put_cmd_in_ert("{")
2068 document.body[p + 21 : p + 21] = put_cmd_in_ert("}")
2072 def convert_ModernCV(document):
2073 " Converts ERT of modernCV to InsetArgument "
2074 if document.textclass == "moderncv":
2082 i = find_token(document.body, "\\begin_layout DoubleItem", i)
2084 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
2085 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout DoubleListItem")
2088 j = find_token(document.body, "\\begin_layout Entry", j)
2090 convert_TeX_brace_to_Argument(document, j, 1, 5, False, False, False)
2093 k = find_token(document.body, "\\begin_layout Item", k)
2095 convert_TeX_brace_to_Argument(document, k, 1, 1, False, False, False)
2098 m = find_token(document.body, "\\begin_layout Language", m)
2100 convert_TeX_brace_to_Argument(document, m, 1, 2, False, False, False)
2102 if i == -1 and j == -1 and k == -1 and m == -1:
2106 def revert_Initials(document):
2107 " Reverts InsetArgument of Initial to TeX-code "
2110 i = find_token(document.body, "\\begin_layout Initial", i)
2113 # first arg (optional) and second arg (first mandatory) are supported in LyX 2.0.x
2114 revert_Argument_to_TeX_brace(document, i, 0, 3, 3, False, False)
2118 def convert_Initials(document):
2119 " Converts ERT of Initial to InsetArgument "
2122 i = find_token(document.body, "\\begin_layout Initial", i)
2125 convert_TeX_brace_to_Argument(document, i, 3, 3, False, False, False)
2129 def revert_literate(document):
2130 " Revert Literate document to old format "
2131 if del_token(document.header, "noweb", 0):
2132 document.textclass = "literate-" + document.textclass
2135 i = find_token(document.body, "\\begin_layout Chunk", i)
2138 document.body[i] = "\\begin_layout Scrap"
2142 def convert_literate(document):
2143 " Convert Literate document to new format"
2144 i = find_token(document.header, "\\textclass", 0)
2145 if (i != -1) and "literate-" in document.header[i]:
2146 document.textclass = document.header[i].replace("\\textclass literate-", "")
2147 j = find_token(document.header, "\\begin_modules", 0)
2149 document.header.insert(j + 1, "noweb")
2151 document.header.insert(i + 1, "\\end_modules")
2152 document.header.insert(i + 1, "noweb")
2153 document.header.insert(i + 1, "\\begin_modules")
2156 i = find_token(document.body, "\\begin_layout Scrap", i)
2159 document.body[i] = "\\begin_layout Chunk"
2163 def revert_itemargs(document):
2164 " Reverts \\item arguments to TeX-code "
2167 i = find_token(document.body, "\\begin_inset Argument item:", i)
2170 j = find_end_of_inset(document.body, i)
2171 # Find containing paragraph layout
2172 parent = get_containing_layout(document.body, i)
2174 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2178 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2179 endPlain = find_end_of_layout(document.body, beginPlain)
2180 content = document.body[beginPlain + 1 : endPlain]
2181 del document.body[i:j+1]
2182 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2183 document.body[parbeg : parbeg] = subst
2187 def revert_garamondx_newtxmath(document):
2188 " Revert native garamond newtxmath definition to LaTeX "
2190 i = find_token(document.header, "\\font_math", 0)
2193 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2194 val = get_value(document.header, "\\font_math", i)
2195 if val == "garamondx-ntxm":
2196 add_to_preamble(document, "\\usepackage[garamondx]{newtxmath}")
2197 document.header[i] = "\\font_math auto"
2200 def revert_garamondx(document):
2201 " Revert native garamond font definition to LaTeX "
2203 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2204 i = find_token(document.header, "\\font_roman garamondx", 0)
2207 j = find_token(document.header, "\\font_osf true", 0)
2210 preamble = "\\usepackage"
2212 preamble += "[osfI]"
2213 preamble += "{garamondx}"
2214 add_to_preamble(document, [preamble])
2215 document.header[i] = "\\font_roman default"
2218 def convert_beamerargs(document):
2219 " Converts beamer arguments to new layout "
2221 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2222 if document.textclass not in beamer_classes:
2225 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2226 list_layouts = ["Itemize", "Enumerate", "Description"]
2227 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
2231 i = find_token(document.body, "\\begin_inset Argument", i)
2234 # Find containing paragraph layout
2235 parent = get_containing_layout(document.body, i)
2237 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2242 layoutname = parent[0]
2243 for p in range(parbeg, parend):
2244 if layoutname in shifted_layouts:
2245 m = rx.match(document.body[p])
2247 argnr = int(m.group(1))
2249 document.body[p] = "\\begin_inset Argument %d" % argnr
2250 if layoutname == "AgainFrame":
2251 m = rx.match(document.body[p])
2253 document.body[p] = "\\begin_inset Argument 3"
2254 if document.body[p + 4] == "\\begin_inset ERT":
2255 if document.body[p + 9].startswith("<"):
2256 # This is an overlay specification
2258 document.body[p + 9] = document.body[p + 9][1:]
2259 if document.body[p + 9].endswith(">"):
2261 document.body[p + 9] = document.body[p + 9][:-1]
2263 document.body[p] = "\\begin_inset Argument 2"
2264 if layoutname in list_layouts:
2265 m = rx.match(document.body[p])
2267 if m.group(1) == "1":
2268 if document.body[p + 4] == "\\begin_inset ERT":
2269 if document.body[p + 9].startswith("<"):
2270 # This is an overlay specification
2272 document.body[p + 9] = document.body[p + 9][1:]
2273 if document.body[p + 9].endswith(">"):
2275 document.body[p + 9] = document.body[p + 9][:-1]
2276 elif document.body[p + 4].startswith("<"):
2277 # This is an overlay specification (without ERT)
2279 document.body[p + 4] = document.body[p + 4][1:]
2280 if document.body[p + 4].endswith(">"):
2282 document.body[p + 4] = document.body[p + 4][:-1]
2283 elif layoutname != "Itemize":
2285 document.body[p] = "\\begin_inset Argument 2"
2290 # Helper function for the frame conversion routines
2292 # FIXME: This method currently requires the arguments to be either
2293 # * In one (whole) ERT each: <ERT>[<arg1>]</ERT><ERT><arg2></ERT><ERT>[arg3]</ERT>
2294 # * Altogether in one whole ERT: <ERT>[<arg1>]<arg2>[arg3]</ERT>
2295 # If individual arguments mix ERT and non-ERT or are splitted
2296 # over several ERTs, the parsing fails.
2297 def convert_beamerframeargs(document, i, parbeg):
2300 if document.body[parbeg] != "\\begin_inset ERT":
2302 ertend = find_end_of_inset(document.body, parbeg)
2304 document.warning("Malformed LyX document: missing ERT \\end_inset")
2306 ertcont = parbeg + 5
2307 if document.body[ertcont].startswith("[<"):
2308 # This is a default overlay specification
2310 document.body[ertcont] = document.body[ertcont][2:]
2311 if document.body[ertcont].endswith(">]"):
2313 document.body[ertcont] = document.body[ertcont][:-2]
2314 elif document.body[ertcont].endswith("]"):
2316 tok = document.body[ertcont].find('>][')
2318 subst = [document.body[ertcont][:tok],
2319 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2320 'status collapsed', '', '\\begin_layout Plain Layout',
2321 document.body[ertcont][tok + 3:-1]]
2322 document.body[ertcont : ertcont + 1] = subst
2324 # Convert to ArgInset
2325 document.body[parbeg] = "\\begin_inset Argument 2"
2326 elif document.body[ertcont].startswith("<"):
2327 # This is an overlay specification
2329 document.body[ertcont] = document.body[ertcont][1:]
2330 if document.body[ertcont].endswith(">"):
2332 document.body[ertcont] = document.body[ertcont][:-1]
2333 # Convert to ArgInset
2334 document.body[parbeg] = "\\begin_inset Argument 1"
2335 elif document.body[ertcont].endswith(">]"):
2337 tok = document.body[ertcont].find('>[<')
2339 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2340 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2341 'status collapsed', '', '\\begin_layout Plain Layout',
2342 document.body[ertcont][tok + 3:-2]]
2343 # Convert to ArgInset
2344 document.body[parbeg] = "\\begin_inset Argument 1"
2346 elif document.body[ertcont].endswith("]"):
2348 tok = document.body[ertcont].find('>[<')
2351 tokk = document.body[ertcont].find('>][')
2353 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2354 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2355 'status collapsed', '', '\\begin_layout Plain Layout',
2356 document.body[ertcont][tok + 3:tokk],
2357 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2358 'status collapsed', '', '\\begin_layout Plain Layout',
2359 document.body[ertcont][tokk + 3:-1]]
2362 tokk = document.body[ertcont].find('>[')
2364 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tokk],
2365 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2366 'status collapsed', '', '\\begin_layout Plain Layout',
2367 document.body[ertcont][tokk + 2:-1]]
2369 # Convert to ArgInset
2370 document.body[parbeg] = "\\begin_inset Argument 1"
2371 elif document.body[ertcont].startswith("["):
2372 # This is an ERT option
2374 document.body[ertcont] = document.body[ertcont][1:]
2375 if document.body[ertcont].endswith("]"):
2377 document.body[ertcont] = document.body[ertcont][:-1]
2378 # Convert to ArgInset
2379 document.body[parbeg] = "\\begin_inset Argument 3"
2385 def convert_againframe_args(document):
2386 " Converts beamer AgainFrame to new layout "
2388 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2389 if document.textclass not in beamer_classes:
2394 i = find_token(document.body, "\\begin_layout AgainFrame", i)
2397 parent = get_containing_layout(document.body, i)
2399 document.warning("Wrong parent layout!")
2403 # Convert ERT arguments
2404 # FIXME: See restrictions in convert_beamerframeargs method
2405 ertend = convert_beamerframeargs(document, i, parbeg)
2411 def convert_corollary_args(document):
2412 " Converts beamer corrolary-style ERT arguments native InsetArgs "
2414 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2415 if document.textclass not in beamer_classes:
2418 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2419 for lay in corollary_layouts:
2422 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2425 parent = get_containing_layout(document.body, i)
2427 document.warning("Wrong parent layout!")
2431 if document.body[parbeg] == "\\begin_inset ERT":
2432 ertcontfirstline = parbeg + 5
2433 # Find the last ERT in this paragraph (which might also be the first)
2434 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
2435 if lastertbeg == -1:
2436 document.warning("Last ERT not found!")
2438 lastertend = find_end_of_inset(document.body, lastertbeg)
2439 if lastertend == -1:
2440 document.warning("End of last ERT not found!")
2442 ertcontlastline = lastertend - 3
2443 if document.body[ertcontfirstline].startswith("<"):
2444 # This is an overlay specification
2446 document.body[ertcontfirstline] = document.body[ertcontfirstline][1:]
2447 if document.body[ertcontlastline].endswith(">"):
2449 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
2450 if ertcontfirstline < ertcontlastline:
2451 # Multiline ERT. Might contain TeX code. Embrace in ERT.
2452 document.body[ertcontlastline : ertcontlastline + 1] = [
2453 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
2454 document.body[ertcontfirstline : ertcontfirstline + 1] = [
2455 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
2456 'status collapsed', '', '\\begin_layout Plain Layout',
2457 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
2458 document.body[ertcontfirstline]]
2460 # Convert to ArgInset
2461 document.body[parbeg] = "\\begin_inset Argument 1"
2462 elif document.body[ertcontlastline].endswith("]"):
2464 tok = document.body[ertcontfirstline].find('>[')
2466 if ertcontfirstline < ertcontlastline:
2467 # Multiline ERT. Might contain TeX code. Embrace in ERT.
2468 document.body[ertcontlastline : ertcontlastline + 1] = [
2469 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
2470 document.body[ertcontfirstline : ertcontfirstline + 1] = [document.body[ertcontfirstline][:tok],
2471 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2472 'status collapsed', '', '\\begin_layout Plain Layout',
2473 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
2474 document.body[ertcontfirstline][tok + 2:-1]]
2476 document.body[ertcontfirstline : ertcontfirstline + 1] = [document.body[ertcontfirstline][:tok],
2477 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2478 'status collapsed', '', '\\begin_layout Plain Layout',
2479 document.body[ertcontfirstline][tok + 2:-1]]
2480 # Convert to ArgInset
2481 document.body[parbeg] = "\\begin_inset Argument 1"
2484 elif document.body[ertcontlastline].startswith("["):
2485 if document.body[ertcontlastline].endswith("]"):
2486 # This is an ERT option
2488 document.body[ertcontlastline] = document.body[ertcontlastline][1:]
2490 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
2491 # Convert to ArgInset
2492 document.body[parbeg] = "\\begin_inset Argument 2"
2494 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, True)
2501 def convert_quote_args(document):
2502 " Converts beamer quote style ERT args to native InsetArgs "
2504 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2505 if document.textclass not in beamer_classes:
2508 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2509 for lay in quote_layouts:
2512 i = find_token(document.body, "\\begin_layout " + lay, i)
2515 parent = get_containing_layout(document.body, i)
2517 document.warning("Wrong parent layout!")
2521 if document.body[parbeg] == "\\begin_inset ERT":
2522 if document.body[i + 6].startswith("<"):
2523 # This is an overlay specification
2525 document.body[i + 6] = document.body[i + 6][1:]
2526 if document.body[i + 6].endswith(">"):
2528 document.body[i + 6] = document.body[i + 6][:-1]
2529 # Convert to ArgInset
2530 document.body[i + 1] = "\\begin_inset Argument 1"
2534 def cleanup_beamerargs(document):
2535 " Clean up empty ERTs (conversion artefacts) "
2537 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2538 if document.textclass not in beamer_classes:
2543 i = find_token(document.body, "\\begin_inset Argument", i)
2546 j = find_end_of_inset(document.body, i)
2548 document.warning("Malformed LyX document: Can't find end of Argument inset")
2552 ertbeg = find_token(document.body, "\\begin_inset ERT", i, j)
2555 ertend = find_end_of_inset(document.body, ertbeg)
2557 document.warning("Malformed LyX document: Can't find end of ERT inset")
2559 stripped = [line for line in document.body[ertbeg : ertend + 1] if line.strip()]
2560 if len(stripped) == 5:
2561 # This is an empty ERT
2562 offset = len(document.body[ertbeg : ertend + 1])
2563 del document.body[ertbeg : ertend + 1]
2570 def revert_beamerargs(document):
2571 " Reverts beamer arguments to old layout "
2573 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2574 if document.textclass not in beamer_classes:
2578 list_layouts = ["Itemize", "Enumerate", "Description"]
2579 headings = ["Part", "Section", "Section*", "Subsection", "Subsection*",
2580 "Subsubsection", "Subsubsection*", "FrameSubtitle", "NoteItem"]
2581 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2582 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2583 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2586 i = find_token(document.body, "\\begin_inset Argument", i)
2589 # Find containing paragraph layout
2590 parent = get_containing_layout(document.body, i)
2592 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2597 realparbeg = parent[3]
2598 layoutname = parent[0]
2600 for p in range(parbeg, parend):
2604 if layoutname in headings:
2605 m = rx.match(document.body[p])
2609 # Find containing paragraph layout
2610 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2611 endPlain = find_end_of_layout(document.body, beginPlain)
2612 endInset = find_end_of_inset(document.body, p)
2613 argcontent = document.body[beginPlain + 1 : endPlain]
2615 realparend = realparend - len(document.body[p : endInset + 1])
2617 del document.body[p : endInset + 1]
2618 if layoutname == "FrameSubtitle":
2619 pre = put_cmd_in_ert("\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2620 elif layoutname == "NoteItem":
2621 pre = put_cmd_in_ert("\\note<") + argcontent + put_cmd_in_ert(">[item]")
2622 elif layoutname.endswith('*'):
2623 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower()[:-1] + "<") + argcontent + put_cmd_in_ert(">*")
2625 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2626 secarg = find_token(document.body, "\\begin_inset Argument 2", parbeg, parend)
2628 # Find containing paragraph layout
2629 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", secarg)
2630 endPlain = find_end_of_layout(document.body, beginPlain)
2631 endInset = find_end_of_inset(document.body, secarg)
2632 argcontent = document.body[beginPlain + 1 : endPlain]
2634 realparend = realparend - len(document.body[secarg : endInset + 1])
2635 del document.body[secarg : endInset + 1]
2636 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2637 pre += put_cmd_in_ert("{")
2638 document.body[parbeg] = "\\begin_layout Standard"
2639 document.body[realparbeg : realparbeg] = pre
2640 pe = find_end_of_layout(document.body, parbeg)
2641 post = put_cmd_in_ert("}")
2642 document.body[pe : pe] = post
2643 realparend += len(pre) + len(post)
2644 if layoutname == "AgainFrame":
2645 m = rx.match(document.body[p])
2649 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2650 endPlain = find_end_of_layout(document.body, beginPlain)
2651 endInset = find_end_of_inset(document.body, p)
2652 content = document.body[beginPlain + 1 : endPlain]
2654 realparend = realparend - len(document.body[p : endInset + 1])
2656 del document.body[p : endInset + 1]
2657 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2658 document.body[realparbeg : realparbeg] = subst
2659 if layoutname == "Overprint":
2660 m = rx.match(document.body[p])
2664 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2665 endPlain = find_end_of_layout(document.body, beginPlain)
2666 endInset = find_end_of_inset(document.body, p)
2667 content = document.body[beginPlain + 1 : endPlain]
2669 realparend = realparend - len(document.body[p : endInset + 1])
2671 del document.body[p : endInset + 1]
2672 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2673 document.body[realparbeg : realparbeg] = subst
2674 if layoutname == "OverlayArea":
2675 m = rx.match(document.body[p])
2679 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2680 endPlain = find_end_of_layout(document.body, beginPlain)
2681 endInset = find_end_of_inset(document.body, p)
2682 content = document.body[beginPlain + 1 : endPlain]
2684 realparend = realparend - len(document.body[p : endInset + 1])
2686 del document.body[p : endInset + 1]
2687 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2688 document.body[realparbeg : realparbeg] = subst
2689 if layoutname in list_layouts:
2690 m = rx.match(document.body[p])
2694 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2695 endPlain = find_end_of_layout(document.body, beginPlain)
2696 endInset = find_end_of_inset(document.body, p)
2697 content = document.body[beginPlain + 1 : endPlain]
2698 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2699 realparend = realparend + len(subst) - len(content)
2700 document.body[beginPlain + 1 : endPlain] = subst
2701 elif argnr == "item:1":
2702 j = find_end_of_inset(document.body, i)
2703 # Find containing paragraph layout
2704 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2705 endPlain = find_end_of_layout(document.body, beginPlain)
2706 content = document.body[beginPlain + 1 : endPlain]
2707 del document.body[i:j+1]
2708 if layoutname == "Description":
2709 # Description only has one (overlay) item arg
2710 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2711 # This must be put after the first space (begin of decription body
2712 # in LyX's arkward description list syntax)
2713 # Try to find that place ...
2714 rxx = re.compile(r'^([^\\ ]+ )(.*)$')
2715 for q in range(parbeg, parend):
2716 m = rxx.match(document.body[q])
2718 # We found it. Now insert the ERT argument just there:
2719 document.body[q : q] = [m.group(1), ''] + subst + ['', m.group(2)]
2722 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2723 document.body[realparbeg : realparbeg] = subst
2724 elif argnr == "item:2":
2725 j = find_end_of_inset(document.body, i)
2726 # Find containing paragraph layout
2727 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2728 endPlain = find_end_of_layout(document.body, beginPlain)
2729 content = document.body[beginPlain + 1 : endPlain]
2730 del document.body[i:j+1]
2731 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2732 document.body[realparbeg : realparbeg] = subst
2733 if layoutname in quote_layouts:
2734 m = rx.match(document.body[p])
2738 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2739 endPlain = find_end_of_layout(document.body, beginPlain)
2740 endInset = find_end_of_inset(document.body, p)
2741 content = document.body[beginPlain + 1 : endPlain]
2743 realparend = realparend - len(document.body[p : endInset + 1])
2745 del document.body[p : endInset + 1]
2746 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2747 document.body[realparbeg : realparbeg] = subst
2748 if layoutname in corollary_layouts:
2749 m = rx.match(document.body[p])
2753 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2754 endPlain = find_end_of_layout(document.body, beginPlain)
2755 endInset = find_end_of_inset(document.body, p)
2756 content = document.body[beginPlain + 1 : endPlain]
2758 realparend = realparend - len(document.body[p : endInset + 1])
2760 del document.body[p : endInset + 1]
2761 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2762 document.body[realparbeg : realparbeg] = subst
2767 def revert_beamerargs2(document):
2768 " Reverts beamer arguments to old layout, step 2 "
2770 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2771 if document.textclass not in beamer_classes:
2775 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2776 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2777 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2780 i = find_token(document.body, "\\begin_inset Argument", i)
2783 # Find containing paragraph layout
2784 parent = get_containing_layout(document.body, i)
2786 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2791 realparbeg = parent[3]
2792 layoutname = parent[0]
2794 for p in range(parbeg, parend):
2798 if layoutname in shifted_layouts:
2799 m = rx.match(document.body[p])
2803 document.body[p] = "\\begin_inset Argument 1"
2804 if layoutname in corollary_layouts:
2805 m = rx.match(document.body[p])
2809 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2810 endPlain = find_end_of_layout(document.body, beginPlain)
2811 endInset = find_end_of_inset(document.body, p)
2812 content = document.body[beginPlain + 1 : endPlain]
2814 realparend = realparend - len(document.body[p : endInset + 1])
2816 del document.body[p : endInset + 1]
2817 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2818 document.body[realparbeg : realparbeg] = subst
2819 if layoutname == "OverlayArea":
2820 m = rx.match(document.body[p])
2824 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2825 endPlain = find_end_of_layout(document.body, beginPlain)
2826 endInset = find_end_of_inset(document.body, p)
2827 content = document.body[beginPlain + 1 : endPlain]
2829 realparend = realparend - len(document.body[p : endInset + 1])
2831 del document.body[p : endInset + 1]
2832 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2833 document.body[realparbeg : realparbeg] = subst
2834 if layoutname == "AgainFrame":
2835 m = rx.match(document.body[p])
2839 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2840 endPlain = find_end_of_layout(document.body, beginPlain)
2841 endInset = find_end_of_inset(document.body, p)
2842 content = document.body[beginPlain + 1 : endPlain]
2844 realparend = realparend - len(document.body[p : endInset + 1])
2846 del document.body[p : endInset + 1]
2847 subst = put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
2848 document.body[realparbeg : realparbeg] = subst
2852 def revert_beamerargs3(document):
2853 " Reverts beamer arguments to old layout, step 3 "
2855 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2856 if document.textclass not in beamer_classes:
2859 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2862 i = find_token(document.body, "\\begin_inset Argument", i)
2865 # Find containing paragraph layout
2866 parent = get_containing_layout(document.body, i)
2868 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2873 realparbeg = parent[3]
2874 layoutname = parent[0]
2876 for p in range(parbeg, parend):
2880 if layoutname == "AgainFrame":
2881 m = rx.match(document.body[p])
2885 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2886 endPlain = find_end_of_layout(document.body, beginPlain)
2887 endInset = find_end_of_inset(document.body, p)
2888 content = document.body[beginPlain + 1 : endPlain]
2890 realparend = realparend - len(document.body[p : endInset + 1])
2892 del document.body[p : endInset + 1]
2893 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2894 document.body[realparbeg : realparbeg] = subst
2898 def revert_beamerflex(document):
2899 " Reverts beamer Flex insets "
2901 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2902 if document.textclass not in beamer_classes:
2905 new_flexes = {"Bold" : "\\textbf", "Emphasize" : "\\emph", "Only" : "\\only",
2906 "Uncover" : "\\uncover", "Visible" : "\\visible",
2907 "Invisible" : "\\invisible", "Alternative" : "\\alt",
2908 "Beamer_Note" : "\\note"}
2909 old_flexes = {"Alert" : "\\alert", "Structure" : "\\structure"}
2910 rx = re.compile(r'^\\begin_inset Flex (.+)$')
2914 i = find_token(document.body, "\\begin_inset Flex", i)
2917 m = rx.match(document.body[i])
2919 flextype = m.group(1)
2920 z = find_end_of_inset(document.body, i)
2922 document.warning("Can't find end of Flex " + flextype + " inset.")
2925 if flextype in new_flexes:
2926 pre = put_cmd_in_ert(new_flexes[flextype])
2927 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2929 argend = find_end_of_inset(document.body, arg)
2931 document.warning("Can't find end of Argument!")
2934 # Find containing paragraph layout
2935 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2936 endPlain = find_end_of_layout(document.body, beginPlain)
2937 argcontent = document.body[beginPlain + 1 : endPlain]
2939 z = z - len(document.body[arg : argend + 1])
2941 del document.body[arg : argend + 1]
2942 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2943 arg = find_token(document.body, "\\begin_inset Argument 2", i, z)
2945 argend = find_end_of_inset(document.body, arg)
2947 document.warning("Can't find end of Argument!")
2950 # Find containing paragraph layout
2951 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2952 endPlain = find_end_of_layout(document.body, beginPlain)
2953 argcontent = document.body[beginPlain + 1 : endPlain]
2955 z = z - len(document.body[arg : argend + 1])
2957 del document.body[arg : argend + 1]
2958 if flextype == "Alternative":
2959 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
2961 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2962 pre += put_cmd_in_ert("{")
2963 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2964 endPlain = find_end_of_layout(document.body, beginPlain)
2966 z = z - len(document.body[i : beginPlain + 1])
2968 document.body[i : beginPlain + 1] = pre
2969 post = put_cmd_in_ert("}")
2970 document.body[z - 2 : z + 1] = post
2971 elif flextype in old_flexes:
2972 pre = put_cmd_in_ert(old_flexes[flextype])
2973 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2977 argend = find_end_of_inset(document.body, arg)
2979 document.warning("Can't find end of Argument!")
2982 # Find containing paragraph layout
2983 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2984 endPlain = find_end_of_layout(document.body, beginPlain)
2985 argcontent = document.body[beginPlain + 1 : endPlain]
2987 z = z - len(document.body[arg : argend + 1])
2989 del document.body[arg : argend + 1]
2990 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2991 pre += put_cmd_in_ert("{")
2992 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2993 endPlain = find_end_of_layout(document.body, beginPlain)
2995 z = z - len(document.body[i : beginPlain + 1])
2997 document.body[i : beginPlain + 1] = pre
2998 post = put_cmd_in_ert("}")
2999 document.body[z - 2 : z + 1] = post
3004 def revert_beamerblocks(document):
3005 " Reverts beamer block arguments to ERT "
3007 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3008 if document.textclass not in beamer_classes:
3011 blocks = ["Block", "ExampleBlock", "AlertBlock"]
3013 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3016 i = find_token(document.body, "\\begin_inset Argument", i)
3019 # Find containing paragraph layout
3020 parent = get_containing_layout(document.body, i)
3022 document.warning("Malformed LyX document: Can't find parent paragraph layout")
3027 realparbeg = parent[3]
3028 layoutname = parent[0]
3030 for p in range(parbeg, parend):
3034 if layoutname in blocks:
3035 m = rx.match(document.body[p])
3039 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3040 endPlain = find_end_of_layout(document.body, beginPlain)
3041 endInset = find_end_of_inset(document.body, p)
3042 content = document.body[beginPlain + 1 : endPlain]
3044 realparend = realparend - len(document.body[p : endInset + 1])
3046 del document.body[p : endInset + 1]
3047 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3048 document.body[realparbeg : realparbeg] = subst
3050 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3051 endPlain = find_end_of_layout(document.body, beginPlain)
3052 endInset = find_end_of_inset(document.body, p)
3053 content = document.body[beginPlain + 1 : endPlain]
3055 realparend = realparend - len(document.body[p : endInset + 1])
3057 del document.body[p : endInset + 1]
3058 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3059 document.body[realparbeg : realparbeg] = subst
3064 def convert_beamerblocks(document):
3065 " Converts beamer block ERT args to native InsetArgs "
3067 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3068 if document.textclass not in beamer_classes:
3071 blocks = ["Block", "ExampleBlock", "AlertBlock"]
3075 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
3078 parent = get_containing_layout(document.body, i)
3079 if parent == False or parent[1] != i:
3080 document.warning("Wrong parent layout!")
3087 # If the paragraph starts with a language switch, adjust parbeg
3088 if len(document.body[parbeg]) == 0 and parbeg < parend \
3089 and document.body[parbeg + 1].startswith("\\lang"):
3091 if document.body[parbeg] == "\\begin_inset ERT":
3092 ertcontfirstline = parbeg + 5
3096 # Find the last ERT in this paragraph used for arguments
3097 # (which might also be the first)
3098 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
3099 if lastertbeg == -1:
3100 document.warning("Last ERT not found!")
3102 lastertend = find_end_of_inset(document.body, lastertbeg)
3103 if lastertend == -1:
3104 document.warning("End of last ERT not found!")
3106 # Is this ERT really used for an argument?
3107 # Note: This will fail when non-argument ERTs actually use brackets
3109 regexp = re.compile(r'.*[>\]\}]', re.IGNORECASE)
3110 cbracket = find_re(document.body, regexp, lastertbeg, lastertend)
3113 if lastertbeg == parbeg:
3116 if lastertbeg == -1 or lastertend == -1:
3118 ertcontlastline = lastertend - 3
3120 if document.body[ertcontfirstline].lstrip().startswith("<"):
3121 # This is an overlay specification
3123 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3124 if document.body[ertcontlastline].rstrip().endswith(">"):
3126 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3127 # Convert to ArgInset
3128 document.body[parbeg] = "\\begin_inset Argument 1"
3129 elif document.body[ertcontlastline].rstrip().endswith("}"):
3131 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3133 ertcontdivline = ertcontfirstline
3134 tok = document.body[ertcontdivline].find('>{')
3136 regexp = re.compile(r'.*>\{', re.IGNORECASE)
3137 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3138 tok = document.body[ertcontdivline].find('>{')
3140 if ertcontfirstline < ertcontlastline:
3141 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3142 document.body[ertcontlastline : ertcontlastline + 1] = [
3143 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3144 if ertcontdivline == ertcontfirstline:
3145 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3146 '\\end_layout', '', '\\end_inset', '',
3147 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3148 'status collapsed', '', '\\begin_layout Plain Layout',
3149 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3150 document.body[ertcontdivline][tok + 2:]]
3152 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3153 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3154 'status collapsed', '', '\\begin_layout Plain Layout',
3155 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3156 document.body[ertcontdivline][tok + 2:]]
3158 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3159 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3160 'status collapsed', '', '\\begin_layout Plain Layout',
3161 document.body[ertcontdivline][tok + 2:]]
3163 # check if have delimiters in two different ERTs
3164 tok = document.body[ertcontdivline].find('>')
3166 regexp = re.compile(r'.*>', re.IGNORECASE)
3167 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3168 tok = document.body[ertcontdivline].find('>')
3170 tokk = document.body[ertcontdivline].find('{')
3172 regexp = re.compile(r'.*\{', re.IGNORECASE)
3173 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, lastertend)
3174 tokk = document.body[ertcontdivlinetwo].find('{')
3176 if ertcontfirstline < ertcontlastline:
3177 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3178 document.body[ertcontlastline : ertcontlastline + 1] = [
3179 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3180 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3181 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3182 '\\end_inset', '', '', '\\begin_inset Argument 2',
3183 'status collapsed', '', '\\begin_layout Plain Layout',
3184 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3185 document.body[ertcontdivlinetwo][tokk + 1:]]
3187 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3188 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3189 'status collapsed', '', '\\begin_layout Plain Layout',
3190 document.body[ertcontdivlinetwo][tokk + 1:]]
3191 # Convert to ArgInset
3192 if ertcontfirstline < ertcontlastline:
3193 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3194 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 1',
3195 'status collapsed', '', '\\begin_layout Plain Layout',
3196 '\\begin_inset ERT', '']
3198 document.body[parbeg] = "\\begin_inset Argument 1"
3199 elif document.body[ertcontfirstline].lstrip().startswith("{"):
3200 # This is the block title
3201 if document.body[ertcontlastline].rstrip().endswith("}"):
3202 # strip off the braces
3203 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3204 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3205 if ertcontfirstline < ertcontlastline:
3206 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3207 document.body[parend : parend + 1] = [
3208 document.body[parend], '\\end_inset', '', '\\end_layout']
3209 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3210 'status collapsed', '', '\\begin_layout Plain Layout',
3211 '\\begin_inset ERT', '']
3213 # Convert to ArgInset
3214 document.body[parbeg] = "\\begin_inset Argument 2"
3215 # the overlay argument can also follow the title, so ...
3216 elif document.body[ertcontlastline].rstrip().endswith(">"):
3218 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3220 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3222 ertcontdivline = ertcontfirstline
3223 tok = document.body[ertcontdivline].find('}<')
3225 regexp = re.compile(r'.*\}<', re.IGNORECASE)
3226 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3227 tok = document.body[ertcontdivline].find('}<')
3229 if ertcontfirstline < ertcontlastline:
3230 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3231 document.body[ertcontlastline : ertcontlastline + 1] = [
3232 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3233 if ertcontdivline == ertcontfirstline:
3234 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3235 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3236 'status collapsed', '', '\\begin_layout Plain Layout',
3237 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3238 document.body[ertcontdivline][tok + 2:]]
3240 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3241 '\\end_layout', '', '\\end_inset', '',
3242 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3243 'status collapsed', '', '\\begin_layout Plain Layout',
3244 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3245 document.body[ertcontdivline][tok + 2:]]
3247 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3248 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3249 'status collapsed', '', '\\begin_layout Plain Layout',
3250 document.body[ertcontdivline][tok + 2:]]
3252 # check if have delimiters in two different ERTs
3253 tok = document.body[ertcontdivline].find('}')
3255 regexp = re.compile(r'.*\}', re.IGNORECASE)
3256 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3257 tok = document.body[ertcontdivline].find('}')
3259 tokk = document.body[ertcontdivline].find('<')
3261 regexp = re.compile(r'.*<', re.IGNORECASE)
3262 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, lastertend)
3263 tokk = document.body[ertcontdivlinetwo].find('<')
3265 if ertcontfirstline < ertcontlastline:
3266 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3267 document.body[ertcontlastline : ertcontlastline + 1] = [
3268 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3269 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3270 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3271 '\\end_inset', '', '', '\\begin_inset Argument 1',
3272 'status collapsed', '', '\\begin_layout Plain Layout',
3273 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3274 document.body[ertcontdivlinetwo][tokk + 1:]]
3276 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3277 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3278 'status collapsed', '', '\\begin_layout Plain Layout',
3279 document.body[ertcontdivlinetwo][tokk + 1:]]
3280 # Convert to ArgInset
3281 if ertcontfirstline < ertcontlastline:
3282 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3283 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3284 'status collapsed', '', '\\begin_layout Plain Layout',
3285 '\\begin_inset ERT', '']
3287 document.body[parbeg] = "\\begin_inset Argument 2"
3288 elif count_pars_in_inset(document.body, ertcontfirstline) > 1:
3289 # Multipar ERT. Skip this.
3292 # ERT has contents after the closing bracket. We cannot convert this.
3293 # convert_TeX_brace_to_Argument cannot either.
3294 #convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, False)
3298 j = find_end_of_layout(document.body, i)
3300 document.warning("end of layout not found!")
3301 k = find_token(document.body, "\\begin_inset Argument", i, j)
3303 document.warning("InsetArgument not found!")
3305 l = find_end_of_inset(document.body, k)
3306 m = find_token(document.body, "\\begin_inset ERT", l, j)
3309 ertcontfirstline = m + 5
3314 def convert_overprint(document):
3315 " Convert old beamer overprint layouts to ERT "
3317 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3318 if document.textclass not in beamer_classes:
3323 i = find_token(document.body, "\\begin_layout Overprint", i)
3326 # Find end of sequence
3327 j = find_end_of_sequence(document.body, i)
3329 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3333 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3335 if document.body[j] == "\\end_deeper":
3336 esubst = ["", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3338 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3339 endseq = endseq + len(esubst) - len(document.body[j : j])
3340 document.body[j : j] = esubst
3341 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3343 argend = find_end_of_layout(document.body, argbeg)
3345 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3348 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3349 endPlain = find_end_of_layout(document.body, beginPlain)
3350 content = document.body[beginPlain + 1 : endPlain]
3352 endseq = endseq - len(document.body[argbeg : argend + 1])
3354 del document.body[argbeg : argend + 1]
3355 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3357 endseq = endseq - len(document.body[i : i])
3358 document.body[i : i] = subst + ["\\end_layout"]
3359 endseq += len(subst)
3361 for p in range(i, endseq):
3362 if document.body[p] == "\\begin_layout Overprint":
3363 document.body[p] = "\\begin_layout Standard"
3368 def revert_overprint(document):
3369 " Revert old beamer overprint layouts to ERT "
3371 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3372 if document.textclass not in beamer_classes:
3377 i = find_token(document.body, "\\begin_layout Overprint", i)
3380 # Find end of sequence
3381 j = find_end_of_sequence(document.body, i)
3383 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3387 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3388 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}")
3389 endseq = endseq + len(esubst) - len(document.body[j : j])
3390 if document.body[j] == "\\end_deeper":
3391 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3393 document.body[j : j] = ["\\end_layout", ""] + esubst
3396 if document.body[r] == "\\begin_deeper":
3397 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3399 document.body[r] = ""
3400 document.body[s] = ""
3404 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3406 # Is this really our argument?
3407 nested = find_token(document.body, "\\begin_deeper", i, argbeg)
3409 argend = find_end_of_inset(document.body, argbeg)
3411 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3414 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3415 endPlain = find_end_of_layout(document.body, beginPlain)
3416 content = document.body[beginPlain + 1 : endPlain]
3418 endseq = endseq - len(document.body[argbeg : argend])
3420 del document.body[argbeg : argend + 1]
3421 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3423 endseq = endseq - len(document.body[i : i])
3424 document.body[i : i] = subst + ["\\end_layout"]
3425 endseq += len(subst)
3431 if document.body[p] == "\\begin_layout Overprint":
3432 q = find_end_of_layout(document.body, p)
3434 document.warning("Malformed LyX document. Cannot find end of Overprint layout!")
3437 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\onslide")
3438 argbeg = find_token(document.body, "\\begin_inset Argument item:1", p, q)
3440 argend = find_end_of_inset(document.body, argbeg)
3442 document.warning("Malformed LyX document. Cannot find end of Overprint item argument!")
3445 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3446 endPlain = find_end_of_layout(document.body, beginPlain)
3447 content = document.body[beginPlain + 1 : endPlain]
3449 endseq = endseq - len(document.body[argbeg : argend + 1])
3451 del document.body[argbeg : argend + 1]
3452 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3453 endseq = endseq - len(document.body[p : p + 1]) + len(subst)
3454 document.body[p : p + 1] = subst
3460 def revert_frametitle(document):
3461 " Reverts beamer frametitle layout to ERT "
3463 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3464 if document.textclass not in beamer_classes:
3467 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3470 i = find_token(document.body, "\\begin_layout FrameTitle", i)
3473 j = find_end_of_layout(document.body, i)
3475 document.warning("Malformed LyX document: Can't find end of FrameTitle layout")
3479 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
3480 endlay += len(put_cmd_in_ert("}"))
3481 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\frametitle")
3482 for p in range(i, j):
3485 m = rx.match(document.body[p])
3489 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3490 endPlain = find_end_of_layout(document.body, beginPlain)
3491 endInset = find_end_of_inset(document.body, p)
3492 content = document.body[beginPlain + 1 : endPlain]
3494 endlay = endlay - len(document.body[p : endInset + 1])
3496 del document.body[p : endInset + 1]
3497 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3499 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3500 endPlain = find_end_of_layout(document.body, beginPlain)
3501 endInset = find_end_of_inset(document.body, p)
3502 content = document.body[beginPlain + 1 : endPlain]
3504 endlay = endlay - len(document.body[p : endInset + 1])
3506 del document.body[p : endInset + 1]
3507 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3509 subst += put_cmd_in_ert("{")
3510 document.body[i : i + 1] = subst
3514 def convert_epigraph(document):
3515 " Converts memoir epigraph to new syntax "
3517 if document.textclass != "memoir":
3522 i = find_token(document.body, "\\begin_layout Epigraph", i)
3525 j = find_end_of_layout(document.body, i)
3527 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3532 ert = find_token(document.body, "\\begin_inset ERT", i, j)
3534 endInset = find_end_of_inset(document.body, ert)
3535 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", ert)
3536 endPlain = find_end_of_layout(document.body, beginPlain)
3537 ertcont = beginPlain + 2
3538 if document.body[ertcont] == "}{":
3540 # Convert to ArgInset
3541 endlay = endlay - 2 * len(document.body[j])
3542 begsubst = ['\\begin_inset Argument post:1', 'status collapsed', '',
3543 '\\begin_layout Plain Layout']
3544 endsubst = ['\\end_layout', '', '\\end_inset', '', document.body[j]]
3545 document.body[j : j + 1] = endsubst
3546 document.body[endInset + 1 : endInset + 1] = begsubst
3548 endlay += len(begsubst) + len(endsubst)
3549 endlay = endlay - len(document.body[ert : endInset + 1])
3550 del document.body[ert : endInset + 1]
3555 def revert_epigraph(document):
3556 " Reverts memoir epigraph argument to ERT "
3558 if document.textclass != "memoir":
3563 i = find_token(document.body, "\\begin_layout Epigraph", i)
3566 j = find_end_of_layout(document.body, i)
3568 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3573 p = find_token(document.body, "\\begin_layout Argument post:1", i, j)
3575 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3576 endPlain = find_end_of_layout(document.body, beginPlain)
3577 endInset = find_end_of_inset(document.body, p)
3578 content = document.body[beginPlain + 1 : endPlain]
3580 endlay = endlay - len(document.body[p : endInset + 1])
3582 del document.body[p : endInset + 1]
3583 subst += put_cmd_in_ert("}{") + content
3585 subst += put_cmd_in_ert("}{")
3587 document.body[j : j] = subst + document.body[j : j]
3591 def convert_captioninsets(document):
3592 " Converts caption insets to new syntax "
3596 i = find_token(document.body, "\\begin_inset Caption", i)
3599 document.body[i] = "\\begin_inset Caption Standard"
3603 def revert_captioninsets(document):
3604 " Reverts caption insets to old syntax "
3608 i = find_token(document.body, "\\begin_inset Caption Standard", i)
3611 document.body[i] = "\\begin_inset Caption"
3615 def convert_captionlayouts(document):
3616 " Convert caption layouts to caption insets. "
3619 "Captionabove": "Above",
3620 "Captionbelow": "Below",
3621 "FigCaption" : "FigCaption",
3622 "Table_Caption" : "Table",
3623 "CenteredCaption" : "Centered",
3624 "Bicaption" : "Bicaption",
3629 i = find_token(document.body, "\\begin_layout", i)
3632 val = get_value(document.body, "\\begin_layout", i)
3633 if val in list(caption_dict.keys()):
3634 j = find_end_of_layout(document.body, i)
3636 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3639 document.body[j:j] = ["\\end_layout", "", "\\end_inset", "", ""]
3640 document.body[i:i+1] = ["\\begin_layout %s" % document.default_layout,
3641 "\\begin_inset Caption %s" % caption_dict[val], "",
3642 "\\begin_layout %s" % document.default_layout]
3646 def revert_captionlayouts(document):
3647 " Revert caption insets to caption layouts. "
3650 "Above" : "Captionabove",
3651 "Below" : "Captionbelow",
3652 "FigCaption" : "FigCaption",
3653 "Table" : "Table_Caption",
3654 "Centered" : "CenteredCaption",
3655 "Bicaption" : "Bicaption",
3659 rx = re.compile(r'^\\begin_inset Caption (\S+)$')
3661 i = find_token(document.body, "\\begin_inset Caption", i)
3665 m = rx.match(document.body[i])
3669 if val not in list(caption_dict.keys()):
3673 # We either need to delete the previous \begin_layout line, or we
3674 # need to end the previous layout if this inset is not in the first
3675 # position of the paragraph.
3676 layout_before = find_token_backwards(document.body, "\\begin_layout", i)
3677 if layout_before == -1:
3678 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3680 layout_line = document.body[layout_before]
3681 del_layout_before = True
3682 l = layout_before + 1
3684 if document.body[l] != "":
3685 del_layout_before = False
3688 if del_layout_before:
3689 del document.body[layout_before:i]
3692 document.body[i:i] = ["\\end_layout", ""]
3695 # Find start of layout in the inset and end of inset
3696 j = find_token(document.body, "\\begin_layout", i)
3698 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3700 k = find_end_of_inset(document.body, i)
3702 document.warning("Malformed LyX document: Missing `\\end_inset'.")
3705 # We either need to delete the following \end_layout line, or we need
3706 # to restart the old layout if this inset is not at the paragraph end.
3707 layout_after = find_token(document.body, "\\end_layout", k)
3708 if layout_after == -1:
3709 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3711 del_layout_after = True
3713 while l < layout_after:
3714 if document.body[l] != "":
3715 del_layout_after = False
3718 if del_layout_after:
3719 del document.body[k+1:layout_after+1]
3721 document.body[k+1:k+1] = [layout_line, ""]
3723 # delete \begin_layout and \end_inset and replace \begin_inset with
3724 # "\begin_layout XXX". This works because we can only have one
3725 # paragraph in the caption inset: The old \end_layout will be recycled.
3726 del document.body[k]
3727 if document.body[k] == "":
3728 del document.body[k]
3729 del document.body[j]
3730 if document.body[j] == "":
3731 del document.body[j]
3732 document.body[i] = "\\begin_layout %s" % caption_dict[val]
3733 if document.body[i+1] == "":
3734 del document.body[i+1]
3738 def revert_fragileframe(document):
3739 " Reverts beamer FragileFrame layout to ERT "
3741 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3742 if document.textclass not in beamer_classes:
3747 i = find_token(document.body, "\\begin_layout FragileFrame", i)
3750 # Find end of sequence
3751 j = find_end_of_sequence(document.body, i)
3753 document.warning("Malformed LyX document. Cannot find end of FragileFrame sequence!")
3757 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{frame}")
3758 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{frame}")
3759 endseq = endseq + len(esubst) - len(document.body[j : j])
3760 if document.body[j] == "\\end_deeper":
3761 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3763 document.body[j : j] = esubst
3764 for q in range(i, j):
3765 if document.body[q] == "\\begin_layout FragileFrame":
3766 document.body[q] = "\\begin_layout %s" % document.default_layout
3769 if document.body[r] == "\\begin_deeper":
3770 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3772 document.body[r] = ""
3773 document.body[s] = ""
3777 for p in range(1, 5):
3778 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, j)
3781 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3782 endPlain = find_end_of_layout(document.body, beginPlain)
3783 endInset = find_end_of_inset(document.body, arg)
3784 content = document.body[beginPlain + 1 : endPlain]
3786 j = j - len(document.body[arg : endInset + 1])
3788 del document.body[arg : endInset + 1]
3789 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3791 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3792 endPlain = find_end_of_layout(document.body, beginPlain)
3793 endInset = find_end_of_inset(document.body, arg)
3794 content = document.body[beginPlain + 1 : endPlain]
3796 j = j - len(document.body[arg : endInset + 1])
3798 del document.body[arg : endInset + 1]
3799 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3801 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3802 endPlain = find_end_of_layout(document.body, beginPlain)
3803 endInset = find_end_of_inset(document.body, arg)
3804 content = document.body[beginPlain + 1 : endPlain]
3806 j = j - len(document.body[arg : endInset + 1])
3808 del document.body[arg : endInset + 1]
3809 subst += put_cmd_in_ert("[fragile,") + content + put_cmd_in_ert("]")
3811 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3812 endPlain = find_end_of_layout(document.body, beginPlain)
3813 endInset = find_end_of_inset(document.body, arg)
3814 content = document.body[beginPlain + 1 : endPlain]
3816 j = j - len(document.body[arg : endInset + 1])
3818 del document.body[arg : endInset + 1]
3819 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3821 subst += put_cmd_in_ert("[fragile]")
3823 document.body[i : i + 1] = subst
3827 def revert_newframes(document):
3828 " Reverts beamer Frame and PlainFrame layouts to old forms "
3830 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3831 if document.textclass not in beamer_classes:
3835 "Frame" : "BeginFrame",
3836 "PlainFrame" : "BeginPlainFrame",
3839 rx = re.compile(r'^\\begin_layout (\S+)$')
3842 i = find_token(document.body, "\\begin_layout", i)
3846 m = rx.match(document.body[i])
3850 if val not in list(frame_dict.keys()):
3853 # Find end of sequence
3854 j = find_end_of_sequence(document.body, i)
3856 document.warning("Malformed LyX document. Cannot find end of Frame sequence!")
3860 subst = ["\\begin_layout %s" % frame_dict[val]]
3861 esubst = ["", "\\begin_layout EndFrame", "", "\\end_layout"]
3862 endseq = endseq + len(esubst) - len(document.body[j : j])
3863 if document.body[j] == "\\end_deeper":
3864 document.body[j : j] = esubst
3866 document.body[j+1 : j+1] = esubst
3867 for q in range(i, j):
3868 if document.body[q] == "\\begin_layout %s" % val:
3869 document.body[q] = "\\begin_layout %s" % document.default_layout
3872 if document.body[r] == "\\begin_deeper":
3873 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3875 document.body[r] = ""
3876 document.body[s] = ""
3880 l = find_end_of_layout(document.body, i)
3881 for p in range(1, 5):
3882 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, l)
3885 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3886 endPlain = find_end_of_layout(document.body, beginPlain)
3887 endInset = find_end_of_inset(document.body, arg)
3888 content = document.body[beginPlain + 1 : endPlain]
3890 l = l - len(document.body[arg : endInset + 1])
3892 del document.body[arg : endInset + 1]
3893 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3895 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3896 endPlain = find_end_of_layout(document.body, beginPlain)
3897 endInset = find_end_of_inset(document.body, arg)
3898 content = document.body[beginPlain + 1 : endPlain]
3900 l = l - len(document.body[arg : endInset + 1])
3902 del document.body[arg : endInset + 1]
3903 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3905 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3906 endPlain = find_end_of_layout(document.body, beginPlain)
3907 endInset = find_end_of_inset(document.body, arg)
3908 content = document.body[beginPlain + 1 : endPlain]
3910 l = l - len(document.body[arg : endInset + 1])
3912 del document.body[arg : endInset + 1]
3913 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3915 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3916 endPlain = find_end_of_layout(document.body, beginPlain)
3917 endInset = find_end_of_inset(document.body, arg)
3918 content = document.body[beginPlain + 1 : endPlain]
3920 l = l - len(document.body[arg : endInset + 1])
3922 del document.body[arg : endInset + 1]
3925 document.body[i : i + 1] = subst
3928 # known encodings that do not change their names (same LyX and LaTeX names)
3929 known_enc_tuple = ("auto", "default", "ansinew", "applemac", "armscii8", "ascii",
3930 "cp437", "cp437de", "cp850", "cp852", "cp855", "cp858", "cp862", "cp865", "cp866",
3931 "cp1250", "cp1251", "cp1252", "cp1255", "cp1256", "cp1257", "koi8-r", "koi8-u",
3932 "pt154", "pt254", "tis620-0", "utf8", "utf8x", "utf8-plain")
3934 def convert_encodings(document):
3935 "Use the LyX names of the encodings instead of the LaTeX names."
3936 LaTeX2LyX_enc_dict = {
3937 "8859-6": "iso8859-6",
3938 "8859-8": "iso8859-8",
3940 "euc": "euc-jp-platex",
3945 "iso88595": "iso8859-5",
3946 "iso-8859-7": "iso8859-7",
3948 "jis": "jis-platex",
3950 "l7xenc": "iso8859-13",
3951 "latin1": "iso8859-1",
3952 "latin2": "iso8859-2",
3953 "latin3": "iso8859-3",
3954 "latin4": "iso8859-4",
3955 "latin5": "iso8859-9",
3956 "latin9": "iso8859-15",
3957 "latin10": "iso8859-16",
3958 "SJIS": "shift-jis",
3959 "sjis": "shift-jis-platex",
3962 i = find_token(document.header, "\\inputencoding" , 0)
3965 val = get_value(document.header, "\\inputencoding", i)
3966 if val in list(LaTeX2LyX_enc_dict.keys()):
3967 document.header[i] = "\\inputencoding %s" % LaTeX2LyX_enc_dict[val]
3968 elif val not in known_enc_tuple:
3969 document.warning("Ignoring unknown input encoding: `%s'" % val)
3972 def revert_encodings(document):
3973 """Revert to using the LaTeX names of the encodings instead of the LyX names.
3974 Also revert utf8-platex to sjis, the language default when using Japanese.
3976 LyX2LaTeX_enc_dict = {
3981 "euc-jp-platex": "euc",
3984 "iso8859-1": "latin1",
3985 "iso8859-2": "latin2",
3986 "iso8859-3": "latin3",
3987 "iso8859-4": "latin4",
3988 "iso8859-5": "iso88595",
3989 "iso8859-6": "8859-6",
3990 "iso8859-7": "iso-8859-7",
3991 "iso8859-8": "8859-8",
3992 "iso8859-9": "latin5",
3993 "iso8859-13": "l7xenc",
3994 "iso8859-15": "latin9",
3995 "iso8859-16": "latin10",
3997 "jis-platex": "jis",
3998 "shift-jis": "SJIS",
3999 "shift-jis-platex": "sjis",
4001 "utf8-platex": "sjis"
4003 i = find_token(document.header, "\\inputencoding" , 0)
4006 val = get_value(document.header, "\\inputencoding", i)
4007 if val in list(LyX2LaTeX_enc_dict.keys()):
4008 document.header[i] = "\\inputencoding %s" % LyX2LaTeX_enc_dict[val]
4009 elif val not in known_enc_tuple:
4010 document.warning("Ignoring unknown input encoding: `%s'" % val)
4013 def revert_IEEEtran_3(document):
4015 Reverts Flex Insets to TeX-code
4017 if document.textclass == "IEEEtran":
4023 h = find_token(document.body, "\\begin_inset Flex Author Mark", h)
4025 endh = find_end_of_inset(document.body, h)
4026 document.body[endh - 2 : endh + 1] = put_cmd_in_ert("}")
4027 document.body[h : h + 4] = put_cmd_in_ert("\\IEEEauthorrefmark{")
4030 i = find_token(document.body, "\\begin_inset Flex Author Name", i)
4032 endi = find_end_of_inset(document.body, i)
4033 document.body[endi - 2 : endi + 1] = put_cmd_in_ert("}")
4034 document.body[i : i + 4] = put_cmd_in_ert("\\IEEEauthorblockN{")
4037 j = find_token(document.body, "\\begin_inset Flex Author Affiliation", j)
4039 endj = find_end_of_inset(document.body, j)
4040 document.body[endj - 2 : endj + 1] = put_cmd_in_ert("}")
4041 document.body[j : j + 4] = put_cmd_in_ert("\\IEEEauthorblockA{")
4043 if i == -1 and j == -1 and h == -1:
4047 def revert_kurier_fonts(document):
4048 " Revert kurier font definition to LaTeX "
4050 i = find_token(document.header, "\\font_math", 0)
4052 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4053 val = get_value(document.header, "\\font_math", i)
4054 if val == "kurier-math":
4055 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
4056 "\\usepackage[math]{kurier}\n" \
4057 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
4058 document.header[i] = "\\font_math auto"
4060 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4061 kurier_fonts = ["kurier", "kurierc", "kurierl", "kurierlc"]
4062 k = find_token(document.header, "\\font_sans kurier", 0)
4064 sf = get_value(document.header, "\\font_sans", k)
4065 if sf in kurier_fonts:
4066 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4067 document.header[k] = "\\font_sans default"
4069 def revert_iwona_fonts(document):
4070 " Revert iwona font definition to LaTeX "
4072 i = find_token(document.header, "\\font_math", 0)
4074 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4075 val = get_value(document.header, "\\font_math", i)
4076 if val == "iwona-math":
4077 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
4078 "\\usepackage[math]{iwona}\n" \
4079 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
4080 document.header[i] = "\\font_math auto"
4082 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4083 iwona_fonts = ["iwona", "iwonac", "iwonal", "iwonalc"]
4084 k = find_token(document.header, "\\font_sans iwona", 0)
4086 sf = get_value(document.header, "\\font_sans", k)
4087 if sf in iwona_fonts:
4088 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4089 document.header[k] = "\\font_sans default"
4092 def revert_new_libertines(document):
4093 " Revert new libertine font definition to LaTeX "
4095 if find_token(document.header, "\\use_non_tex_fonts true", 0) != -1:
4098 i = find_token(document.header, "\\font_typewriter libertine-mono", 0)
4100 preamble = "\\usepackage"
4101 sc = find_token(document.header, "\\font_tt_scale", 0)
4103 scval = get_value(document.header, "\\font_tt_scale", sc)
4105 preamble += "[scale=%f]" % (float(scval) / 100)
4106 document.header[sc] = "\\font_tt_scale 100"
4107 preamble += "{libertineMono-type1}"
4108 add_to_preamble(document, [preamble])
4109 document.header[i] = "\\font_typewriter default"
4111 k = find_token(document.header, "\\font_sans biolinum", 0)
4113 preamble = "\\usepackage"
4115 j = find_token(document.header, "\\font_osf true", 0)
4120 sc = find_token(document.header, "\\font_sf_scale", 0)
4122 scval = get_value(document.header, "\\font_sf_scale", sc)
4124 options += ",scale=%f" % (float(scval) / 100)
4125 document.header[sc] = "\\font_sf_scale 100"
4127 preamble += "[" + options +"]"
4128 preamble += "{biolinum-type1}"
4129 add_to_preamble(document, [preamble])
4130 document.header[k] = "\\font_sans default"
4133 def convert_lyxframes(document):
4134 " Converts old beamer frames to new style "
4136 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4137 if document.textclass not in beamer_classes:
4140 framebeg = ["BeginFrame", "BeginPlainFrame"]
4141 frameend = ["Frame", "PlainFrame", "EndFrame", "BeginFrame", "BeginPlainFrame", "AgainFrame",
4142 "Section", "Section*", "Subsection", "Subsection*", "Subsubsection", "Subsubsection*"]
4143 for lay in framebeg:
4146 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
4149 parent = get_containing_layout(document.body, i)
4150 if parent == False or parent[1] != i:
4151 document.warning("Wrong parent layout!")
4154 frametype = parent[0]
4158 # Step I: Convert ERT arguments
4159 # FIXME: See restrictions in convert_beamerframeargs method
4160 ertend = convert_beamerframeargs(document, i, parbeg)
4163 # Step II: Now rename the layout and convert the title to an argument
4164 j = find_end_of_layout(document.body, i)
4165 document.body[j : j + 1] = ['\\end_layout', '', '\\end_inset', '', '\\end_layout']
4166 if lay == "BeginFrame":
4167 document.body[i] = "\\begin_layout Frame"
4169 document.body[i] = "\\begin_layout PlainFrame"
4170 document.body[ertend + 1 : ertend + 1] = ['\\begin_inset Argument 4',
4171 'status open', '', '\\begin_layout Plain Layout']
4172 # Step III: find real frame end
4175 inInset = get_containing_inset(document.body, i)
4177 fend = find_token(document.body, "\\begin_layout", jj)
4179 document.warning("Malformed LyX document: No real frame end!")
4181 val = get_value(document.body, "\\begin_layout", fend)
4182 if val not in frameend:
4185 # is this frame nested in an inset (e.g., Note)?
4186 if inInset != False:
4187 # if so, end the frame inside the inset
4188 if inInset[2] < fend:
4190 if val == frametype:
4191 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4192 # consider explicit EndFrames between two identical frame types
4193 elif val == "EndFrame":
4194 nextlayout = find_token(document.body, "\\begin_layout", fend + 1)
4195 if nextlayout != -1 and get_value(document.body, "\\begin_layout", nextlayout) == frametype:
4196 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4198 document.body[fend : fend] = ['\\end_deeper']
4200 document.body[fend : fend] = ['\\end_deeper']
4201 document.body[j + 1 : j + 1] = ['', '\\begin_deeper']
4206 def remove_endframes(document):
4207 " Remove deprecated beamer endframes "
4209 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4210 if document.textclass not in beamer_classes:
4215 i = find_token_exact(document.body, "\\begin_layout EndFrame", i)
4218 j = find_end_of_layout(document.body, i)
4220 document.warning("Malformed LyX document: Missing \\end_layout to EndFrame")
4223 del document.body[i : j + 1]
4226 def revert_powerdot_flexes(document):
4227 " Reverts powerdot flex insets "
4229 if document.textclass != "powerdot":
4232 flexes = {"Onslide" : "\\onslide",
4233 "Onslide*" : "\\onslide*",
4234 "Onslide+" : "\\onslide+"}
4235 rx = re.compile(r'^\\begin_inset Flex (.+)$')
4239 i = find_token(document.body, "\\begin_inset Flex", i)
4242 m = rx.match(document.body[i])
4244 flextype = m.group(1)
4245 z = find_end_of_inset(document.body, i)
4247 document.warning("Can't find end of Flex " + flextype + " inset.")
4250 if flextype in flexes:
4251 pre = put_cmd_in_ert(flexes[flextype])
4252 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
4254 argend = find_end_of_inset(document.body, arg)
4256 document.warning("Can't find end of Argument!")
4259 # Find containing paragraph layout
4260 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
4261 endPlain = find_end_of_layout(document.body, beginPlain)
4262 argcontent = document.body[beginPlain + 1 : endPlain]
4264 z = z - len(document.body[arg : argend + 1])
4266 del document.body[arg : argend + 1]
4267 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
4268 pre += put_cmd_in_ert("{")
4269 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4270 endPlain = find_end_of_layout(document.body, beginPlain)
4272 z = z - len(document.body[i : beginPlain + 1])
4274 document.body[i : beginPlain + 1] = pre
4275 post = put_cmd_in_ert("}")
4276 document.body[z - 2 : z + 1] = post
4280 def revert_powerdot_pause(document):
4281 " Reverts powerdot pause layout to ERT "
4283 if document.textclass != "powerdot":
4288 i = find_token(document.body, "\\begin_layout Pause", i)
4291 j = find_end_of_layout(document.body, i)
4293 document.warning("Malformed LyX document: Can't find end of Pause layout")
4297 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\pause")
4298 for p in range(i, j):
4301 arg = find_token(document.body, "\\begin_inset Argument 1", i, j)
4303 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4304 endPlain = find_end_of_layout(document.body, beginPlain)
4305 endInset = find_end_of_inset(document.body, p)
4306 content = document.body[beginPlain + 1 : endPlain]
4308 endlay = endlay - len(document.body[p : endInset + 1])
4310 del document.body[p : endInset + 1]
4311 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4313 document.body[i : i + 1] = subst
4317 def revert_powerdot_itemargs(document):
4318 " Reverts powerdot item arguments to ERT "
4320 if document.textclass != "powerdot":
4324 list_layouts = ["Itemize", "ItemizeType1", "Enumerate", "EnumerateType1"]
4325 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4328 i = find_token(document.body, "\\begin_inset Argument", i)
4331 # Find containing paragraph layout
4332 parent = get_containing_layout(document.body, i)
4334 document.warning("Malformed LyX document: Can't find parent paragraph layout")
4339 realparbeg = parent[3]
4340 layoutname = parent[0]
4342 for p in range(parbeg, parend):
4346 if layoutname in list_layouts:
4347 m = rx.match(document.body[p])
4350 if argnr == "item:1":
4351 j = find_end_of_inset(document.body, i)
4352 # Find containing paragraph layout
4353 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4354 endPlain = find_end_of_layout(document.body, beginPlain)
4355 content = document.body[beginPlain + 1 : endPlain]
4356 del document.body[i:j+1]
4357 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4358 document.body[realparbeg : realparbeg] = subst
4359 elif argnr == "item:2":
4360 j = find_end_of_inset(document.body, i)
4361 # Find containing paragraph layout
4362 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4363 endPlain = find_end_of_layout(document.body, beginPlain)
4364 content = document.body[beginPlain + 1 : endPlain]
4365 del document.body[i:j+1]
4366 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
4367 document.body[realparbeg : realparbeg] = subst
4372 def revert_powerdot_columns(document):
4373 " Reverts powerdot twocolumn to TeX-code "
4374 if document.textclass != "powerdot":
4377 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4380 i = find_token(document.body, "\\begin_layout Twocolumn", i)
4383 j = find_end_of_layout(document.body, i)
4385 document.warning("Malformed LyX document: Can't find end of Twocolumn layout")
4389 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
4390 endlay += len(put_cmd_in_ert("}"))
4391 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\twocolumn")
4392 for p in range(i, j):
4395 m = rx.match(document.body[p])
4399 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4400 endPlain = find_end_of_layout(document.body, beginPlain)
4401 endInset = find_end_of_inset(document.body, p)
4402 content = document.body[beginPlain + 1 : endPlain]
4404 endlay = endlay - len(document.body[p : endInset + 1])
4406 del document.body[p : endInset + 1]
4407 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4409 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4410 endPlain = find_end_of_layout(document.body, beginPlain)
4411 endInset = find_end_of_inset(document.body, p)
4412 content = document.body[beginPlain + 1 : endPlain]
4414 endlay = endlay - len(document.body[p : endInset + 1])
4416 del document.body[p : endInset + 1]
4417 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
4419 subst += put_cmd_in_ert("{")
4420 document.body[i : i + 1] = subst
4424 def revert_mbox_fbox(document):
4425 'Convert revert mbox/fbox boxes to TeX-code'
4428 i = find_token(document.body, "\\begin_inset Box", i)
4431 j = find_token(document.body, "width", i)
4433 document.warning("Malformed LyX document: Can't find box width")
4435 width = get_value(document.body, "width", j)
4436 k = find_end_of_inset(document.body, j)
4438 document.warning("Malformed LyX document: Can't find end of box inset")
4441 BeginLayout = find_token(document.body, "\\begin_layout Plain Layout", j)
4442 EndLayout = find_end_of_layout(document.body, BeginLayout)
4443 # replace if width is ""
4445 document.body[EndLayout:k + 1] = put_cmd_in_ert("}")
4446 if document.body[i] == "\\begin_inset Box Frameless":
4447 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\mbox{")
4448 if document.body[i] == "\\begin_inset Box Boxed":
4449 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\fbox{")
4453 def revert_starred_caption(document):
4454 " Reverts unnumbered longtable caption insets "
4458 i = find_token(document.body, "\\begin_inset Caption LongTableNoNumber", i)
4461 # This is not equivalent, but since the caption inset is a full blown
4462 # text inset a true conversion to ERT is too difficult.
4463 document.body[i] = "\\begin_inset Caption Standard"
4467 def revert_forced_local_layout(document):
4470 i = find_token(document.header, "\\begin_forced_local_layout", i)
4473 j = find_end_of(document.header, i, "\\begin_forced_local_layout", "\\end_forced_local_layout")
4475 # this should not happen
4477 regexp = re.compile(r'\s*forcelocal', re.IGNORECASE)
4478 k = find_re(document.header, regexp, i, j)
4480 del document.header[k]
4482 k = find_re(document.header, regexp, i, j)
4483 k = find_token(document.header, "\\begin_local_layout", 0)
4485 document.header[i] = "\\begin_local_layout"
4486 document.header[j] = "\\end_local_layout"
4488 l = find_end_of(document.header, k, "\\begin_local_layout", "\\end_local_layout")
4490 # this should not happen
4492 lines = document.header[i+1 : j]
4494 document.header[k+1 : k+1] = lines
4495 document.header[i : j ] = []
4497 document.header[i : j ] = []
4498 document.header[k+1 : k+1] = lines
4501 def revert_aa1(document):
4502 " Reverts InsetArguments of aa to TeX-code "
4503 if document.textclass == "aa":
4507 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4509 revert_Argument_to_TeX_brace(document, i, 0, 1, 4, False, False)
4515 def revert_aa2(document):
4516 " Reverts InsetArguments of aa to TeX-code "
4517 if document.textclass == "aa":
4521 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4523 document.body[i] = "\\begin_layout Abstract"
4529 def revert_tibetan(document):
4530 "Set the document language for Tibetan to English"
4532 if document.language == "tibetan":
4533 document.language = "english"
4534 i = find_token(document.header, "\\language", 0)
4536 document.header[i] = "\\language english"
4538 while j < len(document.body):
4539 j = find_token(document.body, "\\lang tibetan", j)
4541 document.body[j] = document.body[j].replace("\\lang tibetan", "\\lang english")
4544 j = len(document.body)
4553 # The idea here is that we will have a sequence of chunk paragraphs.
4554 # We want to convert them to paragraphs in one or several chunk insets.
4555 # Individual chunks are terminated by the character @ on the last line.
4556 # This line will be discarded, and following lines are treated as new
4557 # chunks, which go into their own insets.
4558 # The first line of a chunk should look like: <<CONTENT>>=
4559 # We will discard the delimiters, and put the CONTENT into the
4560 # optional argument of the inset, if the CONTENT is non-empty.
4561 def convert_chunks(document):
4562 first_re = re.compile(r'<<(.*)>>=(.*)')
4565 # find start of a block of chunks
4566 i = find_token(document.body, "\\begin_layout Chunk", file_pos)
4572 chunk_started = False
4575 # process the one we just found
4576 j = find_end_of_layout(document.body, i)
4578 document.warning("Malformed LyX documents. Can't find end of Chunk layout!")
4579 # there is no point continuing, as we will run into the same error again.
4581 this_chunk = "".join(document.body[i + 1:j])
4583 # there may be empty lines between chunks
4584 # we just skip them.
4585 if not chunk_started:
4586 if this_chunk != "":
4588 chunk_started = True
4591 contents.append(document.body[i + 1:j])
4593 # look for potential chunk terminator
4594 # on the last line of the chunk paragraph
4595 if document.body[j - 1] == "@":
4598 # look for subsequent chunk paragraph
4599 i = find_token(document.body, "\\begin_layout", j)
4603 if get_value(document.body, "\\begin_layout", i) != "Chunk":
4606 file_pos = end = j + 1
4608 # The last chunk should simply have an "@" in it
4609 # or at least end with "@" (can happen if @ is
4610 # preceded by a newline)
4612 if len(contents) > 0:
4613 lastpar = ''.join(contents[-1])
4614 if not lastpar.endswith("@"):
4615 document.warning("Unexpected chunk content: chunk not terminated by '@'!")
4616 if len(contents) == 0:
4617 # convert empty chunk layouts to Standard
4618 document.body[start] = "\\begin_layout Standard"
4622 # chunk par only contains "@". Just drop it.
4625 # chunk par contains more. Only drop the "@".
4628 # The first line should look like: <<CONTENT>>=
4629 # We want the CONTENT
4630 optarg = ' '.join(contents[0])
4632 # We can already have real chunk content in
4633 # the first par (separated from the options by a newline).
4634 # We collect such stuff to re-insert it later.
4637 match = first_re.search(optarg)
4639 optarg = match.groups()[0]
4640 if match.groups()[1] != "":
4642 for c in contents[0]:
4643 if c.endswith(">>="):
4647 postoptstuff.append(c)
4648 # We have stripped everything. This can be deleted.
4651 newstuff = ['\\begin_layout Standard']
4653 # Maintain paragraph parameters
4654 par_params = ["\\noindent", "\\indent", "\\indent-toggle", "\\leftindent",
4655 "\\start_of_appendix", "\\paragraph_spacing", "\\align",
4656 "\\labelwidthstring"]
4659 if document.body[parms].split(' ', 1)[0] not in par_params:
4661 newstuff.extend([document.body[parms]])
4665 ['\\begin_inset Flex Chunk',
4667 '\\begin_layout Plain Layout', ''])
4669 # If we have a non-empty optional argument, insert it.
4670 if match and optarg != "":
4672 ['\\begin_inset Argument 1',
4674 '\\begin_layout Plain Layout',
4679 # Since we already opened a Plain layout, the first paragraph
4680 # does not need to do that.
4683 # we need to replace newlines with new layouts
4685 started_text = False
4686 for lno in range(0,len(postoptstuff)):
4687 if postoptstuff[lno].startswith("\\begin_inset Newline newline"):
4689 elif start_newline != -1:
4690 if postoptstuff[lno].startswith("\\end_inset"):
4691 # replace that bit, but only if we already have some text
4692 # and we're not at the end except for a blank line
4693 if started_text and \
4694 (lno != len(postoptstuff) - 2 or postoptstuff[-1] != ""):
4695 newstuff.extend(['\\end_layout', '\n', '\\begin_layout Plain Layout', '\n'])
4699 newstuff.extend([postoptstuff[lno]])
4700 newstuff.append('\\end_layout')
4704 newstuff.extend(['', '\\begin_layout Plain Layout', ''])
4708 newstuff.append('\\end_layout')
4710 newstuff.extend(['', '\\end_inset', '', '\\end_layout', ''])
4712 document.body[start:end] = newstuff
4714 file_pos += len(newstuff) - (end - start)
4717 def revert_chunks(document):
4720 i = find_token(document.body, "\\begin_inset Flex Chunk", i)
4724 iend = find_end_of_inset(document.body, i)
4726 document.warning("Can't find end of Chunk!")
4730 # Look for optional argument
4732 ostart = find_token(document.body, "\\begin_inset Argument 1", i, iend)
4734 oend = find_end_of_inset(document.body, ostart)
4735 k = find_token(document.body, "\\begin_layout Plain Layout", ostart, oend)
4737 document.warning("Malformed LyX document: Can't find argument contents!")
4739 m = find_end_of_layout(document.body, k)
4740 optarg = "".join(document.body[k+1:m])
4742 # We now remove the optional argument, so we have something
4743 # uniform on which to work
4744 document.body[ostart : oend + 1] = []
4745 # iend is now invalid
4746 iend = find_end_of_inset(document.body, i)
4748 retval = get_containing_layout(document.body, i)
4750 document.warning("Can't find containing layout for Chunk!")
4753 (lname, lstart, lend, pstart) = retval
4754 # we now want to work through the various paragraphs, and collect their contents
4758 k = find_token(document.body, "\\begin_layout Plain Layout", k, lend)
4761 j = find_end_of_layout(document.body, k)
4763 document.warning("Can't find end of layout inside chunk!")
4765 parlist.append(document.body[k+1:j])
4767 # we now need to wrap all of these paragraphs in chunks
4769 newlines.extend(["\\begin_layout Chunk", "", "<<" + optarg + ">>=", "\\end_layout", ""])
4770 for stuff in parlist:
4771 newlines.extend(["\\begin_layout Chunk"] + stuff + ["\\end_layout", ""])
4772 newlines.extend(["\\begin_layout Chunk", "", "@", "\\end_layout", ""])
4773 # replace old content with new content
4774 document.body[lstart : lend + 1] = newlines
4775 i = lstart + len(newlines)
4782 supported_versions = ["2.1.0","2.1"]
4785 [415, [convert_undertilde]],
4787 [417, [convert_japanese_encodings]],
4788 [418, [convert_justification]],
4790 [420, [convert_biblio_style]],
4791 [421, [convert_longtable_captions]],
4792 [422, [convert_use_packages]],
4793 [423, [convert_use_mathtools]],
4794 [424, [convert_cite_engine_type]],
4795 # No convert_cancel, since cancel will be loaded automatically
4796 # in format 425 without any possibility to switch it off.
4797 # This has been fixed in format 464.
4801 [428, [convert_cell_rotation]],
4802 [429, [convert_table_rotation]],
4803 [430, [convert_listoflistings]],
4804 [431, [convert_use_amssymb]],
4806 [433, [convert_armenian]],
4814 [441, [convert_mdnomath]],
4819 [446, [convert_latexargs]],
4820 [447, [convert_IEEEtran, convert_AASTeX, convert_AGUTeX, convert_IJMP, convert_SIGPLAN, convert_SIGGRAPH, convert_EuropeCV, convert_Initials, convert_ModernCV]],
4821 [448, [convert_literate]],
4824 [451, [convert_beamerargs, convert_againframe_args, convert_corollary_args, convert_quote_args]],
4825 [452, [convert_beamerblocks]],
4826 [453, [convert_use_stmaryrd]],
4827 [454, [convert_overprint]],
4829 [456, [convert_epigraph]],
4830 [457, [convert_use_stackrel]],
4831 [458, [convert_captioninsets, convert_captionlayouts]],
4836 [463, [convert_encodings]],
4837 [464, [convert_use_cancel]],
4838 [465, [convert_lyxframes, remove_endframes]],
4844 [471, [convert_cite_engine_type_default]],
4847 [474, [convert_chunks, cleanup_beamerargs]],
4851 [473, [revert_chunks]],
4852 [472, [revert_tibetan]],
4853 [471, [revert_aa1,revert_aa2]],
4854 [470, [revert_cite_engine_type_default]],
4855 [469, [revert_forced_local_layout]],
4856 [468, [revert_starred_caption]],
4857 [467, [revert_mbox_fbox]],
4858 [466, [revert_iwona_fonts]],
4859 [465, [revert_powerdot_flexes, revert_powerdot_pause, revert_powerdot_itemargs, revert_powerdot_columns]],
4861 [463, [revert_use_cancel]],
4862 [462, [revert_encodings]],
4863 [461, [revert_new_libertines]],
4864 [460, [revert_kurier_fonts]],
4865 [459, [revert_IEEEtran_3]],
4866 [458, [revert_fragileframe, revert_newframes]],
4867 [457, [revert_captioninsets, revert_captionlayouts]],
4868 [456, [revert_use_stackrel]],
4869 [455, [revert_epigraph]],
4870 [454, [revert_frametitle]],
4871 [453, [revert_overprint]],
4872 [452, [revert_use_stmaryrd]],
4873 [451, [revert_beamerblocks]],
4874 [450, [revert_beamerargs, revert_beamerargs2, revert_beamerargs3, revert_beamerflex]],
4875 [449, [revert_garamondx, revert_garamondx_newtxmath]],
4876 [448, [revert_itemargs]],
4877 [447, [revert_literate]],
4878 [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]],
4879 [445, [revert_latexargs]],
4880 [444, [revert_uop]],
4881 [443, [revert_biolinum]],
4883 [441, [revert_newtxmath]],
4884 [440, [revert_mdnomath]],
4885 [439, [revert_mathfonts]],
4886 [438, [revert_minionpro]],
4887 [437, [revert_ipadeco, revert_ipachar]],
4888 [436, [revert_texgyre]],
4889 [435, [revert_mathdesign]],
4890 [434, [revert_txtt]],
4891 [433, [revert_libertine]],
4892 [432, [revert_armenian]],
4893 [431, [revert_languages, revert_ancientgreek]],
4894 [430, [revert_use_amssymb]],
4895 [429, [revert_listoflistings]],
4896 [428, [revert_table_rotation]],
4897 [427, [revert_cell_rotation]],
4898 [426, [revert_tipa]],
4899 [425, [revert_verbatim]],
4900 [424, [revert_cancel]],
4901 [423, [revert_cite_engine_type]],
4902 [422, [revert_use_mathtools]],
4903 [421, [revert_use_packages]],
4904 [420, [revert_longtable_captions]],
4905 [419, [revert_biblio_style]],
4906 [418, [revert_australian]],
4907 [417, [revert_justification]],
4908 [416, [revert_japanese_encodings]],
4909 [415, [revert_negative_space, revert_math_spaces]],
4910 [414, [revert_undertilde]],
4911 [413, [revert_visible_space]]
4915 if __name__ == "__main__":