1 # -*- coding: utf-8 -*-
2 # This file is part of lyx2lyx
3 # -*- coding: utf-8 -*-
4 # Copyright (C) 2011 The LyX team
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 """ Convert files to the file format generated by LyX 2.1"""
26 # Uncomment only what you need to import, please.
28 from parser_tools import count_pars_in_inset, del_token, find_token, find_token_exact, \
29 find_token_backwards, find_end_of, find_end_of_inset, find_end_of_layout, \
30 find_end_of_sequence, find_re, get_option_value, get_containing_layout, \
31 get_containing_inset, get_value, get_quoted_value, set_option_value
33 #from parser_tools import find_token, find_end_of, find_tokens, \
34 #find_end_of_inset, find_end_of_layout, \
35 #is_in_inset, del_token, check_token
37 from lyx2lyx_tools import add_to_preamble, put_cmd_in_ert, get_ert
39 #from lyx2lyx_tools import insert_to_preamble, \
40 # lyx2latex, latex_length, revert_flex_inset, \
41 # revert_font_attrs, hex2ratio, str2bool
43 ####################################################################
44 # Private helper functions
46 #def remove_option(lines, m, option):
47 #''' removes option from line m. returns whether we did anything '''
48 #l = lines[m].find(option)
51 #val = lines[m][l:].split('"')[1]
52 #lines[m] = lines[m][:l - 1] + lines[m][l+len(option + '="' + val + '"'):]
56 def revert_Argument_to_TeX_brace(document, line, endline, n, nmax, environment, opt):
58 Reverts an InsetArgument to TeX-code
60 revert_Argument_to_TeX_brace(document, LineOfBegin, LineOfEnd, StartArgument, EndArgument, isEnvironment, isOpt)
61 LineOfBegin is the line of the \begin_layout or \begin_inset statement
62 LineOfEnd is the line of the \end_layout or \end_inset statement, if "0" is given, the end of the file is used instead
63 StartArgument is the number of the first argument that needs to be converted
64 EndArgument is the number of the last argument that needs to be converted or the last defined one
65 isEnvironment must be true, if the layout is for a LaTeX environment
66 isOpt must be true, if the argument is an optional one
70 while lineArg != -1 and n < nmax + 1:
71 lineArg = find_token(document.body, "\\begin_inset Argument " + str(n), line)
72 if lineArg > endline and endline != 0:
75 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", lineArg)
76 # we have to assure that no other inset is in the Argument
77 beginInset = find_token(document.body, "\\begin_inset", beginPlain)
78 endInset = find_token(document.body, "\\end_inset", beginPlain)
81 while beginInset < endInset and beginInset != -1:
82 beginInset = find_token(document.body, "\\begin_inset", k)
83 endInset = find_token(document.body, "\\end_inset", l)
86 if environment == False:
88 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}{")
89 del(document.body[lineArg : beginPlain + 1])
92 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("]")
93 document.body[lineArg : beginPlain + 1] = put_cmd_in_ert("[")
96 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}")
97 document.body[lineArg : beginPlain + 1] = put_cmd_in_ert("{")
103 def convert_TeX_brace_to_Argument(document, line, n, nmax, inset, environment, opt):
105 Converts TeX code for mandatory arguments to an InsetArgument
106 The conversion of TeX code for optional arguments must be done with another routine
107 !!! Be careful if the braces are different in your case as expected here:
108 - "}{" separates mandatory arguments of commands
109 - "}" + "{" separates mandatory arguments of commands
110 - "}" + " " + "{" separates mandatory arguments of commands
111 - { and } surround a mandatory argument of an environment
113 convert_TeX_brace_to_Argument(document, LineOfBeginLayout/Inset, StartArgument, EndArgument, isInset, isEnvironment, isOpt)
114 LineOfBeginLayout/Inset is the line of the \begin_layout or \begin_inset statement
115 StartArgument is the number of the first ERT that needs to be converted
116 EndArgument is the number of the last ERT that needs to be converted
117 isInset must be true, if braces inside an InsetLayout needs to be converted
118 isEnvironment must be true, if the layout is for a LaTeX environment
119 isOpt must be true, if the argument is an optional one
121 Todo: this routine can currently handle only one mandatory argument of environments
124 end_layout = find_end_of_layout(document.body, line)
129 lineERT = find_token(document.body, "\\begin_inset ERT", lineERT, end_layout)
132 if environment == False:
133 end_ERT = find_end_of_inset(document.body, lineERT)
135 document.warning("Can't find end of ERT!!")
137 # Note that this only checks for ][ or }{ at the beginning of a line
139 bracePair = find_token(document.body, "][", lineERT, end_ERT)
141 bracePair = find_token(document.body, "}{", lineERT, end_ERT)
143 end = find_token(document.body, "\\end_inset", bracePair)
144 document.body[lineERT : end_ERT + 1] = ["\\end_layout", "", "\\end_inset"]
146 # in the case that n > 1 we have optional arguments before
147 # therefore detect them if any
149 # first check if there is an argument
150 lineArg = find_token(document.body, "\\begin_inset Argument", line)
151 if lineArg < lineERT and lineArg != -1:
152 # we have an argument, so now search backwards for its end
153 # we must now assure that we don't find other insets like e.g. a newline
154 endInsetArg = lineERT
155 endLayoutArg = endInsetArg
156 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
157 endInsetArg = endInsetArg - 1
158 endLayoutArg = endInsetArg
159 endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
160 endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
161 line = endInsetArg + 1
163 document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
165 document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
167 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
172 # no brace pair found
173 # now check the case that we have "}" + "{" in two ERTs
175 endBrace = find_token(document.body, "]", lineERT, end_layout)
177 endBrace = find_token(document.body, "}", lineERT, end_layout)
178 if endBrace == lineERT + 5:
180 beginBrace = find_token(document.body, "[", endBrace, end_layout)
182 beginBrace = find_token(document.body, "{", endBrace, end_layout)
183 # assure that the ERTs are consecutive (11 or 12 depending if there is a space between the ERTs or not)
184 if beginBrace == endBrace + 11 or beginBrace == endBrace + 12:
185 end = find_token(document.body, "\\end_inset", beginBrace)
186 document.body[lineERT : end + 1] = ["\\end_layout", "", "\\end_inset"]
188 # in the case that n > 1 we have optional arguments before
189 # therefore detect them if any
191 # first check if there is an argument
192 lineArg = find_token(document.body, "\\begin_inset Argument", line)
193 if lineArg < lineERT and lineArg != -1:
194 # we have an argument, so now search backwards for its end
195 # we must now assure that we don't find other insets like e.g. a newline
196 endInsetArg = lineERT
197 endLayoutArg = endInsetArg
198 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
199 endInsetArg = endInsetArg - 1
200 endLayoutArg = endInsetArg
201 endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
202 endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
203 line = endInsetArg + 1
205 document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
207 document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
209 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
212 # set the line where the next argument will be inserted
213 if beginBrace == endBrace + 11:
221 if environment == True:
222 end_ERT = find_end_of_inset(document.body, lineERT)
224 document.warning("Can't find end of ERT!!")
226 # Note that this only checks for [ or { at the beginning of a line
228 opening = find_token(document.body, "[", lineERT, end_ERT)
230 opening = find_token(document.body, "{", lineERT, end_ERT)
232 lineERT2 = find_token(document.body, "\\begin_inset ERT", end_ERT, end_layout)
234 # argument in a single ERT
235 # strip off the opening bracket
236 document.body[opening] = document.body[opening][1:]
237 ertcontlastline = end_ERT - 3
238 if (opt and document.body[ertcontlastline].endswith("]")) or document.body[ertcontlastline].endswith("}"):
239 # strip off the closing bracket
240 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
241 end2 = find_token(document.body, "\\end_inset", ertcontlastline)
242 document.body[lineERT : lineERT + 1] = ["\\begin_inset Argument " + str(n)]
244 end_ERT2 = find_end_of_inset(document.body, lineERT2)
246 document.warning("Can't find end of second ERT!!")
249 closing = find_token(document.body, "]", lineERT2, end_ERT2)
251 closing = find_token(document.body, "}", lineERT2, end_ERT2)
252 if closing != -1: # assure that the "}" is in this ERT
253 end2 = find_token(document.body, "\\end_inset", closing)
254 document.body[lineERT2 : end2 + 1] = ["\\end_layout", "", "\\end_inset"]
255 document.body[lineERT : end_ERT + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
259 ###############################################################################
261 ### Conversion and reversion routines
263 ###############################################################################
265 def revert_visible_space(document):
266 "Revert InsetSpace visible into its ERT counterpart"
269 i = find_token(document.body, "\\begin_inset space \\textvisiblespace{}", i)
272 end = find_end_of_inset(document.body, i)
273 subst = put_cmd_in_ert("\\textvisiblespace{}")
274 document.body[i:end + 1] = subst
277 undertilde_commands = ["utilde"]
278 def convert_undertilde(document):
279 " Load undertilde automatically "
280 i = find_token(document.header, "\\use_mathdots" , 0)
282 i = find_token(document.header, "\\use_mhchem" , 0)
284 i = find_token(document.header, "\\use_esint" , 0)
286 document.warning("Malformed LyX document: Can't find \\use_mathdots.")
288 j = find_token(document.preamble, "\\usepackage{undertilde}", 0)
290 # package was loaded in the preamble, convert this to header setting for round trip
291 document.header.insert(i + 1, "\\use_undertilde 2") # on
292 del document.preamble[j]
296 j = find_token(document.body, '\\begin_inset Formula', j)
299 k = find_end_of_inset(document.body, j)
301 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(j))
304 code = "\n".join(document.body[j:k])
305 for c in undertilde_commands:
306 if code.find("\\%s" % c) != -1:
307 # at least one of the commands was found - need to switch package off
308 document.header.insert(i + 1, "\\use_undertilde 0") # off
311 # no command was found - set to auto (bug 9069)
312 document.header.insert(i + 1, "\\use_undertilde 1") # auto
316 def revert_undertilde(document):
317 " Load undertilde if used in the document "
318 regexp = re.compile(r'(\\use_undertilde)')
319 i = find_re(document.header, regexp, 0)
320 value = "1" # default is auto
322 value = get_value(document.header, "\\use_undertilde" , i).split()[0]
323 del document.header[i]
324 if value == "2": # on
325 add_to_preamble(document, ["\\usepackage{undertilde}"])
326 elif value == "1": # auto
329 i = find_token(document.body, '\\begin_inset Formula', i)
332 j = find_end_of_inset(document.body, i)
334 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
337 code = "\n".join(document.body[i:j])
338 for c in undertilde_commands:
339 if code.find("\\%s" % c) != -1:
340 add_to_preamble(document, ["\\usepackage{undertilde}"])
345 def revert_negative_space(document):
346 "Revert InsetSpace negmedspace and negthickspace into its TeX-code counterpart"
351 i = find_token(document.body, "\\begin_inset space \\negmedspace{}", i)
353 j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
355 # load amsmath in the preamble if not already loaded if we are at the end of checking
357 i = find_token(document.header, "\\use_amsmath 2", 0)
359 add_to_preamble(document, ["\\@ifundefined{negthickspace}{\\usepackage{amsmath}}"])
363 end = find_end_of_inset(document.body, i)
364 subst = put_cmd_in_ert("\\negmedspace{}")
365 document.body[i:end + 1] = subst
366 j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
369 end = find_end_of_inset(document.body, j)
370 subst = put_cmd_in_ert("\\negthickspace{}")
371 document.body[j:end + 1] = subst
375 def revert_math_spaces(document):
376 "Revert formulas with protected custom space and protected hfills to TeX-code"
379 i = find_token(document.body, "\\begin_inset Formula", i)
382 j = document.body[i].find("\\hspace*")
384 end = find_end_of_inset(document.body, i)
385 subst = put_cmd_in_ert(document.body[i][21:])
386 document.body[i:end + 1] = subst
390 def convert_japanese_encodings(document):
391 " Rename the japanese encodings to names understood by platex "
393 "EUC-JP-pLaTeX": "euc",
395 "SJIS-pLaTeX": "sjis"
397 i = find_token(document.header, "\\inputencoding" , 0)
400 val = get_value(document.header, "\\inputencoding", i)
401 if val in list(jap_enc_dict.keys()):
402 document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
405 def revert_japanese_encodings(document):
406 " Revert the japanese encodings name changes "
408 "euc": "EUC-JP-pLaTeX",
410 "sjis": "SJIS-pLaTeX"
412 i = find_token(document.header, "\\inputencoding" , 0)
415 val = get_value(document.header, "\\inputencoding", i)
416 if val in list(jap_enc_dict.keys()):
417 document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
420 def convert_justification(document):
421 " Add the \\justification buffer param"
422 i = find_token(document.header, "\\suppress_date" , 0)
424 i = find_token(document.header, "\\paperorientation" , 0)
426 i = find_token(document.header, "\\use_indices" , 0)
428 i = find_token(document.header, "\\use_bibtopic" , 0)
430 document.warning("Malformed LyX document: Missing \\suppress_date.")
432 document.header.insert(i + 1, "\\justification true")
435 def revert_justification(document):
436 " Revert the \\justification buffer param"
437 if not del_token(document.header, '\\justification', 0):
438 document.warning("Malformed LyX document: Missing \\justification.")
441 def revert_australian(document):
442 "Set English language variants Australian and Newzealand to English"
444 if document.language == "australian" or document.language == "newzealand":
445 document.language = "english"
446 i = find_token(document.header, "\\language", 0)
448 document.header[i] = "\\language english"
451 j = find_token(document.body, "\\lang australian", j)
453 j = find_token(document.body, "\\lang newzealand", 0)
457 document.body[j] = document.body[j].replace("\\lang newzealand", "\\lang english")
459 document.body[j] = document.body[j].replace("\\lang australian", "\\lang english")
463 def convert_biblio_style(document):
464 "Add a sensible default for \\biblio_style based on the citation engine."
465 i = find_token(document.header, "\\cite_engine", 0)
467 engine = get_value(document.header, "\\cite_engine", i).split("_")[0]
468 style = {"basic": "plain", "natbib": "plainnat", "jurabib": "jurabib"}
469 document.header.insert(i + 1, "\\biblio_style " + style[engine])
472 def revert_biblio_style(document):
473 "BibTeX insets with default option use the style defined by \\biblio_style."
474 i = find_token(document.header, "\\biblio_style" , 0)
476 document.warning("No \\biblio_style line. Nothing to do.")
479 default_style = get_value(document.header, "\\biblio_style", i)
480 del document.header[i]
482 # We are looking for bibtex insets having the default option
485 i = find_token(document.body, "\\begin_inset CommandInset bibtex", i)
488 j = find_end_of_inset(document.body, i)
490 document.warning("Malformed LyX document: Can't find end of bibtex inset at line " + str(i))
493 k = find_token(document.body, "options", i, j)
495 options = get_quoted_value(document.body, "options", k)
496 if "default" in options.split(","):
497 document.body[k] = 'options "%s"' \
498 % options.replace("default", default_style)
502 def handle_longtable_captions(document, forward):
505 begin_table = find_token(document.body, '<lyxtabular version=', begin_table)
506 if begin_table == -1:
508 end_table = find_end_of(document.body, begin_table, '<lyxtabular', '</lyxtabular>')
510 document.warning("Malformed LyX document: Could not find end of table.")
513 fline = find_token(document.body, "<features", begin_table, end_table)
515 document.warning("Can't find features for inset at line " + str(begin_table))
518 p = document.body[fline].find("islongtable")
523 numrows = get_option_value(document.body[begin_table], "rows")
525 numrows = int(numrows)
527 document.warning(document.body[begin_table])
528 document.warning("Unable to determine rows!")
529 begin_table = end_table
531 begin_row = begin_table
532 for row in range(numrows):
533 begin_row = find_token(document.body, '<row', begin_row, end_table)
535 document.warning("Can't find row " + str(row + 1))
537 end_row = find_end_of(document.body, begin_row, '<row', '</row>')
539 document.warning("Can't find end of row " + str(row + 1))
542 if (get_option_value(document.body[begin_row], 'caption') == 'true' and
543 get_option_value(document.body[begin_row], 'endfirsthead') != 'true' and
544 get_option_value(document.body[begin_row], 'endhead') != 'true' and
545 get_option_value(document.body[begin_row], 'endfoot') != 'true' and
546 get_option_value(document.body[begin_row], 'endlastfoot') != 'true'):
547 document.body[begin_row] = set_option_value(document.body[begin_row], 'caption', 'true", endfirsthead="true')
548 elif get_option_value(document.body[begin_row], 'caption') == 'true':
549 if get_option_value(document.body[begin_row], 'endfirsthead') == 'true':
550 document.body[begin_row] = set_option_value(document.body[begin_row], 'endfirsthead', 'false')
551 if get_option_value(document.body[begin_row], 'endhead') == 'true':
552 document.body[begin_row] = set_option_value(document.body[begin_row], 'endhead', 'false')
553 if get_option_value(document.body[begin_row], 'endfoot') == 'true':
554 document.body[begin_row] = set_option_value(document.body[begin_row], 'endfoot', 'false')
555 if get_option_value(document.body[begin_row], 'endlastfoot') == 'true':
556 document.body[begin_row] = set_option_value(document.body[begin_row], 'endlastfoot', 'false')
558 # since there could be a tabular inside this one, we
559 # cannot jump to end.
563 def convert_longtable_captions(document):
564 "Add a firsthead flag to caption rows"
565 handle_longtable_captions(document, True)
568 def revert_longtable_captions(document):
569 "remove head/foot flag from caption rows"
570 handle_longtable_captions(document, False)
573 def convert_use_packages(document):
574 "use_xxx yyy => use_package xxx yyy"
575 packages = ["amsmath", "esint", "mathdots", "mhchem", "undertilde"]
577 i = find_token(document.header, "\\use_%s" % p, 0)
579 value = get_value(document.header, "\\use_%s" % p, i)
580 document.header[i] = "\\use_package %s %s" % (p, value)
583 def revert_use_packages(document):
584 "use_package xxx yyy => use_xxx yyy"
585 packages = ["amsmath", "esint", "mhchem", "mathdots", "undertilde"]
586 # the order is arbitrary for the use_package version, and not all packages need to be given.
587 # Ensure a complete list and correct order (important for older LyX versions and especially lyx2lyx)
588 # first loop: find line with first package
591 regexp = re.compile(r'(\\use_package\s+%s)' % p)
592 i = find_re(document.header, regexp, 0)
593 if i != -1 and (j < 0 or i < j):
595 # second loop: replace or insert packages in front of all existing ones
597 regexp = re.compile(r'(\\use_package\s+%s)' % p)
598 i = find_re(document.header, regexp, 0)
600 value = get_value(document.header, "\\use_package %s" % p, i).split()[1]
601 del document.header[i]
602 document.header.insert(j, "\\use_%s %s" % (p, value))
604 document.header.insert(j, "\\use_%s 1" % p)
608 def convert_use_package(document, pkg, commands, oldauto):
609 # oldauto defines how the version we are converting from behaves:
610 # if it is true, the old version uses the package automatically.
611 # if it is false, the old version never uses the package.
612 i = find_token(document.header, "\\use_package", 0)
614 document.warning("Malformed LyX document: Can't find \\use_package.")
616 j = find_token(document.preamble, "\\usepackage{" + pkg + "}", 0)
618 # package was loaded in the preamble, convert this to header setting for round trip
619 document.header.insert(i + 1, "\\use_package " + pkg + " 2") # on
620 del document.preamble[j]
621 # If oldauto is true we have two options:
622 # We can either set the package to auto - this is correct for files in
623 # format 425 to 463, and may create a conflict for older files which use
624 # any command in commands with a different definition.
625 # Or we can look whether any command in commands is used, and set it to
626 # auto if not and to off if yes. This will not create a conflict, but will
627 # create uncompilable documents for files in format 425 to 463, which use
628 # any command in commands.
629 # We choose the first option since its error is less likely.
631 document.header.insert(i + 1, "\\use_package " + pkg + " 1") # auto
635 j = find_token(document.body, '\\begin_inset Formula', j)
638 k = find_end_of_inset(document.body, j)
640 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(j))
643 code = "\n".join(document.body[j:k])
645 if code.find("\\%s" % c) != -1:
646 # at least one of the commands was found - need to switch package off
647 document.header.insert(i + 1, "\\use_package " + pkg + " 0") # off
650 # no command was found - set to auto (bug 9069)
651 document.header.insert(i + 1, "\\use_package " + pkg + " 1") # auto
654 def revert_use_package(document, pkg, commands, oldauto):
655 # oldauto defines how the version we are reverting to behaves:
656 # if it is true, the old version uses the package automatically.
657 # if it is false, the old version never uses the package.
658 regexp = re.compile(r'(\\use_package\s+%s)' % pkg)
659 i = find_re(document.header, regexp, 0)
660 value = "1" # default is auto
662 value = get_value(document.header, "\\use_package" , i).split()[1]
663 del document.header[i]
664 if value == "2": # on
665 add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
666 elif value == "1" and not oldauto: # auto
669 i = find_token(document.body, '\\begin_inset Formula', i)
672 j = find_end_of_inset(document.body, i)
674 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
677 code = "\n".join(document.body[i:j])
679 if code.find("\\%s" % c) != -1:
680 add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
685 mathtools_commands = ["mathclap", "mathllap", "mathrlap", \
686 "lgathered", "rgathered", "vcentcolon", "dblcolon", \
687 "coloneqq", "Coloneqq", "coloneq", "Coloneq", "eqqcolon", \
688 "Eqqcolon", "eqcolon", "Eqcolon", "colonapprox", \
689 "Colonapprox", "colonsim", "Colonsim"]
690 def convert_use_mathtools(document):
691 "insert use_package mathtools"
692 convert_use_package(document, "mathtools", mathtools_commands, False)
695 def revert_use_mathtools(document):
696 "remove use_package mathtools"
697 revert_use_package(document, "mathtools", mathtools_commands, False)
700 # commands provided by stmaryrd.sty but LyX uses other packages:
701 # boxdot lightning, bigtriangledown, bigtriangleup
702 stmaryrd_commands = ["shortleftarrow", "shortrightarrow", "shortuparrow", \
703 "shortdownarrow", "Yup", "Ydown", "Yleft", "Yright", \
704 "varcurlyvee", "varcurlywedge", "minuso", "baro", \
705 "sslash", "bbslash", "moo", "varotimes", "varoast", \
706 "varobar", "varodot", "varoslash", "varobslash", \
707 "varocircle", "varoplus", "varominus", "boxast", \
708 "boxbar", "boxslash", "boxbslash", "boxcircle", \
709 "boxbox", "boxempty", "merge", "vartimes", \
710 "fatsemi", "sswarrow", "ssearrow", "curlywedgeuparrow", \
711 "curlywedgedownarrow", "fatslash", "fatbslash", "lbag", \
712 "rbag", "varbigcirc", "leftrightarroweq", \
713 "curlyveedownarrow", "curlyveeuparrow", "nnwarrow", \
714 "nnearrow", "leftslice", "rightslice", "varolessthan", \
715 "varogreaterthan", "varovee", "varowedge", "talloblong", \
716 "interleave", "obar", "obslash", "olessthan", \
717 "ogreaterthan", "ovee", "owedge", "oblong", "inplus", \
718 "niplus", "nplus", "subsetplus", "supsetplus", \
719 "subsetpluseq", "supsetpluseq", "Lbag", "Rbag", \
720 "llbracket", "rrbracket", "llparenthesis", \
721 "rrparenthesis", "binampersand", "bindnasrepma", \
722 "trianglelefteqslant", "trianglerighteqslant", \
723 "ntrianglelefteqslant", "ntrianglerighteqslant", \
724 "llfloor", "rrfloor", "llceil", "rrceil", "arrownot", \
725 "Arrownot", "Mapstochar", "mapsfromchar", "Mapsfromchar", \
726 "leftrightarrowtriangle", "leftarrowtriangle", \
727 "rightarrowtriangle", \
728 "bigcurlyvee", "bigcurlywedge", "bigsqcap", "bigbox", \
729 "bigparallel", "biginterleave", "bignplus", \
730 "varcopyright", "longarrownot", "Longarrownot", \
731 "Mapsto", "mapsfrom", "Mapsfrom" "Longmapsto", \
732 "longmapsfrom", "Longmapsfrom"]
733 def convert_use_stmaryrd(document):
734 "insert use_package stmaryrd"
735 convert_use_package(document, "stmaryrd", stmaryrd_commands, False)
738 def revert_use_stmaryrd(document):
739 "remove use_package stmaryrd"
740 revert_use_package(document, "stmaryrd", stmaryrd_commands, False)
743 stackrel_commands = ["stackrel"]
744 def convert_use_stackrel(document):
745 "insert use_package stackrel"
746 convert_use_package(document, "stackrel", stackrel_commands, False)
749 def revert_use_stackrel(document):
750 "remove use_package stackrel"
751 revert_use_package(document, "stackrel", stackrel_commands, False)
754 def convert_cite_engine_type(document):
755 "Determine the \\cite_engine_type from the citation engine."
756 i = find_token(document.header, "\\cite_engine", 0)
759 engine = get_value(document.header, "\\cite_engine", i)
761 engine, type = engine.split("_")
763 type = {"basic": "numerical", "jurabib": "authoryear"}[engine]
764 document.header[i] = "\\cite_engine " + engine
765 document.header.insert(i + 1, "\\cite_engine_type " + type)
768 def revert_cite_engine_type(document):
769 "Natbib had the type appended with an underscore."
770 engine_type = "numerical"
771 i = find_token(document.header, "\\cite_engine_type" , 0)
773 document.warning("No \\cite_engine_type line. Assuming numerical.")
775 engine_type = get_value(document.header, "\\cite_engine_type", i)
776 del document.header[i]
778 # We are looking for the natbib citation engine
779 i = find_token(document.header, "\\cite_engine natbib", 0)
782 document.header[i] = "\\cite_engine natbib_" + engine_type
785 def convert_cite_engine_type_default(document):
786 "Convert \\cite_engine_type to default for the basic citation engine."
787 i = find_token(document.header, "\\cite_engine basic", 0)
790 i = find_token(document.header, "\\cite_engine_type" , 0)
793 document.header[i] = "\\cite_engine_type default"
796 def revert_cite_engine_type_default(document):
797 """Revert \\cite_engine_type default.
799 Revert to numerical for the basic cite engine, otherwise to authoryear."""
800 engine_type = "authoryear"
801 i = find_token(document.header, "\\cite_engine_type default" , 0)
804 j = find_token(document.header, "\\cite_engine basic", 0)
806 engine_type = "numerical"
807 document.header[i] = "\\cite_engine_type " + engine_type
810 cancel_commands = ["cancel", "bcancel", "xcancel", "cancelto"]
811 # this is the same, as revert_use_cancel() except for the default
812 def revert_cancel(document):
813 "add cancel to the preamble if necessary"
814 revert_use_package(document, "cancel", cancel_commands, False)
817 def revert_verbatim(document, starred = False):
818 " Revert verbatim environments completely to TeX-code. "
822 layout_name = "Verbatim"
823 latex_name = "verbatim"
825 layout_name = "Verbatim*"
826 latex_name = "verbatim*"
828 subst_end = ['\\end_layout', '', '\\begin_layout Plain Layout',
830 '\\begin_layout Plain Layout', '', '',
832 'end{%s}' % (latex_name),
833 '\\end_layout', '', '\\end_inset',
834 '', '', '\\end_layout']
835 subst_begin = ['\\begin_layout Standard', '\\noindent',
836 '\\begin_inset ERT', 'status open', '',
837 '\\begin_layout Plain Layout', '', '', '\\backslash',
838 'begin{%s}' % (latex_name),
839 '\\end_layout', '', '\\begin_layout Plain Layout', '']
842 i = find_token(document.body, "\\begin_layout %s" % (layout_name), i)
845 j = find_end_of_layout(document.body, i)
847 document.warning("Malformed LyX document: Can't find end of %s layout" \
851 # delete all line breaks insets (there are no other insets)
854 n = find_token(document.body, "\\begin_inset Newline newline", l, j)
856 n = find_token(document.body, "\\begin_inset Newline linebreak", l, j)
859 m = find_end_of_inset(document.body, n)
860 del(document.body[m:m+1])
861 document.body[n:n+1] = ['\\end_layout', '', '\\begin_layout Plain Layout']
863 # we deleted a line, so the end of the inset moved forward.
864 # FIXME But we also added some lines, didn't we? I think this
867 # consecutive verbatim environments need to be connected
868 k = find_token(document.body, "\\begin_layout %s" % (layout_name), j)
869 if k == j + 2 and consecutive == False:
871 document.body[j:j+1] = ['\\end_layout', '', '\\begin_layout Plain Layout']
872 document.body[i:i+1] = subst_begin
874 if k == j + 2 and consecutive == True:
875 document.body[j:j+1] = ['\\end_layout', '', '\\begin_layout Plain Layout']
876 del(document.body[i:i+1])
878 if k != j + 2 and consecutive == True:
879 document.body[j:j+1] = subst_end
880 # the next paragraph must not be indented
881 # FIXME This seems to be causing problems, because of the
882 # hardcoded use of 19. We should figure out exactly where
883 # this needs to go by searching for the right tag.
884 document.body[j+19:j+19] = ['\\noindent']
885 del(document.body[i:i+1])
889 document.body[j:j+1] = subst_end
890 # the next paragraph must not be indented
891 # FIXME This seems to be causing problems, because of the
892 # hardcoded use of 19. We should figure out exactly where
893 # this needs to go by searching for the right tag.
894 document.body[j+19:j+19] = ['\\noindent']
895 document.body[i:i+1] = subst_begin
898 def revert_tipa(document):
899 " Revert native TIPA insets to mathed or ERT. "
902 i = find_token(document.body, "\\begin_inset IPA", i)
905 j = find_end_of_inset(document.body, i)
907 document.warning("Malformed LyX document: Can't find end of IPA inset")
911 n = find_token(document.body, "\\begin_layout", i, j)
913 document.warning("Malformed LyX document: IPA inset has no embedded layout")
916 m = find_end_of_layout(document.body, n)
918 document.warning("Malformed LyX document: Can't find end of embedded layout")
921 content = document.body[n+1:m]
922 p = find_token(document.body, "\\begin_layout", m, j)
923 if p != -1 or len(content) > 1:
925 content = document.body[i+1:j]
927 # IPA insets with multiple pars need to be wrapped by \begin{IPA}...\end{IPA}
928 document.body[i:j+1] = ['\\end_layout', '', '\\begin_layout Standard'] + put_cmd_in_ert("\\begin{IPA}") + ['\\end_layout'] + content + ['\\begin_layout Standard'] + put_cmd_in_ert("\\end{IPA}")
929 add_to_preamble(document, ["\\usepackage{tipa,tipx}"])
931 # single-par IPA insets can be reverted to mathed
932 document.body[i:j+1] = ["\\begin_inset Formula $\\text{\\textipa{" + content[0] + "}}$", "\\end_inset"]
936 def revert_cell_rotation(document):
937 "Revert cell rotations to TeX-code"
939 load_rotating = False
943 # first, let's find out if we need to do anything
944 i = find_token(document.body, '<cell ', i)
947 j = document.body[i].find('rotate="')
949 k = document.body[i].find('"', j + 8)
950 value = document.body[i][j + 8 : k]
952 rgx = re.compile(r' rotate="[^"]+?"')
953 # remove rotate option
954 document.body[i] = rgx.sub('', document.body[i])
956 rgx = re.compile(r' rotate="[^"]+?"')
957 document.body[i] = rgx.sub(' rotate="true"', document.body[i])
959 rgx = re.compile(r' rotate="[^"]+?"')
961 # remove rotate option
962 document.body[i] = rgx.sub('', document.body[i])
964 document.body[i + 5 : i + 5] = \
965 put_cmd_in_ert("\\end{turn}")
966 document.body[i + 4 : i + 4] = \
967 put_cmd_in_ert("\\begin{turn}{" + value + "}")
973 add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"])
976 def convert_cell_rotation(document):
977 'Convert cell rotation statements from "true" to "90"'
981 # first, let's find out if we need to do anything
982 i = find_token(document.body, '<cell ', i)
985 j = document.body[i].find('rotate="true"')
987 rgx = re.compile(r'rotate="[^"]+?"')
988 # convert "true" to "90"
989 document.body[i] = rgx.sub('rotate="90"', document.body[i])
994 def revert_table_rotation(document):
995 "Revert table rotations to TeX-code"
997 load_rotating = False
1001 # first, let's find out if we need to do anything
1002 i = find_token(document.body, '<features ', i)
1005 j = document.body[i].find('rotate="')
1007 end_table = find_token(document.body, '</lyxtabular>', j)
1008 k = document.body[i].find('"', j + 8)
1009 value = document.body[i][j + 8 : k]
1011 rgx = re.compile(r' rotate="[^"]+?"')
1012 # remove rotate option
1013 document.body[i] = rgx.sub('', document.body[i])
1015 rgx = re.compile(r'rotate="[^"]+?"')
1016 document.body[i] = rgx.sub('rotate="true"', document.body[i])
1018 rgx = re.compile(r' rotate="[^"]+?"')
1019 load_rotating = True
1020 # remove rotate option
1021 document.body[i] = rgx.sub('', document.body[i])
1023 document.body[end_table + 3 : end_table + 3] = \
1024 put_cmd_in_ert("\\end{turn}")
1025 document.body[i - 2 : i - 2] = \
1026 put_cmd_in_ert("\\begin{turn}{" + value + "}")
1032 add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"])
1035 def convert_table_rotation(document):
1036 'Convert table rotation statements from "true" to "90"'
1040 # first, let's find out if we need to do anything
1041 i = find_token(document.body, '<features ', i)
1044 j = document.body[i].find('rotate="true"')
1046 rgx = re.compile(r'rotate="[^"]+?"')
1047 # convert "true" to "90"
1048 document.body[i] = rgx.sub('rotate="90"', document.body[i])
1053 def convert_listoflistings(document):
1054 'Convert ERT \lstlistoflistings to TOC lstlistoflistings inset'
1055 # We can support roundtrip because the command is so simple
1058 i = find_token(document.body, "\\begin_inset ERT", i)
1061 j = find_end_of_inset(document.body, i)
1063 document.warning("Malformed LyX document: Can't find end of ERT inset")
1066 ert = get_ert(document.body, i)
1067 if ert == "\\lstlistoflistings{}":
1068 document.body[i:j] = ["\\begin_inset CommandInset toc", "LatexCommand lstlistoflistings", ""]
1074 def revert_listoflistings(document):
1075 'Convert TOC lstlistoflistings inset to ERT lstlistoflistings'
1078 i = find_token(document.body, "\\begin_inset CommandInset toc", i)
1081 if document.body[i+1] == "LatexCommand lstlistoflistings":
1082 j = find_end_of_inset(document.body, i)
1084 document.warning("Malformed LyX document: Can't find end of TOC inset")
1087 subst = put_cmd_in_ert("\\lstlistoflistings{}")
1088 document.body[i:j+1] = subst
1089 add_to_preamble(document, ["\\usepackage{listings}"])
1093 def convert_use_amssymb(document):
1094 "insert use_package amssymb"
1095 regexp = re.compile(r'(\\use_package\s+amsmath)')
1096 i = find_re(document.header, regexp, 0)
1098 document.warning("Malformed LyX document: Can't find \\use_package amsmath.")
1100 value = get_value(document.header, "\\use_package" , i).split()[1]
1103 useamsmath = int(value)
1105 document.warning("Invalid \\use_package amsmath: " + value + ". Assuming auto.")
1107 j = find_token(document.preamble, "\\usepackage{amssymb}", 0)
1109 document.header.insert(i + 1, "\\use_package amssymb %d" % useamsmath)
1111 document.header.insert(i + 1, "\\use_package amssymb 2")
1112 del document.preamble[j]
1115 def revert_use_amssymb(document):
1116 "remove use_package amssymb"
1117 regexp1 = re.compile(r'(\\use_package\s+amsmath)')
1118 regexp2 = re.compile(r'(\\use_package\s+amssymb)')
1119 i = find_re(document.header, regexp1, 0)
1120 j = find_re(document.header, regexp2, 0)
1121 value1 = "1" # default is auto
1122 value2 = "1" # default is auto
1124 value1 = get_value(document.header, "\\use_package" , i).split()[1]
1126 value2 = get_value(document.header, "\\use_package" , j).split()[1]
1127 del document.header[j]
1128 if value1 != value2 and value2 == "2": # on
1129 add_to_preamble(document, ["\\usepackage{amssymb}"])
1132 def convert_use_cancel(document):
1133 "insert use_package cancel"
1134 convert_use_package(document, "cancel", cancel_commands, True)
1137 def revert_use_cancel(document):
1138 "remove use_package cancel"
1139 revert_use_package(document, "cancel", cancel_commands, True)
1142 def revert_ancientgreek(document):
1143 "Set the document language for ancientgreek to greek"
1145 if document.language == "ancientgreek":
1146 document.language = "greek"
1147 i = find_token(document.header, "\\language", 0)
1149 document.header[i] = "\\language greek"
1152 j = find_token(document.body, "\\lang ancientgreek", j)
1156 document.body[j] = document.body[j].replace("\\lang ancientgreek", "\\lang greek")
1160 def revert_languages(document):
1161 "Set the document language for new supported languages to English"
1164 "coptic", "divehi", "hindi", "kurmanji", "lao", "marathi", "occitan", "sanskrit",
1165 "syriac", "tamil", "telugu", "urdu"
1167 for n in range(len(languages)):
1168 if document.language == languages[n]:
1169 document.language = "english"
1170 i = find_token(document.header, "\\language", 0)
1172 document.header[i] = "\\language english"
1174 while j < len(document.body):
1175 j = find_token(document.body, "\\lang " + languages[n], j)
1177 document.body[j] = document.body[j].replace("\\lang " + languages[n], "\\lang english")
1180 j = len(document.body)
1183 def convert_armenian(document):
1184 "Use polyglossia and thus non-TeX fonts for Armenian"
1186 if document.language == "armenian":
1187 i = find_token(document.header, "\\use_non_tex_fonts", 0)
1189 document.header[i] = "\\use_non_tex_fonts true"
1192 def revert_armenian(document):
1193 "Use ArmTeX and thus TeX fonts for Armenian"
1195 if document.language == "armenian":
1196 i = find_token(document.header, "\\use_non_tex_fonts", 0)
1198 document.header[i] = "\\use_non_tex_fonts false"
1201 def revert_libertine(document):
1202 " Revert native libertine font definition to LaTeX "
1204 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1205 i = find_token(document.header, "\\font_roman libertine", 0)
1208 j = find_token(document.header, "\\font_osf true", 0)
1211 preamble = "\\usepackage"
1213 document.header[j] = "\\font_osf false"
1216 preamble += "[lining]"
1217 preamble += "{libertine-type1}"
1218 add_to_preamble(document, [preamble])
1219 document.header[i] = "\\font_roman default"
1222 def revert_txtt(document):
1223 " Revert native txtt font definition to LaTeX "
1225 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1226 i = find_token(document.header, "\\font_typewriter txtt", 0)
1228 preamble = "\\renewcommand{\\ttdefault}{txtt}"
1229 add_to_preamble(document, [preamble])
1230 document.header[i] = "\\font_typewriter default"
1233 def revert_mathdesign(document):
1234 " Revert native mathdesign font definition to LaTeX "
1236 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1242 i = find_token(document.header, "\\font_roman", 0)
1245 val = get_value(document.header, "\\font_roman", i)
1246 if val in list(mathdesign_dict.keys()):
1247 preamble = "\\usepackage[%s" % mathdesign_dict[val]
1249 j = find_token(document.header, "\\font_osf true", 0)
1252 document.header[j] = "\\font_osf false"
1253 l = find_token(document.header, "\\font_sc true", 0)
1256 document.header[l] = "\\font_sc false"
1258 preamble += ",expert"
1259 preamble += "]{mathdesign}"
1260 add_to_preamble(document, [preamble])
1261 document.header[i] = "\\font_roman default"
1264 def revert_texgyre(document):
1265 " Revert native TeXGyre font definition to LaTeX "
1267 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1268 texgyre_fonts = ["tgadventor", "tgbonum", "tgchorus", "tgcursor", \
1269 "tgheros", "tgpagella", "tgschola", "tgtermes"]
1270 i = find_token(document.header, "\\font_roman", 0)
1272 val = get_value(document.header, "\\font_roman", i)
1273 if val in texgyre_fonts:
1274 preamble = "\\usepackage{%s}" % val
1275 add_to_preamble(document, [preamble])
1276 document.header[i] = "\\font_roman default"
1277 i = find_token(document.header, "\\font_sans", 0)
1279 val = get_value(document.header, "\\font_sans", i)
1280 if val in texgyre_fonts:
1281 preamble = "\\usepackage{%s}" % val
1282 add_to_preamble(document, [preamble])
1283 document.header[i] = "\\font_sans default"
1284 i = find_token(document.header, "\\font_typewriter", 0)
1286 val = get_value(document.header, "\\font_typewriter", i)
1287 if val in texgyre_fonts:
1288 preamble = "\\usepackage{%s}" % val
1289 add_to_preamble(document, [preamble])
1290 document.header[i] = "\\font_typewriter default"
1293 def revert_ipadeco(document):
1294 " Revert IPA decorations to ERT "
1297 i = find_token(document.body, "\\begin_inset IPADeco", i)
1300 end = find_end_of_inset(document.body, i)
1302 document.warning("Can't find end of inset at line " + str(i))
1305 line = document.body[i]
1306 rx = re.compile(r'\\begin_inset IPADeco (.*)$')
1308 decotype = m.group(1)
1309 if decotype != "toptiebar" and decotype != "bottomtiebar":
1310 document.warning("Invalid IPADeco type: " + decotype)
1313 blay = find_token(document.body, "\\begin_layout Plain Layout", i, end)
1315 document.warning("Can't find layout for inset at line " + str(i))
1318 bend = find_end_of_layout(document.body, blay)
1320 document.warning("Malformed LyX document: Could not find end of IPADeco inset's layout.")
1323 substi = ["\\begin_inset ERT", "status collapsed", "",
1324 "\\begin_layout Plain Layout", "", "", "\\backslash",
1325 decotype + "{", "\\end_layout", "", "\\end_inset"]
1326 substj = ["\\size default", "", "\\begin_inset ERT", "status collapsed", "",
1327 "\\begin_layout Plain Layout", "", "}", "\\end_layout", "", "\\end_inset"]
1328 # do the later one first so as not to mess up the numbering
1329 document.body[bend:end + 1] = substj
1330 document.body[i:blay + 1] = substi
1331 i = end + len(substi) + len(substj) - (end - bend) - (blay - i) - 2
1332 add_to_preamble(document, "\\usepackage{tipa}")
1335 def revert_ipachar(document):
1336 ' Revert \\IPAChar to ERT '
1339 while i < len(document.body):
1340 m = re.match(r'(.*)\\IPAChar \\(\w+\{\w+\})(.*)', document.body[i])
1344 ipachar = m.group(2)
1347 '\\begin_inset ERT',
1348 'status collapsed', '',
1349 '\\begin_layout Standard',
1350 '', '', '\\backslash',
1355 document.body[i: i+1] = subst
1360 add_to_preamble(document, "\\usepackage{tone}")
1363 def revert_minionpro(document):
1364 " Revert native MinionPro font definition to LaTeX "
1366 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1367 i = find_token(document.header, "\\font_roman minionpro", 0)
1370 j = find_token(document.header, "\\font_osf true", 0)
1373 preamble = "\\usepackage"
1375 document.header[j] = "\\font_osf false"
1378 preamble += "{MinionPro}"
1379 add_to_preamble(document, [preamble])
1380 document.header[i] = "\\font_roman default"
1383 def revert_mathfonts(document):
1384 " Revert native math font definitions to LaTeX "
1386 i = find_token(document.header, "\\font_math", 0)
1389 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1390 val = get_value(document.header, "\\font_math", i)
1391 if val == "eulervm":
1392 add_to_preamble(document, "\\usepackage{eulervm}")
1393 elif val == "default":
1395 "lmodern": "\\renewcommand{\\rmdefault}{lmr}",
1396 "minionpro": "\\usepackage[onlytext,lf]{MinionPro}",
1397 "minionpro-osf": "\\usepackage[onlytext]{MinionPro}",
1398 "palatino": "\\renewcommand{\\rmdefault}{ppl}",
1399 "palatino-osf": "\\renewcommand{\\rmdefault}{pplj}",
1400 "times": "\\renewcommand{\\rmdefault}{ptm}",
1401 "utopia": "\\renewcommand{\\rmdefault}{futs}",
1402 "utopia-osf": "\\renewcommand{\\rmdefault}{futj}",
1404 j = find_token(document.header, "\\font_roman", 0)
1406 rm = get_value(document.header, "\\font_roman", j)
1407 k = find_token(document.header, "\\font_osf true", 0)
1410 if rm in list(mathfont_dict.keys()):
1411 add_to_preamble(document, mathfont_dict[rm])
1412 document.header[j] = "\\font_roman default"
1414 document.header[k] = "\\font_osf false"
1415 del document.header[i]
1418 def revert_mdnomath(document):
1419 " Revert mathdesign and fourier without math "
1421 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1423 "md-charter": "mdbch",
1424 "md-utopia": "mdput",
1425 "md-garamond": "mdugm"
1427 i = find_token(document.header, "\\font_roman", 0)
1430 val = get_value(document.header, "\\font_roman", i)
1431 if val in list(mathdesign_dict.keys()):
1432 j = find_token(document.header, "\\font_math", 0)
1434 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1435 mval = get_value(document.header, "\\font_math", j)
1436 if mval == "default":
1437 document.header[i] = "\\font_roman default"
1438 add_to_preamble(document, "\\renewcommand{\\rmdefault}{%s}" % mathdesign_dict[val])
1440 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1443 def convert_mdnomath(document):
1444 " Change mathdesign font name "
1446 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1448 "mdbch": "md-charter",
1449 "mdput": "md-utopia",
1450 "mdugm": "md-garamond"
1452 i = find_token(document.header, "\\font_roman", 0)
1455 val = get_value(document.header, "\\font_roman", i)
1456 if val in list(mathdesign_dict.keys()):
1457 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1460 def revert_newtxmath(document):
1461 " Revert native newtxmath definitions to LaTeX "
1463 i = find_token(document.header, "\\font_math", 0)
1466 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1467 val = get_value(document.header, "\\font_math", i)
1469 "libertine-ntxm": "\\usepackage[libertine]{newtxmath}",
1470 "minion-ntxm": "\\usepackage[minion]{newtxmath}",
1471 "newtxmath": "\\usepackage{newtxmath}",
1473 if val in list(mathfont_dict.keys()):
1474 add_to_preamble(document, mathfont_dict[val])
1475 document.header[i] = "\\font_math auto"
1478 def revert_biolinum(document):
1479 " Revert native biolinum font definition to LaTeX "
1481 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1482 i = find_token(document.header, "\\font_sans biolinum", 0)
1485 j = find_token(document.header, "\\font_osf true", 0)
1488 preamble = "\\usepackage"
1491 preamble += "{biolinum-type1}"
1492 add_to_preamble(document, [preamble])
1493 document.header[i] = "\\font_sans default"
1496 def revert_uop(document):
1497 " Revert native URW Classico (Optima) font definition to LaTeX "
1499 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1500 i = find_token(document.header, "\\font_sans uop", 0)
1502 preamble = "\\renewcommand{\\sfdefault}{uop}"
1503 add_to_preamble(document, [preamble])
1504 document.header[i] = "\\font_sans default"
1507 def convert_latexargs(document):
1508 " Convert InsetArgument to new syntax "
1510 if find_token(document.body, "\\begin_inset Argument", 0) == -1:
1514 # A list of layouts (document classes) with only optional or no arguments.
1515 # These can be safely converted to the new syntax
1516 # (I took the liberty to add some of my personal layouts/modules here; JSP)
1517 safe_layouts = ["aa", "aapaper", "aastex", "achemso", "acmsiggraph", "AEA",
1518 "agu-dtd", "agums", "agutex", "amsart", "amsbook", "apa",
1519 "arab-article", "armenian-article", "article-beamer", "article",
1520 "beamer", "book", "broadway", "chess", "cl2emult", "ctex-article",
1521 "ctex-book", "ctex-report", "dinbrief", "docbook-book", "docbook-chapter",
1522 "docbook", "docbook-section", "doublecol-new", "dtk", "ectaart", "egs",
1523 "elsarticle", "elsart", "entcs", "europecv", "extarticle", "extbook",
1524 "extletter", "extreport", "foils", "frletter", "g-brief2", "g-brief",
1525 "heb-article", "heb-letter", "hollywood", "IEEEtran", "ijmpc", "ijmpd",
1526 "iopart", "isprs", "jarticle", "jasatex", "jbook", "jgrga", "jreport",
1527 "jsarticle", "jsbeamer", "jsbook", "jss", "kluwer", "latex8", "letter", "lettre",
1528 "literate-article", "literate-book", "literate-report", "llncs", "ltugboat",
1529 "memoir", "moderncv", "mwart", "mwbk", "mwrep", "paper", "powerdot",
1530 "recipebook", "report", "revtex4", "revtex", "scrartcl", "scrarticle-beamer",
1531 "scrbook", "scrlettr", "scrlttr2", "scrreprt", "seminar", "siamltex",
1532 "sigplanconf", "simplecv", "singlecol", "singlecol-new", "slides", "spie",
1533 "svglobal3", "svglobal", "svjog", "svmono", "svmult", "svprobth", "tarticle",
1534 "tbook", "treport", "tufte-book", "tufte-handout"]
1535 # A list of "safe" modules, same as above
1536 safe_modules = ["biblatex", "beameraddons", "beamer-resenumerate", "beamersession", "braille",
1537 "customHeadersFooters", "endnotes", "enumitem", "eqs-within-sections", "figs-within-sections",
1538 "fix-cm", "fixltx2e", "foottoend", "hanging", "jscharstyles", "knitr", "lilypond",
1539 "linguistics", "linguisticx", "logicalmkup", "minimalistic", "nomindex", "noweb",
1540 "pdfcomment", "sweave", "tabs-within-sections", "theorems-ams-bytype",
1541 "theorems-ams-extended-bytype", "theorems-ams-extended", "theorems-ams", "theorems-bytype",
1542 "theorems-chap-bytype", "theorems-chap", "theorems-named", "theorems-sec-bytype",
1543 "theorems-sec", "theorems-starred", "theorems-std", "todonotes"]
1544 # Modules we need to take care of
1545 caveat_modules = ["initials"]
1546 # information about the relevant styles in caveat_modules (number of opt and req args)
1547 # use this if we get more caveat_modules. For now, use hard coding (see below).
1548 # initials = [{'Layout' : 'Initial', 'opt' : 1, 'req' : 1}]
1550 # Is this a known safe layout?
1551 safe_layout = document.textclass in safe_layouts
1553 document.warning("Lyx2lyx knows nothing about textclass '%s'. "
1554 "Please check if short title insets have been converted correctly."
1555 % document.textclass)
1556 # Do we use unsafe or unknown modules
1557 mods = document.get_module_list()
1558 unknown_modules = False
1559 used_caveat_modules = list()
1561 if mod in safe_modules:
1563 if mod in caveat_modules:
1564 used_caveat_modules.append(mod)
1566 unknown_modules = True
1567 document.warning("Lyx2lyx knows nothing about module '%s'. "
1568 "Please check if short title insets have been converted correctly."
1573 i = find_token(document.body, "\\begin_inset Argument", i)
1577 if not safe_layout or unknown_modules:
1578 # We cannot do more here since we have no access to this layout.
1579 # InsetArgument itself will do the real work
1580 # (see InsetArgument::updateBuffer())
1581 document.body[i] = "\\begin_inset Argument 999"
1585 # Find containing paragraph layout
1586 parent = get_containing_layout(document.body, i)
1588 document.warning("Malformed LyX document: Can't find parent paragraph layout")
1595 if len(used_caveat_modules) > 0:
1596 # We know for now that this must be the initials module with the Initial layout
1597 # If we get more such modules, we need some automating.
1598 if parent[0] == "Initial":
1599 # Layout has 1 opt and 1 req arg.
1600 # Count the actual arguments
1602 for p in range(parbeg, parend):
1603 if document.body[p] == "\\begin_inset Argument":
1608 # Collect all arguments in this paragraph
1610 for p in range(parbeg, parend):
1611 if document.body[p] == "\\begin_inset Argument":
1613 if allowed_opts != -1:
1614 # We have less arguments than opt + required.
1615 # required must take precedence.
1616 if argnr > allowed_opts and argnr < first_req:
1618 document.body[p] = "\\begin_inset Argument %d" % argnr
1622 def revert_latexargs(document):
1623 " Revert InsetArgument to old syntax "
1626 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
1629 # Search for Argument insets
1630 i = find_token(document.body, "\\begin_inset Argument", i)
1633 m = rx.match(document.body[i])
1635 # No ID: inset already reverted
1638 # Find containing paragraph layout
1639 parent = get_containing_layout(document.body, i)
1641 document.warning("Malformed LyX document: Can't find parent paragraph layout")
1646 # Do not set realparbeg to parent[3], since this does not work if we
1647 # have another inset (e.g. label or index) before the first argument
1648 # inset (this is the case in the user guide of LyX 2.0.8)
1650 # Collect all arguments in this paragraph
1652 for p in range(parbeg, parend):
1653 m = rx.match(document.body[p])
1656 # This is the first argument inset
1658 val = int(m.group(1))
1659 j = find_end_of_inset(document.body, p)
1660 # Revert to old syntax
1661 document.body[p] = "\\begin_inset Argument"
1663 document.warning("Malformed LyX document: Can't find end of Argument inset")
1666 args[val] = document.body[p : j + 1]
1668 realparend = realparend - len(document.body[p : j + 1])
1669 # Remove arg inset at this position
1670 del document.body[p : j + 1]
1674 # No argument inset found
1675 realparbeg = parent[3]
1676 # Now sort the arg insets
1678 for f in sorted(args):
1681 # Insert the sorted arg insets at paragraph begin
1682 document.body[realparbeg : realparbeg] = subst
1684 i = realparbeg + 1 + len(subst)
1687 def revert_IEEEtran(document):
1689 Reverts InsetArgument of
1692 Biography without photo
1695 if document.textclass == "IEEEtran":
1702 i = find_token(document.body, "\\begin_layout Page headings", i)
1704 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1707 i2 = find_token(document.body, "\\begin_inset Flex Paragraph Start", i2)
1709 revert_Argument_to_TeX_brace(document, i2, 0, 1, 1, False, False)
1712 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1714 revert_Argument_to_TeX_brace(document, j, 0, 1, 1, True, False)
1717 k = find_token(document.body, "\\begin_layout Biography", k)
1718 kA = find_token(document.body, "\\begin_layout Biography without photo", k)
1719 if k == kA and k != -1:
1723 # start with the second argument, therefore 2
1724 revert_Argument_to_TeX_brace(document, k, 0, 2, 2, True, False)
1726 if i == -1 and i2 == -1 and j == -1 and k == -1:
1730 def revert_IEEEtran_2(document):
1732 Reverts Flex Paragraph Start to TeX-code
1734 if document.textclass == "IEEEtran":
1737 begin = find_token(document.body, "\\begin_inset Flex Paragraph Start", begin)
1740 end1 = find_end_of_inset(document.body, begin)
1741 document.body[end1 - 2 : end1 + 1] = put_cmd_in_ert("}")
1742 document.body[begin : begin + 4] = put_cmd_in_ert("\\IEEEPARstart{")
1746 def convert_IEEEtran(document):
1751 Biography without photo
1754 if document.textclass == "IEEEtran":
1760 i = find_token(document.body, "\\begin_layout Page headings", i)
1762 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1765 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1767 convert_TeX_brace_to_Argument(document, j, 1, 1, False, True, False)
1770 # assure that we don't handle Biography Biography without photo
1771 k = find_token(document.body, "\\begin_layout Biography", k)
1772 kA = find_token(document.body, "\\begin_layout Biography without photo", k - 1)
1773 if k == kA and k != -1:
1777 # the argument we want to convert is the second one
1778 convert_TeX_brace_to_Argument(document, k, 2, 2, False, True, False)
1780 if i == -1 and j == -1 and k == -1:
1784 def revert_AASTeX(document):
1785 " Reverts InsetArgument of Altaffilation to TeX-code "
1786 if document.textclass == "aastex":
1789 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1792 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1796 def convert_AASTeX(document):
1797 " Converts ERT of Altaffilation to InsetArgument "
1798 if document.textclass == "aastex":
1801 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1804 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1808 def revert_AGUTeX(document):
1809 " Reverts InsetArgument of Author affiliation to TeX-code "
1810 if document.textclass == "agutex":
1813 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1816 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1820 def convert_AGUTeX(document):
1821 " Converts ERT of Author affiliation to InsetArgument "
1822 if document.textclass == "agutex":
1825 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1828 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1832 def revert_IJMP(document):
1833 " Reverts InsetArgument of MarkBoth to TeX-code "
1834 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1837 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1840 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1844 def convert_IJMP(document):
1845 " Converts ERT of MarkBoth to InsetArgument "
1846 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1849 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1852 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1856 def revert_SIGPLAN(document):
1857 " Reverts InsetArguments of SIGPLAN to TeX-code "
1858 if document.textclass == "sigplanconf":
1863 i = find_token(document.body, "\\begin_layout Conference", i)
1865 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1868 j = find_token(document.body, "\\begin_layout Author", j)
1870 revert_Argument_to_TeX_brace(document, j, 0, 1, 2, False, False)
1872 if i == -1 and j == -1:
1876 def convert_SIGPLAN(document):
1877 " Converts ERT of SIGPLAN to InsetArgument "
1878 if document.textclass == "sigplanconf":
1883 i = find_token(document.body, "\\begin_layout Conference", i)
1885 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1888 j = find_token(document.body, "\\begin_layout Author", j)
1890 convert_TeX_brace_to_Argument(document, j, 1, 2, False, False, False)
1892 if i == -1 and j == -1:
1896 def revert_SIGGRAPH(document):
1897 " Reverts InsetArgument of Flex CRcat to TeX-code "
1898 if document.textclass == "acmsiggraph":
1901 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1904 revert_Argument_to_TeX_brace(document, i, 0, 1, 3, False, False)
1908 def convert_SIGGRAPH(document):
1909 " Converts ERT of Flex CRcat to InsetArgument "
1910 if document.textclass == "acmsiggraph":
1913 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1916 convert_TeX_brace_to_Argument(document, i, 1, 3, True, False, False)
1920 def revert_EuropeCV(document):
1921 " Reverts InsetArguments of europeCV to TeX-code "
1922 if document.textclass == "europecv":
1929 i = find_token(document.body, "\\begin_layout Item", i)
1931 revert_Argument_to_TeX_brace(document, i, 0, 2, 2, False, False)
1934 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1936 revert_Argument_to_TeX_brace(document, j, 0, 2, 2, False, False)
1939 k = find_token(document.body, "\\begin_layout Language", k)
1941 revert_Argument_to_TeX_brace(document, k, 0, 2, 6, False, False)
1944 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1946 revert_Argument_to_TeX_brace(document, m, 0, 2, 6, False, False)
1948 if i == -1 and j == -1 and k == -1 and m == -1:
1952 def convert_EuropeCV(document):
1953 " Converts ERT of europeCV to InsetArgument "
1954 if document.textclass == "europecv":
1961 i = find_token(document.body, "\\begin_layout Item", i)
1963 convert_TeX_brace_to_Argument(document, i, 2, 2, False, False, False)
1966 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1968 convert_TeX_brace_to_Argument(document, j, 2, 2, False, False, False)
1971 k = find_token(document.body, "\\begin_layout Language", k)
1973 convert_TeX_brace_to_Argument(document, k, 2, 6, False, False, False)
1976 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1978 convert_TeX_brace_to_Argument(document, m, 2, 6, False, False, False)
1980 if i == -1 and j == -1 and k == -1 and m == -1:
1984 def revert_ModernCV(document):
1985 " Reverts InsetArguments of modernCV to TeX-code "
1986 if document.textclass == "moderncv":
1994 j = find_token(document.body, "\\begin_layout Entry", j)
1996 revert_Argument_to_TeX_brace(document, j, 0, 1, 5, False, False)
1999 k = find_token(document.body, "\\begin_layout Item", k)
2001 revert_Argument_to_TeX_brace(document, k, 0, 1, 1, False, False)
2004 m = find_token(document.body, "\\begin_layout ItemWithComment", m)
2006 revert_Argument_to_TeX_brace(document, m, 0, 1, 2, False, False)
2007 document.body[m] = document.body[m].replace("\\begin_layout ItemWithComment", "\\begin_layout Language")
2010 o = find_token(document.body, "\\begin_layout DoubleItem", o)
2012 revert_Argument_to_TeX_brace(document, o, 0, 1, 3, False, False)
2013 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout Computer")
2016 p = find_token(document.body, "\\begin_layout Social", p)
2018 revert_Argument_to_TeX_brace(document, p, 0, 1, 1, False, True)
2020 if j == -1 and k == -1 and m == -1 and o == -1 and p == -1:
2024 def revert_ModernCV_2(document):
2025 " Reverts the Flex:Column inset of modernCV to TeX-code "
2026 if document.textclass == "moderncv":
2030 flex = find_token(document.body, "\\begin_inset Flex Column", flex)
2033 flexEnd = find_end_of_inset(document.body, flex)
2034 wasOpt = revert_Argument_to_TeX_brace(document, flex, flexEnd, 1, 1, False, True)
2035 revert_Argument_to_TeX_brace(document, flex, 0, 2, 2, False, False)
2036 flexEnd = find_end_of_inset(document.body, flex)
2038 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn")
2040 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn{")
2041 document.body[flexEnd + 4 : flexEnd + 7] = put_cmd_in_ert("}")
2045 def revert_ModernCV_3(document):
2046 " Reverts the Column style of modernCV to TeX-code "
2047 if document.textclass == "moderncv":
2048 # revert the layouts
2049 revert_ModernCV(document)
2051 # get the position of the end of the last column inset
2052 LastFlexEnd = revert_ModernCV_2(document)
2054 p = find_token(document.body, "\\begin_layout Columns", p)
2057 pEnd = find_end_of_layout(document.body, p)
2058 document.body[p] = document.body[p].replace("\\begin_layout Columns", "\\begin_layout Standard")
2059 if LastFlexEnd != -1:
2060 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\begin{cvcolumns}")
2061 document.body[LastFlexEnd + 24 : LastFlexEnd + 24] = put_cmd_in_ert("\\end{cvcolumns}")
2065 def revert_ModernCV_4(document):
2066 " Reverts the style Social to TeX-code "
2067 if document.textclass == "moderncv":
2068 # revert the layouts
2069 revert_ModernCV(document)
2072 p = find_token(document.body, "\\begin_layout Social", p)
2075 pEnd = find_end_of_layout(document.body, p)
2076 document.body[p] = document.body[p].replace("\\begin_layout Social", "\\begin_layout Standard")
2077 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\social")
2078 hasOpt = find_token(document.body, "[", p + 9)
2080 document.body[p + 30 : p + 30] = put_cmd_in_ert("{")
2081 document.body[p + 41 : p + 41] = put_cmd_in_ert("}")
2083 document.body[p + 11 : p + 11] = put_cmd_in_ert("{")
2084 document.body[p + 21 : p + 21] = put_cmd_in_ert("}")
2088 def convert_ModernCV(document):
2089 " Converts ERT of modernCV to InsetArgument "
2090 if document.textclass == "moderncv":
2098 i = find_token(document.body, "\\begin_layout DoubleItem", i)
2100 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
2101 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout DoubleListItem")
2104 j = find_token(document.body, "\\begin_layout Entry", j)
2106 convert_TeX_brace_to_Argument(document, j, 1, 5, False, False, False)
2109 k = find_token(document.body, "\\begin_layout Item", k)
2111 convert_TeX_brace_to_Argument(document, k, 1, 1, False, False, False)
2114 m = find_token(document.body, "\\begin_layout Language", m)
2116 convert_TeX_brace_to_Argument(document, m, 1, 2, False, False, False)
2118 if i == -1 and j == -1 and k == -1 and m == -1:
2122 def revert_Initials(document):
2123 " Reverts InsetArgument of Initial to TeX-code "
2126 i = find_token(document.body, "\\begin_layout Initial", i)
2129 # first arg (optional) and second arg (first mandatory) are supported in LyX 2.0.x
2130 revert_Argument_to_TeX_brace(document, i, 0, 3, 3, False, False)
2134 def convert_Initials(document):
2135 " Converts ERT of Initial to InsetArgument "
2138 i = find_token(document.body, "\\begin_layout Initial", i)
2141 convert_TeX_brace_to_Argument(document, i, 3, 3, False, False, False)
2145 def revert_literate(document):
2146 " Revert Literate document to old format "
2147 if del_token(document.header, "noweb", 0):
2148 document.textclass = "literate-" + document.textclass
2151 i = find_token(document.body, "\\begin_layout Chunk", i)
2154 document.body[i] = "\\begin_layout Scrap"
2158 def convert_literate(document):
2159 " Convert Literate document to new format"
2160 i = find_token(document.header, "\\textclass", 0)
2161 if (i != -1) and "literate-" in document.header[i]:
2162 document.textclass = document.header[i].replace("\\textclass literate-", "")
2163 j = find_token(document.header, "\\begin_modules", 0)
2165 document.header.insert(j + 1, "noweb")
2167 document.header.insert(i + 1, "\\end_modules")
2168 document.header.insert(i + 1, "noweb")
2169 document.header.insert(i + 1, "\\begin_modules")
2172 i = find_token(document.body, "\\begin_layout Scrap", i)
2175 document.body[i] = "\\begin_layout Chunk"
2179 def revert_itemargs(document):
2180 " Reverts \\item arguments to TeX-code "
2183 i = find_token(document.body, "\\begin_inset Argument item:", i)
2186 j = find_end_of_inset(document.body, i)
2187 # Find containing paragraph layout
2188 parent = get_containing_layout(document.body, i)
2190 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2194 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2195 endPlain = find_end_of_layout(document.body, beginPlain)
2196 content = document.body[beginPlain + 1 : endPlain]
2197 del document.body[i:j+1]
2198 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2199 document.body[parbeg : parbeg] = subst
2203 def revert_garamondx_newtxmath(document):
2204 " Revert native garamond newtxmath definition to LaTeX "
2206 i = find_token(document.header, "\\font_math", 0)
2209 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2210 val = get_value(document.header, "\\font_math", i)
2211 if val == "garamondx-ntxm":
2212 add_to_preamble(document, "\\usepackage[garamondx]{newtxmath}")
2213 document.header[i] = "\\font_math auto"
2216 def revert_garamondx(document):
2217 " Revert native garamond font definition to LaTeX "
2219 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2220 i = find_token(document.header, "\\font_roman garamondx", 0)
2223 j = find_token(document.header, "\\font_osf true", 0)
2226 preamble = "\\usepackage"
2228 preamble += "[osfI]"
2229 preamble += "{garamondx}"
2230 add_to_preamble(document, [preamble])
2231 document.header[i] = "\\font_roman default"
2234 def convert_beamerargs(document):
2235 " Converts beamer arguments to new layout "
2237 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2238 if document.textclass not in beamer_classes:
2241 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2242 list_layouts = ["Itemize", "Enumerate", "Description"]
2243 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
2247 i = find_token(document.body, "\\begin_inset Argument", i)
2250 # Find containing paragraph layout
2251 parent = get_containing_layout(document.body, i)
2253 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2258 layoutname = parent[0]
2259 for p in range(parbeg, parend):
2260 if layoutname in shifted_layouts:
2261 m = rx.match(document.body[p])
2263 argnr = int(m.group(1))
2265 document.body[p] = "\\begin_inset Argument %d" % argnr
2266 if layoutname == "AgainFrame":
2267 m = rx.match(document.body[p])
2269 document.body[p] = "\\begin_inset Argument 3"
2270 if document.body[p + 4] == "\\begin_inset ERT":
2271 if document.body[p + 9].startswith("<"):
2272 # This is an overlay specification
2274 document.body[p + 9] = document.body[p + 9][1:]
2275 if document.body[p + 9].endswith(">"):
2277 document.body[p + 9] = document.body[p + 9][:-1]
2279 document.body[p] = "\\begin_inset Argument 2"
2280 if layoutname in list_layouts:
2281 m = rx.match(document.body[p])
2283 if m.group(1) == "1":
2284 if document.body[p + 4] == "\\begin_inset ERT":
2285 if document.body[p + 9].startswith("<"):
2286 # This is an overlay specification
2288 document.body[p + 9] = document.body[p + 9][1:]
2289 if document.body[p + 9].endswith(">"):
2291 document.body[p + 9] = document.body[p + 9][:-1]
2292 elif document.body[p + 4].startswith("<"):
2293 # This is an overlay specification (without ERT)
2295 document.body[p + 4] = document.body[p + 4][1:]
2296 if document.body[p + 4].endswith(">"):
2298 document.body[p + 4] = document.body[p + 4][:-1]
2299 elif layoutname != "Itemize":
2301 document.body[p] = "\\begin_inset Argument 2"
2306 # Helper function for the frame conversion routines
2308 # FIXME: This method currently requires the arguments to be either
2309 # * In one (whole) ERT each: <ERT>[<arg1>]</ERT><ERT><arg2></ERT><ERT>[arg3]</ERT>
2310 # * Altogether in one whole ERT: <ERT>[<arg1>]<arg2>[arg3]</ERT>
2311 # If individual arguments mix ERT and non-ERT or are splitted
2312 # over several ERTs, the parsing fails.
2313 def convert_beamerframeargs(document, i, parbeg):
2316 if document.body[parbeg] != "\\begin_inset ERT":
2318 ertend = find_end_of_inset(document.body, parbeg)
2320 document.warning("Malformed LyX document: missing ERT \\end_inset")
2322 ertcont = parbeg + 5
2323 if document.body[ertcont].startswith("[<"):
2324 # This is a default overlay specification
2326 document.body[ertcont] = document.body[ertcont][2:]
2327 if document.body[ertcont].endswith(">]"):
2329 document.body[ertcont] = document.body[ertcont][:-2]
2330 elif document.body[ertcont].endswith("]"):
2332 tok = document.body[ertcont].find('>][')
2334 subst = [document.body[ertcont][:tok],
2335 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2336 'status collapsed', '', '\\begin_layout Plain Layout',
2337 document.body[ertcont][tok + 3:-1]]
2338 document.body[ertcont : ertcont + 1] = subst
2340 # Convert to ArgInset
2341 document.body[parbeg] = "\\begin_inset Argument 2"
2342 elif document.body[ertcont].startswith("<"):
2343 # This is an overlay specification
2345 document.body[ertcont] = document.body[ertcont][1:]
2346 if document.body[ertcont].endswith(">"):
2348 document.body[ertcont] = document.body[ertcont][:-1]
2349 # Convert to ArgInset
2350 document.body[parbeg] = "\\begin_inset Argument 1"
2351 elif document.body[ertcont].endswith(">]"):
2353 tok = document.body[ertcont].find('>[<')
2355 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2356 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2357 'status collapsed', '', '\\begin_layout Plain Layout',
2358 document.body[ertcont][tok + 3:-2]]
2359 # Convert to ArgInset
2360 document.body[parbeg] = "\\begin_inset Argument 1"
2362 elif document.body[ertcont].endswith("]"):
2364 tok = document.body[ertcont].find('>[<')
2367 tokk = document.body[ertcont].find('>][')
2369 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2370 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2371 'status collapsed', '', '\\begin_layout Plain Layout',
2372 document.body[ertcont][tok + 3:tokk],
2373 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2374 'status collapsed', '', '\\begin_layout Plain Layout',
2375 document.body[ertcont][tokk + 3:-1]]
2378 tokk = document.body[ertcont].find('>[')
2380 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tokk],
2381 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2382 'status collapsed', '', '\\begin_layout Plain Layout',
2383 document.body[ertcont][tokk + 2:-1]]
2385 # Convert to ArgInset
2386 document.body[parbeg] = "\\begin_inset Argument 1"
2387 elif document.body[ertcont].startswith("["):
2388 # This is an ERT option
2390 document.body[ertcont] = document.body[ertcont][1:]
2391 if document.body[ertcont].endswith("]"):
2393 document.body[ertcont] = document.body[ertcont][:-1]
2394 # Convert to ArgInset
2395 document.body[parbeg] = "\\begin_inset Argument 3"
2401 def convert_againframe_args(document):
2402 " Converts beamer AgainFrame to new layout "
2404 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2405 if document.textclass not in beamer_classes:
2410 i = find_token(document.body, "\\begin_layout AgainFrame", i)
2413 parent = get_containing_layout(document.body, i)
2415 document.warning("Wrong parent layout!")
2419 # Convert ERT arguments
2420 # FIXME: See restrictions in convert_beamerframeargs method
2421 ertend = convert_beamerframeargs(document, i, parbeg)
2427 def convert_corollary_args(document):
2428 " Converts beamer corrolary-style ERT arguments native InsetArgs "
2430 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2431 if document.textclass not in beamer_classes:
2434 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2435 for lay in corollary_layouts:
2438 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2441 parent = get_containing_layout(document.body, i)
2443 document.warning("Wrong parent layout!")
2447 if document.body[parbeg] == "\\begin_inset ERT":
2448 ertcontfirstline = parbeg + 5
2449 # Find the last ERT in this paragraph (which might also be the first)
2450 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
2451 if lastertbeg == -1:
2452 document.warning("Last ERT not found!")
2454 lastertend = find_end_of_inset(document.body, lastertbeg)
2455 if lastertend == -1:
2456 document.warning("End of last ERT not found!")
2458 ertcontlastline = lastertend - 3
2459 if document.body[ertcontfirstline].startswith("<"):
2460 # This is an overlay specification
2462 document.body[ertcontfirstline] = document.body[ertcontfirstline][1:]
2463 if document.body[ertcontlastline].endswith(">"):
2465 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
2466 if ertcontfirstline < ertcontlastline:
2467 # Multiline ERT. Might contain TeX code. Embrace in ERT.
2468 document.body[ertcontlastline : ertcontlastline + 1] = [
2469 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
2470 document.body[ertcontfirstline : ertcontfirstline + 1] = [
2471 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
2472 'status collapsed', '', '\\begin_layout Plain Layout',
2473 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
2474 document.body[ertcontfirstline]]
2476 # Convert to ArgInset
2477 document.body[parbeg] = "\\begin_inset Argument 1"
2478 elif document.body[ertcontlastline].endswith("]"):
2480 tok = document.body[ertcontfirstline].find('>[')
2482 if ertcontfirstline < ertcontlastline:
2483 # Multiline ERT. Might contain TeX code. Embrace in ERT.
2484 document.body[ertcontlastline : ertcontlastline + 1] = [
2485 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
2486 document.body[ertcontfirstline : ertcontfirstline + 1] = [document.body[ertcontfirstline][:tok],
2487 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2488 'status collapsed', '', '\\begin_layout Plain Layout',
2489 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
2490 document.body[ertcontfirstline][tok + 2:-1]]
2492 document.body[ertcontfirstline : ertcontfirstline + 1] = [document.body[ertcontfirstline][:tok],
2493 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2494 'status collapsed', '', '\\begin_layout Plain Layout',
2495 document.body[ertcontfirstline][tok + 2:-1]]
2496 # Convert to ArgInset
2497 document.body[parbeg] = "\\begin_inset Argument 1"
2500 elif document.body[ertcontlastline].startswith("["):
2501 if document.body[ertcontlastline].endswith("]"):
2502 # This is an ERT option
2504 document.body[ertcontlastline] = document.body[ertcontlastline][1:]
2506 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
2507 # Convert to ArgInset
2508 document.body[parbeg] = "\\begin_inset Argument 2"
2510 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, True)
2517 def convert_quote_args(document):
2518 " Converts beamer quote style ERT args to native InsetArgs "
2520 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2521 if document.textclass not in beamer_classes:
2524 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2525 for lay in quote_layouts:
2528 i = find_token(document.body, "\\begin_layout " + lay, i)
2531 parent = get_containing_layout(document.body, i)
2533 document.warning("Wrong parent layout!")
2537 if document.body[parbeg] == "\\begin_inset ERT":
2538 if document.body[i + 6].startswith("<"):
2539 # This is an overlay specification
2541 document.body[i + 6] = document.body[i + 6][1:]
2542 if document.body[i + 6].endswith(">"):
2544 document.body[i + 6] = document.body[i + 6][:-1]
2545 # Convert to ArgInset
2546 document.body[i + 1] = "\\begin_inset Argument 1"
2550 def cleanup_beamerargs(document):
2551 " Clean up empty ERTs (conversion artefacts) "
2553 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2554 if document.textclass not in beamer_classes:
2559 i = find_token(document.body, "\\begin_inset Argument", i)
2562 j = find_end_of_inset(document.body, i)
2564 document.warning("Malformed LyX document: Can't find end of Argument inset")
2568 ertbeg = find_token(document.body, "\\begin_inset ERT", i, j)
2571 ertend = find_end_of_inset(document.body, ertbeg)
2573 document.warning("Malformed LyX document: Can't find end of ERT inset")
2575 stripped = [line for line in document.body[ertbeg : ertend + 1] if line.strip()]
2576 if len(stripped) == 5:
2577 # This is an empty ERT
2578 offset = len(document.body[ertbeg : ertend + 1])
2579 del document.body[ertbeg : ertend + 1]
2586 def revert_beamerargs(document):
2587 " Reverts beamer arguments to old layout "
2589 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2590 if document.textclass not in beamer_classes:
2594 list_layouts = ["Itemize", "Enumerate", "Description"]
2595 headings = ["Part", "Section", "Section*", "Subsection", "Subsection*",
2596 "Subsubsection", "Subsubsection*", "FrameSubtitle", "NoteItem"]
2597 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2598 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2599 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2602 i = find_token(document.body, "\\begin_inset Argument", i)
2605 # Find containing paragraph layout
2606 parent = get_containing_layout(document.body, i)
2608 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2613 realparbeg = parent[3]
2614 layoutname = parent[0]
2616 for p in range(parbeg, parend):
2620 if layoutname in headings:
2621 m = rx.match(document.body[p])
2625 # Find containing paragraph layout
2626 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2627 endPlain = find_end_of_layout(document.body, beginPlain)
2628 endInset = find_end_of_inset(document.body, p)
2629 argcontent = document.body[beginPlain + 1 : endPlain]
2631 realparend = realparend - len(document.body[p : endInset + 1])
2633 del document.body[p : endInset + 1]
2634 if layoutname == "FrameSubtitle":
2635 pre = put_cmd_in_ert("\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2636 elif layoutname == "NoteItem":
2637 pre = put_cmd_in_ert("\\note<") + argcontent + put_cmd_in_ert(">[item]")
2638 elif layoutname.endswith('*'):
2639 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower()[:-1] + "<") + argcontent + put_cmd_in_ert(">*")
2641 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2642 secarg = find_token(document.body, "\\begin_inset Argument 2", parbeg, parend)
2644 # Find containing paragraph layout
2645 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", secarg)
2646 endPlain = find_end_of_layout(document.body, beginPlain)
2647 endInset = find_end_of_inset(document.body, secarg)
2648 argcontent = document.body[beginPlain + 1 : endPlain]
2650 realparend = realparend - len(document.body[secarg : endInset + 1])
2651 del document.body[secarg : endInset + 1]
2652 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2653 pre += put_cmd_in_ert("{")
2654 document.body[parbeg] = "\\begin_layout Standard"
2655 document.body[realparbeg : realparbeg] = pre
2656 pe = find_end_of_layout(document.body, parbeg)
2657 post = put_cmd_in_ert("}")
2658 document.body[pe : pe] = post
2659 realparend += len(pre) + len(post)
2660 if layoutname == "AgainFrame":
2661 m = rx.match(document.body[p])
2665 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2666 endPlain = find_end_of_layout(document.body, beginPlain)
2667 endInset = find_end_of_inset(document.body, p)
2668 content = document.body[beginPlain + 1 : endPlain]
2670 realparend = realparend - len(document.body[p : endInset + 1])
2672 del document.body[p : endInset + 1]
2673 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2674 document.body[realparbeg : realparbeg] = subst
2675 if layoutname == "Overprint":
2676 m = rx.match(document.body[p])
2680 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2681 endPlain = find_end_of_layout(document.body, beginPlain)
2682 endInset = find_end_of_inset(document.body, p)
2683 content = document.body[beginPlain + 1 : endPlain]
2685 realparend = realparend - len(document.body[p : endInset + 1])
2687 del document.body[p : endInset + 1]
2688 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2689 document.body[realparbeg : realparbeg] = subst
2690 if layoutname == "OverlayArea":
2691 m = rx.match(document.body[p])
2695 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2696 endPlain = find_end_of_layout(document.body, beginPlain)
2697 endInset = find_end_of_inset(document.body, p)
2698 content = document.body[beginPlain + 1 : endPlain]
2700 realparend = realparend - len(document.body[p : endInset + 1])
2702 del document.body[p : endInset + 1]
2703 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2704 document.body[realparbeg : realparbeg] = subst
2705 if layoutname in list_layouts:
2706 m = rx.match(document.body[p])
2710 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2711 endPlain = find_end_of_layout(document.body, beginPlain)
2712 endInset = find_end_of_inset(document.body, p)
2713 content = document.body[beginPlain + 1 : endPlain]
2714 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2715 realparend = realparend + len(subst) - len(content)
2716 document.body[beginPlain + 1 : endPlain] = subst
2717 elif argnr == "item:1":
2718 j = find_end_of_inset(document.body, i)
2719 # Find containing paragraph layout
2720 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2721 endPlain = find_end_of_layout(document.body, beginPlain)
2722 content = document.body[beginPlain + 1 : endPlain]
2723 del document.body[i:j+1]
2724 if layoutname == "Description":
2725 # Description only has one (overlay) item arg
2726 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2727 # This must be put after the first space (begin of decription body
2728 # in LyX's arkward description list syntax)
2729 # Try to find that place ...
2730 rxx = re.compile(r'^([^\\ ]+ )(.*)$')
2731 for q in range(parbeg, parend):
2732 m = rxx.match(document.body[q])
2734 # We found it. Now insert the ERT argument just there:
2735 document.body[q : q] = [m.group(1), ''] + subst + ['', m.group(2)]
2738 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2739 document.body[realparbeg : realparbeg] = subst
2740 elif argnr == "item:2":
2741 j = find_end_of_inset(document.body, i)
2742 # Find containing paragraph layout
2743 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2744 endPlain = find_end_of_layout(document.body, beginPlain)
2745 content = document.body[beginPlain + 1 : endPlain]
2746 del document.body[i:j+1]
2747 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2748 document.body[realparbeg : realparbeg] = subst
2749 if layoutname in quote_layouts:
2750 m = rx.match(document.body[p])
2754 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2755 endPlain = find_end_of_layout(document.body, beginPlain)
2756 endInset = find_end_of_inset(document.body, p)
2757 content = document.body[beginPlain + 1 : endPlain]
2759 realparend = realparend - len(document.body[p : endInset + 1])
2761 del document.body[p : endInset + 1]
2762 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2763 document.body[realparbeg : realparbeg] = subst
2764 if layoutname in corollary_layouts:
2765 m = rx.match(document.body[p])
2769 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2770 endPlain = find_end_of_layout(document.body, beginPlain)
2771 endInset = find_end_of_inset(document.body, p)
2772 content = document.body[beginPlain + 1 : endPlain]
2774 realparend = realparend - len(document.body[p : endInset + 1])
2776 del document.body[p : endInset + 1]
2777 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2778 document.body[realparbeg : realparbeg] = subst
2783 def revert_beamerargs2(document):
2784 " Reverts beamer arguments to old layout, step 2 "
2786 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2787 if document.textclass not in beamer_classes:
2791 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2792 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2793 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2796 i = find_token(document.body, "\\begin_inset Argument", i)
2799 # Find containing paragraph layout
2800 parent = get_containing_layout(document.body, i)
2802 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2807 realparbeg = parent[3]
2808 layoutname = parent[0]
2810 for p in range(parbeg, parend):
2814 if layoutname in shifted_layouts:
2815 m = rx.match(document.body[p])
2819 document.body[p] = "\\begin_inset Argument 1"
2820 if layoutname in corollary_layouts:
2821 m = rx.match(document.body[p])
2825 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2826 endPlain = find_end_of_layout(document.body, beginPlain)
2827 endInset = find_end_of_inset(document.body, p)
2828 content = document.body[beginPlain + 1 : endPlain]
2830 realparend = realparend - len(document.body[p : endInset + 1])
2832 del document.body[p : endInset + 1]
2833 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2834 document.body[realparbeg : realparbeg] = subst
2835 if layoutname == "OverlayArea":
2836 m = rx.match(document.body[p])
2840 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2841 endPlain = find_end_of_layout(document.body, beginPlain)
2842 endInset = find_end_of_inset(document.body, p)
2843 content = document.body[beginPlain + 1 : endPlain]
2845 realparend = realparend - len(document.body[p : endInset + 1])
2847 del document.body[p : endInset + 1]
2848 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2849 document.body[realparbeg : realparbeg] = subst
2850 if layoutname == "AgainFrame":
2851 m = rx.match(document.body[p])
2855 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2856 endPlain = find_end_of_layout(document.body, beginPlain)
2857 endInset = find_end_of_inset(document.body, p)
2858 content = document.body[beginPlain + 1 : endPlain]
2860 realparend = realparend - len(document.body[p : endInset + 1])
2862 del document.body[p : endInset + 1]
2863 subst = put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
2864 document.body[realparbeg : realparbeg] = subst
2868 def revert_beamerargs3(document):
2869 " Reverts beamer arguments to old layout, step 3 "
2871 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2872 if document.textclass not in beamer_classes:
2875 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2878 i = find_token(document.body, "\\begin_inset Argument", i)
2881 # Find containing paragraph layout
2882 parent = get_containing_layout(document.body, i)
2884 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2889 realparbeg = parent[3]
2890 layoutname = parent[0]
2892 for p in range(parbeg, parend):
2896 if layoutname == "AgainFrame":
2897 m = rx.match(document.body[p])
2901 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2902 endPlain = find_end_of_layout(document.body, beginPlain)
2903 endInset = find_end_of_inset(document.body, p)
2904 content = document.body[beginPlain + 1 : endPlain]
2906 realparend = realparend - len(document.body[p : endInset + 1])
2908 del document.body[p : endInset + 1]
2909 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2910 document.body[realparbeg : realparbeg] = subst
2914 def revert_beamerflex(document):
2915 " Reverts beamer Flex insets "
2917 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2918 if document.textclass not in beamer_classes:
2921 new_flexes = {"Bold" : "\\textbf", "Emphasize" : "\\emph", "Only" : "\\only",
2922 "Uncover" : "\\uncover", "Visible" : "\\visible",
2923 "Invisible" : "\\invisible", "Alternative" : "\\alt",
2924 "Beamer_Note" : "\\note"}
2925 old_flexes = {"Alert" : "\\alert", "Structure" : "\\structure"}
2926 rx = re.compile(r'^\\begin_inset Flex (.+)$')
2930 i = find_token(document.body, "\\begin_inset Flex", i)
2933 m = rx.match(document.body[i])
2935 flextype = m.group(1)
2936 z = find_end_of_inset(document.body, i)
2938 document.warning("Can't find end of Flex " + flextype + " inset.")
2941 if flextype in new_flexes:
2942 pre = put_cmd_in_ert(new_flexes[flextype])
2943 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2945 argend = find_end_of_inset(document.body, arg)
2947 document.warning("Can't find end of Argument!")
2950 # Find containing paragraph layout
2951 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2952 endPlain = find_end_of_layout(document.body, beginPlain)
2953 argcontent = document.body[beginPlain + 1 : endPlain]
2955 z = z - len(document.body[arg : argend + 1])
2957 del document.body[arg : argend + 1]
2958 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2959 arg = find_token(document.body, "\\begin_inset Argument 2", i, z)
2961 argend = find_end_of_inset(document.body, arg)
2963 document.warning("Can't find end of Argument!")
2966 # Find containing paragraph layout
2967 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2968 endPlain = find_end_of_layout(document.body, beginPlain)
2969 argcontent = document.body[beginPlain + 1 : endPlain]
2971 z = z - len(document.body[arg : argend + 1])
2973 del document.body[arg : argend + 1]
2974 if flextype == "Alternative":
2975 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
2977 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2978 pre += put_cmd_in_ert("{")
2979 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2980 endPlain = find_end_of_layout(document.body, beginPlain)
2982 z = z - len(document.body[i : beginPlain + 1])
2984 document.body[i : beginPlain + 1] = pre
2985 post = put_cmd_in_ert("}")
2986 document.body[z - 2 : z + 1] = post
2987 elif flextype in old_flexes:
2988 pre = put_cmd_in_ert(old_flexes[flextype])
2989 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2993 argend = find_end_of_inset(document.body, arg)
2995 document.warning("Can't find end of Argument!")
2998 # Find containing paragraph layout
2999 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3000 endPlain = find_end_of_layout(document.body, beginPlain)
3001 argcontent = document.body[beginPlain + 1 : endPlain]
3003 z = z - len(document.body[arg : argend + 1])
3005 del document.body[arg : argend + 1]
3006 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
3007 pre += put_cmd_in_ert("{")
3008 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
3009 endPlain = find_end_of_layout(document.body, beginPlain)
3011 z = z - len(document.body[i : beginPlain + 1])
3013 document.body[i : beginPlain + 1] = pre
3014 post = put_cmd_in_ert("}")
3015 document.body[z - 2 : z + 1] = post
3020 def revert_beamerblocks(document):
3021 " Reverts beamer block arguments to ERT "
3023 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3024 if document.textclass not in beamer_classes:
3027 blocks = ["Block", "ExampleBlock", "AlertBlock"]
3029 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3032 i = find_token(document.body, "\\begin_inset Argument", i)
3035 # Find containing paragraph layout
3036 parent = get_containing_layout(document.body, i)
3038 document.warning("Malformed LyX document: Can't find parent paragraph layout")
3043 realparbeg = parent[3]
3044 layoutname = parent[0]
3046 for p in range(parbeg, parend):
3050 if layoutname in blocks:
3051 m = rx.match(document.body[p])
3055 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3056 endPlain = find_end_of_layout(document.body, beginPlain)
3057 endInset = find_end_of_inset(document.body, p)
3058 content = document.body[beginPlain + 1 : endPlain]
3060 realparend = realparend - len(document.body[p : endInset + 1])
3062 del document.body[p : endInset + 1]
3063 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3064 document.body[realparbeg : realparbeg] = subst
3066 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3067 endPlain = find_end_of_layout(document.body, beginPlain)
3068 endInset = find_end_of_inset(document.body, p)
3069 content = document.body[beginPlain + 1 : endPlain]
3071 realparend = realparend - len(document.body[p : endInset + 1])
3073 del document.body[p : endInset + 1]
3074 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3075 document.body[realparbeg : realparbeg] = subst
3080 def convert_beamerblocks(document):
3081 " Converts beamer block ERT args to native InsetArgs "
3083 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3084 if document.textclass not in beamer_classes:
3087 blocks = ["Block", "ExampleBlock", "AlertBlock"]
3091 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
3094 parent = get_containing_layout(document.body, i)
3095 if parent == False or parent[1] != i:
3096 document.warning("Wrong parent layout!")
3103 # If the paragraph starts with a language switch, adjust parbeg
3104 if len(document.body[parbeg]) == 0 and parbeg < parend \
3105 and document.body[parbeg + 1].startswith("\\lang"):
3107 if document.body[parbeg] == "\\begin_inset ERT":
3108 ertcontfirstline = parbeg + 5
3112 # Find the last ERT in this paragraph used for arguments
3113 # (which might also be the first)
3114 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
3115 if lastertbeg == -1:
3116 document.warning("Last ERT not found!")
3118 lastertend = find_end_of_inset(document.body, lastertbeg)
3119 if lastertend == -1:
3120 document.warning("End of last ERT not found!")
3122 # Is this ERT really used for an argument?
3123 # Note: This will fail when non-argument ERTs actually use brackets
3125 regexp = re.compile(r'.*[>\]\}]', re.IGNORECASE)
3126 cbracket = find_re(document.body, regexp, lastertbeg, lastertend)
3129 if lastertbeg == parbeg:
3132 if lastertbeg == -1 or lastertend == -1:
3134 ertcontlastline = lastertend - 3
3136 if document.body[ertcontfirstline].lstrip().startswith("<"):
3137 # This is an overlay specification
3139 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3140 if document.body[ertcontlastline].rstrip().endswith(">"):
3142 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3143 # Convert to ArgInset
3144 document.body[parbeg] = "\\begin_inset Argument 1"
3145 elif document.body[ertcontlastline].rstrip().endswith("}"):
3147 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3149 ertcontdivline = ertcontfirstline
3150 tok = document.body[ertcontdivline].find('>{')
3152 regexp = re.compile(r'.*>\{', re.IGNORECASE)
3153 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3154 tok = document.body[ertcontdivline].find('>{')
3156 if ertcontfirstline < ertcontlastline:
3157 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3158 document.body[ertcontlastline : ertcontlastline + 1] = [
3159 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3160 if ertcontdivline == ertcontfirstline:
3161 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3162 '\\end_layout', '', '\\end_inset', '',
3163 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3164 'status collapsed', '', '\\begin_layout Plain Layout',
3165 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3166 document.body[ertcontdivline][tok + 2:]]
3168 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3169 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3170 'status collapsed', '', '\\begin_layout Plain Layout',
3171 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3172 document.body[ertcontdivline][tok + 2:]]
3174 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3175 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3176 'status collapsed', '', '\\begin_layout Plain Layout',
3177 document.body[ertcontdivline][tok + 2:]]
3179 # check if have delimiters in two different ERTs
3180 tok = document.body[ertcontdivline].find('>')
3182 regexp = re.compile(r'.*>', re.IGNORECASE)
3183 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3184 tok = document.body[ertcontdivline].find('>')
3186 tokk = document.body[ertcontdivline].find('{')
3188 regexp = re.compile(r'.*\{', re.IGNORECASE)
3189 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, lastertend)
3190 tokk = document.body[ertcontdivlinetwo].find('{')
3192 if ertcontfirstline < ertcontlastline:
3193 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3194 document.body[ertcontlastline : ertcontlastline + 1] = [
3195 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3196 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3197 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3198 '\\end_inset', '', '', '\\begin_inset Argument 2',
3199 'status collapsed', '', '\\begin_layout Plain Layout',
3200 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3201 document.body[ertcontdivlinetwo][tokk + 1:]]
3203 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3204 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3205 'status collapsed', '', '\\begin_layout Plain Layout',
3206 document.body[ertcontdivlinetwo][tokk + 1:]]
3207 # Convert to ArgInset
3208 if ertcontfirstline < ertcontlastline:
3209 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3210 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 1',
3211 'status collapsed', '', '\\begin_layout Plain Layout',
3212 '\\begin_inset ERT', '']
3214 document.body[parbeg] = "\\begin_inset Argument 1"
3215 elif document.body[ertcontfirstline].lstrip().startswith("{"):
3216 # This is the block title
3217 if document.body[ertcontlastline].rstrip().endswith("}"):
3218 # strip off the braces
3219 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3220 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3221 if ertcontfirstline < ertcontlastline:
3222 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3223 document.body[parend : parend + 1] = [
3224 document.body[parend], '\\end_inset', '', '\\end_layout']
3225 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3226 'status collapsed', '', '\\begin_layout Plain Layout',
3227 '\\begin_inset ERT', '']
3229 # Convert to ArgInset
3230 document.body[parbeg] = "\\begin_inset Argument 2"
3231 # the overlay argument can also follow the title, so ...
3232 elif document.body[ertcontlastline].rstrip().endswith(">"):
3234 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3236 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3238 ertcontdivline = ertcontfirstline
3239 tok = document.body[ertcontdivline].find('}<')
3241 regexp = re.compile(r'.*\}<', re.IGNORECASE)
3242 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3243 tok = document.body[ertcontdivline].find('}<')
3245 if ertcontfirstline < ertcontlastline:
3246 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3247 document.body[ertcontlastline : ertcontlastline + 1] = [
3248 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3249 if ertcontdivline == ertcontfirstline:
3250 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3251 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3252 'status collapsed', '', '\\begin_layout Plain Layout',
3253 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3254 document.body[ertcontdivline][tok + 2:]]
3256 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3257 '\\end_layout', '', '\\end_inset', '',
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', '', '', '\\begin_inset Argument 1',
3265 'status collapsed', '', '\\begin_layout Plain Layout',
3266 document.body[ertcontdivline][tok + 2:]]
3268 # check if have delimiters in two different ERTs
3269 tok = document.body[ertcontdivline].find('}')
3271 regexp = re.compile(r'.*\}', re.IGNORECASE)
3272 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3273 tok = document.body[ertcontdivline].find('}')
3275 tokk = document.body[ertcontdivline].find('<')
3277 regexp = re.compile(r'.*<', re.IGNORECASE)
3278 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, lastertend)
3279 tokk = document.body[ertcontdivlinetwo].find('<')
3281 if ertcontfirstline < ertcontlastline:
3282 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3283 document.body[ertcontlastline : ertcontlastline + 1] = [
3284 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3285 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3286 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3287 '\\end_inset', '', '', '\\begin_inset Argument 1',
3288 'status collapsed', '', '\\begin_layout Plain Layout',
3289 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3290 document.body[ertcontdivlinetwo][tokk + 1:]]
3292 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3293 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3294 'status collapsed', '', '\\begin_layout Plain Layout',
3295 document.body[ertcontdivlinetwo][tokk + 1:]]
3296 # Convert to ArgInset
3297 if ertcontfirstline < ertcontlastline:
3298 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3299 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3300 'status collapsed', '', '\\begin_layout Plain Layout',
3301 '\\begin_inset ERT', '']
3303 document.body[parbeg] = "\\begin_inset Argument 2"
3304 elif count_pars_in_inset(document.body, ertcontfirstline) > 1:
3305 # Multipar ERT. Skip this.
3308 # ERT has contents after the closing bracket. We cannot convert this.
3309 # convert_TeX_brace_to_Argument cannot either.
3310 #convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, False)
3314 j = find_end_of_layout(document.body, i)
3316 document.warning("end of layout not found!")
3317 k = find_token(document.body, "\\begin_inset Argument", i, j)
3319 document.warning("InsetArgument not found!")
3321 l = find_end_of_inset(document.body, k)
3322 m = find_token(document.body, "\\begin_inset ERT", l, j)
3325 ertcontfirstline = m + 5
3330 def convert_overprint(document):
3331 " Convert old beamer overprint layouts to ERT "
3333 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3334 if document.textclass not in beamer_classes:
3339 i = find_token(document.body, "\\begin_layout Overprint", i)
3342 # Find end of sequence
3343 j = find_end_of_sequence(document.body, i)
3345 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3349 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3351 if document.body[j] == "\\end_deeper":
3352 esubst = ["", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3354 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3355 endseq = endseq + len(esubst) - len(document.body[j : j])
3356 document.body[j : j] = esubst
3357 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3359 argend = find_end_of_layout(document.body, argbeg)
3361 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3364 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3365 endPlain = find_end_of_layout(document.body, beginPlain)
3366 content = document.body[beginPlain + 1 : endPlain]
3368 endseq = endseq - len(document.body[argbeg : argend + 1])
3370 del document.body[argbeg : argend + 1]
3371 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3373 endseq = endseq - len(document.body[i : i])
3374 document.body[i : i] = subst + ["\\end_layout"]
3375 endseq += len(subst)
3377 for p in range(i, endseq):
3378 if document.body[p] == "\\begin_layout Overprint":
3379 document.body[p] = "\\begin_layout Standard"
3384 def revert_overprint(document):
3385 " Revert old beamer overprint layouts to ERT "
3387 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3388 if document.textclass not in beamer_classes:
3393 i = find_token(document.body, "\\begin_layout Overprint", i)
3396 # Find end of sequence
3397 j = find_end_of_sequence(document.body, i)
3399 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3403 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3404 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}")
3405 endseq = endseq + len(esubst) - len(document.body[j : j])
3406 if document.body[j] == "\\end_deeper":
3407 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3409 document.body[j : j] = ["\\end_layout", ""] + esubst
3412 if document.body[r] == "\\begin_deeper":
3413 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3415 document.body[r] = ""
3416 document.body[s] = ""
3420 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3422 # Is this really our argument?
3423 nested = find_token(document.body, "\\begin_deeper", i, argbeg)
3425 argend = find_end_of_inset(document.body, argbeg)
3427 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3430 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3431 endPlain = find_end_of_layout(document.body, beginPlain)
3432 content = document.body[beginPlain + 1 : endPlain]
3434 endseq = endseq - len(document.body[argbeg : argend])
3436 del document.body[argbeg : argend + 1]
3437 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3439 endseq = endseq - len(document.body[i : i])
3440 document.body[i : i] = subst + ["\\end_layout"]
3441 endseq += len(subst)
3447 if document.body[p] == "\\begin_layout Overprint":
3448 q = find_end_of_layout(document.body, p)
3450 document.warning("Malformed LyX document. Cannot find end of Overprint layout!")
3453 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\onslide")
3454 argbeg = find_token(document.body, "\\begin_inset Argument item:1", p, q)
3456 argend = find_end_of_inset(document.body, argbeg)
3458 document.warning("Malformed LyX document. Cannot find end of Overprint item argument!")
3461 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3462 endPlain = find_end_of_layout(document.body, beginPlain)
3463 content = document.body[beginPlain + 1 : endPlain]
3465 endseq = endseq - len(document.body[argbeg : argend + 1])
3467 del document.body[argbeg : argend + 1]
3468 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3469 endseq = endseq - len(document.body[p : p + 1]) + len(subst)
3470 document.body[p : p + 1] = subst
3476 def revert_frametitle(document):
3477 " Reverts beamer frametitle layout to ERT "
3479 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3480 if document.textclass not in beamer_classes:
3483 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3486 i = find_token(document.body, "\\begin_layout FrameTitle", i)
3489 j = find_end_of_layout(document.body, i)
3491 document.warning("Malformed LyX document: Can't find end of FrameTitle layout")
3495 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
3496 endlay += len(put_cmd_in_ert("}"))
3497 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\frametitle")
3498 for p in range(i, j):
3501 m = rx.match(document.body[p])
3505 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3506 endPlain = find_end_of_layout(document.body, beginPlain)
3507 endInset = find_end_of_inset(document.body, p)
3508 content = document.body[beginPlain + 1 : endPlain]
3510 endlay = endlay - len(document.body[p : endInset + 1])
3512 del document.body[p : endInset + 1]
3513 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3515 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3516 endPlain = find_end_of_layout(document.body, beginPlain)
3517 endInset = find_end_of_inset(document.body, p)
3518 content = document.body[beginPlain + 1 : endPlain]
3520 endlay = endlay - len(document.body[p : endInset + 1])
3522 del document.body[p : endInset + 1]
3523 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3525 subst += put_cmd_in_ert("{")
3526 document.body[i : i + 1] = subst
3530 def convert_epigraph(document):
3531 " Converts memoir epigraph to new syntax "
3533 if document.textclass != "memoir":
3538 i = find_token(document.body, "\\begin_layout Epigraph", i)
3541 j = find_end_of_layout(document.body, i)
3543 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3548 ert = find_token(document.body, "\\begin_inset ERT", i, j)
3550 endInset = find_end_of_inset(document.body, ert)
3551 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", ert)
3552 endPlain = find_end_of_layout(document.body, beginPlain)
3553 ertcont = beginPlain + 2
3554 if document.body[ertcont] == "}{":
3556 # Convert to ArgInset
3557 endlay = endlay - 2 * len(document.body[j])
3558 begsubst = ['\\begin_inset Argument post:1', 'status collapsed', '',
3559 '\\begin_layout Plain Layout']
3560 endsubst = ['\\end_layout', '', '\\end_inset', '', document.body[j]]
3561 document.body[j : j + 1] = endsubst
3562 document.body[endInset + 1 : endInset + 1] = begsubst
3564 endlay += len(begsubst) + len(endsubst)
3565 endlay = endlay - len(document.body[ert : endInset + 1])
3566 del document.body[ert : endInset + 1]
3571 def revert_epigraph(document):
3572 " Reverts memoir epigraph argument to ERT "
3574 if document.textclass != "memoir":
3579 i = find_token(document.body, "\\begin_layout Epigraph", i)
3582 j = find_end_of_layout(document.body, i)
3584 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3589 p = find_token(document.body, "\\begin_layout Argument post:1", i, j)
3591 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3592 endPlain = find_end_of_layout(document.body, beginPlain)
3593 endInset = find_end_of_inset(document.body, p)
3594 content = document.body[beginPlain + 1 : endPlain]
3596 endlay = endlay - len(document.body[p : endInset + 1])
3598 del document.body[p : endInset + 1]
3599 subst += put_cmd_in_ert("}{") + content
3601 subst += put_cmd_in_ert("}{")
3603 document.body[j : j] = subst + document.body[j : j]
3607 def convert_captioninsets(document):
3608 " Converts caption insets to new syntax "
3612 i = find_token(document.body, "\\begin_inset Caption", i)
3615 document.body[i] = "\\begin_inset Caption Standard"
3619 def revert_captioninsets(document):
3620 " Reverts caption insets to old syntax "
3624 i = find_token(document.body, "\\begin_inset Caption Standard", i)
3627 document.body[i] = "\\begin_inset Caption"
3631 def convert_captionlayouts(document):
3632 " Convert caption layouts to caption insets. "
3635 "Captionabove": "Above",
3636 "Captionbelow": "Below",
3637 "FigCaption" : "FigCaption",
3638 "Table_Caption" : "Table",
3639 "CenteredCaption" : "Centered",
3640 "Bicaption" : "Bicaption",
3645 i = find_token(document.body, "\\begin_layout", i)
3648 val = get_value(document.body, "\\begin_layout", i)
3649 if val in list(caption_dict.keys()):
3650 j = find_end_of_layout(document.body, i)
3652 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3655 document.body[j:j] = ["\\end_layout", "", "\\end_inset", "", ""]
3656 document.body[i:i+1] = ["\\begin_layout %s" % document.default_layout,
3657 "\\begin_inset Caption %s" % caption_dict[val], "",
3658 "\\begin_layout %s" % document.default_layout]
3662 def revert_captionlayouts(document):
3663 " Revert caption insets to caption layouts. "
3666 "Above" : "Captionabove",
3667 "Below" : "Captionbelow",
3668 "FigCaption" : "FigCaption",
3669 "Table" : "Table_Caption",
3670 "Centered" : "CenteredCaption",
3671 "Bicaption" : "Bicaption",
3675 rx = re.compile(r'^\\begin_inset Caption (\S+)$')
3677 i = find_token(document.body, "\\begin_inset Caption", i)
3681 m = rx.match(document.body[i])
3685 if val not in list(caption_dict.keys()):
3689 # We either need to delete the previous \begin_layout line, or we
3690 # need to end the previous layout if this inset is not in the first
3691 # position of the paragraph.
3692 layout_before = find_token_backwards(document.body, "\\begin_layout", i)
3693 if layout_before == -1:
3694 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3696 layout_line = document.body[layout_before]
3697 del_layout_before = True
3698 l = layout_before + 1
3700 if document.body[l] != "":
3701 del_layout_before = False
3704 if del_layout_before:
3705 del document.body[layout_before:i]
3708 document.body[i:i] = ["\\end_layout", ""]
3711 # Find start of layout in the inset and end of inset
3712 j = find_token(document.body, "\\begin_layout", i)
3714 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3716 k = find_end_of_inset(document.body, i)
3718 document.warning("Malformed LyX document: Missing `\\end_inset'.")
3721 # We either need to delete the following \end_layout line, or we need
3722 # to restart the old layout if this inset is not at the paragraph end.
3723 layout_after = find_token(document.body, "\\end_layout", k)
3724 if layout_after == -1:
3725 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3727 del_layout_after = True
3729 while l < layout_after:
3730 if document.body[l] != "":
3731 del_layout_after = False
3734 if del_layout_after:
3735 del document.body[k+1:layout_after+1]
3737 document.body[k+1:k+1] = [layout_line, ""]
3739 # delete \begin_layout and \end_inset and replace \begin_inset with
3740 # "\begin_layout XXX". This works because we can only have one
3741 # paragraph in the caption inset: The old \end_layout will be recycled.
3742 del document.body[k]
3743 if document.body[k] == "":
3744 del document.body[k]
3745 del document.body[j]
3746 if document.body[j] == "":
3747 del document.body[j]
3748 document.body[i] = "\\begin_layout %s" % caption_dict[val]
3749 if document.body[i+1] == "":
3750 del document.body[i+1]
3754 def revert_fragileframe(document):
3755 " Reverts beamer FragileFrame layout to ERT "
3757 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3758 if document.textclass not in beamer_classes:
3763 i = find_token(document.body, "\\begin_layout FragileFrame", i)
3766 # Find end of sequence
3767 j = find_end_of_sequence(document.body, i)
3769 document.warning("Malformed LyX document. Cannot find end of FragileFrame sequence!")
3773 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{frame}")
3774 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{frame}")
3775 endseq = endseq + len(esubst) - len(document.body[j : j])
3776 if document.body[j] == "\\end_deeper":
3777 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3779 document.body[j : j] = esubst
3780 for q in range(i, j):
3781 if document.body[q] == "\\begin_layout FragileFrame":
3782 document.body[q] = "\\begin_layout %s" % document.default_layout
3785 if document.body[r] == "\\begin_deeper":
3786 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3788 document.body[r] = ""
3789 document.body[s] = ""
3793 for p in range(1, 5):
3794 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, j)
3797 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3798 endPlain = find_end_of_layout(document.body, beginPlain)
3799 endInset = find_end_of_inset(document.body, arg)
3800 content = document.body[beginPlain + 1 : endPlain]
3802 j = j - len(document.body[arg : endInset + 1])
3804 del document.body[arg : endInset + 1]
3805 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3807 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3808 endPlain = find_end_of_layout(document.body, beginPlain)
3809 endInset = find_end_of_inset(document.body, arg)
3810 content = document.body[beginPlain + 1 : endPlain]
3812 j = j - len(document.body[arg : endInset + 1])
3814 del document.body[arg : endInset + 1]
3815 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3817 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3818 endPlain = find_end_of_layout(document.body, beginPlain)
3819 endInset = find_end_of_inset(document.body, arg)
3820 content = document.body[beginPlain + 1 : endPlain]
3822 j = j - len(document.body[arg : endInset + 1])
3824 del document.body[arg : endInset + 1]
3825 subst += put_cmd_in_ert("[fragile,") + content + put_cmd_in_ert("]")
3827 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3828 endPlain = find_end_of_layout(document.body, beginPlain)
3829 endInset = find_end_of_inset(document.body, arg)
3830 content = document.body[beginPlain + 1 : endPlain]
3832 j = j - len(document.body[arg : endInset + 1])
3834 del document.body[arg : endInset + 1]
3835 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3837 subst += put_cmd_in_ert("[fragile]")
3839 document.body[i : i + 1] = subst
3843 def revert_newframes(document):
3844 " Reverts beamer Frame and PlainFrame layouts to old forms "
3846 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3847 if document.textclass not in beamer_classes:
3851 "Frame" : "BeginFrame",
3852 "PlainFrame" : "BeginPlainFrame",
3855 rx = re.compile(r'^\\begin_layout (\S+)$')
3858 i = find_token(document.body, "\\begin_layout", i)
3862 m = rx.match(document.body[i])
3866 if val not in list(frame_dict.keys()):
3869 # Find end of sequence
3870 j = find_end_of_sequence(document.body, i)
3872 document.warning("Malformed LyX document. Cannot find end of Frame sequence!")
3876 subst = ["\\begin_layout %s" % frame_dict[val]]
3877 esubst = ["", "\\begin_layout EndFrame", "", "\\end_layout"]
3878 endseq = endseq + len(esubst) - len(document.body[j : j])
3879 if document.body[j] == "\\end_deeper":
3880 document.body[j : j] = esubst
3882 document.body[j+1 : j+1] = esubst
3883 for q in range(i, j):
3884 if document.body[q] == "\\begin_layout %s" % val:
3885 document.body[q] = "\\begin_layout %s" % document.default_layout
3888 if document.body[r] == "\\begin_deeper":
3889 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3891 document.body[r] = ""
3892 document.body[s] = ""
3896 l = find_end_of_layout(document.body, i)
3897 for p in range(1, 5):
3898 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, l)
3901 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3902 endPlain = find_end_of_layout(document.body, beginPlain)
3903 endInset = find_end_of_inset(document.body, arg)
3904 content = document.body[beginPlain + 1 : endPlain]
3906 l = l - len(document.body[arg : endInset + 1])
3908 del document.body[arg : endInset + 1]
3909 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3911 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3912 endPlain = find_end_of_layout(document.body, beginPlain)
3913 endInset = find_end_of_inset(document.body, arg)
3914 content = document.body[beginPlain + 1 : endPlain]
3916 l = l - len(document.body[arg : endInset + 1])
3918 del document.body[arg : endInset + 1]
3919 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3921 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3922 endPlain = find_end_of_layout(document.body, beginPlain)
3923 endInset = find_end_of_inset(document.body, arg)
3924 content = document.body[beginPlain + 1 : endPlain]
3926 l = l - len(document.body[arg : endInset + 1])
3928 del document.body[arg : endInset + 1]
3929 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3931 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3932 endPlain = find_end_of_layout(document.body, beginPlain)
3933 endInset = find_end_of_inset(document.body, arg)
3934 content = document.body[beginPlain + 1 : endPlain]
3936 l = l - len(document.body[arg : endInset + 1])
3938 del document.body[arg : endInset + 1]
3941 document.body[i : i + 1] = subst
3944 # known encodings that do not change their names (same LyX and LaTeX names)
3945 known_enc_tuple = ("auto", "default", "ansinew", "applemac", "armscii8", "ascii",
3946 "cp437", "cp437de", "cp850", "cp852", "cp855", "cp858", "cp862", "cp865", "cp866",
3947 "cp1250", "cp1251", "cp1252", "cp1255", "cp1256", "cp1257", "koi8-r", "koi8-u",
3948 "pt154", "pt254", "tis620-0", "utf8", "utf8x", "utf8-plain")
3950 def convert_encodings(document):
3951 "Use the LyX names of the encodings instead of the LaTeX names."
3952 LaTeX2LyX_enc_dict = {
3953 "8859-6": "iso8859-6",
3954 "8859-8": "iso8859-8",
3956 "euc": "euc-jp-platex",
3961 "iso88595": "iso8859-5",
3962 "iso-8859-7": "iso8859-7",
3964 "jis": "jis-platex",
3966 "l7xenc": "iso8859-13",
3967 "latin1": "iso8859-1",
3968 "latin2": "iso8859-2",
3969 "latin3": "iso8859-3",
3970 "latin4": "iso8859-4",
3971 "latin5": "iso8859-9",
3972 "latin9": "iso8859-15",
3973 "latin10": "iso8859-16",
3974 "SJIS": "shift-jis",
3975 "sjis": "shift-jis-platex",
3978 i = find_token(document.header, "\\inputencoding" , 0)
3981 val = get_value(document.header, "\\inputencoding", i)
3982 if val in list(LaTeX2LyX_enc_dict.keys()):
3983 document.header[i] = "\\inputencoding %s" % LaTeX2LyX_enc_dict[val]
3984 elif val not in known_enc_tuple:
3985 document.warning("Ignoring unknown input encoding: `%s'" % val)
3988 def revert_encodings(document):
3989 """Revert to using the LaTeX names of the encodings instead of the LyX names.
3990 Also revert utf8-platex to sjis, the language default when using Japanese.
3992 LyX2LaTeX_enc_dict = {
3997 "euc-jp-platex": "euc",
4000 "iso8859-1": "latin1",
4001 "iso8859-2": "latin2",
4002 "iso8859-3": "latin3",
4003 "iso8859-4": "latin4",
4004 "iso8859-5": "iso88595",
4005 "iso8859-6": "8859-6",
4006 "iso8859-7": "iso-8859-7",
4007 "iso8859-8": "8859-8",
4008 "iso8859-9": "latin5",
4009 "iso8859-13": "l7xenc",
4010 "iso8859-15": "latin9",
4011 "iso8859-16": "latin10",
4013 "jis-platex": "jis",
4014 "shift-jis": "SJIS",
4015 "shift-jis-platex": "sjis",
4017 "utf8-platex": "sjis"
4019 i = find_token(document.header, "\\inputencoding" , 0)
4022 val = get_value(document.header, "\\inputencoding", i)
4023 if val in list(LyX2LaTeX_enc_dict.keys()):
4024 document.header[i] = "\\inputencoding %s" % LyX2LaTeX_enc_dict[val]
4025 elif val not in known_enc_tuple:
4026 document.warning("Ignoring unknown input encoding: `%s'" % val)
4029 def revert_IEEEtran_3(document):
4031 Reverts Flex Insets to TeX-code
4033 if document.textclass == "IEEEtran":
4039 h = find_token(document.body, "\\begin_inset Flex Author Mark", h)
4041 endh = find_end_of_inset(document.body, h)
4042 document.body[endh - 2 : endh + 1] = put_cmd_in_ert("}")
4043 document.body[h : h + 4] = put_cmd_in_ert("\\IEEEauthorrefmark{")
4046 i = find_token(document.body, "\\begin_inset Flex Author Name", i)
4048 endi = find_end_of_inset(document.body, i)
4049 document.body[endi - 2 : endi + 1] = put_cmd_in_ert("}")
4050 document.body[i : i + 4] = put_cmd_in_ert("\\IEEEauthorblockN{")
4053 j = find_token(document.body, "\\begin_inset Flex Author Affiliation", j)
4055 endj = find_end_of_inset(document.body, j)
4056 document.body[endj - 2 : endj + 1] = put_cmd_in_ert("}")
4057 document.body[j : j + 4] = put_cmd_in_ert("\\IEEEauthorblockA{")
4059 if i == -1 and j == -1 and h == -1:
4063 def revert_kurier_fonts(document):
4064 " Revert kurier font definition to LaTeX "
4066 i = find_token(document.header, "\\font_math", 0)
4068 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4069 val = get_value(document.header, "\\font_math", i)
4070 if val == "kurier-math":
4071 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
4072 "\\usepackage[math]{kurier}\n" \
4073 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
4074 document.header[i] = "\\font_math auto"
4076 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4077 kurier_fonts = ["kurier", "kurierc", "kurierl", "kurierlc"]
4078 k = find_token(document.header, "\\font_sans kurier", 0)
4080 sf = get_value(document.header, "\\font_sans", k)
4081 if sf in kurier_fonts:
4082 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4083 document.header[k] = "\\font_sans default"
4085 def revert_iwona_fonts(document):
4086 " Revert iwona font definition to LaTeX "
4088 i = find_token(document.header, "\\font_math", 0)
4090 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4091 val = get_value(document.header, "\\font_math", i)
4092 if val == "iwona-math":
4093 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
4094 "\\usepackage[math]{iwona}\n" \
4095 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
4096 document.header[i] = "\\font_math auto"
4098 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4099 iwona_fonts = ["iwona", "iwonac", "iwonal", "iwonalc"]
4100 k = find_token(document.header, "\\font_sans iwona", 0)
4102 sf = get_value(document.header, "\\font_sans", k)
4103 if sf in iwona_fonts:
4104 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4105 document.header[k] = "\\font_sans default"
4108 def revert_new_libertines(document):
4109 " Revert new libertine font definition to LaTeX "
4111 if find_token(document.header, "\\use_non_tex_fonts true", 0) != -1:
4114 i = find_token(document.header, "\\font_typewriter libertine-mono", 0)
4116 preamble = "\\usepackage"
4117 sc = find_token(document.header, "\\font_tt_scale", 0)
4119 scval = get_value(document.header, "\\font_tt_scale", sc)
4121 preamble += "[scale=%f]" % (float(scval) / 100)
4122 document.header[sc] = "\\font_tt_scale 100"
4123 preamble += "{libertineMono-type1}"
4124 add_to_preamble(document, [preamble])
4125 document.header[i] = "\\font_typewriter default"
4127 k = find_token(document.header, "\\font_sans biolinum", 0)
4129 preamble = "\\usepackage"
4131 j = find_token(document.header, "\\font_osf true", 0)
4136 sc = find_token(document.header, "\\font_sf_scale", 0)
4138 scval = get_value(document.header, "\\font_sf_scale", sc)
4140 options += ",scale=%f" % (float(scval) / 100)
4141 document.header[sc] = "\\font_sf_scale 100"
4143 preamble += "[" + options +"]"
4144 preamble += "{biolinum-type1}"
4145 add_to_preamble(document, [preamble])
4146 document.header[k] = "\\font_sans default"
4149 def convert_lyxframes(document):
4150 " Converts old beamer frames to new style "
4152 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4153 if document.textclass not in beamer_classes:
4156 framebeg = ["BeginFrame", "BeginPlainFrame"]
4157 frameend = ["Frame", "PlainFrame", "EndFrame", "BeginFrame", "BeginPlainFrame", "AgainFrame",
4158 "Section", "Section*", "Subsection", "Subsection*", "Subsubsection", "Subsubsection*"]
4159 for lay in framebeg:
4162 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
4165 parent = get_containing_layout(document.body, i)
4166 if parent == False or parent[1] != i:
4167 document.warning("Wrong parent layout!")
4170 frametype = parent[0]
4174 # Step I: Convert ERT arguments
4175 # FIXME: See restrictions in convert_beamerframeargs method
4176 ertend = convert_beamerframeargs(document, i, parbeg)
4179 # Step II: Now rename the layout and convert the title to an argument
4180 j = find_end_of_layout(document.body, i)
4181 document.body[j : j + 1] = ['\\end_layout', '', '\\end_inset', '', '\\end_layout']
4182 if lay == "BeginFrame":
4183 document.body[i] = "\\begin_layout Frame"
4185 document.body[i] = "\\begin_layout PlainFrame"
4186 document.body[ertend + 1 : ertend + 1] = ['\\begin_inset Argument 4',
4187 'status open', '', '\\begin_layout Plain Layout']
4188 # Step III: find real frame end
4191 inInset = get_containing_inset(document.body, i)
4193 fend = find_token(document.body, "\\begin_layout", jj)
4195 document.warning("Malformed LyX document: No real frame end!")
4197 val = get_value(document.body, "\\begin_layout", fend)
4198 if val not in frameend:
4201 # is this frame nested in an inset (e.g., Note)?
4202 if inInset != False:
4203 # if so, end the frame inside the inset
4204 if inInset[2] < fend:
4206 if val == frametype:
4207 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4208 # consider explicit EndFrames between two identical frame types
4209 elif val == "EndFrame":
4210 nextlayout = find_token(document.body, "\\begin_layout", fend + 1)
4211 if nextlayout != -1 and get_value(document.body, "\\begin_layout", nextlayout) == frametype:
4212 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4214 document.body[fend : fend] = ['\\end_deeper']
4216 document.body[fend : fend] = ['\\end_deeper']
4217 document.body[j + 1 : j + 1] = ['', '\\begin_deeper']
4222 def remove_endframes(document):
4223 " Remove deprecated beamer endframes "
4225 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4226 if document.textclass not in beamer_classes:
4231 i = find_token_exact(document.body, "\\begin_layout EndFrame", i)
4234 j = find_end_of_layout(document.body, i)
4236 document.warning("Malformed LyX document: Missing \\end_layout to EndFrame")
4239 del document.body[i : j + 1]
4242 def revert_powerdot_flexes(document):
4243 " Reverts powerdot flex insets "
4245 if document.textclass != "powerdot":
4248 flexes = {"Onslide" : "\\onslide",
4249 "Onslide*" : "\\onslide*",
4250 "Onslide+" : "\\onslide+"}
4251 rx = re.compile(r'^\\begin_inset Flex (.+)$')
4255 i = find_token(document.body, "\\begin_inset Flex", i)
4258 m = rx.match(document.body[i])
4260 flextype = m.group(1)
4261 z = find_end_of_inset(document.body, i)
4263 document.warning("Can't find end of Flex " + flextype + " inset.")
4266 if flextype in flexes:
4267 pre = put_cmd_in_ert(flexes[flextype])
4268 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
4270 argend = find_end_of_inset(document.body, arg)
4272 document.warning("Can't find end of Argument!")
4275 # Find containing paragraph layout
4276 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
4277 endPlain = find_end_of_layout(document.body, beginPlain)
4278 argcontent = document.body[beginPlain + 1 : endPlain]
4280 z = z - len(document.body[arg : argend + 1])
4282 del document.body[arg : argend + 1]
4283 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
4284 pre += put_cmd_in_ert("{")
4285 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4286 endPlain = find_end_of_layout(document.body, beginPlain)
4288 z = z - len(document.body[i : beginPlain + 1])
4290 document.body[i : beginPlain + 1] = pre
4291 post = put_cmd_in_ert("}")
4292 document.body[z - 2 : z + 1] = post
4296 def revert_powerdot_pause(document):
4297 " Reverts powerdot pause layout to ERT "
4299 if document.textclass != "powerdot":
4304 i = find_token(document.body, "\\begin_layout Pause", i)
4307 j = find_end_of_layout(document.body, i)
4309 document.warning("Malformed LyX document: Can't find end of Pause layout")
4313 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\pause")
4314 for p in range(i, j):
4317 arg = find_token(document.body, "\\begin_inset Argument 1", i, j)
4319 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4320 endPlain = find_end_of_layout(document.body, beginPlain)
4321 endInset = find_end_of_inset(document.body, p)
4322 content = document.body[beginPlain + 1 : endPlain]
4324 endlay = endlay - len(document.body[p : endInset + 1])
4326 del document.body[p : endInset + 1]
4327 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4329 document.body[i : i + 1] = subst
4333 def revert_powerdot_itemargs(document):
4334 " Reverts powerdot item arguments to ERT "
4336 if document.textclass != "powerdot":
4340 list_layouts = ["Itemize", "ItemizeType1", "Enumerate", "EnumerateType1"]
4341 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4344 i = find_token(document.body, "\\begin_inset Argument", i)
4347 # Find containing paragraph layout
4348 parent = get_containing_layout(document.body, i)
4350 document.warning("Malformed LyX document: Can't find parent paragraph layout")
4355 realparbeg = parent[3]
4356 layoutname = parent[0]
4358 for p in range(parbeg, parend):
4362 if layoutname in list_layouts:
4363 m = rx.match(document.body[p])
4366 if argnr == "item:1":
4367 j = find_end_of_inset(document.body, i)
4368 # Find containing paragraph layout
4369 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4370 endPlain = find_end_of_layout(document.body, beginPlain)
4371 content = document.body[beginPlain + 1 : endPlain]
4372 del document.body[i:j+1]
4373 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4374 document.body[realparbeg : realparbeg] = subst
4375 elif argnr == "item:2":
4376 j = find_end_of_inset(document.body, i)
4377 # Find containing paragraph layout
4378 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4379 endPlain = find_end_of_layout(document.body, beginPlain)
4380 content = document.body[beginPlain + 1 : endPlain]
4381 del document.body[i:j+1]
4382 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
4383 document.body[realparbeg : realparbeg] = subst
4388 def revert_powerdot_columns(document):
4389 " Reverts powerdot twocolumn to TeX-code "
4390 if document.textclass != "powerdot":
4393 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4396 i = find_token(document.body, "\\begin_layout Twocolumn", i)
4399 j = find_end_of_layout(document.body, i)
4401 document.warning("Malformed LyX document: Can't find end of Twocolumn layout")
4405 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
4406 endlay += len(put_cmd_in_ert("}"))
4407 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\twocolumn")
4408 for p in range(i, j):
4411 m = rx.match(document.body[p])
4415 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4416 endPlain = find_end_of_layout(document.body, beginPlain)
4417 endInset = find_end_of_inset(document.body, p)
4418 content = document.body[beginPlain + 1 : endPlain]
4420 endlay = endlay - len(document.body[p : endInset + 1])
4422 del document.body[p : endInset + 1]
4423 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4425 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4426 endPlain = find_end_of_layout(document.body, beginPlain)
4427 endInset = find_end_of_inset(document.body, p)
4428 content = document.body[beginPlain + 1 : endPlain]
4430 endlay = endlay - len(document.body[p : endInset + 1])
4432 del document.body[p : endInset + 1]
4433 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
4435 subst += put_cmd_in_ert("{")
4436 document.body[i : i + 1] = subst
4440 def revert_mbox_fbox(document):
4441 'Convert revert mbox/fbox boxes to TeX-code'
4444 i = find_token(document.body, "\\begin_inset Box", i)
4447 j = find_token(document.body, "width", i)
4449 document.warning("Malformed LyX document: Can't find box width")
4451 width = get_value(document.body, "width", j)
4452 k = find_end_of_inset(document.body, j)
4454 document.warning("Malformed LyX document: Can't find end of box inset")
4457 BeginLayout = find_token(document.body, "\\begin_layout Plain Layout", j)
4458 EndLayout = find_end_of_layout(document.body, BeginLayout)
4459 # replace if width is ""
4461 document.body[EndLayout:k + 1] = put_cmd_in_ert("}")
4462 if document.body[i] == "\\begin_inset Box Frameless":
4463 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\mbox{")
4464 if document.body[i] == "\\begin_inset Box Boxed":
4465 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\fbox{")
4469 def revert_starred_caption(document):
4470 " Reverts unnumbered longtable caption insets "
4474 i = find_token(document.body, "\\begin_inset Caption LongTableNoNumber", i)
4477 # This is not equivalent, but since the caption inset is a full blown
4478 # text inset a true conversion to ERT is too difficult.
4479 document.body[i] = "\\begin_inset Caption Standard"
4483 def revert_forced_local_layout(document):
4486 i = find_token(document.header, "\\begin_forced_local_layout", i)
4489 j = find_end_of(document.header, i, "\\begin_forced_local_layout", "\\end_forced_local_layout")
4491 # this should not happen
4493 regexp = re.compile(r'\s*forcelocal', re.IGNORECASE)
4494 k = find_re(document.header, regexp, i, j)
4496 del document.header[k]
4498 k = find_re(document.header, regexp, i, j)
4499 k = find_token(document.header, "\\begin_local_layout", 0)
4501 document.header[i] = "\\begin_local_layout"
4502 document.header[j] = "\\end_local_layout"
4504 l = find_end_of(document.header, k, "\\begin_local_layout", "\\end_local_layout")
4506 # this should not happen
4508 lines = document.header[i+1 : j]
4510 document.header[k+1 : k+1] = lines
4511 document.header[i : j ] = []
4513 document.header[i : j ] = []
4514 document.header[k+1 : k+1] = lines
4517 def revert_aa1(document):
4518 " Reverts InsetArguments of aa to TeX-code "
4519 if document.textclass == "aa":
4523 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4525 revert_Argument_to_TeX_brace(document, i, 0, 1, 4, False, False)
4531 def revert_aa2(document):
4532 " Reverts InsetArguments of aa to TeX-code "
4533 if document.textclass == "aa":
4537 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4539 document.body[i] = "\\begin_layout Abstract"
4545 def revert_tibetan(document):
4546 "Set the document language for Tibetan to English"
4548 if document.language == "tibetan":
4549 document.language = "english"
4550 i = find_token(document.header, "\\language", 0)
4552 document.header[i] = "\\language english"
4554 while j < len(document.body):
4555 j = find_token(document.body, "\\lang tibetan", j)
4557 document.body[j] = document.body[j].replace("\\lang tibetan", "\\lang english")
4560 j = len(document.body)
4569 # The idea here is that we will have a sequence of chunk paragraphs.
4570 # We want to convert them to paragraphs in one or several chunk insets.
4571 # Individual chunks are terminated by the character @ on the last line.
4572 # This line will be discarded, and following lines are treated as new
4573 # chunks, which go into their own insets.
4574 # The first line of a chunk should look like: <<CONTENT>>=
4575 # We will discard the delimiters, and put the CONTENT into the
4576 # optional argument of the inset, if the CONTENT is non-empty.
4577 def convert_chunks(document):
4578 first_re = re.compile(r'<<(.*)>>=(.*)')
4581 # find start of a block of chunks
4582 i = find_token(document.body, "\\begin_layout Chunk", file_pos)
4588 chunk_started = False
4591 # process the one we just found
4592 j = find_end_of_layout(document.body, i)
4594 document.warning("Malformed LyX documents. Can't find end of Chunk layout!")
4595 # there is no point continuing, as we will run into the same error again.
4597 this_chunk = "".join(document.body[i + 1:j])
4599 # there may be empty lines between chunks
4600 # we just skip them.
4601 if not chunk_started:
4602 if this_chunk != "":
4604 chunk_started = True
4607 contents.append(document.body[i + 1:j])
4609 # look for potential chunk terminator
4610 # on the last line of the chunk paragraph
4611 if document.body[j - 1] == "@":
4614 # look for subsequent chunk paragraph
4615 i = find_token(document.body, "\\begin_layout", j)
4619 if get_value(document.body, "\\begin_layout", i) != "Chunk":
4622 file_pos = end = j + 1
4624 # The last chunk should simply have an "@" in it
4625 # or at least end with "@" (can happen if @ is
4626 # preceded by a newline)
4628 if len(contents) > 0:
4629 lastpar = ''.join(contents[-1])
4630 if not lastpar.endswith("@"):
4631 document.warning("Unexpected chunk content: chunk not terminated by '@'!")
4632 if len(contents) == 0:
4633 # convert empty chunk layouts to Standard
4634 document.body[start] = "\\begin_layout Standard"
4638 # chunk par only contains "@". Just drop it.
4641 # chunk par contains more. Only drop the "@".
4644 # The first line should look like: <<CONTENT>>=
4645 # We want the CONTENT
4646 optarg = ' '.join(contents[0])
4648 # We can already have real chunk content in
4649 # the first par (separated from the options by a newline).
4650 # We collect such stuff to re-insert it later.
4653 match = first_re.search(optarg)
4655 optarg = match.groups()[0]
4656 if match.groups()[1] != "":
4658 for c in contents[0]:
4659 if c.endswith(">>="):
4663 postoptstuff.append(c)
4664 # We have stripped everything. This can be deleted.
4667 newstuff = ['\\begin_layout Standard']
4669 # Maintain paragraph parameters
4670 par_params = ["\\noindent", "\\indent", "\\indent-toggle", "\\leftindent",
4671 "\\start_of_appendix", "\\paragraph_spacing", "\\align",
4672 "\\labelwidthstring"]
4675 if document.body[parms].split(' ', 1)[0] not in par_params:
4677 newstuff.extend([document.body[parms]])
4681 ['\\begin_inset Flex Chunk',
4683 '\\begin_layout Plain Layout', ''])
4685 # If we have a non-empty optional argument, insert it.
4686 if match and optarg != "":
4688 ['\\begin_inset Argument 1',
4690 '\\begin_layout Plain Layout',
4695 # Since we already opened a Plain layout, the first paragraph
4696 # does not need to do that.
4699 # we need to replace newlines with new layouts
4701 started_text = False
4702 for lno in range(0,len(postoptstuff)):
4703 if postoptstuff[lno].startswith("\\begin_inset Newline newline"):
4705 elif start_newline != -1:
4706 if postoptstuff[lno].startswith("\\end_inset"):
4707 # replace that bit, but only if we already have some text
4708 # and we're not at the end except for a blank line
4709 if started_text and \
4710 (lno != len(postoptstuff) - 2 or postoptstuff[-1] != ""):
4711 newstuff.extend(['\\end_layout', '\n', '\\begin_layout Plain Layout', '\n'])
4715 newstuff.extend([postoptstuff[lno]])
4716 newstuff.append('\\end_layout')
4720 newstuff.extend(['', '\\begin_layout Plain Layout', ''])
4724 newstuff.append('\\end_layout')
4726 newstuff.extend(['', '\\end_inset', '', '\\end_layout', ''])
4728 document.body[start:end] = newstuff
4730 file_pos += len(newstuff) - (end - start)
4733 def revert_chunks(document):
4736 i = find_token(document.body, "\\begin_inset Flex Chunk", i)
4740 iend = find_end_of_inset(document.body, i)
4742 document.warning("Can't find end of Chunk!")
4746 # Look for optional argument
4748 ostart = find_token(document.body, "\\begin_inset Argument 1", i, iend)
4750 oend = find_end_of_inset(document.body, ostart)
4751 k = find_token(document.body, "\\begin_layout Plain Layout", ostart, oend)
4753 document.warning("Malformed LyX document: Can't find argument contents!")
4755 m = find_end_of_layout(document.body, k)
4756 optarg = "".join(document.body[k+1:m])
4758 # We now remove the optional argument, so we have something
4759 # uniform on which to work
4760 document.body[ostart : oend + 1] = []
4761 # iend is now invalid
4762 iend = find_end_of_inset(document.body, i)
4764 retval = get_containing_layout(document.body, i)
4766 document.warning("Can't find containing layout for Chunk!")
4769 (lname, lstart, lend, pstart) = retval
4770 # we now want to work through the various paragraphs, and collect their contents
4774 k = find_token(document.body, "\\begin_layout Plain Layout", k, lend)
4777 j = find_end_of_layout(document.body, k)
4779 document.warning("Can't find end of layout inside chunk!")
4781 parlist.append(document.body[k+1:j])
4783 # we now need to wrap all of these paragraphs in chunks
4785 newlines.extend(["\\begin_layout Chunk", "", "<<" + optarg + ">>=", "\\end_layout", ""])
4786 for stuff in parlist:
4787 newlines.extend(["\\begin_layout Chunk"] + stuff + ["\\end_layout", ""])
4788 newlines.extend(["\\begin_layout Chunk", "", "@", "\\end_layout", ""])
4789 # replace old content with new content
4790 document.body[lstart : lend + 1] = newlines
4791 i = lstart + len(newlines)
4798 supported_versions = ["2.1.0","2.1"]
4801 [415, [convert_undertilde]],
4803 [417, [convert_japanese_encodings]],
4804 [418, [convert_justification]],
4806 [420, [convert_biblio_style]],
4807 [421, [convert_longtable_captions]],
4808 [422, [convert_use_packages]],
4809 [423, [convert_use_mathtools]],
4810 [424, [convert_cite_engine_type]],
4811 # No convert_cancel, since cancel will be loaded automatically
4812 # in format 425 without any possibility to switch it off.
4813 # This has been fixed in format 464.
4817 [428, [convert_cell_rotation]],
4818 [429, [convert_table_rotation]],
4819 [430, [convert_listoflistings]],
4820 [431, [convert_use_amssymb]],
4822 [433, [convert_armenian]],
4830 [441, [convert_mdnomath]],
4835 [446, [convert_latexargs]],
4836 [447, [convert_IEEEtran, convert_AASTeX, convert_AGUTeX, convert_IJMP, convert_SIGPLAN, convert_SIGGRAPH, convert_EuropeCV, convert_Initials, convert_ModernCV]],
4837 [448, [convert_literate]],
4840 [451, [convert_beamerargs, convert_againframe_args, convert_corollary_args, convert_quote_args]],
4841 [452, [convert_beamerblocks]],
4842 [453, [convert_use_stmaryrd]],
4843 [454, [convert_overprint]],
4845 [456, [convert_epigraph]],
4846 [457, [convert_use_stackrel]],
4847 [458, [convert_captioninsets, convert_captionlayouts]],
4852 [463, [convert_encodings]],
4853 [464, [convert_use_cancel]],
4854 [465, [convert_lyxframes, remove_endframes]],
4860 [471, [convert_cite_engine_type_default]],
4863 [474, [convert_chunks, cleanup_beamerargs]],
4867 [473, [revert_chunks]],
4868 [472, [revert_tibetan]],
4869 [471, [revert_aa1,revert_aa2]],
4870 [470, [revert_cite_engine_type_default]],
4871 [469, [revert_forced_local_layout]],
4872 [468, [revert_starred_caption]],
4873 [467, [revert_mbox_fbox]],
4874 [466, [revert_iwona_fonts]],
4875 [465, [revert_powerdot_flexes, revert_powerdot_pause, revert_powerdot_itemargs, revert_powerdot_columns]],
4877 [463, [revert_use_cancel]],
4878 [462, [revert_encodings]],
4879 [461, [revert_new_libertines]],
4880 [460, [revert_kurier_fonts]],
4881 [459, [revert_IEEEtran_3]],
4882 [458, [revert_fragileframe, revert_newframes]],
4883 [457, [revert_captioninsets, revert_captionlayouts]],
4884 [456, [revert_use_stackrel]],
4885 [455, [revert_epigraph]],
4886 [454, [revert_frametitle]],
4887 [453, [revert_overprint]],
4888 [452, [revert_use_stmaryrd]],
4889 [451, [revert_beamerblocks]],
4890 [450, [revert_beamerargs, revert_beamerargs2, revert_beamerargs3, revert_beamerflex]],
4891 [449, [revert_garamondx, revert_garamondx_newtxmath]],
4892 [448, [revert_itemargs]],
4893 [447, [revert_literate]],
4894 [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]],
4895 [445, [revert_latexargs]],
4896 [444, [revert_uop]],
4897 [443, [revert_biolinum]],
4899 [441, [revert_newtxmath]],
4900 [440, [revert_mdnomath]],
4901 [439, [revert_mathfonts]],
4902 [438, [revert_minionpro]],
4903 [437, [revert_ipadeco, revert_ipachar]],
4904 [436, [revert_texgyre]],
4905 [435, [revert_mathdesign]],
4906 [434, [revert_txtt]],
4907 [433, [revert_libertine]],
4908 [432, [revert_armenian]],
4909 [431, [revert_languages, revert_ancientgreek]],
4910 [430, [revert_use_amssymb]],
4911 [429, [revert_listoflistings]],
4912 [428, [revert_table_rotation]],
4913 [427, [revert_cell_rotation]],
4914 [426, [revert_tipa]],
4915 [425, [revert_verbatim]],
4916 [424, [revert_cancel]],
4917 [423, [revert_cite_engine_type]],
4918 [422, [revert_use_mathtools]],
4919 [421, [revert_use_packages]],
4920 [420, [revert_longtable_captions]],
4921 [419, [revert_biblio_style]],
4922 [418, [revert_australian]],
4923 [417, [revert_justification]],
4924 [416, [revert_japanese_encodings]],
4925 [415, [revert_negative_space, revert_math_spaces]],
4926 [414, [revert_undertilde]],
4927 [413, [revert_visible_space]]
4931 if __name__ == "__main__":