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 beginBrance != -1 and (beginBrace == endBrace + 11 or beginBrace == endBrace + 12):
185 end = find_token(document.body, "\\end_inset", beginBrace)
186 document.body[lineERT : end + 1] = ["\\end_layout", "", "\\end_inset"]
188 # in the case that n > 1 we have optional arguments before
189 # therefore detect them if any
191 # first check if there is an argument
192 lineArg = find_token(document.body, "\\begin_inset Argument", line)
193 if lineArg < lineERT and lineArg != -1:
194 # we have an argument, so now search backwards for its end
195 # we must now assure that we don't find other insets like e.g. a newline
196 endInsetArg = lineERT
197 endLayoutArg = endInsetArg
198 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
199 endInsetArg = endInsetArg - 1
200 endLayoutArg = endInsetArg
201 endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
202 endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
203 line = endInsetArg + 1
205 document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
207 document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
209 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
212 # set the line where the next argument will be inserted
213 if beginBrace == endBrace + 11:
221 if environment == True:
222 end_ERT = find_end_of_inset(document.body, lineERT)
224 document.warning("Can't find end of ERT!!")
226 # Note that this only checks for [ or { at the beginning of a line
228 opening = find_token(document.body, "[", lineERT, end_ERT)
230 opening = find_token(document.body, "{", lineERT, end_ERT)
232 lineERT2 = find_token(document.body, "\\begin_inset ERT", end_ERT, end_layout)
234 # argument in a single ERT
235 # strip off the opening bracket
236 document.body[opening] = document.body[opening][1:]
237 ertcontlastline = end_ERT - 3
238 if (opt and document.body[ertcontlastline].endswith("]")) or document.body[ertcontlastline].endswith("}"):
239 # strip off the closing bracket
240 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
241 end2 = find_token(document.body, "\\end_inset", ertcontlastline)
242 document.body[lineERT : lineERT + 1] = ["\\begin_inset Argument " + str(n)]
244 end_ERT2 = find_end_of_inset(document.body, lineERT2)
246 document.warning("Can't find end of second ERT!!")
249 closing = find_token(document.body, "]", lineERT2, end_ERT2)
251 closing = find_token(document.body, "}", lineERT2, end_ERT2)
252 if closing != -1: # assure that the "}" is in this ERT
253 end2 = find_token(document.body, "\\end_inset", closing)
254 document.body[lineERT2 : end2 + 1] = ["\\end_layout", "", "\\end_inset"]
255 document.body[lineERT : end_ERT + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
259 ###############################################################################
261 ### Conversion and reversion routines
263 ###############################################################################
265 def revert_visible_space(document):
266 "Revert InsetSpace visible into its ERT counterpart"
269 i = find_token(document.body, "\\begin_inset space \\textvisiblespace{}", i)
272 end = find_end_of_inset(document.body, i)
273 subst = put_cmd_in_ert("\\textvisiblespace{}")
274 document.body[i:end + 1] = subst
277 undertilde_commands = ["utilde"]
278 def convert_undertilde(document):
279 " Load undertilde automatically "
280 i = find_token(document.header, "\\use_mathdots" , 0)
282 i = find_token(document.header, "\\use_mhchem" , 0)
284 i = find_token(document.header, "\\use_esint" , 0)
286 document.warning("Malformed LyX document: Can't find \\use_mathdots.")
288 j = find_token(document.preamble, "\\usepackage{undertilde}", 0)
290 # package was loaded in the preamble, convert this to header setting for round trip
291 document.header.insert(i + 1, "\\use_undertilde 2") # on
292 del document.preamble[j]
296 j = find_token(document.body, '\\begin_inset Formula', j)
299 k = find_end_of_inset(document.body, j)
301 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(j))
304 code = "\n".join(document.body[j:k])
305 for c in undertilde_commands:
306 if code.find("\\%s" % c) != -1:
307 # at least one of the commands was found - need to switch package off
308 document.header.insert(i + 1, "\\use_undertilde 0") # off
311 # no command was found - set to auto (bug 9069)
312 document.header.insert(i + 1, "\\use_undertilde 1") # auto
316 def revert_undertilde(document):
317 " Load undertilde if used in the document "
318 regexp = re.compile(r'(\\use_undertilde)')
319 i = find_re(document.header, regexp, 0)
320 value = "1" # default is auto
322 value = get_value(document.header, "\\use_undertilde" , i).split()[0]
323 del document.header[i]
324 if value == "2": # on
325 add_to_preamble(document, ["\\usepackage{undertilde}"])
326 elif value == "1": # auto
329 i = find_token(document.body, '\\begin_inset Formula', i)
332 j = find_end_of_inset(document.body, i)
334 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
337 code = "\n".join(document.body[i:j])
338 for c in undertilde_commands:
339 if code.find("\\%s" % c) != -1:
340 add_to_preamble(document, ["\\usepackage{undertilde}"])
345 def revert_negative_space(document):
346 "Revert InsetSpace negmedspace and negthickspace into its TeX-code counterpart"
351 i = find_token(document.body, "\\begin_inset space \\negmedspace{}", i)
353 j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
355 # load amsmath in the preamble if not already loaded if we are at the end of checking
357 i = find_token(document.header, "\\use_amsmath 2", 0)
359 add_to_preamble(document, ["\\@ifundefined{negthickspace}{\\usepackage{amsmath}}"])
363 end = find_end_of_inset(document.body, i)
364 subst = put_cmd_in_ert("\\negmedspace{}")
365 document.body[i:end + 1] = subst
366 j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
369 end = find_end_of_inset(document.body, j)
370 subst = put_cmd_in_ert("\\negthickspace{}")
371 document.body[j:end + 1] = subst
375 def revert_math_spaces(document):
376 "Revert formulas with protected custom space and protected hfills to TeX-code"
379 i = find_token(document.body, "\\begin_inset Formula", i)
382 j = document.body[i].find("\\hspace*")
384 end = find_end_of_inset(document.body, i)
385 subst = put_cmd_in_ert(document.body[i][21:])
386 document.body[i:end + 1] = subst
390 def convert_japanese_encodings(document):
391 " Rename the japanese encodings to names understood by platex "
393 "EUC-JP-pLaTeX": "euc",
395 "SJIS-pLaTeX": "sjis"
397 i = find_token(document.header, "\\inputencoding" , 0)
400 val = get_value(document.header, "\\inputencoding", i)
401 if val in list(jap_enc_dict.keys()):
402 document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
405 def revert_japanese_encodings(document):
406 " Revert the japanese encodings name changes "
408 "euc": "EUC-JP-pLaTeX",
410 "sjis": "SJIS-pLaTeX"
412 i = find_token(document.header, "\\inputencoding" , 0)
415 val = get_value(document.header, "\\inputencoding", i)
416 if val in list(jap_enc_dict.keys()):
417 document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
420 def convert_justification(document):
421 " Add the \\justification buffer param"
422 i = find_token(document.header, "\\suppress_date" , 0)
424 i = find_token(document.header, "\\paperorientation" , 0)
426 i = find_token(document.header, "\\use_indices" , 0)
428 i = find_token(document.header, "\\use_bibtopic" , 0)
430 document.warning("Malformed LyX document: Missing \\suppress_date.")
432 document.header.insert(i + 1, "\\justification true")
435 def revert_justification(document):
436 " Revert the \\justification buffer param"
437 if not del_token(document.header, '\\justification', 0):
438 document.warning("Malformed LyX document: Missing \\justification.")
441 def revert_australian(document):
442 "Set English language variants Australian and Newzealand to English"
444 if document.language == "australian" or document.language == "newzealand":
445 document.language = "english"
446 i = find_token(document.header, "\\language", 0)
448 document.header[i] = "\\language english"
451 j = find_token(document.body, "\\lang australian", j)
453 j = find_token(document.body, "\\lang newzealand", 0)
457 document.body[j] = document.body[j].replace("\\lang newzealand", "\\lang english")
459 document.body[j] = document.body[j].replace("\\lang australian", "\\lang english")
463 def convert_biblio_style(document):
464 "Add a sensible default for \\biblio_style based on the citation engine."
465 i = find_token(document.header, "\\cite_engine", 0)
467 engine = get_value(document.header, "\\cite_engine", i).split("_")[0]
468 style = {"basic": "plain", "natbib": "plainnat", "jurabib": "jurabib"}
469 document.header.insert(i + 1, "\\biblio_style " + style[engine])
472 def revert_biblio_style(document):
473 "BibTeX insets with default option use the style defined by \\biblio_style."
474 i = find_token(document.header, "\\biblio_style" , 0)
476 document.warning("No \\biblio_style line. Nothing to do.")
479 default_style = get_value(document.header, "\\biblio_style", i)
480 del document.header[i]
482 # We are looking for bibtex insets having the default option
485 i = find_token(document.body, "\\begin_inset CommandInset bibtex", i)
488 j = find_end_of_inset(document.body, i)
490 document.warning("Malformed LyX document: Can't find end of bibtex inset at line " + str(i))
493 k = find_token(document.body, "options", i, j)
495 options = get_quoted_value(document.body, "options", k)
496 if "default" in options.split(","):
497 document.body[k] = 'options "%s"' \
498 % options.replace("default", default_style)
502 def handle_longtable_captions(document, forward):
505 begin_table = find_token(document.body, '<lyxtabular version=', begin_table)
506 if begin_table == -1:
508 end_table = find_end_of(document.body, begin_table, '<lyxtabular', '</lyxtabular>')
510 document.warning("Malformed LyX document: Could not find end of table.")
513 fline = find_token(document.body, "<features", begin_table, end_table)
515 document.warning("Can't find features for inset at line " + str(begin_table))
518 p = document.body[fline].find("islongtable")
523 numrows = get_option_value(document.body[begin_table], "rows")
525 numrows = int(numrows)
527 document.warning(document.body[begin_table])
528 document.warning("Unable to determine rows!")
529 begin_table = end_table
531 begin_row = begin_table
532 for row in range(numrows):
533 begin_row = find_token(document.body, '<row', begin_row, end_table)
535 document.warning("Can't find row " + str(row + 1))
537 end_row = find_end_of(document.body, begin_row, '<row', '</row>')
539 document.warning("Can't find end of row " + str(row + 1))
542 if (get_option_value(document.body[begin_row], 'caption') == 'true' and
543 get_option_value(document.body[begin_row], 'endfirsthead') != 'true' and
544 get_option_value(document.body[begin_row], 'endhead') != 'true' and
545 get_option_value(document.body[begin_row], 'endfoot') != 'true' and
546 get_option_value(document.body[begin_row], 'endlastfoot') != 'true'):
547 document.body[begin_row] = set_option_value(document.body[begin_row], 'caption', 'true", endfirsthead="true')
548 elif get_option_value(document.body[begin_row], 'caption') == 'true':
549 if get_option_value(document.body[begin_row], 'endfirsthead') == 'true':
550 document.body[begin_row] = set_option_value(document.body[begin_row], 'endfirsthead', 'false')
551 if get_option_value(document.body[begin_row], 'endhead') == 'true':
552 document.body[begin_row] = set_option_value(document.body[begin_row], 'endhead', 'false')
553 if get_option_value(document.body[begin_row], 'endfoot') == 'true':
554 document.body[begin_row] = set_option_value(document.body[begin_row], 'endfoot', 'false')
555 if get_option_value(document.body[begin_row], 'endlastfoot') == 'true':
556 document.body[begin_row] = set_option_value(document.body[begin_row], 'endlastfoot', 'false')
558 # since there could be a tabular inside this one, we
559 # cannot jump to end.
563 def convert_longtable_captions(document):
564 "Add a firsthead flag to caption rows"
565 handle_longtable_captions(document, True)
568 def revert_longtable_captions(document):
569 "remove head/foot flag from caption rows"
570 handle_longtable_captions(document, False)
573 def convert_use_packages(document):
574 "use_xxx yyy => use_package xxx yyy"
575 packages = ["amsmath", "esint", "mathdots", "mhchem", "undertilde"]
577 i = find_token(document.header, "\\use_%s" % p, 0)
579 value = get_value(document.header, "\\use_%s" % p, i)
580 document.header[i] = "\\use_package %s %s" % (p, value)
583 def revert_use_packages(document):
584 "use_package xxx yyy => use_xxx yyy"
585 packages = ["amsmath", "esint", "mhchem", "mathdots", "undertilde"]
586 # the order is arbitrary for the use_package version, and not all packages need to be given.
587 # Ensure a complete list and correct order (important for older LyX versions and especially lyx2lyx)
588 # first loop: find line with first package
591 regexp = re.compile(r'(\\use_package\s+%s)' % p)
592 i = find_re(document.header, regexp, 0)
593 if i != -1 and (j < 0 or i < j):
595 # second loop: replace or insert packages in front of all existing ones
597 regexp = re.compile(r'(\\use_package\s+%s)' % p)
598 i = find_re(document.header, regexp, 0)
600 value = get_value(document.header, "\\use_package %s" % p, i).split()[1]
601 del document.header[i]
602 document.header.insert(j, "\\use_%s %s" % (p, value))
604 document.header.insert(j, "\\use_%s 1" % p)
608 def convert_use_package(document, pkg, commands, oldauto):
609 # oldauto defines how the version we are converting from behaves:
610 # if it is true, the old version uses the package automatically.
611 # if it is false, the old version never uses the package.
612 i = find_token(document.header, "\\use_package", 0)
614 document.warning("Malformed LyX document: Can't find \\use_package.")
616 j = find_token(document.preamble, "\\usepackage{" + pkg + "}", 0)
618 # package was loaded in the preamble, convert this to header setting for round trip
619 document.header.insert(i + 1, "\\use_package " + pkg + " 2") # on
620 del document.preamble[j]
621 # If oldauto is true we have two options:
622 # We can either set the package to auto - this is correct for files in
623 # format 425 to 463, and may create a conflict for older files which use
624 # any command in commands with a different definition.
625 # Or we can look whether any command in commands is used, and set it to
626 # auto if not and to off if yes. This will not create a conflict, but will
627 # create uncompilable documents for files in format 425 to 463, which use
628 # any command in commands.
629 # We choose the first option since its error is less likely.
631 document.header.insert(i + 1, "\\use_package " + pkg + " 1") # auto
635 j = find_token(document.body, '\\begin_inset Formula', j)
638 k = find_end_of_inset(document.body, j)
640 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(j))
643 code = "\n".join(document.body[j:k])
645 if code.find("\\%s" % c) != -1:
646 # at least one of the commands was found - need to switch package off
647 document.header.insert(i + 1, "\\use_package " + pkg + " 0") # off
650 # no command was found - set to auto (bug 9069)
651 document.header.insert(i + 1, "\\use_package " + pkg + " 1") # auto
654 def revert_use_package(document, pkg, commands, oldauto):
655 # oldauto defines how the version we are reverting to behaves:
656 # if it is true, the old version uses the package automatically.
657 # if it is false, the old version never uses the package.
658 regexp = re.compile(r'(\\use_package\s+%s)' % pkg)
659 i = find_re(document.header, regexp, 0)
660 value = "1" # default is auto
662 value = get_value(document.header, "\\use_package" , i).split()[1]
663 del document.header[i]
664 if value == "2": # on
665 add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
666 elif value == "1" and not oldauto: # auto
669 i = find_token(document.body, '\\begin_inset Formula', i)
672 j = find_end_of_inset(document.body, i)
674 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
677 code = "\n".join(document.body[i:j])
679 if code.find("\\%s" % c) != -1:
680 add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
685 mathtools_commands = ["mathclap", "mathllap", "mathrlap", \
686 "lgathered", "rgathered", "vcentcolon", "dblcolon", \
687 "coloneqq", "Coloneqq", "coloneq", "Coloneq", "eqqcolon", \
688 "Eqqcolon", "eqcolon", "Eqcolon", "colonapprox", \
689 "Colonapprox", "colonsim", "Colonsim"]
690 def convert_use_mathtools(document):
691 "insert use_package mathtools"
692 convert_use_package(document, "mathtools", mathtools_commands, False)
695 def revert_use_mathtools(document):
696 "remove use_package mathtools"
697 revert_use_package(document, "mathtools", mathtools_commands, False)
700 # commands provided by stmaryrd.sty but LyX uses other packages:
701 # boxdot lightning, bigtriangledown, bigtriangleup
702 stmaryrd_commands = ["shortleftarrow", "shortrightarrow", "shortuparrow", \
703 "shortdownarrow", "Yup", "Ydown", "Yleft", "Yright", \
704 "varcurlyvee", "varcurlywedge", "minuso", "baro", \
705 "sslash", "bbslash", "moo", "varotimes", "varoast", \
706 "varobar", "varodot", "varoslash", "varobslash", \
707 "varocircle", "varoplus", "varominus", "boxast", \
708 "boxbar", "boxslash", "boxbslash", "boxcircle", \
709 "boxbox", "boxempty", "merge", "vartimes", \
710 "fatsemi", "sswarrow", "ssearrow", "curlywedgeuparrow", \
711 "curlywedgedownarrow", "fatslash", "fatbslash", "lbag", \
712 "rbag", "varbigcirc", "leftrightarroweq", \
713 "curlyveedownarrow", "curlyveeuparrow", "nnwarrow", \
714 "nnearrow", "leftslice", "rightslice", "varolessthan", \
715 "varogreaterthan", "varovee", "varowedge", "talloblong", \
716 "interleave", "obar", "obslash", "olessthan", \
717 "ogreaterthan", "ovee", "owedge", "oblong", "inplus", \
718 "niplus", "nplus", "subsetplus", "supsetplus", \
719 "subsetpluseq", "supsetpluseq", "Lbag", "Rbag", \
720 "llbracket", "rrbracket", "llparenthesis", \
721 "rrparenthesis", "binampersand", "bindnasrepma", \
722 "trianglelefteqslant", "trianglerighteqslant", \
723 "ntrianglelefteqslant", "ntrianglerighteqslant", \
724 "llfloor", "rrfloor", "llceil", "rrceil", "arrownot", \
725 "Arrownot", "Mapstochar", "mapsfromchar", "Mapsfromchar", \
726 "leftrightarrowtriangle", "leftarrowtriangle", \
727 "rightarrowtriangle", \
728 "bigcurlyvee", "bigcurlywedge", "bigsqcap", "bigbox", \
729 "bigparallel", "biginterleave", "bignplus", \
730 "varcopyright", "longarrownot", "Longarrownot", \
731 "Mapsto", "mapsfrom", "Mapsfrom" "Longmapsto", \
732 "longmapsfrom", "Longmapsfrom"]
733 def convert_use_stmaryrd(document):
734 "insert use_package stmaryrd"
735 convert_use_package(document, "stmaryrd", stmaryrd_commands, False)
738 def revert_use_stmaryrd(document):
739 "remove use_package stmaryrd"
740 revert_use_package(document, "stmaryrd", stmaryrd_commands, False)
743 stackrel_commands = ["stackrel"]
744 def convert_use_stackrel(document):
745 "insert use_package stackrel"
746 convert_use_package(document, "stackrel", stackrel_commands, False)
749 def revert_use_stackrel(document):
750 "remove use_package stackrel"
751 revert_use_package(document, "stackrel", stackrel_commands, False)
754 def convert_cite_engine_type(document):
755 "Determine the \\cite_engine_type from the citation engine."
756 i = find_token(document.header, "\\cite_engine", 0)
759 engine = get_value(document.header, "\\cite_engine", i)
761 engine, type = engine.split("_")
763 type = {"basic": "numerical", "jurabib": "authoryear"}[engine]
764 document.header[i] = "\\cite_engine " + engine
765 document.header.insert(i + 1, "\\cite_engine_type " + type)
768 def revert_cite_engine_type(document):
769 "Natbib had the type appended with an underscore."
770 engine_type = "numerical"
771 i = find_token(document.header, "\\cite_engine_type" , 0)
773 document.warning("No \\cite_engine_type line. Assuming numerical.")
775 engine_type = get_value(document.header, "\\cite_engine_type", i)
776 del document.header[i]
778 # We are looking for the natbib citation engine
779 i = find_token(document.header, "\\cite_engine natbib", 0)
782 document.header[i] = "\\cite_engine natbib_" + engine_type
785 def convert_cite_engine_type_default(document):
786 "Convert \\cite_engine_type to default for the basic citation engine."
787 i = find_token(document.header, "\\cite_engine basic", 0)
790 i = find_token(document.header, "\\cite_engine_type" , 0)
793 document.header[i] = "\\cite_engine_type default"
796 def revert_cite_engine_type_default(document):
797 """Revert \\cite_engine_type default.
799 Revert to numerical for the basic cite engine, otherwise to authoryear."""
800 engine_type = "authoryear"
801 i = find_token(document.header, "\\cite_engine_type default" , 0)
804 j = find_token(document.header, "\\cite_engine basic", 0)
806 engine_type = "numerical"
807 document.header[i] = "\\cite_engine_type " + engine_type
810 cancel_commands = ["cancel", "bcancel", "xcancel", "cancelto"]
811 # this is the same, as revert_use_cancel() except for the default
812 def revert_cancel(document):
813 "add cancel to the preamble if necessary"
814 revert_use_package(document, "cancel", cancel_commands, False)
817 def revert_verbatim(document, starred = False):
818 " Revert verbatim environments completely to TeX-code. "
822 layout_name = "Verbatim"
823 latex_name = "verbatim"
825 layout_name = "Verbatim*"
826 latex_name = "verbatim*"
828 subst_end = ['\\end_layout', '', '\\begin_layout Plain Layout',
830 '\\begin_layout Plain Layout', '', '',
832 'end{%s}' % (latex_name),
833 '\\end_layout', '', '\\end_inset',
834 '', '', '\\end_layout']
835 subst_begin = ['\\begin_layout Standard', '\\noindent',
836 '\\begin_inset ERT', 'status open', '',
837 '\\begin_layout Plain Layout', '', '', '\\backslash',
838 'begin{%s}' % (latex_name),
839 '\\end_layout', '', '\\begin_layout Plain Layout', '']
842 i = find_token(document.body, "\\begin_layout %s" % (layout_name), i)
845 j = find_end_of_layout(document.body, i)
847 document.warning("Malformed LyX document: Can't find end of %s layout" \
851 # delete all line breaks insets (there are no other insets)
854 n = find_token(document.body, "\\begin_inset Newline newline", l, j)
856 n = find_token(document.body, "\\begin_inset Newline linebreak", l, j)
859 m = find_end_of_inset(document.body, n)
860 del(document.body[m:m+1])
861 document.body[n:n+1] = ['\\end_layout', '', '\\begin_layout Plain Layout']
863 # we deleted a line, so the end of the inset moved forward.
864 # FIXME But we also added some lines, didn't we? I think this
867 # consecutive verbatim environments need to be connected
868 k = find_token(document.body, "\\begin_layout %s" % (layout_name), j)
869 if k == j + 2 and consecutive == False:
871 document.body[j:j+1] = ['\\end_layout', '', '\\begin_layout Plain Layout']
872 document.body[i:i+1] = subst_begin
874 if k == j + 2 and consecutive == True:
875 document.body[j:j+1] = ['\\end_layout', '', '\\begin_layout Plain Layout']
876 del(document.body[i:i+1])
878 if k != j + 2 and consecutive == True:
879 document.body[j:j+1] = subst_end
880 # the next paragraph must not be indented
881 # FIXME This seems to be causing problems, because of the
882 # hardcoded use of 19. We should figure out exactly where
883 # this needs to go by searching for the right tag.
884 document.body[j+19:j+19] = ['\\noindent']
885 del(document.body[i:i+1])
889 document.body[j:j+1] = subst_end
890 # the next paragraph must not be indented
891 # FIXME This seems to be causing problems, because of the
892 # hardcoded use of 19. We should figure out exactly where
893 # this needs to go by searching for the right tag.
894 document.body[j+19:j+19] = ['\\noindent']
895 document.body[i:i+1] = subst_begin
898 def revert_tipa(document):
899 " Revert native TIPA insets to mathed or ERT. "
902 i = find_token(document.body, "\\begin_inset IPA", i)
905 j = find_end_of_inset(document.body, i)
907 document.warning("Malformed LyX document: Can't find end of IPA inset")
911 n = find_token(document.body, "\\begin_layout", i, j)
913 document.warning("Malformed LyX document: IPA inset has no embedded layout")
916 m = find_end_of_layout(document.body, n)
918 document.warning("Malformed LyX document: Can't find end of embedded layout")
921 content = document.body[n+1:m]
922 p = find_token(document.body, "\\begin_layout", m, j)
923 if p != -1 or len(content) > 1:
925 content = document.body[i+1:j]
927 # IPA insets with multiple pars need to be wrapped by \begin{IPA}...\end{IPA}
928 document.body[i:j+1] = ['\\end_layout', '', '\\begin_layout Standard'] + put_cmd_in_ert("\\begin{IPA}") + ['\\end_layout'] + content + ['\\begin_layout Standard'] + put_cmd_in_ert("\\end{IPA}")
929 add_to_preamble(document, ["\\usepackage{tipa,tipx}"])
931 # single-par IPA insets can be reverted to mathed
932 document.body[i:j+1] = ["\\begin_inset Formula $\\text{\\textipa{" + content[0] + "}}$", "\\end_inset"]
936 def revert_cell_rotation(document):
937 "Revert cell rotations to TeX-code"
939 load_rotating = False
943 # first, let's find out if we need to do anything
944 i = find_token(document.body, '<cell ', i)
947 j = document.body[i].find('rotate="')
949 k = document.body[i].find('"', j + 8)
950 value = document.body[i][j + 8 : k]
952 rgx = re.compile(r' rotate="[^"]+?"')
953 # remove rotate option
954 document.body[i] = rgx.sub('', document.body[i])
956 rgx = re.compile(r' rotate="[^"]+?"')
957 document.body[i] = rgx.sub(' rotate="true"', document.body[i])
959 rgx = re.compile(r' rotate="[^"]+?"')
961 # remove rotate option
962 document.body[i] = rgx.sub('', document.body[i])
964 document.body[i + 5 : i + 5] = \
965 put_cmd_in_ert("\\end{turn}")
966 document.body[i + 4 : i + 4] = \
967 put_cmd_in_ert("\\begin{turn}{" + value + "}")
973 add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"])
976 def convert_cell_rotation(document):
977 'Convert cell rotation statements from "true" to "90"'
981 # first, let's find out if we need to do anything
982 i = find_token(document.body, '<cell ', i)
985 j = document.body[i].find('rotate="true"')
987 rgx = re.compile(r'rotate="[^"]+?"')
988 # convert "true" to "90"
989 document.body[i] = rgx.sub('rotate="90"', document.body[i])
994 def revert_table_rotation(document):
995 "Revert table rotations to TeX-code"
997 load_rotating = False
1001 # first, let's find out if we need to do anything
1002 i = find_token(document.body, '<features ', i)
1005 j = document.body[i].find('rotate="')
1007 end_table = find_token(document.body, '</lyxtabular>', j)
1008 k = document.body[i].find('"', j + 8)
1009 value = document.body[i][j + 8 : k]
1011 rgx = re.compile(r' rotate="[^"]+?"')
1012 # remove rotate option
1013 document.body[i] = rgx.sub('', document.body[i])
1015 rgx = re.compile(r'rotate="[^"]+?"')
1016 document.body[i] = rgx.sub('rotate="true"', document.body[i])
1018 rgx = re.compile(r' rotate="[^"]+?"')
1019 load_rotating = True
1020 # remove rotate option
1021 document.body[i] = rgx.sub('', document.body[i])
1023 document.body[end_table + 3 : end_table + 3] = \
1024 put_cmd_in_ert("\\end{turn}")
1025 document.body[i - 2 : i - 2] = \
1026 put_cmd_in_ert("\\begin{turn}{" + value + "}")
1032 add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"])
1035 def convert_table_rotation(document):
1036 'Convert table rotation statements from "true" to "90"'
1040 # first, let's find out if we need to do anything
1041 i = find_token(document.body, '<features ', i)
1044 j = document.body[i].find('rotate="true"')
1046 rgx = re.compile(r'rotate="[^"]+?"')
1047 # convert "true" to "90"
1048 document.body[i] = rgx.sub('rotate="90"', document.body[i])
1053 def convert_listoflistings(document):
1054 'Convert ERT \lstlistoflistings to TOC lstlistoflistings inset'
1055 # We can support roundtrip because the command is so simple
1058 i = find_token(document.body, "\\begin_inset ERT", i)
1061 j = find_end_of_inset(document.body, i)
1063 document.warning("Malformed LyX document: Can't find end of ERT inset")
1066 ert = get_ert(document.body, i)
1067 if ert == "\\lstlistoflistings{}":
1068 document.body[i:j] = ["\\begin_inset CommandInset toc", "LatexCommand lstlistoflistings", ""]
1074 def revert_listoflistings(document):
1075 'Convert TOC lstlistoflistings inset to ERT lstlistoflistings'
1078 i = find_token(document.body, "\\begin_inset CommandInset toc", i)
1081 if document.body[i+1] == "LatexCommand lstlistoflistings":
1082 j = find_end_of_inset(document.body, i)
1084 document.warning("Malformed LyX document: Can't find end of TOC inset")
1087 subst = put_cmd_in_ert("\\lstlistoflistings{}")
1088 document.body[i:j+1] = subst
1089 add_to_preamble(document, ["\\usepackage{listings}"])
1093 def convert_use_amssymb(document):
1094 "insert use_package amssymb"
1095 regexp = re.compile(r'(\\use_package\s+amsmath)')
1096 i = find_re(document.header, regexp, 0)
1098 document.warning("Malformed LyX document: Can't find \\use_package amsmath.")
1100 value = get_value(document.header, "\\use_package" , i).split()[1]
1103 useamsmath = int(value)
1105 document.warning("Invalid \\use_package amsmath: " + value + ". Assuming auto.")
1107 j = find_token(document.preamble, "\\usepackage{amssymb}", 0)
1109 document.header.insert(i + 1, "\\use_package amssymb %d" % useamsmath)
1111 document.header.insert(i + 1, "\\use_package amssymb 2")
1112 del document.preamble[j]
1115 def revert_use_amssymb(document):
1116 "remove use_package amssymb"
1117 regexp1 = re.compile(r'(\\use_package\s+amsmath)')
1118 regexp2 = re.compile(r'(\\use_package\s+amssymb)')
1119 i = find_re(document.header, regexp1, 0)
1120 j = find_re(document.header, regexp2, 0)
1121 value1 = "1" # default is auto
1122 value2 = "1" # default is auto
1124 value1 = get_value(document.header, "\\use_package" , i).split()[1]
1126 value2 = get_value(document.header, "\\use_package" , j).split()[1]
1127 del document.header[j]
1128 if value1 != value2 and value2 == "2": # on
1129 add_to_preamble(document, ["\\usepackage{amssymb}"])
1132 def convert_use_cancel(document):
1133 "insert use_package cancel"
1134 convert_use_package(document, "cancel", cancel_commands, True)
1137 def revert_use_cancel(document):
1138 "remove use_package cancel"
1139 revert_use_package(document, "cancel", cancel_commands, True)
1142 def revert_ancientgreek(document):
1143 "Set the document language for ancientgreek to greek"
1145 if document.language == "ancientgreek":
1146 document.language = "greek"
1147 i = find_token(document.header, "\\language", 0)
1149 document.header[i] = "\\language greek"
1152 j = find_token(document.body, "\\lang ancientgreek", j)
1156 document.body[j] = document.body[j].replace("\\lang ancientgreek", "\\lang greek")
1160 def revert_languages(document):
1161 "Set the document language for new supported languages to English"
1164 "coptic", "divehi", "hindi", "kurmanji", "lao", "marathi", "occitan", "sanskrit",
1165 "syriac", "tamil", "telugu", "urdu"
1167 for n in range(len(languages)):
1168 if document.language == languages[n]:
1169 document.language = "english"
1170 i = find_token(document.header, "\\language", 0)
1172 document.header[i] = "\\language english"
1174 while j < len(document.body):
1175 j = find_token(document.body, "\\lang " + languages[n], j)
1177 document.body[j] = document.body[j].replace("\\lang " + languages[n], "\\lang english")
1180 j = len(document.body)
1183 def convert_armenian(document):
1184 "Use polyglossia and thus non-TeX fonts for Armenian"
1186 if document.language == "armenian":
1187 i = find_token(document.header, "\\use_non_tex_fonts", 0)
1189 document.header[i] = "\\use_non_tex_fonts true"
1192 def revert_armenian(document):
1193 "Use ArmTeX and thus TeX fonts for Armenian"
1195 if document.language == "armenian":
1196 i = find_token(document.header, "\\use_non_tex_fonts", 0)
1198 document.header[i] = "\\use_non_tex_fonts false"
1201 def revert_libertine(document):
1202 " Revert native libertine font definition to LaTeX "
1204 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1205 i = find_token(document.header, "\\font_roman libertine", 0)
1208 j = find_token(document.header, "\\font_osf true", 0)
1211 preamble = "\\usepackage"
1213 document.header[j] = "\\font_osf false"
1216 preamble += "[lining]"
1217 preamble += "{libertine-type1}"
1218 add_to_preamble(document, [preamble])
1219 document.header[i] = "\\font_roman default"
1222 def revert_txtt(document):
1223 " Revert native txtt font definition to LaTeX "
1225 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1226 i = find_token(document.header, "\\font_typewriter txtt", 0)
1228 preamble = "\\renewcommand{\\ttdefault}{txtt}"
1229 add_to_preamble(document, [preamble])
1230 document.header[i] = "\\font_typewriter default"
1233 def revert_mathdesign(document):
1234 " Revert native mathdesign font definition to LaTeX "
1236 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1242 i = find_token(document.header, "\\font_roman", 0)
1245 val = get_value(document.header, "\\font_roman", i)
1246 if val in list(mathdesign_dict.keys()):
1247 preamble = "\\usepackage[%s" % mathdesign_dict[val]
1249 j = find_token(document.header, "\\font_osf true", 0)
1252 document.header[j] = "\\font_osf false"
1253 l = find_token(document.header, "\\font_sc true", 0)
1256 document.header[l] = "\\font_sc false"
1258 preamble += ",expert"
1259 preamble += "]{mathdesign}"
1260 add_to_preamble(document, [preamble])
1261 document.header[i] = "\\font_roman default"
1264 def revert_texgyre(document):
1265 " Revert native TeXGyre font definition to LaTeX "
1267 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1268 texgyre_fonts = ["tgadventor", "tgbonum", "tgchorus", "tgcursor", \
1269 "tgheros", "tgpagella", "tgschola", "tgtermes"]
1270 i = find_token(document.header, "\\font_roman", 0)
1272 val = get_value(document.header, "\\font_roman", i)
1273 if val in texgyre_fonts:
1274 preamble = "\\usepackage{%s}" % val
1275 add_to_preamble(document, [preamble])
1276 document.header[i] = "\\font_roman default"
1277 i = find_token(document.header, "\\font_sans", 0)
1279 val = get_value(document.header, "\\font_sans", i)
1280 if val in texgyre_fonts:
1281 preamble = "\\usepackage{%s}" % val
1282 add_to_preamble(document, [preamble])
1283 document.header[i] = "\\font_sans default"
1284 i = find_token(document.header, "\\font_typewriter", 0)
1286 val = get_value(document.header, "\\font_typewriter", i)
1287 if val in texgyre_fonts:
1288 preamble = "\\usepackage{%s}" % val
1289 add_to_preamble(document, [preamble])
1290 document.header[i] = "\\font_typewriter default"
1293 def revert_ipadeco(document):
1294 " Revert IPA decorations to ERT "
1297 i = find_token(document.body, "\\begin_inset IPADeco", i)
1300 end = find_end_of_inset(document.body, i)
1302 document.warning("Can't find end of inset at line " + str(i))
1305 line = document.body[i]
1306 rx = re.compile(r'\\begin_inset IPADeco (.*)$')
1308 decotype = m.group(1)
1309 if decotype != "toptiebar" and decotype != "bottomtiebar":
1310 document.warning("Invalid IPADeco type: " + decotype)
1313 blay = find_token(document.body, "\\begin_layout Plain Layout", i, end)
1315 document.warning("Can't find layout for inset at line " + str(i))
1318 bend = find_end_of_layout(document.body, blay)
1320 document.warning("Malformed LyX document: Could not find end of IPADeco inset's layout.")
1323 substi = ["\\begin_inset ERT", "status collapsed", "",
1324 "\\begin_layout Plain Layout", "", "", "\\backslash",
1325 decotype + "{", "\\end_layout", "", "\\end_inset"]
1326 substj = ["\\size default", "", "\\begin_inset ERT", "status collapsed", "",
1327 "\\begin_layout Plain Layout", "", "}", "\\end_layout", "", "\\end_inset"]
1328 # do the later one first so as not to mess up the numbering
1329 document.body[bend:end + 1] = substj
1330 document.body[i:blay + 1] = substi
1331 i = end + len(substi) + len(substj) - (end - bend) - (blay - i) - 2
1332 add_to_preamble(document, "\\usepackage{tipa}")
1335 def revert_ipachar(document):
1336 ' Revert \\IPAChar to ERT '
1339 while i < len(document.body):
1340 m = re.match(r'(.*)\\IPAChar \\(\w+\{\w+\})(.*)', document.body[i])
1344 ipachar = m.group(2)
1347 '\\begin_inset ERT',
1348 'status collapsed', '',
1349 '\\begin_layout Standard',
1350 '', '', '\\backslash',
1355 document.body[i: i+1] = subst
1360 add_to_preamble(document, "\\usepackage{tone}")
1363 def revert_minionpro(document):
1364 " Revert native MinionPro font definition to LaTeX "
1366 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1367 i = find_token(document.header, "\\font_roman minionpro", 0)
1370 j = find_token(document.header, "\\font_osf true", 0)
1373 preamble = "\\usepackage"
1375 document.header[j] = "\\font_osf false"
1378 preamble += "{MinionPro}"
1379 add_to_preamble(document, [preamble])
1380 document.header[i] = "\\font_roman default"
1383 def revert_mathfonts(document):
1384 " Revert native math font definitions to LaTeX "
1386 i = find_token(document.header, "\\font_math", 0)
1389 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1390 val = get_value(document.header, "\\font_math", i)
1391 if val == "eulervm":
1392 add_to_preamble(document, "\\usepackage{eulervm}")
1393 elif val == "default":
1395 "lmodern": "\\renewcommand{\\rmdefault}{lmr}",
1396 "minionpro": "\\usepackage[onlytext,lf]{MinionPro}",
1397 "minionpro-osf": "\\usepackage[onlytext]{MinionPro}",
1398 "palatino": "\\renewcommand{\\rmdefault}{ppl}",
1399 "palatino-osf": "\\renewcommand{\\rmdefault}{pplj}",
1400 "times": "\\renewcommand{\\rmdefault}{ptm}",
1401 "utopia": "\\renewcommand{\\rmdefault}{futs}",
1402 "utopia-osf": "\\renewcommand{\\rmdefault}{futj}",
1404 j = find_token(document.header, "\\font_roman", 0)
1406 rm = get_value(document.header, "\\font_roman", j)
1407 k = find_token(document.header, "\\font_osf true", 0)
1410 if rm in list(mathfont_dict.keys()):
1411 add_to_preamble(document, mathfont_dict[rm])
1412 document.header[j] = "\\font_roman default"
1414 document.header[k] = "\\font_osf false"
1415 del document.header[i]
1418 def revert_mdnomath(document):
1419 " Revert mathdesign and fourier without math "
1421 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1423 "md-charter": "mdbch",
1424 "md-utopia": "mdput",
1425 "md-garamond": "mdugm"
1427 i = find_token(document.header, "\\font_roman", 0)
1430 val = get_value(document.header, "\\font_roman", i)
1431 if val in list(mathdesign_dict.keys()):
1432 j = find_token(document.header, "\\font_math", 0)
1434 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1435 mval = get_value(document.header, "\\font_math", j)
1436 if mval == "default":
1437 document.header[i] = "\\font_roman default"
1438 add_to_preamble(document, "\\renewcommand{\\rmdefault}{%s}" % mathdesign_dict[val])
1440 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1443 def convert_mathfonts(document):
1444 document.header.insert(-1, "\\font_math auto")
1447 def convert_mdnomath(document):
1448 " Change mathdesign font name "
1450 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1452 "mdbch": "md-charter",
1453 "mdput": "md-utopia",
1454 "mdugm": "md-garamond"
1456 i = find_token(document.header, "\\font_roman", 0)
1459 val = get_value(document.header, "\\font_roman", i)
1460 if val in list(mathdesign_dict.keys()):
1461 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1464 def revert_newtxmath(document):
1465 " Revert native newtxmath definitions to LaTeX "
1467 i = find_token(document.header, "\\font_math", 0)
1470 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1471 val = get_value(document.header, "\\font_math", i)
1473 "libertine-ntxm": "\\usepackage[libertine]{newtxmath}",
1474 "minion-ntxm": "\\usepackage[minion]{newtxmath}",
1475 "newtxmath": "\\usepackage{newtxmath}",
1477 if val in list(mathfont_dict.keys()):
1478 add_to_preamble(document, mathfont_dict[val])
1479 document.header[i] = "\\font_math auto"
1482 def revert_biolinum(document):
1483 " Revert native biolinum font definition to LaTeX "
1485 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1486 i = find_token(document.header, "\\font_sans biolinum", 0)
1489 j = find_token(document.header, "\\font_osf true", 0)
1492 preamble = "\\usepackage"
1495 preamble += "{biolinum-type1}"
1496 add_to_preamble(document, [preamble])
1497 document.header[i] = "\\font_sans default"
1500 def revert_uop(document):
1501 " Revert native URW Classico (Optima) font definition to LaTeX "
1503 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1504 i = find_token(document.header, "\\font_sans uop", 0)
1506 preamble = "\\renewcommand{\\sfdefault}{uop}"
1507 add_to_preamble(document, [preamble])
1508 document.header[i] = "\\font_sans default"
1511 def convert_latexargs(document):
1512 " Convert InsetArgument to new syntax "
1514 if find_token(document.body, "\\begin_inset Argument", 0) == -1:
1518 # A list of layouts (document classes) with only optional or no arguments.
1519 # These can be safely converted to the new syntax
1520 # (I took the liberty to add some of my personal layouts/modules here; JSP)
1521 safe_layouts = ["aa", "aapaper", "aastex", "achemso", "acmsiggraph", "AEA",
1522 "agu-dtd", "agums", "agutex", "amsart", "amsbook", "apa",
1523 "arab-article", "armenian-article", "article-beamer", "article",
1524 "beamer", "book", "broadway", "chess", "cl2emult", "ctex-article",
1525 "ctex-book", "ctex-report", "dinbrief", "docbook-book", "docbook-chapter",
1526 "docbook", "docbook-section", "doublecol-new", "dtk", "ectaart", "egs",
1527 "elsarticle", "elsart", "entcs", "europecv", "extarticle", "extbook",
1528 "extletter", "extreport", "foils", "frletter", "g-brief2", "g-brief",
1529 "heb-article", "heb-letter", "hollywood", "IEEEtran", "ijmpc", "ijmpd",
1530 "iopart", "isprs", "jarticle", "jasatex", "jbook", "jgrga", "jreport",
1531 "jsarticle", "jsbeamer", "jsbook", "jss", "kluwer", "latex8", "letter", "lettre",
1532 "literate-article", "literate-book", "literate-report", "llncs", "ltugboat",
1533 "memoir", "moderncv", "mwart", "mwbk", "mwrep", "paper", "powerdot",
1534 "recipebook", "report", "revtex4", "revtex", "scrartcl", "scrarticle-beamer",
1535 "scrbook", "scrlettr", "scrlttr2", "scrreprt", "seminar", "siamltex",
1536 "sigplanconf", "simplecv", "singlecol", "singlecol-new", "slides", "spie",
1537 "svglobal3", "svglobal", "svjog", "svmono", "svmult", "svprobth", "tarticle",
1538 "tbook", "treport", "tufte-book", "tufte-handout"]
1539 # A list of "safe" modules, same as above
1540 safe_modules = ["biblatex", "beameraddons", "beamer-resenumerate", "beamersession", "braille",
1541 "customHeadersFooters", "endnotes", "enumitem", "eqs-within-sections", "figs-within-sections",
1542 "fix-cm", "fixltx2e", "foottoend", "hanging", "jscharstyles", "knitr", "lilypond",
1543 "linguistics", "linguisticx", "logicalmkup", "minimalistic", "nomindex", "noweb",
1544 "pdfcomment", "sweave", "tabs-within-sections", "theorems-ams-bytype",
1545 "theorems-ams-extended-bytype", "theorems-ams-extended", "theorems-ams", "theorems-bytype",
1546 "theorems-chap-bytype", "theorems-chap", "theorems-named", "theorems-sec-bytype",
1547 "theorems-sec", "theorems-starred", "theorems-std", "todonotes"]
1548 # Modules we need to take care of
1549 caveat_modules = ["initials"]
1550 # information about the relevant styles in caveat_modules (number of opt and req args)
1551 # use this if we get more caveat_modules. For now, use hard coding (see below).
1552 # initials = [{'Layout' : 'Initial', 'opt' : 1, 'req' : 1}]
1554 # Is this a known safe layout?
1555 safe_layout = document.textclass in safe_layouts
1557 document.warning("Lyx2lyx knows nothing about textclass '%s'. "
1558 "Please check if short title insets have been converted correctly."
1559 % document.textclass)
1560 # Do we use unsafe or unknown modules
1561 mods = document.get_module_list()
1562 unknown_modules = False
1563 used_caveat_modules = list()
1565 if mod in safe_modules:
1567 if mod in caveat_modules:
1568 used_caveat_modules.append(mod)
1570 unknown_modules = True
1571 document.warning("Lyx2lyx knows nothing about module '%s'. "
1572 "Please check if short title insets have been converted correctly."
1577 i = find_token(document.body, "\\begin_inset Argument", i)
1581 if not safe_layout or unknown_modules:
1582 # We cannot do more here since we have no access to this layout.
1583 # InsetArgument itself will do the real work
1584 # (see InsetArgument::updateBuffer())
1585 document.body[i] = "\\begin_inset Argument 999"
1589 # Find containing paragraph layout
1590 parent = get_containing_layout(document.body, i)
1592 document.warning("Malformed LyX document: Can't find parent paragraph layout")
1599 if len(used_caveat_modules) > 0:
1600 # We know for now that this must be the initials module with the Initial layout
1601 # If we get more such modules, we need some automating.
1602 if parent[0] == "Initial":
1603 # Layout has 1 opt and 1 req arg.
1604 # Count the actual arguments
1606 for p in range(parbeg, parend):
1607 if document.body[p] == "\\begin_inset Argument":
1612 # Collect all arguments in this paragraph
1614 for p in range(parbeg, parend):
1615 if document.body[p] == "\\begin_inset Argument":
1617 if allowed_opts != -1:
1618 # We have less arguments than opt + required.
1619 # required must take precedence.
1620 if argnr > allowed_opts and argnr < first_req:
1622 document.body[p] = "\\begin_inset Argument %d" % argnr
1626 def revert_latexargs(document):
1627 " Revert InsetArgument to old syntax "
1630 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
1633 # Search for Argument insets
1634 i = find_token(document.body, "\\begin_inset Argument", i)
1637 m = rx.match(document.body[i])
1639 # No ID: inset already reverted
1642 # Find containing paragraph layout
1643 parent = get_containing_layout(document.body, i)
1645 document.warning("Malformed LyX document: Can't find parent paragraph layout")
1650 # Do not set realparbeg to parent[3], since this does not work if we
1651 # have another inset (e.g. label or index) before the first argument
1652 # inset (this is the case in the user guide of LyX 2.0.8)
1654 # Collect all arguments in this paragraph
1656 for p in range(parbeg, parend):
1657 m = rx.match(document.body[p])
1660 # This is the first argument inset
1662 val = int(m.group(1))
1663 j = find_end_of_inset(document.body, p)
1664 # Revert to old syntax
1665 document.body[p] = "\\begin_inset Argument"
1667 document.warning("Malformed LyX document: Can't find end of Argument inset")
1670 args[val] = document.body[p : j + 1]
1672 realparend = realparend - len(document.body[p : j + 1])
1673 # Remove arg inset at this position
1674 del document.body[p : j + 1]
1678 # No argument inset found
1679 realparbeg = parent[3]
1680 # Now sort the arg insets
1682 for f in sorted(args):
1685 # Insert the sorted arg insets at paragraph begin
1686 document.body[realparbeg : realparbeg] = subst
1688 i = realparbeg + 1 + len(subst)
1691 def revert_IEEEtran(document):
1693 Reverts InsetArgument of
1696 Biography without photo
1699 if document.textclass != "IEEEtran":
1702 layouts = {"Page headings": False,
1703 "Biography without photo": True}
1705 for layout in list(layouts.keys()):
1708 i = find_token(document.body, '\\begin_layout ' + layout, i)
1711 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, layouts[layout], False)
1716 i = find_token(document.body, '\\begin_inset Flex Paragraph Start', i)
1719 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1724 i = find_token_exact(document.body, "\\begin_layout Biography", i)
1728 if document.body[i] == "\\begin_layout Biography without photo":
1732 # start with the second argument, therefore 2
1733 revert_Argument_to_TeX_brace(document, i, 0, 2, 2, True, False)
1737 def revert_IEEEtran_2(document):
1739 Reverts Flex Paragraph Start to TeX-code
1741 if document.textclass == "IEEEtran":
1744 begin = find_token(document.body, "\\begin_inset Flex Paragraph Start", begin)
1747 end1 = find_end_of_inset(document.body, begin)
1748 document.body[end1 - 2 : end1 + 1] = put_cmd_in_ert("}")
1749 document.body[begin : begin + 4] = put_cmd_in_ert("\\IEEEPARstart{")
1753 def convert_IEEEtran(document):
1758 Biography without photo
1761 if document.textclass != "IEEEtran":
1764 layouts = {"Page headings": False,
1765 "Biography without photo": True}
1767 for layout in list(layouts.keys()):
1770 i = find_token(document.body, '\\begin_layout ' + layout, i)
1773 convert_TeX_brace_to_Argument(document, i, 1, 1, False, layouts[layout], False)
1778 i = find_token_exact(document.body, "\\begin_layout Biography", i)
1782 if document.body[i] == "\\begin_layout Biography without photo":
1786 # the argument we want to convert is the second one
1787 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, False)
1791 def revert_AASTeX(document):
1792 " Reverts InsetArgument of Altaffilation to TeX-code "
1793 if document.textclass == "aastex":
1796 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1799 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1803 def convert_AASTeX(document):
1804 " Converts ERT of Altaffilation to InsetArgument "
1805 if document.textclass == "aastex":
1808 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1811 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1815 def revert_AGUTeX(document):
1816 " Reverts InsetArgument of Author affiliation to TeX-code "
1817 if document.textclass == "agutex":
1820 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1823 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1827 def convert_AGUTeX(document):
1828 " Converts ERT of Author affiliation to InsetArgument "
1829 if document.textclass == "agutex":
1832 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1835 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1839 def revert_IJMP(document):
1840 " Reverts InsetArgument of MarkBoth to TeX-code "
1841 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1844 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1847 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1851 def convert_IJMP(document):
1852 " Converts ERT of MarkBoth to InsetArgument "
1853 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1856 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1859 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1863 def revert_SIGPLAN(document):
1864 " Reverts InsetArguments of SIGPLAN to TeX-code "
1865 if document.textclass == "sigplanconf":
1870 i = find_token(document.body, "\\begin_layout Conference", i)
1872 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1875 j = find_token(document.body, "\\begin_layout Author", j)
1877 revert_Argument_to_TeX_brace(document, j, 0, 1, 2, False, False)
1879 if i == -1 and j == -1:
1883 def convert_SIGPLAN(document):
1884 " Converts ERT of SIGPLAN to InsetArgument "
1885 if document.textclass == "sigplanconf":
1890 i = find_token(document.body, "\\begin_layout Conference", i)
1892 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1895 j = find_token(document.body, "\\begin_layout Author", j)
1897 convert_TeX_brace_to_Argument(document, j, 1, 2, False, False, False)
1899 if i == -1 and j == -1:
1903 def revert_SIGGRAPH(document):
1904 " Reverts InsetArgument of Flex CRcat to TeX-code "
1905 if document.textclass == "acmsiggraph":
1908 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1911 revert_Argument_to_TeX_brace(document, i, 0, 1, 3, False, False)
1915 def convert_SIGGRAPH(document):
1916 " Converts ERT of Flex CRcat to InsetArgument "
1917 if document.textclass == "acmsiggraph":
1920 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1923 convert_TeX_brace_to_Argument(document, i, 1, 3, True, False, False)
1927 def revert_EuropeCV(document):
1928 " Reverts InsetArguments of europeCV to TeX-code "
1929 if document.textclass == "europecv":
1936 i = find_token(document.body, "\\begin_layout Item", i)
1938 revert_Argument_to_TeX_brace(document, i, 0, 2, 2, False, False)
1941 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1943 revert_Argument_to_TeX_brace(document, j, 0, 2, 2, False, False)
1946 k = find_token(document.body, "\\begin_layout Language", k)
1948 revert_Argument_to_TeX_brace(document, k, 0, 2, 6, False, False)
1951 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1953 revert_Argument_to_TeX_brace(document, m, 0, 2, 6, False, False)
1955 if i == -1 and j == -1 and k == -1 and m == -1:
1959 def convert_EuropeCV(document):
1960 " Converts ERT of europeCV to InsetArgument "
1961 if document.textclass == "europecv":
1968 i = find_token(document.body, "\\begin_layout Item", i)
1970 convert_TeX_brace_to_Argument(document, i, 2, 2, False, False, False)
1973 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1975 convert_TeX_brace_to_Argument(document, j, 2, 2, False, False, False)
1978 k = find_token(document.body, "\\begin_layout Language", k)
1980 convert_TeX_brace_to_Argument(document, k, 2, 6, False, False, False)
1983 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1985 convert_TeX_brace_to_Argument(document, m, 2, 6, False, False, False)
1987 if i == -1 and j == -1 and k == -1 and m == -1:
1991 def revert_ModernCV(document):
1992 " Reverts InsetArguments of modernCV to TeX-code "
1993 if document.textclass == "moderncv":
2001 j = find_token(document.body, "\\begin_layout Entry", j)
2003 revert_Argument_to_TeX_brace(document, j, 0, 1, 5, False, False)
2006 k = find_token(document.body, "\\begin_layout Item", k)
2008 revert_Argument_to_TeX_brace(document, k, 0, 1, 1, False, False)
2011 m = find_token(document.body, "\\begin_layout ItemWithComment", m)
2013 revert_Argument_to_TeX_brace(document, m, 0, 1, 2, False, False)
2014 document.body[m] = document.body[m].replace("\\begin_layout ItemWithComment", "\\begin_layout Language")
2017 o = find_token(document.body, "\\begin_layout DoubleItem", o)
2019 revert_Argument_to_TeX_brace(document, o, 0, 1, 3, False, False)
2020 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout Computer")
2023 p = find_token(document.body, "\\begin_layout Social", p)
2025 revert_Argument_to_TeX_brace(document, p, 0, 1, 1, False, True)
2027 if j == -1 and k == -1 and m == -1 and o == -1 and p == -1:
2031 def revert_ModernCV_2(document):
2032 " Reverts the Flex:Column inset of modernCV to TeX-code "
2033 if document.textclass == "moderncv":
2037 flex = find_token(document.body, "\\begin_inset Flex Column", flex)
2040 flexEnd = find_end_of_inset(document.body, flex)
2041 wasOpt = revert_Argument_to_TeX_brace(document, flex, flexEnd, 1, 1, False, True)
2042 revert_Argument_to_TeX_brace(document, flex, 0, 2, 2, False, False)
2043 flexEnd = find_end_of_inset(document.body, flex)
2045 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn")
2047 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn{")
2048 document.body[flexEnd + 4 : flexEnd + 7] = put_cmd_in_ert("}")
2052 def revert_ModernCV_3(document):
2053 " Reverts the Column style of modernCV to TeX-code "
2054 if document.textclass == "moderncv":
2055 # revert the layouts
2056 revert_ModernCV(document)
2058 # get the position of the end of the last column inset
2059 LastFlexEnd = revert_ModernCV_2(document)
2061 p = find_token(document.body, "\\begin_layout Columns", p)
2064 pEnd = find_end_of_layout(document.body, p)
2065 document.body[p] = document.body[p].replace("\\begin_layout Columns", "\\begin_layout Standard")
2066 if LastFlexEnd != -1:
2067 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\begin{cvcolumns}")
2068 document.body[LastFlexEnd + 24 : LastFlexEnd + 24] = put_cmd_in_ert("\\end{cvcolumns}")
2072 def revert_ModernCV_4(document):
2073 " Reverts the style Social to TeX-code "
2074 if document.textclass == "moderncv":
2075 # revert the layouts
2076 revert_ModernCV(document)
2079 p = find_token(document.body, "\\begin_layout Social", p)
2082 pEnd = find_end_of_layout(document.body, p)
2083 document.body[p] = document.body[p].replace("\\begin_layout Social", "\\begin_layout Standard")
2084 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\social")
2085 hasOpt = find_token(document.body, "[", p + 9)
2087 document.body[p + 30 : p + 30] = put_cmd_in_ert("{")
2088 document.body[p + 41 : p + 41] = put_cmd_in_ert("}")
2090 document.body[p + 11 : p + 11] = put_cmd_in_ert("{")
2091 document.body[p + 21 : p + 21] = put_cmd_in_ert("}")
2095 def convert_ModernCV(document):
2096 " Converts ERT of modernCV to InsetArgument "
2097 if document.textclass == "moderncv":
2105 i = find_token(document.body, "\\begin_layout DoubleItem", i)
2107 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
2108 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout DoubleListItem")
2111 j = find_token(document.body, "\\begin_layout Entry", j)
2113 convert_TeX_brace_to_Argument(document, j, 1, 5, False, False, False)
2116 k = find_token(document.body, "\\begin_layout Item", k)
2118 convert_TeX_brace_to_Argument(document, k, 1, 1, False, False, False)
2121 m = find_token(document.body, "\\begin_layout Language", m)
2123 convert_TeX_brace_to_Argument(document, m, 1, 2, False, False, False)
2125 if i == -1 and j == -1 and k == -1 and m == -1:
2129 def revert_Initials(document):
2130 " Reverts InsetArgument of Initial to TeX-code "
2133 i = find_token(document.body, "\\begin_layout Initial", i)
2136 # first arg (optional) and second arg (first mandatory) are supported in LyX 2.0.x
2137 revert_Argument_to_TeX_brace(document, i, 0, 3, 3, False, False)
2141 def convert_Initials(document):
2142 " Converts ERT of Initial to InsetArgument "
2145 i = find_token(document.body, "\\begin_layout Initial", i)
2148 convert_TeX_brace_to_Argument(document, i, 3, 3, False, False, False)
2152 def revert_literate(document):
2153 " Revert Literate document to old format "
2154 if del_token(document.header, "noweb", 0):
2155 document.textclass = "literate-" + document.textclass
2158 i = find_token(document.body, "\\begin_layout Chunk", i)
2161 document.body[i] = "\\begin_layout Scrap"
2165 def convert_literate(document):
2166 " Convert Literate document to new format"
2167 i = find_token(document.header, "\\textclass", 0)
2168 if (i != -1) and "literate-" in document.header[i]:
2169 document.textclass = document.header[i].replace("\\textclass literate-", "")
2170 j = find_token(document.header, "\\begin_modules", 0)
2172 document.header.insert(j + 1, "noweb")
2174 document.header.insert(i + 1, "\\end_modules")
2175 document.header.insert(i + 1, "noweb")
2176 document.header.insert(i + 1, "\\begin_modules")
2179 i = find_token(document.body, "\\begin_layout Scrap", i)
2182 document.body[i] = "\\begin_layout Chunk"
2186 def revert_itemargs(document):
2187 " Reverts \\item arguments to TeX-code "
2190 i = find_token(document.body, "\\begin_inset Argument item:", i)
2193 j = find_end_of_inset(document.body, i)
2194 # Find containing paragraph layout
2195 parent = get_containing_layout(document.body, i)
2197 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2201 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2202 endPlain = find_end_of_layout(document.body, beginPlain)
2203 content = document.body[beginPlain + 1 : endPlain]
2204 del document.body[i:j+1]
2205 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2206 document.body[parbeg : parbeg] = subst
2210 def revert_garamondx_newtxmath(document):
2211 " Revert native garamond newtxmath definition to LaTeX "
2213 i = find_token(document.header, "\\font_math", 0)
2216 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2217 val = get_value(document.header, "\\font_math", i)
2218 if val == "garamondx-ntxm":
2219 add_to_preamble(document, "\\usepackage[garamondx]{newtxmath}")
2220 document.header[i] = "\\font_math auto"
2223 def revert_garamondx(document):
2224 " Revert native garamond font definition to LaTeX "
2226 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2227 i = find_token(document.header, "\\font_roman garamondx", 0)
2230 j = find_token(document.header, "\\font_osf true", 0)
2233 preamble = "\\usepackage"
2235 preamble += "[osfI]"
2236 preamble += "{garamondx}"
2237 add_to_preamble(document, [preamble])
2238 document.header[i] = "\\font_roman default"
2241 def convert_beamerargs(document):
2242 " Converts beamer arguments to new layout "
2244 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2245 if document.textclass not in beamer_classes:
2248 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2249 list_layouts = ["Itemize", "Enumerate", "Description"]
2250 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
2254 i = find_token(document.body, "\\begin_inset Argument", i)
2257 # Find containing paragraph layout
2258 parent = get_containing_layout(document.body, i)
2260 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2265 layoutname = parent[0]
2266 for p in range(parbeg, parend):
2267 if layoutname in shifted_layouts:
2268 m = rx.match(document.body[p])
2270 argnr = int(m.group(1))
2272 document.body[p] = "\\begin_inset Argument %d" % argnr
2273 if layoutname == "AgainFrame":
2274 m = rx.match(document.body[p])
2276 document.body[p] = "\\begin_inset Argument 3"
2277 if document.body[p + 4] == "\\begin_inset ERT":
2278 if document.body[p + 9].startswith("<"):
2279 # This is an overlay specification
2281 document.body[p + 9] = document.body[p + 9][1:]
2282 if document.body[p + 9].endswith(">"):
2284 document.body[p + 9] = document.body[p + 9][:-1]
2286 document.body[p] = "\\begin_inset Argument 2"
2287 if layoutname in list_layouts:
2288 m = rx.match(document.body[p])
2290 if m.group(1) == "1":
2291 if document.body[p + 4] == "\\begin_inset ERT":
2292 if document.body[p + 9].startswith("<"):
2293 # This is an overlay specification
2295 document.body[p + 9] = document.body[p + 9][1:]
2296 if document.body[p + 9].endswith(">"):
2298 document.body[p + 9] = document.body[p + 9][:-1]
2299 elif document.body[p + 4].startswith("<"):
2300 # This is an overlay specification (without ERT)
2302 document.body[p + 4] = document.body[p + 4][1:]
2303 if document.body[p + 4].endswith(">"):
2305 document.body[p + 4] = document.body[p + 4][:-1]
2306 elif layoutname != "Itemize":
2308 document.body[p] = "\\begin_inset Argument 2"
2313 # Helper function for the frame conversion routines
2315 # FIXME: This method currently requires the arguments to be either
2316 # * In one (whole) ERT each: <ERT>[<arg1>]</ERT><ERT><arg2></ERT><ERT>[arg3]</ERT>
2317 # * Altogether in one whole ERT: <ERT>[<arg1>]<arg2>[arg3]</ERT>
2318 # If individual arguments mix ERT and non-ERT or are splitted
2319 # over several ERTs, the parsing fails.
2320 def convert_beamerframeargs(document, i, parbeg):
2323 if document.body[parbeg] != "\\begin_inset ERT":
2325 ertend = find_end_of_inset(document.body, parbeg)
2327 document.warning("Malformed LyX document: missing ERT \\end_inset")
2329 ertcont = parbeg + 5
2330 if document.body[ertcont].startswith("[<"):
2331 # This is a default overlay specification
2333 document.body[ertcont] = document.body[ertcont][2:]
2334 if document.body[ertcont].endswith(">]"):
2336 document.body[ertcont] = document.body[ertcont][:-2]
2337 elif document.body[ertcont].endswith("]"):
2339 tok = document.body[ertcont].find('>][')
2341 subst = [document.body[ertcont][:tok],
2342 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2343 'status collapsed', '', '\\begin_layout Plain Layout',
2344 document.body[ertcont][tok + 3:-1]]
2345 document.body[ertcont : ertcont + 1] = subst
2347 # Convert to ArgInset
2348 document.body[parbeg] = "\\begin_inset Argument 2"
2349 elif document.body[ertcont].startswith("<"):
2350 # This is an overlay specification
2352 document.body[ertcont] = document.body[ertcont][1:]
2353 if document.body[ertcont].endswith(">"):
2355 document.body[ertcont] = document.body[ertcont][:-1]
2356 # Convert to ArgInset
2357 document.body[parbeg] = "\\begin_inset Argument 1"
2358 elif document.body[ertcont].endswith(">]"):
2360 tok = document.body[ertcont].find('>[<')
2362 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2363 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2364 'status collapsed', '', '\\begin_layout Plain Layout',
2365 document.body[ertcont][tok + 3:-2]]
2366 # Convert to ArgInset
2367 document.body[parbeg] = "\\begin_inset Argument 1"
2369 elif document.body[ertcont].endswith("]"):
2371 tok = document.body[ertcont].find('>[<')
2374 tokk = document.body[ertcont].find('>][')
2376 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2377 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2378 'status collapsed', '', '\\begin_layout Plain Layout',
2379 document.body[ertcont][tok + 3:tokk],
2380 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2381 'status collapsed', '', '\\begin_layout Plain Layout',
2382 document.body[ertcont][tokk + 3:-1]]
2385 tokk = document.body[ertcont].find('>[')
2387 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tokk],
2388 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2389 'status collapsed', '', '\\begin_layout Plain Layout',
2390 document.body[ertcont][tokk + 2:-1]]
2392 # Convert to ArgInset
2393 document.body[parbeg] = "\\begin_inset Argument 1"
2394 elif document.body[ertcont].startswith("["):
2395 # This is an ERT option
2397 document.body[ertcont] = document.body[ertcont][1:]
2398 if document.body[ertcont].endswith("]"):
2400 document.body[ertcont] = document.body[ertcont][:-1]
2401 # Convert to ArgInset
2402 document.body[parbeg] = "\\begin_inset Argument 3"
2408 def convert_againframe_args(document):
2409 " Converts beamer AgainFrame to new layout "
2411 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2412 if document.textclass not in beamer_classes:
2417 i = find_token(document.body, "\\begin_layout AgainFrame", i)
2420 parent = get_containing_layout(document.body, i)
2422 document.warning("Wrong parent layout!")
2426 # Convert ERT arguments
2427 # FIXME: See restrictions in convert_beamerframeargs method
2428 ertend = convert_beamerframeargs(document, i, parbeg)
2434 def convert_corollary_args(document):
2435 " Converts beamer corrolary-style ERT arguments native InsetArgs "
2437 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2438 if document.textclass not in beamer_classes:
2441 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2442 for lay in corollary_layouts:
2445 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2448 parent = get_containing_layout(document.body, i)
2450 document.warning("Wrong parent layout!")
2454 if document.body[parbeg] == "\\begin_inset ERT":
2455 ertcontfirstline = parbeg + 5
2456 # Find the last ERT in this paragraph (which might also be the first)
2457 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
2458 if lastertbeg == -1:
2459 document.warning("Last ERT not found!")
2461 lastertend = find_end_of_inset(document.body, lastertbeg)
2462 if lastertend == -1:
2463 document.warning("End of last ERT not found!")
2465 ertcontlastline = lastertend - 3
2466 if document.body[ertcontfirstline].startswith("<"):
2467 # This is an overlay specification
2469 document.body[ertcontfirstline] = document.body[ertcontfirstline][1:]
2470 if document.body[ertcontlastline].endswith(">"):
2472 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
2473 if ertcontfirstline < ertcontlastline:
2474 # Multiline ERT. Might contain TeX code. Embrace in ERT.
2475 document.body[ertcontlastline : ertcontlastline + 1] = [
2476 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
2477 document.body[ertcontfirstline : ertcontfirstline + 1] = [
2478 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
2479 'status collapsed', '', '\\begin_layout Plain Layout',
2480 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
2481 document.body[ertcontfirstline]]
2483 # Convert to ArgInset
2484 document.body[parbeg] = "\\begin_inset Argument 1"
2485 elif document.body[ertcontlastline].endswith("]"):
2487 tok = document.body[ertcontfirstline].find('>[')
2489 if ertcontfirstline < ertcontlastline:
2490 # Multiline ERT. Might contain TeX code. Embrace in ERT.
2491 document.body[ertcontlastline : ertcontlastline + 1] = [
2492 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
2493 document.body[ertcontfirstline : ertcontfirstline + 1] = [document.body[ertcontfirstline][:tok],
2494 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2495 'status collapsed', '', '\\begin_layout Plain Layout',
2496 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
2497 document.body[ertcontfirstline][tok + 2:-1]]
2499 document.body[ertcontfirstline : ertcontfirstline + 1] = [document.body[ertcontfirstline][:tok],
2500 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2501 'status collapsed', '', '\\begin_layout Plain Layout',
2502 document.body[ertcontfirstline][tok + 2:-1]]
2503 # Convert to ArgInset
2504 document.body[parbeg] = "\\begin_inset Argument 1"
2507 elif document.body[ertcontlastline].startswith("["):
2508 if document.body[ertcontlastline].endswith("]"):
2509 # This is an ERT option
2511 document.body[ertcontlastline] = document.body[ertcontlastline][1:]
2513 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
2514 # Convert to ArgInset
2515 document.body[parbeg] = "\\begin_inset Argument 2"
2517 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, True)
2524 def convert_quote_args(document):
2525 " Converts beamer quote style ERT args to native InsetArgs "
2527 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2528 if document.textclass not in beamer_classes:
2531 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2532 for lay in quote_layouts:
2535 i = find_token(document.body, "\\begin_layout " + lay, i)
2538 parent = get_containing_layout(document.body, i)
2540 document.warning("Wrong parent layout!")
2544 if document.body[parbeg] == "\\begin_inset ERT":
2545 if document.body[i + 6].startswith("<"):
2546 # This is an overlay specification
2548 document.body[i + 6] = document.body[i + 6][1:]
2549 if document.body[i + 6].endswith(">"):
2551 document.body[i + 6] = document.body[i + 6][:-1]
2552 # Convert to ArgInset
2553 document.body[i + 1] = "\\begin_inset Argument 1"
2557 def cleanup_beamerargs(document):
2558 " Clean up empty ERTs (conversion artefacts) "
2560 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2561 if document.textclass not in beamer_classes:
2566 i = find_token(document.body, "\\begin_inset Argument", i)
2569 j = find_end_of_inset(document.body, i)
2571 document.warning("Malformed LyX document: Can't find end of Argument inset")
2575 ertbeg = find_token(document.body, "\\begin_inset ERT", i, j)
2578 ertend = find_end_of_inset(document.body, ertbeg)
2580 document.warning("Malformed LyX document: Can't find end of ERT inset")
2582 stripped = [line for line in document.body[ertbeg : ertend + 1] if line.strip()]
2583 if len(stripped) == 5:
2584 # This is an empty ERT
2585 offset = len(document.body[ertbeg : ertend + 1])
2586 del document.body[ertbeg : ertend + 1]
2593 def revert_beamerargs(document):
2594 " Reverts beamer arguments to old layout "
2596 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2597 if document.textclass not in beamer_classes:
2601 list_layouts = ["Itemize", "Enumerate", "Description"]
2602 headings = ["Part", "Section", "Section*", "Subsection", "Subsection*",
2603 "Subsubsection", "Subsubsection*", "FrameSubtitle", "NoteItem"]
2604 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2605 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2606 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2609 i = find_token(document.body, "\\begin_inset Argument", i)
2612 # Find containing paragraph layout
2613 parent = get_containing_layout(document.body, i)
2615 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2620 realparbeg = parent[3]
2621 layoutname = parent[0]
2623 for p in range(parbeg, parend):
2627 if layoutname in headings:
2628 m = rx.match(document.body[p])
2632 # Find containing paragraph layout
2633 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2634 endPlain = find_end_of_layout(document.body, beginPlain)
2635 endInset = find_end_of_inset(document.body, p)
2636 argcontent = document.body[beginPlain + 1 : endPlain]
2638 realparend = realparend - len(document.body[p : endInset + 1])
2640 del document.body[p : endInset + 1]
2641 if layoutname == "FrameSubtitle":
2642 pre = put_cmd_in_ert("\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2643 elif layoutname == "NoteItem":
2644 pre = put_cmd_in_ert("\\note<") + argcontent + put_cmd_in_ert(">[item]")
2645 elif layoutname.endswith('*'):
2646 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower()[:-1] + "<") + argcontent + put_cmd_in_ert(">*")
2648 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2649 secarg = find_token(document.body, "\\begin_inset Argument 2", parbeg, parend)
2651 # Find containing paragraph layout
2652 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", secarg)
2653 endPlain = find_end_of_layout(document.body, beginPlain)
2654 endInset = find_end_of_inset(document.body, secarg)
2655 argcontent = document.body[beginPlain + 1 : endPlain]
2657 realparend = realparend - len(document.body[secarg : endInset + 1])
2658 del document.body[secarg : endInset + 1]
2659 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2660 pre += put_cmd_in_ert("{")
2661 document.body[parbeg] = "\\begin_layout Standard"
2662 document.body[realparbeg : realparbeg] = pre
2663 pe = find_end_of_layout(document.body, parbeg)
2664 post = put_cmd_in_ert("}")
2665 document.body[pe : pe] = post
2666 realparend += len(pre) + len(post)
2667 if layoutname == "AgainFrame":
2668 m = rx.match(document.body[p])
2672 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2673 endPlain = find_end_of_layout(document.body, beginPlain)
2674 endInset = find_end_of_inset(document.body, p)
2675 content = document.body[beginPlain + 1 : endPlain]
2677 realparend = realparend - len(document.body[p : endInset + 1])
2679 del document.body[p : endInset + 1]
2680 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2681 document.body[realparbeg : realparbeg] = subst
2682 if layoutname == "Overprint":
2683 m = rx.match(document.body[p])
2687 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2688 endPlain = find_end_of_layout(document.body, beginPlain)
2689 endInset = find_end_of_inset(document.body, p)
2690 content = document.body[beginPlain + 1 : endPlain]
2692 realparend = realparend - len(document.body[p : endInset + 1])
2694 del document.body[p : endInset + 1]
2695 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2696 document.body[realparbeg : realparbeg] = subst
2697 if layoutname == "OverlayArea":
2698 m = rx.match(document.body[p])
2702 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2703 endPlain = find_end_of_layout(document.body, beginPlain)
2704 endInset = find_end_of_inset(document.body, p)
2705 content = document.body[beginPlain + 1 : endPlain]
2707 realparend = realparend - len(document.body[p : endInset + 1])
2709 del document.body[p : endInset + 1]
2710 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2711 document.body[realparbeg : realparbeg] = subst
2712 if layoutname in list_layouts:
2713 m = rx.match(document.body[p])
2717 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2718 endPlain = find_end_of_layout(document.body, beginPlain)
2719 endInset = find_end_of_inset(document.body, p)
2720 content = document.body[beginPlain + 1 : endPlain]
2721 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2722 realparend = realparend + len(subst) - len(content)
2723 document.body[beginPlain + 1 : endPlain] = subst
2724 elif argnr == "item:1":
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 if layoutname == "Description":
2732 # Description only has one (overlay) item arg
2733 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2734 # This must be put after the first space (begin of decription body
2735 # in LyX's arkward description list syntax)
2736 # Try to find that place ...
2737 rxx = re.compile(r'^([^\\ ]+ )(.*)$')
2738 for q in range(parbeg, parend):
2739 m = rxx.match(document.body[q])
2741 # We found it. Now insert the ERT argument just there:
2742 document.body[q : q] = [m.group(1), ''] + subst + ['', m.group(2)]
2745 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2746 document.body[realparbeg : realparbeg] = subst
2747 elif argnr == "item:2":
2748 j = find_end_of_inset(document.body, i)
2749 # Find containing paragraph layout
2750 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2751 endPlain = find_end_of_layout(document.body, beginPlain)
2752 content = document.body[beginPlain + 1 : endPlain]
2753 del document.body[i:j+1]
2754 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2755 document.body[realparbeg : realparbeg] = subst
2756 if layoutname in quote_layouts:
2757 m = rx.match(document.body[p])
2761 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2762 endPlain = find_end_of_layout(document.body, beginPlain)
2763 endInset = find_end_of_inset(document.body, p)
2764 content = document.body[beginPlain + 1 : endPlain]
2766 realparend = realparend - len(document.body[p : endInset + 1])
2768 del document.body[p : endInset + 1]
2769 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2770 document.body[realparbeg : realparbeg] = subst
2771 if layoutname in corollary_layouts:
2772 m = rx.match(document.body[p])
2776 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2777 endPlain = find_end_of_layout(document.body, beginPlain)
2778 endInset = find_end_of_inset(document.body, p)
2779 content = document.body[beginPlain + 1 : endPlain]
2781 realparend = realparend - len(document.body[p : endInset + 1])
2783 del document.body[p : endInset + 1]
2784 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2785 document.body[realparbeg : realparbeg] = subst
2790 def revert_beamerargs2(document):
2791 " Reverts beamer arguments to old layout, step 2 "
2793 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2794 if document.textclass not in beamer_classes:
2798 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2799 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2800 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2803 i = find_token(document.body, "\\begin_inset Argument", i)
2806 # Find containing paragraph layout
2807 parent = get_containing_layout(document.body, i)
2809 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2814 realparbeg = parent[3]
2815 layoutname = parent[0]
2817 for p in range(parbeg, parend):
2821 if layoutname in shifted_layouts:
2822 m = rx.match(document.body[p])
2826 document.body[p] = "\\begin_inset Argument 1"
2827 if layoutname in corollary_layouts:
2828 m = rx.match(document.body[p])
2832 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2833 endPlain = find_end_of_layout(document.body, beginPlain)
2834 endInset = find_end_of_inset(document.body, p)
2835 content = document.body[beginPlain + 1 : endPlain]
2837 realparend = realparend - len(document.body[p : endInset + 1])
2839 del document.body[p : endInset + 1]
2840 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2841 document.body[realparbeg : realparbeg] = subst
2842 if layoutname == "OverlayArea":
2843 m = rx.match(document.body[p])
2847 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2848 endPlain = find_end_of_layout(document.body, beginPlain)
2849 endInset = find_end_of_inset(document.body, p)
2850 content = document.body[beginPlain + 1 : endPlain]
2852 realparend = realparend - len(document.body[p : endInset + 1])
2854 del document.body[p : endInset + 1]
2855 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2856 document.body[realparbeg : realparbeg] = subst
2857 if layoutname == "AgainFrame":
2858 m = rx.match(document.body[p])
2862 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2863 endPlain = find_end_of_layout(document.body, beginPlain)
2864 endInset = find_end_of_inset(document.body, p)
2865 content = document.body[beginPlain + 1 : endPlain]
2867 realparend = realparend - len(document.body[p : endInset + 1])
2869 del document.body[p : endInset + 1]
2870 subst = put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
2871 document.body[realparbeg : realparbeg] = subst
2875 def revert_beamerargs3(document):
2876 " Reverts beamer arguments to old layout, step 3 "
2878 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2879 if document.textclass not in beamer_classes:
2882 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2885 i = find_token(document.body, "\\begin_inset Argument", i)
2888 # Find containing paragraph layout
2889 parent = get_containing_layout(document.body, i)
2891 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2896 realparbeg = parent[3]
2897 layoutname = parent[0]
2899 for p in range(parbeg, parend):
2903 if layoutname == "AgainFrame":
2904 m = rx.match(document.body[p])
2908 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2909 endPlain = find_end_of_layout(document.body, beginPlain)
2910 endInset = find_end_of_inset(document.body, p)
2911 content = document.body[beginPlain + 1 : endPlain]
2913 realparend = realparend - len(document.body[p : endInset + 1])
2915 del document.body[p : endInset + 1]
2916 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2917 document.body[realparbeg : realparbeg] = subst
2921 def revert_beamerflex(document):
2922 " Reverts beamer Flex insets "
2924 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2925 if document.textclass not in beamer_classes:
2928 new_flexes = {"Bold" : "\\textbf", "Emphasize" : "\\emph", "Only" : "\\only",
2929 "Uncover" : "\\uncover", "Visible" : "\\visible",
2930 "Invisible" : "\\invisible", "Alternative" : "\\alt",
2931 "Beamer_Note" : "\\note"}
2932 old_flexes = {"Alert" : "\\alert", "Structure" : "\\structure"}
2933 rx = re.compile(r'^\\begin_inset Flex (.+)$')
2937 i = find_token(document.body, "\\begin_inset Flex", i)
2940 m = rx.match(document.body[i])
2942 flextype = m.group(1)
2943 z = find_end_of_inset(document.body, i)
2945 document.warning("Can't find end of Flex " + flextype + " inset.")
2948 if flextype in new_flexes:
2949 pre = put_cmd_in_ert(new_flexes[flextype])
2950 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2952 argend = find_end_of_inset(document.body, arg)
2954 document.warning("Can't find end of Argument!")
2957 # Find containing paragraph layout
2958 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2959 endPlain = find_end_of_layout(document.body, beginPlain)
2960 argcontent = document.body[beginPlain + 1 : endPlain]
2962 z = z - len(document.body[arg : argend + 1])
2964 del document.body[arg : argend + 1]
2965 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2966 arg = find_token(document.body, "\\begin_inset Argument 2", i, z)
2968 argend = find_end_of_inset(document.body, arg)
2970 document.warning("Can't find end of Argument!")
2973 # Find containing paragraph layout
2974 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2975 endPlain = find_end_of_layout(document.body, beginPlain)
2976 argcontent = document.body[beginPlain + 1 : endPlain]
2978 z = z - len(document.body[arg : argend + 1])
2980 del document.body[arg : argend + 1]
2981 if flextype == "Alternative":
2982 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
2984 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2985 pre += put_cmd_in_ert("{")
2986 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2987 endPlain = find_end_of_layout(document.body, beginPlain)
2989 z = z - len(document.body[i : beginPlain + 1])
2991 document.body[i : beginPlain + 1] = pre
2992 post = put_cmd_in_ert("}")
2993 document.body[z - 2 : z + 1] = post
2994 elif flextype in old_flexes:
2995 pre = put_cmd_in_ert(old_flexes[flextype])
2996 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
3000 argend = find_end_of_inset(document.body, arg)
3002 document.warning("Can't find end of Argument!")
3005 # Find containing paragraph layout
3006 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3007 endPlain = find_end_of_layout(document.body, beginPlain)
3008 argcontent = document.body[beginPlain + 1 : endPlain]
3010 z = z - len(document.body[arg : argend + 1])
3012 del document.body[arg : argend + 1]
3013 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
3014 pre += put_cmd_in_ert("{")
3015 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
3016 endPlain = find_end_of_layout(document.body, beginPlain)
3018 z = z - len(document.body[i : beginPlain + 1])
3020 document.body[i : beginPlain + 1] = pre
3021 post = put_cmd_in_ert("}")
3022 document.body[z - 2 : z + 1] = post
3027 def revert_beamerblocks(document):
3028 " Reverts beamer block arguments to ERT "
3030 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3031 if document.textclass not in beamer_classes:
3034 blocks = ["Block", "ExampleBlock", "AlertBlock"]
3036 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3039 i = find_token(document.body, "\\begin_inset Argument", i)
3042 # Find containing paragraph layout
3043 parent = get_containing_layout(document.body, i)
3045 document.warning("Malformed LyX document: Can't find parent paragraph layout")
3050 realparbeg = parent[3]
3051 layoutname = parent[0]
3053 for p in range(parbeg, parend):
3057 if layoutname in blocks:
3058 m = rx.match(document.body[p])
3062 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3063 endPlain = find_end_of_layout(document.body, beginPlain)
3064 endInset = find_end_of_inset(document.body, p)
3065 content = document.body[beginPlain + 1 : endPlain]
3067 realparend = realparend - len(document.body[p : endInset + 1])
3069 del document.body[p : endInset + 1]
3070 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3071 document.body[realparbeg : realparbeg] = subst
3073 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3074 endPlain = find_end_of_layout(document.body, beginPlain)
3075 endInset = find_end_of_inset(document.body, p)
3076 content = document.body[beginPlain + 1 : endPlain]
3078 realparend = realparend - len(document.body[p : endInset + 1])
3080 del document.body[p : endInset + 1]
3081 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3082 document.body[realparbeg : realparbeg] = subst
3087 def convert_beamerblocks(document):
3088 " Converts beamer block ERT args to native InsetArgs "
3090 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3091 if document.textclass not in beamer_classes:
3094 blocks = ["Block", "ExampleBlock", "AlertBlock"]
3098 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
3101 parent = get_containing_layout(document.body, i)
3102 if parent == False or parent[1] != i:
3103 document.warning("Wrong parent layout!")
3110 # If the paragraph starts with a language switch, adjust parbeg
3111 if len(document.body[parbeg]) == 0 and parbeg < parend \
3112 and document.body[parbeg + 1].startswith("\\lang"):
3114 if document.body[parbeg] == "\\begin_inset ERT":
3115 ertcontfirstline = parbeg + 5
3119 # Find the last ERT in this paragraph used for arguments
3120 # (which might also be the first)
3121 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
3122 if lastertbeg == -1:
3123 document.warning("Last ERT not found!")
3125 lastertend = find_end_of_inset(document.body, lastertbeg)
3126 if lastertend == -1:
3127 document.warning("End of last ERT not found!")
3129 # Is this ERT really used for an argument?
3130 # Note: This will fail when non-argument ERTs actually use brackets
3132 regexp = re.compile(r'.*[>\]\}]', re.IGNORECASE)
3133 cbracket = find_re(document.body, regexp, lastertbeg, lastertend)
3136 if lastertbeg == parbeg:
3139 if lastertbeg == -1 or lastertend == -1:
3141 ertcontlastline = lastertend - 3
3143 if document.body[ertcontfirstline].lstrip().startswith("<"):
3144 # This is an overlay specification
3146 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3147 if document.body[ertcontlastline].rstrip().endswith(">"):
3149 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3150 # Convert to ArgInset
3151 document.body[parbeg] = "\\begin_inset Argument 1"
3152 elif document.body[ertcontlastline].rstrip().endswith("}"):
3154 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3156 ertcontdivline = ertcontfirstline
3157 tok = document.body[ertcontdivline].find('>{')
3159 regexp = re.compile(r'.*>\{', re.IGNORECASE)
3160 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3161 tok = document.body[ertcontdivline].find('>{')
3163 if ertcontfirstline < ertcontlastline:
3164 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3165 document.body[ertcontlastline : ertcontlastline + 1] = [
3166 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3167 if ertcontdivline == ertcontfirstline:
3168 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3169 '\\end_layout', '', '\\end_inset', '',
3170 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3171 'status collapsed', '', '\\begin_layout Plain Layout',
3172 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3173 document.body[ertcontdivline][tok + 2:]]
3175 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3176 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3177 'status collapsed', '', '\\begin_layout Plain Layout',
3178 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3179 document.body[ertcontdivline][tok + 2:]]
3181 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3182 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3183 'status collapsed', '', '\\begin_layout Plain Layout',
3184 document.body[ertcontdivline][tok + 2:]]
3186 # check if have delimiters in two different ERTs
3187 tok = document.body[ertcontdivline].find('>')
3189 regexp = re.compile(r'.*>', re.IGNORECASE)
3190 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3191 tok = document.body[ertcontdivline].find('>')
3193 tokk = document.body[ertcontdivline].find('{')
3195 regexp = re.compile(r'.*\{', re.IGNORECASE)
3196 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, lastertend)
3197 tokk = document.body[ertcontdivlinetwo].find('{')
3199 if ertcontfirstline < ertcontlastline:
3200 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3201 document.body[ertcontlastline : ertcontlastline + 1] = [
3202 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3203 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3204 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3205 '\\end_inset', '', '', '\\begin_inset Argument 2',
3206 'status collapsed', '', '\\begin_layout Plain Layout',
3207 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3208 document.body[ertcontdivlinetwo][tokk + 1:]]
3210 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3211 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3212 'status collapsed', '', '\\begin_layout Plain Layout',
3213 document.body[ertcontdivlinetwo][tokk + 1:]]
3214 # Convert to ArgInset
3215 if ertcontfirstline < ertcontlastline:
3216 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3217 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 1',
3218 'status collapsed', '', '\\begin_layout Plain Layout',
3219 '\\begin_inset ERT', '']
3221 document.body[parbeg] = "\\begin_inset Argument 1"
3222 elif document.body[ertcontfirstline].lstrip().startswith("{"):
3223 # This is the block title
3224 if document.body[ertcontlastline].rstrip().endswith("}"):
3225 # strip off the braces
3226 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3227 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3228 if ertcontfirstline < ertcontlastline:
3229 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3230 document.body[parend : parend + 1] = [
3231 document.body[parend], '\\end_inset', '', '\\end_layout']
3232 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3233 'status collapsed', '', '\\begin_layout Plain Layout',
3234 '\\begin_inset ERT', '']
3236 # Convert to ArgInset
3237 document.body[parbeg] = "\\begin_inset Argument 2"
3238 # the overlay argument can also follow the title, so ...
3239 elif document.body[ertcontlastline].rstrip().endswith(">"):
3241 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3243 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3245 ertcontdivline = ertcontfirstline
3246 tok = document.body[ertcontdivline].find('}<')
3248 regexp = re.compile(r'.*\}<', re.IGNORECASE)
3249 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3250 tok = document.body[ertcontdivline].find('}<')
3252 if ertcontfirstline < ertcontlastline:
3253 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3254 document.body[ertcontlastline : ertcontlastline + 1] = [
3255 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3256 if ertcontdivline == ertcontfirstline:
3257 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3258 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3259 'status collapsed', '', '\\begin_layout Plain Layout',
3260 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3261 document.body[ertcontdivline][tok + 2:]]
3263 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3264 '\\end_layout', '', '\\end_inset', '',
3265 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3266 'status collapsed', '', '\\begin_layout Plain Layout',
3267 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3268 document.body[ertcontdivline][tok + 2:]]
3270 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3271 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3272 'status collapsed', '', '\\begin_layout Plain Layout',
3273 document.body[ertcontdivline][tok + 2:]]
3275 # check if have delimiters in two different ERTs
3276 tok = document.body[ertcontdivline].find('}')
3278 regexp = re.compile(r'.*\}', re.IGNORECASE)
3279 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3280 tok = document.body[ertcontdivline].find('}')
3282 tokk = document.body[ertcontdivline].find('<')
3284 regexp = re.compile(r'.*<', re.IGNORECASE)
3285 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, lastertend)
3286 tokk = document.body[ertcontdivlinetwo].find('<')
3288 if ertcontfirstline < ertcontlastline:
3289 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3290 document.body[ertcontlastline : ertcontlastline + 1] = [
3291 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3292 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3293 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3294 '\\end_inset', '', '', '\\begin_inset Argument 1',
3295 'status collapsed', '', '\\begin_layout Plain Layout',
3296 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3297 document.body[ertcontdivlinetwo][tokk + 1:]]
3299 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3300 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3301 'status collapsed', '', '\\begin_layout Plain Layout',
3302 document.body[ertcontdivlinetwo][tokk + 1:]]
3303 # Convert to ArgInset
3304 if ertcontfirstline < ertcontlastline:
3305 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3306 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3307 'status collapsed', '', '\\begin_layout Plain Layout',
3308 '\\begin_inset ERT', '']
3310 document.body[parbeg] = "\\begin_inset Argument 2"
3311 elif count_pars_in_inset(document.body, ertcontfirstline) > 1:
3312 # Multipar ERT. Skip this.
3315 # ERT has contents after the closing bracket. We cannot convert this.
3316 # convert_TeX_brace_to_Argument cannot either.
3317 #convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, False)
3321 j = find_end_of_layout(document.body, i)
3323 document.warning("end of layout not found!")
3324 k = find_token(document.body, "\\begin_inset Argument", i, j)
3326 document.warning("InsetArgument not found!")
3328 l = find_end_of_inset(document.body, k)
3329 m = find_token(document.body, "\\begin_inset ERT", l, j)
3332 ertcontfirstline = m + 5
3337 def convert_overprint(document):
3338 " Convert old beamer overprint layouts to ERT "
3340 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3341 if document.textclass not in beamer_classes:
3346 i = find_token(document.body, "\\begin_layout Overprint", i)
3349 # Find end of sequence
3350 j = find_end_of_sequence(document.body, i)
3352 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3356 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3358 if document.body[j] == "\\end_deeper":
3359 esubst = ["", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3361 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3362 endseq = endseq + len(esubst) - len(document.body[j : j])
3363 document.body[j : j] = esubst
3364 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3366 argend = find_end_of_layout(document.body, argbeg)
3368 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3371 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3372 endPlain = find_end_of_layout(document.body, beginPlain)
3373 content = document.body[beginPlain + 1 : endPlain]
3375 endseq = endseq - len(document.body[argbeg : argend + 1])
3377 del document.body[argbeg : argend + 1]
3378 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3380 endseq = endseq - len(document.body[i : i])
3381 document.body[i : i] = subst + ["\\end_layout"]
3382 endseq += len(subst)
3384 for p in range(i, endseq):
3385 if document.body[p] == "\\begin_layout Overprint":
3386 document.body[p] = "\\begin_layout Standard"
3391 def revert_overprint(document):
3392 " Revert old beamer overprint layouts to ERT "
3394 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3395 if document.textclass not in beamer_classes:
3400 i = find_token(document.body, "\\begin_layout Overprint", i)
3403 # Find end of sequence
3404 j = find_end_of_sequence(document.body, i)
3406 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3410 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3411 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}")
3412 endseq = endseq + len(esubst) - len(document.body[j : j])
3413 if document.body[j] == "\\end_deeper":
3414 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3416 document.body[j : j] = ["\\end_layout", ""] + esubst
3419 if document.body[r] == "\\begin_deeper":
3420 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3422 document.body[r] = ""
3423 document.body[s] = ""
3427 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3429 # Is this really our argument?
3430 nested = find_token(document.body, "\\begin_deeper", i, argbeg)
3432 argend = find_end_of_inset(document.body, argbeg)
3434 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3437 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3438 endPlain = find_end_of_layout(document.body, beginPlain)
3439 content = document.body[beginPlain + 1 : endPlain]
3441 endseq = endseq - len(document.body[argbeg : argend])
3443 del document.body[argbeg : argend + 1]
3444 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3446 endseq = endseq - len(document.body[i : i])
3447 document.body[i : i] = subst + ["\\end_layout"]
3448 endseq += len(subst)
3454 if document.body[p] == "\\begin_layout Overprint":
3455 q = find_end_of_layout(document.body, p)
3457 document.warning("Malformed LyX document. Cannot find end of Overprint layout!")
3460 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\onslide")
3461 argbeg = find_token(document.body, "\\begin_inset Argument item:1", p, q)
3463 argend = find_end_of_inset(document.body, argbeg)
3465 document.warning("Malformed LyX document. Cannot find end of Overprint item argument!")
3468 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3469 endPlain = find_end_of_layout(document.body, beginPlain)
3470 content = document.body[beginPlain + 1 : endPlain]
3472 endseq = endseq - len(document.body[argbeg : argend + 1])
3474 del document.body[argbeg : argend + 1]
3475 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3476 endseq = endseq - len(document.body[p : p + 1]) + len(subst)
3477 document.body[p : p + 1] = subst
3483 def revert_frametitle(document):
3484 " Reverts beamer frametitle layout to ERT "
3486 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3487 if document.textclass not in beamer_classes:
3490 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3493 i = find_token(document.body, "\\begin_layout FrameTitle", i)
3496 j = find_end_of_layout(document.body, i)
3498 document.warning("Malformed LyX document: Can't find end of FrameTitle layout")
3502 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
3503 endlay += len(put_cmd_in_ert("}"))
3504 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\frametitle")
3505 for p in range(i, j):
3508 m = rx.match(document.body[p])
3512 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3513 endPlain = find_end_of_layout(document.body, beginPlain)
3514 endInset = find_end_of_inset(document.body, p)
3515 content = document.body[beginPlain + 1 : endPlain]
3517 endlay = endlay - len(document.body[p : endInset + 1])
3519 del document.body[p : endInset + 1]
3520 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3522 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3523 endPlain = find_end_of_layout(document.body, beginPlain)
3524 endInset = find_end_of_inset(document.body, p)
3525 content = document.body[beginPlain + 1 : endPlain]
3527 endlay = endlay - len(document.body[p : endInset + 1])
3529 del document.body[p : endInset + 1]
3530 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3532 subst += put_cmd_in_ert("{")
3533 document.body[i : i + 1] = subst
3537 def convert_epigraph(document):
3538 " Converts memoir epigraph to new syntax "
3540 if document.textclass != "memoir":
3545 i = find_token(document.body, "\\begin_layout Epigraph", i)
3548 j = find_end_of_layout(document.body, i)
3550 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3555 ert = find_token(document.body, "\\begin_inset ERT", i, j)
3557 endInset = find_end_of_inset(document.body, ert)
3558 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", ert)
3559 endPlain = find_end_of_layout(document.body, beginPlain)
3560 ertcont = beginPlain + 2
3561 if document.body[ertcont] == "}{":
3563 # Convert to ArgInset
3564 endlay = endlay - 2 * len(document.body[j])
3565 begsubst = ['\\begin_inset Argument post:1', 'status collapsed', '',
3566 '\\begin_layout Plain Layout']
3567 endsubst = ['\\end_layout', '', '\\end_inset', '', document.body[j]]
3568 document.body[j : j + 1] = endsubst
3569 document.body[endInset + 1 : endInset + 1] = begsubst
3571 endlay += len(begsubst) + len(endsubst)
3572 endlay = endlay - len(document.body[ert : endInset + 1])
3573 del document.body[ert : endInset + 1]
3578 def revert_epigraph(document):
3579 " Reverts memoir epigraph argument to ERT "
3581 if document.textclass != "memoir":
3586 i = find_token(document.body, "\\begin_layout Epigraph", i)
3589 j = find_end_of_layout(document.body, i)
3591 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3596 p = find_token(document.body, "\\begin_layout Argument post:1", i, j)
3598 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3599 endPlain = find_end_of_layout(document.body, beginPlain)
3600 endInset = find_end_of_inset(document.body, p)
3601 content = document.body[beginPlain + 1 : endPlain]
3603 endlay = endlay - len(document.body[p : endInset + 1])
3605 del document.body[p : endInset + 1]
3606 subst += put_cmd_in_ert("}{") + content
3608 subst += put_cmd_in_ert("}{")
3610 document.body[j : j] = subst + document.body[j : j]
3614 def convert_captioninsets(document):
3615 " Converts caption insets to new syntax "
3619 i = find_token(document.body, "\\begin_inset Caption", i)
3622 document.body[i] = "\\begin_inset Caption Standard"
3626 def revert_captioninsets(document):
3627 " Reverts caption insets to old syntax "
3631 i = find_token(document.body, "\\begin_inset Caption Standard", i)
3634 document.body[i] = "\\begin_inset Caption"
3638 def convert_captionlayouts(document):
3639 " Convert caption layouts to caption insets. "
3642 "Captionabove": "Above",
3643 "Captionbelow": "Below",
3644 "FigCaption" : "FigCaption",
3645 "Table_Caption" : "Table",
3646 "CenteredCaption" : "Centered",
3647 "Bicaption" : "Bicaption",
3652 i = find_token(document.body, "\\begin_layout", i)
3655 val = get_value(document.body, "\\begin_layout", i)
3656 if val in list(caption_dict.keys()):
3657 j = find_end_of_layout(document.body, i)
3659 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3662 document.body[j:j] = ["\\end_layout", "", "\\end_inset", "", ""]
3663 document.body[i:i+1] = ["\\begin_layout %s" % document.default_layout,
3664 "\\begin_inset Caption %s" % caption_dict[val], "",
3665 "\\begin_layout %s" % document.default_layout]
3669 def revert_captionlayouts(document):
3670 " Revert caption insets to caption layouts. "
3673 "Above" : "Captionabove",
3674 "Below" : "Captionbelow",
3675 "FigCaption" : "FigCaption",
3676 "Table" : "Table_Caption",
3677 "Centered" : "CenteredCaption",
3678 "Bicaption" : "Bicaption",
3682 rx = re.compile(r'^\\begin_inset Caption (\S+)$')
3684 i = find_token(document.body, "\\begin_inset Caption", i)
3688 m = rx.match(document.body[i])
3692 if val not in list(caption_dict.keys()):
3696 # We either need to delete the previous \begin_layout line, or we
3697 # need to end the previous layout if this inset is not in the first
3698 # position of the paragraph.
3699 layout_before = find_token_backwards(document.body, "\\begin_layout", i)
3700 if layout_before == -1:
3701 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3703 layout_line = document.body[layout_before]
3704 del_layout_before = True
3705 l = layout_before + 1
3707 if document.body[l] != "":
3708 del_layout_before = False
3711 if del_layout_before:
3712 del document.body[layout_before:i]
3715 document.body[i:i] = ["\\end_layout", ""]
3718 # Find start of layout in the inset and end of inset
3719 j = find_token(document.body, "\\begin_layout", i)
3721 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3723 k = find_end_of_inset(document.body, i)
3725 document.warning("Malformed LyX document: Missing `\\end_inset'.")
3728 # We either need to delete the following \end_layout line, or we need
3729 # to restart the old layout if this inset is not at the paragraph end.
3730 layout_after = find_token(document.body, "\\end_layout", k)
3731 if layout_after == -1:
3732 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3734 del_layout_after = True
3736 while l < layout_after:
3737 if document.body[l] != "":
3738 del_layout_after = False
3741 if del_layout_after:
3742 del document.body[k+1:layout_after+1]
3744 document.body[k+1:k+1] = [layout_line, ""]
3746 # delete \begin_layout and \end_inset and replace \begin_inset with
3747 # "\begin_layout XXX". This works because we can only have one
3748 # paragraph in the caption inset: The old \end_layout will be recycled.
3749 del document.body[k]
3750 if document.body[k] == "":
3751 del document.body[k]
3752 del document.body[j]
3753 if document.body[j] == "":
3754 del document.body[j]
3755 document.body[i] = "\\begin_layout %s" % caption_dict[val]
3756 if document.body[i+1] == "":
3757 del document.body[i+1]
3761 def revert_fragileframe(document):
3762 " Reverts beamer FragileFrame layout to ERT "
3764 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3765 if document.textclass not in beamer_classes:
3770 i = find_token(document.body, "\\begin_layout FragileFrame", i)
3773 # Find end of sequence
3774 j = find_end_of_sequence(document.body, i)
3776 document.warning("Malformed LyX document. Cannot find end of FragileFrame sequence!")
3780 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{frame}")
3781 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{frame}")
3782 endseq = endseq + len(esubst) - len(document.body[j : j])
3783 if document.body[j] == "\\end_deeper":
3784 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3786 document.body[j : j] = esubst
3787 for q in range(i, j):
3788 if document.body[q] == "\\begin_layout FragileFrame":
3789 document.body[q] = "\\begin_layout %s" % document.default_layout
3792 if document.body[r] == "\\begin_deeper":
3793 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3795 document.body[r] = ""
3796 document.body[s] = ""
3800 for p in range(1, 5):
3801 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, j)
3804 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3805 endPlain = find_end_of_layout(document.body, beginPlain)
3806 endInset = find_end_of_inset(document.body, arg)
3807 content = document.body[beginPlain + 1 : endPlain]
3809 j = j - len(document.body[arg : endInset + 1])
3811 del document.body[arg : endInset + 1]
3812 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3814 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3815 endPlain = find_end_of_layout(document.body, beginPlain)
3816 endInset = find_end_of_inset(document.body, arg)
3817 content = document.body[beginPlain + 1 : endPlain]
3819 j = j - len(document.body[arg : endInset + 1])
3821 del document.body[arg : endInset + 1]
3822 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3824 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3825 endPlain = find_end_of_layout(document.body, beginPlain)
3826 endInset = find_end_of_inset(document.body, arg)
3827 content = document.body[beginPlain + 1 : endPlain]
3829 j = j - len(document.body[arg : endInset + 1])
3831 del document.body[arg : endInset + 1]
3832 subst += put_cmd_in_ert("[fragile,") + content + put_cmd_in_ert("]")
3834 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3835 endPlain = find_end_of_layout(document.body, beginPlain)
3836 endInset = find_end_of_inset(document.body, arg)
3837 content = document.body[beginPlain + 1 : endPlain]
3839 j = j - len(document.body[arg : endInset + 1])
3841 del document.body[arg : endInset + 1]
3842 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3844 subst += put_cmd_in_ert("[fragile]")
3846 document.body[i : i + 1] = subst
3850 def revert_newframes(document):
3851 " Reverts beamer Frame and PlainFrame layouts to old forms "
3853 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3854 if document.textclass not in beamer_classes:
3858 "Frame" : "BeginFrame",
3859 "PlainFrame" : "BeginPlainFrame",
3862 rx = re.compile(r'^\\begin_layout (\S+)$')
3865 i = find_token(document.body, "\\begin_layout", i)
3869 m = rx.match(document.body[i])
3873 if val not in list(frame_dict.keys()):
3876 # Find end of sequence
3877 j = find_end_of_sequence(document.body, i)
3879 document.warning("Malformed LyX document. Cannot find end of Frame sequence!")
3883 subst = ["\\begin_layout %s" % frame_dict[val]]
3884 esubst = ["", "\\begin_layout EndFrame", "", "\\end_layout"]
3885 endseq = endseq + len(esubst) - len(document.body[j : j])
3886 if document.body[j] == "\\end_deeper":
3887 document.body[j : j] = esubst
3889 document.body[j+1 : j+1] = esubst
3890 for q in range(i, j):
3891 if document.body[q] == "\\begin_layout %s" % val:
3892 document.body[q] = "\\begin_layout %s" % document.default_layout
3895 if document.body[r] == "\\begin_deeper":
3896 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3898 document.body[r] = ""
3899 document.body[s] = ""
3903 l = find_end_of_layout(document.body, i)
3904 for p in range(1, 5):
3905 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, l)
3908 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3909 endPlain = find_end_of_layout(document.body, beginPlain)
3910 endInset = find_end_of_inset(document.body, arg)
3911 content = document.body[beginPlain + 1 : endPlain]
3913 l = l - len(document.body[arg : endInset + 1])
3915 del document.body[arg : endInset + 1]
3916 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3918 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3919 endPlain = find_end_of_layout(document.body, beginPlain)
3920 endInset = find_end_of_inset(document.body, arg)
3921 content = document.body[beginPlain + 1 : endPlain]
3923 l = l - len(document.body[arg : endInset + 1])
3925 del document.body[arg : endInset + 1]
3926 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3928 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3929 endPlain = find_end_of_layout(document.body, beginPlain)
3930 endInset = find_end_of_inset(document.body, arg)
3931 content = document.body[beginPlain + 1 : endPlain]
3933 l = l - len(document.body[arg : endInset + 1])
3935 del document.body[arg : endInset + 1]
3936 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3938 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3939 endPlain = find_end_of_layout(document.body, beginPlain)
3940 endInset = find_end_of_inset(document.body, arg)
3941 content = document.body[beginPlain + 1 : endPlain]
3943 l = l - len(document.body[arg : endInset + 1])
3945 del document.body[arg : endInset + 1]
3948 document.body[i : i + 1] = subst
3951 # known encodings that do not change their names (same LyX and LaTeX names)
3952 known_enc_tuple = ("auto", "default", "ansinew", "applemac", "armscii8", "ascii",
3953 "cp437", "cp437de", "cp850", "cp852", "cp855", "cp858", "cp862", "cp865", "cp866",
3954 "cp1250", "cp1251", "cp1252", "cp1255", "cp1256", "cp1257", "koi8-r", "koi8-u",
3955 "pt154", "pt254", "tis620-0", "utf8", "utf8x", "utf8-plain")
3957 def convert_encodings(document):
3958 "Use the LyX names of the encodings instead of the LaTeX names."
3959 LaTeX2LyX_enc_dict = {
3960 "8859-6": "iso8859-6",
3961 "8859-8": "iso8859-8",
3963 "euc": "euc-jp-platex",
3968 "iso88595": "iso8859-5",
3969 "iso-8859-7": "iso8859-7",
3971 "jis": "jis-platex",
3973 "l7xenc": "iso8859-13",
3974 "latin1": "iso8859-1",
3975 "latin2": "iso8859-2",
3976 "latin3": "iso8859-3",
3977 "latin4": "iso8859-4",
3978 "latin5": "iso8859-9",
3979 "latin9": "iso8859-15",
3980 "latin10": "iso8859-16",
3981 "SJIS": "shift-jis",
3982 "sjis": "shift-jis-platex",
3985 i = find_token(document.header, "\\inputencoding" , 0)
3988 val = get_value(document.header, "\\inputencoding", i)
3989 if val in list(LaTeX2LyX_enc_dict.keys()):
3990 document.header[i] = "\\inputencoding %s" % LaTeX2LyX_enc_dict[val]
3991 elif val not in known_enc_tuple:
3992 document.warning("Ignoring unknown input encoding: `%s'" % val)
3995 def revert_encodings(document):
3996 """Revert to using the LaTeX names of the encodings instead of the LyX names.
3997 Also revert utf8-platex to sjis, the language default when using Japanese.
3999 LyX2LaTeX_enc_dict = {
4004 "euc-jp-platex": "euc",
4007 "iso8859-1": "latin1",
4008 "iso8859-2": "latin2",
4009 "iso8859-3": "latin3",
4010 "iso8859-4": "latin4",
4011 "iso8859-5": "iso88595",
4012 "iso8859-6": "8859-6",
4013 "iso8859-7": "iso-8859-7",
4014 "iso8859-8": "8859-8",
4015 "iso8859-9": "latin5",
4016 "iso8859-13": "l7xenc",
4017 "iso8859-15": "latin9",
4018 "iso8859-16": "latin10",
4020 "jis-platex": "jis",
4021 "shift-jis": "SJIS",
4022 "shift-jis-platex": "sjis",
4024 "utf8-platex": "sjis"
4026 i = find_token(document.header, "\\inputencoding" , 0)
4029 val = get_value(document.header, "\\inputencoding", i)
4030 if val in list(LyX2LaTeX_enc_dict.keys()):
4031 document.header[i] = "\\inputencoding %s" % LyX2LaTeX_enc_dict[val]
4032 elif val not in known_enc_tuple:
4033 document.warning("Ignoring unknown input encoding: `%s'" % val)
4036 def revert_IEEEtran_3(document):
4038 Reverts Flex Insets to TeX-code
4040 if document.textclass == "IEEEtran":
4046 h = find_token(document.body, "\\begin_inset Flex Author Mark", h)
4048 endh = find_end_of_inset(document.body, h)
4049 document.body[endh - 2 : endh + 1] = put_cmd_in_ert("}")
4050 document.body[h : h + 4] = put_cmd_in_ert("\\IEEEauthorrefmark{")
4053 i = find_token(document.body, "\\begin_inset Flex Author Name", i)
4055 endi = find_end_of_inset(document.body, i)
4056 document.body[endi - 2 : endi + 1] = put_cmd_in_ert("}")
4057 document.body[i : i + 4] = put_cmd_in_ert("\\IEEEauthorblockN{")
4060 j = find_token(document.body, "\\begin_inset Flex Author Affiliation", j)
4062 endj = find_end_of_inset(document.body, j)
4063 document.body[endj - 2 : endj + 1] = put_cmd_in_ert("}")
4064 document.body[j : j + 4] = put_cmd_in_ert("\\IEEEauthorblockA{")
4066 if i == -1 and j == -1 and h == -1:
4070 def revert_kurier_fonts(document):
4071 " Revert kurier font definition to LaTeX "
4073 i = find_token(document.header, "\\font_math", 0)
4075 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4076 val = get_value(document.header, "\\font_math", i)
4077 if val == "kurier-math":
4078 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
4079 "\\usepackage[math]{kurier}\n" \
4080 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
4081 document.header[i] = "\\font_math auto"
4083 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4084 kurier_fonts = ["kurier", "kurierc", "kurierl", "kurierlc"]
4085 k = find_token(document.header, "\\font_sans kurier", 0)
4087 sf = get_value(document.header, "\\font_sans", k)
4088 if sf in kurier_fonts:
4089 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4090 document.header[k] = "\\font_sans default"
4092 def revert_iwona_fonts(document):
4093 " Revert iwona font definition to LaTeX "
4095 i = find_token(document.header, "\\font_math", 0)
4097 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4098 val = get_value(document.header, "\\font_math", i)
4099 if val == "iwona-math":
4100 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
4101 "\\usepackage[math]{iwona}\n" \
4102 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
4103 document.header[i] = "\\font_math auto"
4105 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4106 iwona_fonts = ["iwona", "iwonac", "iwonal", "iwonalc"]
4107 k = find_token(document.header, "\\font_sans iwona", 0)
4109 sf = get_value(document.header, "\\font_sans", k)
4110 if sf in iwona_fonts:
4111 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4112 document.header[k] = "\\font_sans default"
4115 def revert_new_libertines(document):
4116 " Revert new libertine font definition to LaTeX "
4118 if find_token(document.header, "\\use_non_tex_fonts true", 0) != -1:
4121 i = find_token(document.header, "\\font_typewriter libertine-mono", 0)
4123 preamble = "\\usepackage"
4124 sc = find_token(document.header, "\\font_tt_scale", 0)
4126 scval = get_value(document.header, "\\font_tt_scale", sc)
4128 preamble += "[scale=%f]" % (float(scval) / 100)
4129 document.header[sc] = "\\font_tt_scale 100"
4130 preamble += "{libertineMono-type1}"
4131 add_to_preamble(document, [preamble])
4132 document.header[i] = "\\font_typewriter default"
4134 k = find_token(document.header, "\\font_sans biolinum", 0)
4136 preamble = "\\usepackage"
4138 j = find_token(document.header, "\\font_osf true", 0)
4143 sc = find_token(document.header, "\\font_sf_scale", 0)
4145 scval = get_value(document.header, "\\font_sf_scale", sc)
4147 options += ",scale=%f" % (float(scval) / 100)
4148 document.header[sc] = "\\font_sf_scale 100"
4150 preamble += "[" + options +"]"
4151 preamble += "{biolinum-type1}"
4152 add_to_preamble(document, [preamble])
4153 document.header[k] = "\\font_sans default"
4156 def convert_lyxframes(document):
4157 " Converts old beamer frames to new style "
4159 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4160 if document.textclass not in beamer_classes:
4163 framebeg = ["BeginFrame", "BeginPlainFrame"]
4164 frameend = ["Frame", "PlainFrame", "EndFrame", "BeginFrame", "BeginPlainFrame", "AgainFrame",
4165 "Section", "Section*", "Subsection", "Subsection*", "Subsubsection", "Subsubsection*"]
4166 for lay in framebeg:
4169 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
4172 parent = get_containing_layout(document.body, i)
4173 if parent == False or parent[1] != i:
4174 document.warning("Wrong parent layout!")
4177 frametype = parent[0]
4181 # Step I: Convert ERT arguments
4182 # FIXME: See restrictions in convert_beamerframeargs method
4183 ertend = convert_beamerframeargs(document, i, parbeg)
4186 # Step II: Now rename the layout and convert the title to an argument
4187 j = find_end_of_layout(document.body, i)
4188 document.body[j : j + 1] = ['\\end_layout', '', '\\end_inset', '', '\\end_layout']
4189 if lay == "BeginFrame":
4190 document.body[i] = "\\begin_layout Frame"
4192 document.body[i] = "\\begin_layout PlainFrame"
4193 document.body[ertend + 1 : ertend + 1] = ['\\begin_inset Argument 4',
4194 'status open', '', '\\begin_layout Plain Layout']
4195 # Step III: find real frame end
4198 inInset = get_containing_inset(document.body, i)
4200 fend = find_token(document.body, "\\begin_layout", jj)
4202 document.warning("Malformed LyX document: No real frame end!")
4204 val = get_value(document.body, "\\begin_layout", fend)
4205 if val not in frameend:
4208 # is this frame nested in an inset (e.g., Note)?
4209 if inInset != False:
4210 # if so, end the frame inside the inset
4211 if inInset[2] < fend:
4213 if val == frametype:
4214 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4215 # consider explicit EndFrames between two identical frame types
4216 elif val == "EndFrame":
4217 nextlayout = find_token(document.body, "\\begin_layout", fend + 1)
4218 if nextlayout != -1 and get_value(document.body, "\\begin_layout", nextlayout) == frametype:
4219 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4221 document.body[fend : fend] = ['\\end_deeper']
4223 document.body[fend : fend] = ['\\end_deeper']
4224 document.body[j + 1 : j + 1] = ['', '\\begin_deeper']
4229 def remove_endframes(document):
4230 " Remove deprecated beamer endframes "
4232 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4233 if document.textclass not in beamer_classes:
4238 i = find_token_exact(document.body, "\\begin_layout EndFrame", i)
4241 j = find_end_of_layout(document.body, i)
4243 document.warning("Malformed LyX document: Missing \\end_layout to EndFrame")
4246 del document.body[i : j + 1]
4249 def revert_powerdot_flexes(document):
4250 " Reverts powerdot flex insets "
4252 if document.textclass != "powerdot":
4255 flexes = {"Onslide" : "\\onslide",
4256 "Onslide*" : "\\onslide*",
4257 "Onslide+" : "\\onslide+"}
4258 rx = re.compile(r'^\\begin_inset Flex (.+)$')
4262 i = find_token(document.body, "\\begin_inset Flex", i)
4265 m = rx.match(document.body[i])
4267 flextype = m.group(1)
4268 z = find_end_of_inset(document.body, i)
4270 document.warning("Can't find end of Flex " + flextype + " inset.")
4273 if flextype in flexes:
4274 pre = put_cmd_in_ert(flexes[flextype])
4275 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
4277 argend = find_end_of_inset(document.body, arg)
4279 document.warning("Can't find end of Argument!")
4282 # Find containing paragraph layout
4283 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
4284 endPlain = find_end_of_layout(document.body, beginPlain)
4285 argcontent = document.body[beginPlain + 1 : endPlain]
4287 z = z - len(document.body[arg : argend + 1])
4289 del document.body[arg : argend + 1]
4290 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
4291 pre += put_cmd_in_ert("{")
4292 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4293 endPlain = find_end_of_layout(document.body, beginPlain)
4295 z = z - len(document.body[i : beginPlain + 1])
4297 document.body[i : beginPlain + 1] = pre
4298 post = put_cmd_in_ert("}")
4299 document.body[z - 2 : z + 1] = post
4303 def revert_powerdot_pause(document):
4304 " Reverts powerdot pause layout to ERT "
4306 if document.textclass != "powerdot":
4311 i = find_token(document.body, "\\begin_layout Pause", i)
4314 j = find_end_of_layout(document.body, i)
4316 document.warning("Malformed LyX document: Can't find end of Pause layout")
4320 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\pause")
4321 for p in range(i, j):
4324 arg = find_token(document.body, "\\begin_inset Argument 1", i, j)
4326 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4327 endPlain = find_end_of_layout(document.body, beginPlain)
4328 endInset = find_end_of_inset(document.body, p)
4329 content = document.body[beginPlain + 1 : endPlain]
4331 endlay = endlay - len(document.body[p : endInset + 1])
4333 del document.body[p : endInset + 1]
4334 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4336 document.body[i : i + 1] = subst
4340 def revert_powerdot_itemargs(document):
4341 " Reverts powerdot item arguments to ERT "
4343 if document.textclass != "powerdot":
4347 list_layouts = ["Itemize", "ItemizeType1", "Enumerate", "EnumerateType1"]
4348 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4351 i = find_token(document.body, "\\begin_inset Argument", i)
4354 # Find containing paragraph layout
4355 parent = get_containing_layout(document.body, i)
4357 document.warning("Malformed LyX document: Can't find parent paragraph layout")
4362 realparbeg = parent[3]
4363 layoutname = parent[0]
4365 for p in range(parbeg, parend):
4369 if layoutname in list_layouts:
4370 m = rx.match(document.body[p])
4373 if argnr == "item:1":
4374 j = find_end_of_inset(document.body, i)
4375 # Find containing paragraph layout
4376 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4377 endPlain = find_end_of_layout(document.body, beginPlain)
4378 content = document.body[beginPlain + 1 : endPlain]
4379 del document.body[i:j+1]
4380 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4381 document.body[realparbeg : realparbeg] = subst
4382 elif argnr == "item:2":
4383 j = find_end_of_inset(document.body, i)
4384 # Find containing paragraph layout
4385 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4386 endPlain = find_end_of_layout(document.body, beginPlain)
4387 content = document.body[beginPlain + 1 : endPlain]
4388 del document.body[i:j+1]
4389 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
4390 document.body[realparbeg : realparbeg] = subst
4395 def revert_powerdot_columns(document):
4396 " Reverts powerdot twocolumn to TeX-code "
4397 if document.textclass != "powerdot":
4400 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4403 i = find_token(document.body, "\\begin_layout Twocolumn", i)
4406 j = find_end_of_layout(document.body, i)
4408 document.warning("Malformed LyX document: Can't find end of Twocolumn layout")
4412 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
4413 endlay += len(put_cmd_in_ert("}"))
4414 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\twocolumn")
4415 for p in range(i, j):
4418 m = rx.match(document.body[p])
4422 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4423 endPlain = find_end_of_layout(document.body, beginPlain)
4424 endInset = find_end_of_inset(document.body, p)
4425 content = document.body[beginPlain + 1 : endPlain]
4427 endlay = endlay - len(document.body[p : endInset + 1])
4429 del document.body[p : endInset + 1]
4430 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4432 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4433 endPlain = find_end_of_layout(document.body, beginPlain)
4434 endInset = find_end_of_inset(document.body, p)
4435 content = document.body[beginPlain + 1 : endPlain]
4437 endlay = endlay - len(document.body[p : endInset + 1])
4439 del document.body[p : endInset + 1]
4440 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
4442 subst += put_cmd_in_ert("{")
4443 document.body[i : i + 1] = subst
4447 def revert_mbox_fbox(document):
4448 'Convert revert mbox/fbox boxes to TeX-code'
4451 i = find_token(document.body, "\\begin_inset Box", i)
4454 j = find_token(document.body, "width", i)
4456 document.warning("Malformed LyX document: Can't find box width")
4458 width = get_value(document.body, "width", j)
4459 k = find_end_of_inset(document.body, j)
4461 document.warning("Malformed LyX document: Can't find end of box inset")
4464 BeginLayout = find_token(document.body, "\\begin_layout Plain Layout", j)
4465 EndLayout = find_end_of_layout(document.body, BeginLayout)
4466 # replace if width is ""
4468 document.body[EndLayout:k + 1] = put_cmd_in_ert("}")
4469 if document.body[i] == "\\begin_inset Box Frameless":
4470 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\mbox{")
4471 if document.body[i] == "\\begin_inset Box Boxed":
4472 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\fbox{")
4476 def revert_starred_caption(document):
4477 " Reverts unnumbered longtable caption insets "
4481 i = find_token(document.body, "\\begin_inset Caption LongTableNoNumber", i)
4484 # This is not equivalent, but since the caption inset is a full blown
4485 # text inset a true conversion to ERT is too difficult.
4486 document.body[i] = "\\begin_inset Caption Standard"
4490 def revert_forced_local_layout(document):
4493 i = find_token(document.header, "\\begin_forced_local_layout", i)
4496 j = find_end_of(document.header, i, "\\begin_forced_local_layout", "\\end_forced_local_layout")
4498 # this should not happen
4500 regexp = re.compile(r'\s*forcelocal', re.IGNORECASE)
4501 k = find_re(document.header, regexp, i, j)
4503 del document.header[k]
4505 k = find_re(document.header, regexp, i, j)
4506 k = find_token(document.header, "\\begin_local_layout", 0)
4508 document.header[i] = "\\begin_local_layout"
4509 document.header[j] = "\\end_local_layout"
4511 l = find_end_of(document.header, k, "\\begin_local_layout", "\\end_local_layout")
4513 # this should not happen
4515 lines = document.header[i+1 : j]
4517 document.header[k+1 : k+1] = lines
4518 document.header[i : j ] = []
4520 document.header[i : j ] = []
4521 document.header[k+1 : k+1] = lines
4524 def revert_aa1(document):
4525 " Reverts InsetArguments of aa to TeX-code "
4526 if document.textclass == "aa":
4530 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4532 revert_Argument_to_TeX_brace(document, i, 0, 1, 4, False, False)
4538 def revert_aa2(document):
4539 " Reverts InsetArguments of aa to TeX-code "
4540 if document.textclass == "aa":
4544 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4546 document.body[i] = "\\begin_layout Abstract"
4552 def revert_tibetan(document):
4553 "Set the document language for Tibetan to English"
4555 if document.language == "tibetan":
4556 document.language = "english"
4557 i = find_token(document.header, "\\language", 0)
4559 document.header[i] = "\\language english"
4561 while j < len(document.body):
4562 j = find_token(document.body, "\\lang tibetan", j)
4564 document.body[j] = document.body[j].replace("\\lang tibetan", "\\lang english")
4567 j = len(document.body)
4576 # The idea here is that we will have a sequence of chunk paragraphs.
4577 # We want to convert them to paragraphs in one or several chunk insets.
4578 # Individual chunks are terminated by the character @ on the last line.
4579 # This line will be discarded, and following lines are treated as new
4580 # chunks, which go into their own insets.
4581 # The first line of a chunk should look like: <<CONTENT>>=
4582 # We will discard the delimiters, and put the CONTENT into the
4583 # optional argument of the inset, if the CONTENT is non-empty.
4584 def convert_chunks(document):
4585 first_re = re.compile(r'<<(.*)>>=(.*)')
4588 # find start of a block of chunks
4589 i = find_token(document.body, "\\begin_layout Chunk", file_pos)
4595 chunk_started = False
4598 # process the one we just found
4599 j = find_end_of_layout(document.body, i)
4601 document.warning("Malformed LyX documents. Can't find end of Chunk layout!")
4602 # there is no point continuing, as we will run into the same error again.
4604 this_chunk = "".join(document.body[i + 1:j])
4606 # there may be empty lines between chunks
4607 # we just skip them.
4608 if not chunk_started:
4609 if this_chunk != "":
4611 chunk_started = True
4614 contents.append(document.body[i + 1:j])
4616 # look for potential chunk terminator
4617 # on the last line of the chunk paragraph
4618 if document.body[j - 1] == "@":
4621 # look for subsequent chunk paragraph
4622 i = find_token(document.body, "\\begin_layout", j)
4626 if get_value(document.body, "\\begin_layout", i) != "Chunk":
4629 file_pos = end = j + 1
4631 # The last chunk should simply have an "@" in it
4632 # or at least end with "@" (can happen if @ is
4633 # preceded by a newline)
4635 if len(contents) > 0:
4636 lastpar = ''.join(contents[-1])
4637 if not lastpar.endswith("@"):
4638 document.warning("Unexpected chunk content: chunk not terminated by '@'!")
4639 if len(contents) == 0:
4640 # convert empty chunk layouts to Standard
4641 document.body[start] = "\\begin_layout Standard"
4645 # chunk par only contains "@". Just drop it.
4648 # chunk par contains more. Only drop the "@".
4651 # The first line should look like: <<CONTENT>>=
4652 # We want the CONTENT
4653 optarg = ' '.join(contents[0])
4655 # We can already have real chunk content in
4656 # the first par (separated from the options by a newline).
4657 # We collect such stuff to re-insert it later.
4660 match = first_re.search(optarg)
4662 optarg = match.groups()[0]
4663 if match.groups()[1] != "":
4665 for c in contents[0]:
4666 if c.endswith(">>="):
4670 postoptstuff.append(c)
4671 # We have stripped everything. This can be deleted.
4674 newstuff = ['\\begin_layout Standard']
4676 # Maintain paragraph parameters
4677 par_params = ["\\noindent", "\\indent", "\\indent-toggle", "\\leftindent",
4678 "\\start_of_appendix", "\\paragraph_spacing", "\\align",
4679 "\\labelwidthstring"]
4682 if document.body[parms].split(' ', 1)[0] not in par_params:
4684 newstuff.extend([document.body[parms]])
4688 ['\\begin_inset Flex Chunk',
4690 '\\begin_layout Plain Layout', ''])
4692 # If we have a non-empty optional argument, insert it.
4693 if match and optarg != "":
4695 ['\\begin_inset Argument 1',
4697 '\\begin_layout Plain Layout',
4702 # Since we already opened a Plain layout, the first paragraph
4703 # does not need to do that.
4706 # we need to replace newlines with new layouts
4708 started_text = False
4709 for lno in range(0,len(postoptstuff)):
4710 if postoptstuff[lno].startswith("\\begin_inset Newline newline"):
4712 elif start_newline != -1:
4713 if postoptstuff[lno].startswith("\\end_inset"):
4714 # replace that bit, but only if we already have some text
4715 # and we're not at the end except for a blank line
4716 if started_text and \
4717 (lno != len(postoptstuff) - 2 or postoptstuff[-1] != ""):
4718 newstuff.extend(['\\end_layout', '\n', '\\begin_layout Plain Layout', '\n'])
4722 newstuff.extend([postoptstuff[lno]])
4723 newstuff.append('\\end_layout')
4727 newstuff.extend(['', '\\begin_layout Plain Layout', ''])
4731 newstuff.append('\\end_layout')
4733 newstuff.extend(['', '\\end_inset', '', '\\end_layout', ''])
4735 document.body[start:end] = newstuff
4737 file_pos += len(newstuff) - (end - start)
4740 def revert_chunks(document):
4743 i = find_token(document.body, "\\begin_inset Flex Chunk", i)
4747 iend = find_end_of_inset(document.body, i)
4749 document.warning("Can't find end of Chunk!")
4753 # Look for optional argument
4755 ostart = find_token(document.body, "\\begin_inset Argument 1", i, iend)
4757 oend = find_end_of_inset(document.body, ostart)
4758 k = find_token(document.body, "\\begin_layout Plain Layout", ostart, oend)
4760 document.warning("Malformed LyX document: Can't find argument contents!")
4762 m = find_end_of_layout(document.body, k)
4763 optarg = "".join(document.body[k+1:m])
4765 # We now remove the optional argument, so we have something
4766 # uniform on which to work
4767 document.body[ostart : oend + 1] = []
4768 # iend is now invalid
4769 iend = find_end_of_inset(document.body, i)
4771 retval = get_containing_layout(document.body, i)
4773 document.warning("Can't find containing layout for Chunk!")
4776 (lname, lstart, lend, pstart) = retval
4777 # we now want to work through the various paragraphs, and collect their contents
4781 k = find_token(document.body, "\\begin_layout Plain Layout", k, lend)
4784 j = find_end_of_layout(document.body, k)
4786 document.warning("Can't find end of layout inside chunk!")
4788 parlist.append(document.body[k+1:j])
4790 # we now need to wrap all of these paragraphs in chunks
4792 newlines.extend(["\\begin_layout Chunk", "", "<<" + optarg + ">>=", "\\end_layout", ""])
4793 for stuff in parlist:
4794 newlines.extend(["\\begin_layout Chunk"] + stuff + ["\\end_layout", ""])
4795 newlines.extend(["\\begin_layout Chunk", "", "@", "\\end_layout", ""])
4796 # replace old content with new content
4797 document.body[lstart : lend + 1] = newlines
4798 i = lstart + len(newlines)
4805 supported_versions = ["2.1.0","2.1"]
4808 [415, [convert_undertilde]],
4810 [417, [convert_japanese_encodings]],
4811 [418, [convert_justification]],
4813 [420, [convert_biblio_style]],
4814 [421, [convert_longtable_captions]],
4815 [422, [convert_use_packages]],
4816 [423, [convert_use_mathtools]],
4817 [424, [convert_cite_engine_type]],
4818 # No convert_cancel, since cancel will be loaded automatically
4819 # in format 425 without any possibility to switch it off.
4820 # This has been fixed in format 464.
4824 [428, [convert_cell_rotation]],
4825 [429, [convert_table_rotation]],
4826 [430, [convert_listoflistings]],
4827 [431, [convert_use_amssymb]],
4829 [433, [convert_armenian]],
4836 [440, [convert_mathfonts]],
4837 [441, [convert_mdnomath]],
4842 [446, [convert_latexargs]],
4843 [447, [convert_IEEEtran, convert_AASTeX, convert_AGUTeX, convert_IJMP, convert_SIGPLAN, convert_SIGGRAPH, convert_EuropeCV, convert_Initials, convert_ModernCV]],
4844 [448, [convert_literate]],
4847 [451, [convert_beamerargs, convert_againframe_args, convert_corollary_args, convert_quote_args]],
4848 [452, [convert_beamerblocks]],
4849 [453, [convert_use_stmaryrd]],
4850 [454, [convert_overprint]],
4852 [456, [convert_epigraph]],
4853 [457, [convert_use_stackrel]],
4854 [458, [convert_captioninsets, convert_captionlayouts]],
4859 [463, [convert_encodings]],
4860 [464, [convert_use_cancel]],
4861 [465, [convert_lyxframes, remove_endframes]],
4867 [471, [convert_cite_engine_type_default]],
4870 [474, [convert_chunks, cleanup_beamerargs]],
4874 [473, [revert_chunks]],
4875 [472, [revert_tibetan]],
4876 [471, [revert_aa1,revert_aa2]],
4877 [470, [revert_cite_engine_type_default]],
4878 [469, [revert_forced_local_layout]],
4879 [468, [revert_starred_caption]],
4880 [467, [revert_mbox_fbox]],
4881 [466, [revert_iwona_fonts]],
4882 [465, [revert_powerdot_flexes, revert_powerdot_pause, revert_powerdot_itemargs, revert_powerdot_columns]],
4884 [463, [revert_use_cancel]],
4885 [462, [revert_encodings]],
4886 [461, [revert_new_libertines]],
4887 [460, [revert_kurier_fonts]],
4888 [459, [revert_IEEEtran_3]],
4889 [458, [revert_fragileframe, revert_newframes]],
4890 [457, [revert_captioninsets, revert_captionlayouts]],
4891 [456, [revert_use_stackrel]],
4892 [455, [revert_epigraph]],
4893 [454, [revert_frametitle]],
4894 [453, [revert_overprint]],
4895 [452, [revert_use_stmaryrd]],
4896 [451, [revert_beamerblocks]],
4897 [450, [revert_beamerargs, revert_beamerargs2, revert_beamerargs3, revert_beamerflex]],
4898 [449, [revert_garamondx, revert_garamondx_newtxmath]],
4899 [448, [revert_itemargs]],
4900 [447, [revert_literate]],
4901 [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]],
4902 [445, [revert_latexargs]],
4903 [444, [revert_uop]],
4904 [443, [revert_biolinum]],
4906 [441, [revert_newtxmath]],
4907 [440, [revert_mdnomath]],
4908 [439, [revert_mathfonts]],
4909 [438, [revert_minionpro]],
4910 [437, [revert_ipadeco, revert_ipachar]],
4911 [436, [revert_texgyre]],
4912 [435, [revert_mathdesign]],
4913 [434, [revert_txtt]],
4914 [433, [revert_libertine]],
4915 [432, [revert_armenian]],
4916 [431, [revert_languages, revert_ancientgreek]],
4917 [430, [revert_use_amssymb]],
4918 [429, [revert_listoflistings]],
4919 [428, [revert_table_rotation]],
4920 [427, [revert_cell_rotation]],
4921 [426, [revert_tipa]],
4922 [425, [revert_verbatim]],
4923 [424, [revert_cancel]],
4924 [423, [revert_cite_engine_type]],
4925 [422, [revert_use_mathtools]],
4926 [421, [revert_use_packages]],
4927 [420, [revert_longtable_captions]],
4928 [419, [revert_biblio_style]],
4929 [418, [revert_australian]],
4930 [417, [revert_justification]],
4931 [416, [revert_japanese_encodings]],
4932 [415, [revert_negative_space, revert_math_spaces]],
4933 [414, [revert_undertilde]],
4934 [413, [revert_visible_space]]
4938 if __name__ == "__main__":