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_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 document.body[lineERT : end_ERT + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
234 lineERT2 = find_token(document.body, "\\begin_inset ERT", end_ERT, end_layout)
236 end_ERT2 = find_end_of_inset(document.body, lineERT2)
238 document.warning("Can't find end of second ERT!!")
241 closing = find_token(document.body, "]", lineERT2, end_ERT2)
243 closing = find_token(document.body, "}", lineERT2, end_ERT2)
244 if closing != -1: # assure that the "}" is in this ERT
245 end2 = find_token(document.body, "\\end_inset", closing)
246 document.body[lineERT2 : end2 + 1] = ["\\end_layout", "", "\\end_inset"]
249 ###############################################################################
251 ### Conversion and reversion routines
253 ###############################################################################
255 def revert_visible_space(document):
256 "Revert InsetSpace visible into its ERT counterpart"
259 i = find_token(document.body, "\\begin_inset space \\textvisiblespace{}", i)
262 end = find_end_of_inset(document.body, i)
263 subst = put_cmd_in_ert("\\textvisiblespace{}")
264 document.body[i:end + 1] = subst
267 undertilde_commands = ["utilde"]
268 def convert_undertilde(document):
269 " Load undertilde automatically "
270 i = find_token(document.header, "\\use_mathdots" , 0)
272 i = find_token(document.header, "\\use_mhchem" , 0)
274 i = find_token(document.header, "\\use_esint" , 0)
276 document.warning("Malformed LyX document: Can't find \\use_mathdots.")
278 j = find_token(document.preamble, "\\usepackage{undertilde}", 0)
280 # package was loaded in the preamble, convert this to header setting for round trip
281 document.header.insert(i + 1, "\\use_undertilde 2") # on
282 del document.preamble[j]
286 j = find_token(document.body, '\\begin_inset Formula', j)
289 k = find_end_of_inset(document.body, j)
291 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(j))
294 code = "\n".join(document.body[j:k])
295 for c in undertilde_commands:
296 if code.find("\\%s" % c) != -1:
297 # at least one of the commands was found - need to switch package off
298 document.header.insert(i + 1, "\\use_undertilde 0") # off
301 # no command was found - set to auto (bug 9069)
302 document.header.insert(i + 1, "\\use_undertilde 1") # auto
306 def revert_undertilde(document):
307 " Load undertilde if used in the document "
308 regexp = re.compile(r'(\\use_undertilde)')
309 i = find_re(document.header, regexp, 0)
310 value = "1" # default is auto
312 value = get_value(document.header, "\\use_undertilde" , i).split()[0]
313 del document.header[i]
314 if value == "2": # on
315 add_to_preamble(document, ["\\usepackage{undertilde}"])
316 elif value == "1": # auto
319 i = find_token(document.body, '\\begin_inset Formula', i)
322 j = find_end_of_inset(document.body, i)
324 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
327 code = "\n".join(document.body[i:j])
328 for c in undertilde_commands:
329 if code.find("\\%s" % c) != -1:
330 add_to_preamble(document, ["\\usepackage{undertilde}"])
335 def revert_negative_space(document):
336 "Revert InsetSpace negmedspace and negthickspace into its TeX-code counterpart"
341 i = find_token(document.body, "\\begin_inset space \\negmedspace{}", i)
343 j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
345 # load amsmath in the preamble if not already loaded if we are at the end of checking
347 i = find_token(document.header, "\\use_amsmath 2", 0)
349 add_to_preamble(document, ["\\@ifundefined{negthickspace}{\\usepackage{amsmath}}"])
353 end = find_end_of_inset(document.body, i)
354 subst = put_cmd_in_ert("\\negmedspace{}")
355 document.body[i:end + 1] = subst
356 j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
359 end = find_end_of_inset(document.body, j)
360 subst = put_cmd_in_ert("\\negthickspace{}")
361 document.body[j:end + 1] = subst
365 def revert_math_spaces(document):
366 "Revert formulas with protected custom space and protected hfills to TeX-code"
369 i = find_token(document.body, "\\begin_inset Formula", i)
372 j = document.body[i].find("\\hspace*")
374 end = find_end_of_inset(document.body, i)
375 subst = put_cmd_in_ert(document.body[i][21:])
376 document.body[i:end + 1] = subst
380 def convert_japanese_encodings(document):
381 " Rename the japanese encodings to names understood by platex "
383 "EUC-JP-pLaTeX": "euc",
385 "SJIS-pLaTeX": "sjis"
387 i = find_token(document.header, "\\inputencoding" , 0)
390 val = get_value(document.header, "\\inputencoding", i)
391 if val in jap_enc_dict.keys():
392 document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
395 def revert_japanese_encodings(document):
396 " Revert the japanese encodings name changes "
398 "euc": "EUC-JP-pLaTeX",
400 "sjis": "SJIS-pLaTeX"
402 i = find_token(document.header, "\\inputencoding" , 0)
405 val = get_value(document.header, "\\inputencoding", i)
406 if val in jap_enc_dict.keys():
407 document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
410 def convert_justification(document):
411 " Add the \\justification buffer param"
412 i = find_token(document.header, "\\use_indices" , 0)
414 document.warning("Malformed LyX document: Missing \\use_indices.")
416 document.header.insert(i + 1, "\\justification true")
419 def revert_justification(document):
420 " Revert the \\justification buffer param"
421 if not del_token(document.header, '\\justification', 0):
422 document.warning("Malformed LyX document: Missing \\justification.")
425 def revert_australian(document):
426 "Set English language variants Australian and Newzealand to English"
428 if document.language == "australian" or document.language == "newzealand":
429 document.language = "english"
430 i = find_token(document.header, "\\language", 0)
432 document.header[i] = "\\language english"
435 j = find_token(document.body, "\\lang australian", j)
437 j = find_token(document.body, "\\lang newzealand", 0)
441 document.body[j] = document.body[j].replace("\\lang newzealand", "\\lang english")
443 document.body[j] = document.body[j].replace("\\lang australian", "\\lang english")
447 def convert_biblio_style(document):
448 "Add a sensible default for \\biblio_style based on the citation engine."
449 i = find_token(document.header, "\\cite_engine", 0)
451 engine = get_value(document.header, "\\cite_engine", i).split("_")[0]
452 style = {"basic": "plain", "natbib": "plainnat", "jurabib": "jurabib"}
453 document.header.insert(i + 1, "\\biblio_style " + style[engine])
456 def revert_biblio_style(document):
457 "BibTeX insets with default option use the style defined by \\biblio_style."
458 i = find_token(document.header, "\\biblio_style" , 0)
460 document.warning("No \\biblio_style line. Nothing to do.")
463 default_style = get_value(document.header, "\\biblio_style", i)
464 del document.header[i]
466 # We are looking for bibtex insets having the default option
469 i = find_token(document.body, "\\begin_inset CommandInset bibtex", i)
472 j = find_end_of_inset(document.body, i)
474 document.warning("Malformed LyX document: Can't find end of bibtex inset at line " + str(i))
477 k = find_token(document.body, "options", i, j)
479 options = get_quoted_value(document.body, "options", k)
480 if "default" in options.split(","):
481 document.body[k] = 'options "%s"' \
482 % options.replace("default", default_style)
486 def handle_longtable_captions(document, forward):
489 begin_table = find_token(document.body, '<lyxtabular version=', begin_table)
490 if begin_table == -1:
492 end_table = find_end_of(document.body, begin_table, '<lyxtabular', '</lyxtabular>')
494 document.warning("Malformed LyX document: Could not find end of table.")
497 fline = find_token(document.body, "<features", begin_table, end_table)
499 document.warning("Can't find features for inset at line " + str(begin_table))
502 p = document.body[fline].find("islongtable")
507 numrows = get_option_value(document.body[begin_table], "rows")
509 numrows = int(numrows)
511 document.warning(document.body[begin_table])
512 document.warning("Unable to determine rows!")
513 begin_table = end_table
515 begin_row = begin_table
516 for row in range(numrows):
517 begin_row = find_token(document.body, '<row', begin_row, end_table)
519 document.warning("Can't find row " + str(row + 1))
521 end_row = find_end_of(document.body, begin_row, '<row', '</row>')
523 document.warning("Can't find end of row " + str(row + 1))
526 if (get_option_value(document.body[begin_row], 'caption') == 'true' and
527 get_option_value(document.body[begin_row], 'endfirsthead') != 'true' and
528 get_option_value(document.body[begin_row], 'endhead') != 'true' and
529 get_option_value(document.body[begin_row], 'endfoot') != 'true' and
530 get_option_value(document.body[begin_row], 'endlastfoot') != 'true'):
531 document.body[begin_row] = set_option_value(document.body[begin_row], 'caption', 'true", endfirsthead="true')
532 elif get_option_value(document.body[begin_row], 'caption') == 'true':
533 if get_option_value(document.body[begin_row], 'endfirsthead') == 'true':
534 document.body[begin_row] = set_option_value(document.body[begin_row], 'endfirsthead', 'false')
535 if get_option_value(document.body[begin_row], 'endhead') == 'true':
536 document.body[begin_row] = set_option_value(document.body[begin_row], 'endhead', 'false')
537 if get_option_value(document.body[begin_row], 'endfoot') == 'true':
538 document.body[begin_row] = set_option_value(document.body[begin_row], 'endfoot', 'false')
539 if get_option_value(document.body[begin_row], 'endlastfoot') == 'true':
540 document.body[begin_row] = set_option_value(document.body[begin_row], 'endlastfoot', 'false')
542 # since there could be a tabular inside this one, we
543 # cannot jump to end.
547 def convert_longtable_captions(document):
548 "Add a firsthead flag to caption rows"
549 handle_longtable_captions(document, True)
552 def revert_longtable_captions(document):
553 "remove head/foot flag from caption rows"
554 handle_longtable_captions(document, False)
557 def convert_use_packages(document):
558 "use_xxx yyy => use_package xxx yyy"
559 packages = ["amsmath", "esint", "mathdots", "mhchem", "undertilde"]
561 i = find_token(document.header, "\\use_%s" % p, 0)
563 value = get_value(document.header, "\\use_%s" % p, i)
564 document.header[i] = "\\use_package %s %s" % (p, value)
567 def revert_use_packages(document):
568 "use_package xxx yyy => use_xxx yyy"
569 packages = ["amsmath", "esint", "mhchem", "mathdots", "undertilde"]
570 # the order is arbitrary for the use_package version, and not all packages need to be given.
571 # Ensure a complete list and correct order (important for older LyX versions and especially lyx2lyx)
572 # first loop: find line with first package
575 regexp = re.compile(r'(\\use_package\s+%s)' % p)
576 i = find_re(document.header, regexp, 0)
577 if i != -1 and (j < 0 or i < j):
579 # second loop: replace or insert packages in front of all existing ones
581 regexp = re.compile(r'(\\use_package\s+%s)' % p)
582 i = find_re(document.header, regexp, 0)
584 value = get_value(document.header, "\\use_package %s" % p, i).split()[1]
585 del document.header[i]
586 document.header.insert(j, "\\use_%s %s" % (p, value))
588 document.header.insert(j, "\\use_%s 1" % p)
592 def convert_use_package(document, pkg, commands, oldauto):
593 # oldauto defines how the version we are converting from behaves:
594 # if it is true, the old version uses the package automatically.
595 # if it is false, the old version never uses the package.
596 i = find_token(document.header, "\\use_package", 0)
598 document.warning("Malformed LyX document: Can't find \\use_package.")
600 j = find_token(document.preamble, "\\usepackage{" + pkg + "}", 0)
602 # package was loaded in the preamble, convert this to header setting for round trip
603 document.header.insert(i + 1, "\\use_package " + pkg + " 2") # on
604 del document.preamble[j]
605 # If oldauto is true we have two options:
606 # We can either set the package to auto - this is correct for files in
607 # format 425 to 463, and may create a conflict for older files which use
608 # any command in commands with a different definition.
609 # Or we can look whether any command in commands is used, and set it to
610 # auto if not and to off if yes. This will not create a conflict, but will
611 # create uncompilable documents for files in format 425 to 463, which use
612 # any command in commands.
613 # We choose the first option since its error is less likely.
615 document.header.insert(i + 1, "\\use_package " + pkg + " 1") # auto
619 j = find_token(document.body, '\\begin_inset Formula', j)
622 k = find_end_of_inset(document.body, j)
624 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(j))
627 code = "\n".join(document.body[j:k])
629 if code.find("\\%s" % c) != -1:
630 # at least one of the commands was found - need to switch package off
631 document.header.insert(i + 1, "\\use_package " + pkg + " 0") # off
634 # no command was found - set to auto (bug 9069)
635 document.header.insert(i + 1, "\\use_package " + pkg + " 1") # auto
638 def revert_use_package(document, pkg, commands, oldauto):
639 # oldauto defines how the version we are reverting to behaves:
640 # if it is true, the old version uses the package automatically.
641 # if it is false, the old version never uses the package.
642 regexp = re.compile(r'(\\use_package\s+%s)' % pkg)
643 i = find_re(document.header, regexp, 0)
644 value = "1" # default is auto
646 value = get_value(document.header, "\\use_package" , i).split()[1]
647 del document.header[i]
648 if value == "2": # on
649 add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
650 elif value == "1" and not oldauto: # auto
653 i = find_token(document.body, '\\begin_inset Formula', i)
656 j = find_end_of_inset(document.body, i)
658 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
661 code = "\n".join(document.body[i:j])
663 if code.find("\\%s" % c) != -1:
664 add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
669 mathtools_commands = ["mathclap", "mathllap", "mathrlap", \
670 "lgathered", "rgathered", "vcentcolon", "dblcolon", \
671 "coloneqq", "Coloneqq", "coloneq", "Coloneq", "eqqcolon", \
672 "Eqqcolon", "eqcolon", "Eqcolon", "colonapprox", \
673 "Colonapprox", "colonsim", "Colonsim"]
674 def convert_use_mathtools(document):
675 "insert use_package mathtools"
676 convert_use_package(document, "mathtools", mathtools_commands, False)
679 def revert_use_mathtools(document):
680 "remove use_package mathtools"
681 revert_use_package(document, "mathtools", mathtools_commands, False)
684 # commands provided by stmaryrd.sty but LyX uses other packages:
685 # boxdot lightning, bigtriangledown, bigtriangleup
686 stmaryrd_commands = ["shortleftarrow", "shortrightarrow", "shortuparrow", \
687 "shortdownarrow", "Yup", "Ydown", "Yleft", "Yright", \
688 "varcurlyvee", "varcurlywedge", "minuso", "baro", \
689 "sslash", "bbslash", "moo", "varotimes", "varoast", \
690 "varobar", "varodot", "varoslash", "varobslash", \
691 "varocircle", "varoplus", "varominus", "boxast", \
692 "boxbar", "boxslash", "boxbslash", "boxcircle", \
693 "boxbox", "boxempty", "merge", "vartimes", \
694 "fatsemi", "sswarrow", "ssearrow", "curlywedgeuparrow", \
695 "curlywedgedownarrow", "fatslash", "fatbslash", "lbag", \
696 "rbag", "varbigcirc", "leftrightarroweq", \
697 "curlyveedownarrow", "curlyveeuparrow", "nnwarrow", \
698 "nnearrow", "leftslice", "rightslice", "varolessthan", \
699 "varogreaterthan", "varovee", "varowedge", "talloblong", \
700 "interleave", "obar", "obslash", "olessthan", \
701 "ogreaterthan", "ovee", "owedge", "oblong", "inplus", \
702 "niplus", "nplus", "subsetplus", "supsetplus", \
703 "subsetpluseq", "supsetpluseq", "Lbag", "Rbag", \
704 "llbracket", "rrbracket", "llparenthesis", \
705 "rrparenthesis", "binampersand", "bindnasrepma", \
706 "trianglelefteqslant", "trianglerighteqslant", \
707 "ntrianglelefteqslant", "ntrianglerighteqslant", \
708 "llfloor", "rrfloor", "llceil", "rrceil", "arrownot", \
709 "Arrownot", "Mapstochar", "mapsfromchar", "Mapsfromchar", \
710 "leftrightarrowtriangle", "leftarrowtriangle", \
711 "rightarrowtriangle", \
712 "bigcurlyvee", "bigcurlywedge", "bigsqcap", "bigbox", \
713 "bigparallel", "biginterleave", "bignplus", \
714 "varcopyright", "longarrownot", "Longarrownot", \
715 "Mapsto", "mapsfrom", "Mapsfrom" "Longmapsto", \
716 "longmapsfrom", "Longmapsfrom"]
717 def convert_use_stmaryrd(document):
718 "insert use_package stmaryrd"
719 convert_use_package(document, "stmaryrd", stmaryrd_commands, False)
722 def revert_use_stmaryrd(document):
723 "remove use_package stmaryrd"
724 revert_use_package(document, "stmaryrd", stmaryrd_commands, False)
727 stackrel_commands = ["stackrel"]
728 def convert_use_stackrel(document):
729 "insert use_package stackrel"
730 convert_use_package(document, "stackrel", stackrel_commands, False)
733 def revert_use_stackrel(document):
734 "remove use_package stackrel"
735 revert_use_package(document, "stackrel", stackrel_commands, False)
738 def convert_cite_engine_type(document):
739 "Determine the \\cite_engine_type from the citation engine."
740 i = find_token(document.header, "\\cite_engine", 0)
743 engine = get_value(document.header, "\\cite_engine", i)
745 engine, type = engine.split("_")
747 type = {"basic": "numerical", "jurabib": "authoryear"}[engine]
748 document.header[i] = "\\cite_engine " + engine
749 document.header.insert(i + 1, "\\cite_engine_type " + type)
752 def revert_cite_engine_type(document):
753 "Natbib had the type appended with an underscore."
754 engine_type = "numerical"
755 i = find_token(document.header, "\\cite_engine_type" , 0)
757 document.warning("No \\cite_engine_type line. Assuming numerical.")
759 engine_type = get_value(document.header, "\\cite_engine_type", i)
760 del document.header[i]
762 # We are looking for the natbib citation engine
763 i = find_token(document.header, "\\cite_engine natbib", 0)
766 document.header[i] = "\\cite_engine natbib_" + engine_type
769 def convert_cite_engine_type_default(document):
770 "Convert \\cite_engine_type to default for the basic citation engine."
771 i = find_token(document.header, "\\cite_engine basic", 0)
774 i = find_token(document.header, "\\cite_engine_type" , 0)
777 document.header[i] = "\\cite_engine_type default"
780 def revert_cite_engine_type_default(document):
781 """Revert \\cite_engine_type default.
783 Revert to numerical for the basic cite engine, otherwise to authoryear."""
784 engine_type = "authoryear"
785 i = find_token(document.header, "\\cite_engine_type default" , 0)
788 j = find_token(document.header, "\\cite_engine basic", 0)
790 engine_type = "numerical"
791 document.header[i] = "\\cite_engine_type " + engine_type
794 cancel_commands = ["cancel", "bcancel", "xcancel", "cancelto"]
795 # this is the same, as revert_use_cancel() except for the default
796 def revert_cancel(document):
797 "add cancel to the preamble if necessary"
798 revert_use_package(document, "cancel", cancel_commands, False)
801 def revert_verbatim(document):
802 " Revert verbatim einvironments completely to TeX-code. "
805 subst_end = ['\end_layout', '', '\\begin_layout Plain Layout',
807 '\\begin_layout Plain Layout', '', '',
810 '\\end_layout', '', '\\end_inset',
811 '', '', '\\end_layout']
812 subst_begin = ['\\begin_layout Standard', '\\noindent',
813 '\\begin_inset ERT', 'status open', '',
814 '\\begin_layout Plain Layout', '', '', '\\backslash',
816 '\\end_layout', '', '\\begin_layout Plain Layout', '']
819 i = find_token(document.body, "\\begin_layout Verbatim", i)
822 j = find_end_of_layout(document.body, i)
824 document.warning("Malformed LyX document: Can't find end of Verbatim layout")
827 # delete all line breaks insets (there are no other insets)
830 n = find_token(document.body, "\\begin_inset Newline newline", l, j)
832 n = find_token(document.body, "\\begin_inset Newline linebreak", l, j)
835 m = find_end_of_inset(document.body, n)
836 del(document.body[m:m+1])
837 document.body[n:n+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
839 # we deleted a line, so the end of the inset moved forward.
841 # consecutive verbatim environments need to be connected
842 k = find_token(document.body, "\\begin_layout Verbatim", j)
843 if k == j + 2 and consecutive == False:
845 document.body[j:j+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
846 document.body[i:i+1] = subst_begin
848 if k == j + 2 and consecutive == True:
849 document.body[j:j+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
850 del(document.body[i:i+1])
852 if k != j + 2 and consecutive == True:
853 document.body[j:j+1] = subst_end
854 # the next paragraph must not be indented
855 document.body[j+19:j+19] = ['\\noindent']
856 del(document.body[i:i+1])
860 document.body[j:j+1] = subst_end
861 # the next paragraph must not be indented
862 document.body[j+19:j+19] = ['\\noindent']
863 document.body[i:i+1] = subst_begin
866 def revert_tipa(document):
867 " Revert native TIPA insets to mathed or ERT. "
870 i = find_token(document.body, "\\begin_inset IPA", i)
873 j = find_end_of_inset(document.body, i)
875 document.warning("Malformed LyX document: Can't find end of IPA inset")
879 n = find_token(document.body, "\\begin_layout", i, j)
881 document.warning("Malformed LyX document: IPA inset has no embedded layout")
884 m = find_end_of_layout(document.body, n)
886 document.warning("Malformed LyX document: Can't find end of embedded layout")
889 content = document.body[n+1:m]
890 p = find_token(document.body, "\\begin_layout", m, j)
891 if p != -1 or len(content) > 1:
893 content = document.body[i+1:j]
895 # IPA insets with multiple pars need to be wrapped by \begin{IPA}...\end{IPA}
896 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}")
897 add_to_preamble(document, ["\\usepackage{tipa,tipx}"])
899 # single-par IPA insets can be reverted to mathed
900 document.body[i:j+1] = ["\\begin_inset Formula $\\text{\\textipa{" + content[0] + "}}$", "\\end_inset"]
904 def revert_cell_rotation(document):
905 "Revert cell rotations to TeX-code"
907 load_rotating = False
911 # first, let's find out if we need to do anything
912 i = find_token(document.body, '<cell ', i)
915 j = document.body[i].find('rotate="')
917 k = document.body[i].find('"', j + 8)
918 value = document.body[i][j + 8 : k]
920 rgx = re.compile(r' rotate="[^"]+?"')
921 # remove rotate option
922 document.body[i] = rgx.sub('', document.body[i])
924 rgx = re.compile(r' rotate="[^"]+?"')
925 document.body[i] = rgx.sub(' rotate="true"', document.body[i])
927 rgx = re.compile(r' rotate="[^"]+?"')
929 # remove rotate option
930 document.body[i] = rgx.sub('', document.body[i])
932 document.body[i + 5 : i + 5] = \
933 put_cmd_in_ert("\\end{turn}")
934 document.body[i + 4 : i + 4] = \
935 put_cmd_in_ert("\\begin{turn}{" + value + "}")
941 add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"])
944 def convert_cell_rotation(document):
945 'Convert cell rotation statements from "true" to "90"'
949 # first, let's find out if we need to do anything
950 i = find_token(document.body, '<cell ', i)
953 j = document.body[i].find('rotate="true"')
955 rgx = re.compile(r'rotate="[^"]+?"')
956 # convert "true" to "90"
957 document.body[i] = rgx.sub('rotate="90"', document.body[i])
962 def revert_table_rotation(document):
963 "Revert table rotations to TeX-code"
965 load_rotating = False
969 # first, let's find out if we need to do anything
970 i = find_token(document.body, '<features ', i)
973 j = document.body[i].find('rotate="')
975 end_table = find_token(document.body, '</lyxtabular>', j)
976 k = document.body[i].find('"', j + 8)
977 value = document.body[i][j + 8 : k]
979 rgx = re.compile(r' rotate="[^"]+?"')
980 # remove rotate option
981 document.body[i] = rgx.sub('', document.body[i])
983 rgx = re.compile(r'rotate="[^"]+?"')
984 document.body[i] = rgx.sub('rotate="true"', document.body[i])
986 rgx = re.compile(r' rotate="[^"]+?"')
988 # remove rotate option
989 document.body[i] = rgx.sub('', document.body[i])
991 document.body[end_table + 3 : end_table + 3] = \
992 put_cmd_in_ert("\\end{turn}")
993 document.body[i - 2 : i - 2] = \
994 put_cmd_in_ert("\\begin{turn}{" + value + "}")
1000 add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"])
1003 def convert_table_rotation(document):
1004 'Convert table rotation statements from "true" to "90"'
1008 # first, let's find out if we need to do anything
1009 i = find_token(document.body, '<features ', i)
1012 j = document.body[i].find('rotate="true"')
1014 rgx = re.compile(r'rotate="[^"]+?"')
1015 # convert "true" to "90"
1016 document.body[i] = rgx.sub('rotate="90"', document.body[i])
1021 def convert_listoflistings(document):
1022 'Convert ERT \lstlistoflistings to TOC lstlistoflistings inset'
1023 # We can support roundtrip because the command is so simple
1026 i = find_token(document.body, "\\begin_inset ERT", i)
1029 j = find_end_of_inset(document.body, i)
1031 document.warning("Malformed LyX document: Can't find end of ERT inset")
1034 ert = get_ert(document.body, i)
1035 if ert == "\\lstlistoflistings{}":
1036 document.body[i:j] = ["\\begin_inset CommandInset toc", "LatexCommand lstlistoflistings", ""]
1042 def revert_listoflistings(document):
1043 'Convert TOC lstlistoflistings inset to ERT lstlistoflistings'
1046 i = find_token(document.body, "\\begin_inset CommandInset toc", i)
1049 if document.body[i+1] == "LatexCommand lstlistoflistings":
1050 j = find_end_of_inset(document.body, i)
1052 document.warning("Malformed LyX document: Can't find end of TOC inset")
1055 subst = put_cmd_in_ert("\\lstlistoflistings{}")
1056 document.body[i:j+1] = subst
1057 add_to_preamble(document, ["\\usepackage{listings}"])
1061 def convert_use_amssymb(document):
1062 "insert use_package amssymb"
1063 regexp = re.compile(r'(\\use_package\s+amsmath)')
1064 i = find_re(document.header, regexp, 0)
1066 document.warning("Malformed LyX document: Can't find \\use_package amsmath.")
1068 value = get_value(document.header, "\\use_package" , i).split()[1]
1071 useamsmath = int(value)
1073 document.warning("Invalid \\use_package amsmath: " + value + ". Assuming auto.")
1075 j = find_token(document.preamble, "\\usepackage{amssymb}", 0)
1077 document.header.insert(i + 1, "\\use_package amssymb %d" % useamsmath)
1079 document.header.insert(i + 1, "\\use_package amssymb 2")
1080 del document.preamble[j]
1083 def revert_use_amssymb(document):
1084 "remove use_package amssymb"
1085 regexp1 = re.compile(r'(\\use_package\s+amsmath)')
1086 regexp2 = re.compile(r'(\\use_package\s+amssymb)')
1087 i = find_re(document.header, regexp1, 0)
1088 j = find_re(document.header, regexp2, 0)
1089 value1 = "1" # default is auto
1090 value2 = "1" # default is auto
1092 value1 = get_value(document.header, "\\use_package" , i).split()[1]
1094 value2 = get_value(document.header, "\\use_package" , j).split()[1]
1095 del document.header[j]
1096 if value1 != value2 and value2 == "2": # on
1097 add_to_preamble(document, ["\\usepackage{amssymb}"])
1100 def convert_use_cancel(document):
1101 "insert use_package cancel"
1102 convert_use_package(document, "cancel", cancel_commands, True)
1105 def revert_use_cancel(document):
1106 "remove use_package cancel"
1107 revert_use_package(document, "cancel", cancel_commands, True)
1110 def revert_ancientgreek(document):
1111 "Set the document language for ancientgreek to greek"
1113 if document.language == "ancientgreek":
1114 document.language = "greek"
1115 i = find_token(document.header, "\\language", 0)
1117 document.header[i] = "\\language greek"
1120 j = find_token(document.body, "\\lang ancientgreek", j)
1124 document.body[j] = document.body[j].replace("\\lang ancientgreek", "\\lang greek")
1128 def revert_languages(document):
1129 "Set the document language for new supported languages to English"
1132 "coptic", "divehi", "hindi", "kurmanji", "lao", "marathi", "occitan", "sanskrit",
1133 "syriac", "tamil", "telugu", "urdu"
1135 for n in range(len(languages)):
1136 if document.language == languages[n]:
1137 document.language = "english"
1138 i = find_token(document.header, "\\language", 0)
1140 document.header[i] = "\\language english"
1142 while j < len(document.body):
1143 j = find_token(document.body, "\\lang " + languages[n], j)
1145 document.body[j] = document.body[j].replace("\\lang " + languages[n], "\\lang english")
1148 j = len(document.body)
1151 def convert_armenian(document):
1152 "Use polyglossia and thus non-TeX fonts for Armenian"
1154 if document.language == "armenian":
1155 i = find_token(document.header, "\\use_non_tex_fonts", 0)
1157 document.header[i] = "\\use_non_tex_fonts true"
1160 def revert_armenian(document):
1161 "Use ArmTeX and thus TeX fonts for Armenian"
1163 if document.language == "armenian":
1164 i = find_token(document.header, "\\use_non_tex_fonts", 0)
1166 document.header[i] = "\\use_non_tex_fonts false"
1169 def revert_libertine(document):
1170 " Revert native libertine font definition to LaTeX "
1172 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1173 i = find_token(document.header, "\\font_roman libertine", 0)
1176 j = find_token(document.header, "\\font_osf true", 0)
1179 preamble = "\\usepackage"
1181 document.header[j] = "\\font_osf false"
1184 preamble += "[lining]"
1185 preamble += "{libertine-type1}"
1186 add_to_preamble(document, [preamble])
1187 document.header[i] = "\\font_roman default"
1190 def revert_txtt(document):
1191 " Revert native txtt font definition to LaTeX "
1193 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1194 i = find_token(document.header, "\\font_typewriter txtt", 0)
1196 preamble = "\\renewcommand{\\ttdefault}{txtt}"
1197 add_to_preamble(document, [preamble])
1198 document.header[i] = "\\font_typewriter default"
1201 def revert_mathdesign(document):
1202 " Revert native mathdesign font definition to LaTeX "
1204 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1210 i = find_token(document.header, "\\font_roman", 0)
1213 val = get_value(document.header, "\\font_roman", i)
1214 if val in mathdesign_dict.keys():
1215 preamble = "\\usepackage[%s" % mathdesign_dict[val]
1217 j = find_token(document.header, "\\font_osf true", 0)
1220 document.header[j] = "\\font_osf false"
1221 l = find_token(document.header, "\\font_sc true", 0)
1224 document.header[l] = "\\font_sc false"
1226 preamble += ",expert"
1227 preamble += "]{mathdesign}"
1228 add_to_preamble(document, [preamble])
1229 document.header[i] = "\\font_roman default"
1232 def revert_texgyre(document):
1233 " Revert native TeXGyre font definition to LaTeX "
1235 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1236 texgyre_fonts = ["tgadventor", "tgbonum", "tgchorus", "tgcursor", \
1237 "tgheros", "tgpagella", "tgschola", "tgtermes"]
1238 i = find_token(document.header, "\\font_roman", 0)
1240 val = get_value(document.header, "\\font_roman", i)
1241 if val in texgyre_fonts:
1242 preamble = "\\usepackage{%s}" % val
1243 add_to_preamble(document, [preamble])
1244 document.header[i] = "\\font_roman default"
1245 i = find_token(document.header, "\\font_sans", 0)
1247 val = get_value(document.header, "\\font_sans", i)
1248 if val in texgyre_fonts:
1249 preamble = "\\usepackage{%s}" % val
1250 add_to_preamble(document, [preamble])
1251 document.header[i] = "\\font_sans default"
1252 i = find_token(document.header, "\\font_typewriter", 0)
1254 val = get_value(document.header, "\\font_typewriter", i)
1255 if val in texgyre_fonts:
1256 preamble = "\\usepackage{%s}" % val
1257 add_to_preamble(document, [preamble])
1258 document.header[i] = "\\font_typewriter default"
1261 def revert_ipadeco(document):
1262 " Revert IPA decorations to ERT "
1265 i = find_token(document.body, "\\begin_inset IPADeco", i)
1268 end = find_end_of_inset(document.body, i)
1270 document.warning("Can't find end of inset at line " + str(i))
1273 line = document.body[i]
1274 rx = re.compile(r'\\begin_inset IPADeco (.*)$')
1276 decotype = m.group(1)
1277 if decotype != "toptiebar" and decotype != "bottomtiebar":
1278 document.warning("Invalid IPADeco type: " + decotype)
1281 blay = find_token(document.body, "\\begin_layout Plain Layout", i, end)
1283 document.warning("Can't find layout for inset at line " + str(i))
1286 bend = find_end_of_layout(document.body, blay)
1288 document.warning("Malformed LyX document: Could not find end of IPADeco inset's layout.")
1291 substi = ["\\begin_inset ERT", "status collapsed", "",
1292 "\\begin_layout Plain Layout", "", "", "\\backslash",
1293 decotype + "{", "\\end_layout", "", "\\end_inset"]
1294 substj = ["\\size default", "", "\\begin_inset ERT", "status collapsed", "",
1295 "\\begin_layout Plain Layout", "", "}", "\\end_layout", "", "\\end_inset"]
1296 # do the later one first so as not to mess up the numbering
1297 document.body[bend:end + 1] = substj
1298 document.body[i:blay + 1] = substi
1299 i = end + len(substi) + len(substj) - (end - bend) - (blay - i) - 2
1300 add_to_preamble(document, "\\usepackage{tipa}")
1303 def revert_ipachar(document):
1304 ' Revert \\IPAChar to ERT '
1307 while i < len(document.body):
1308 m = re.match(r'(.*)\\IPAChar \\(\w+\{\w+\})(.*)', document.body[i])
1312 ipachar = m.group(2)
1315 '\\begin_inset ERT',
1316 'status collapsed', '',
1317 '\\begin_layout Standard',
1318 '', '', '\\backslash',
1323 document.body[i: i+1] = subst
1328 add_to_preamble(document, "\\usepackage{tone}")
1331 def revert_minionpro(document):
1332 " Revert native MinionPro font definition to LaTeX "
1334 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1335 i = find_token(document.header, "\\font_roman minionpro", 0)
1338 j = find_token(document.header, "\\font_osf true", 0)
1341 preamble = "\\usepackage"
1343 document.header[j] = "\\font_osf false"
1346 preamble += "{MinionPro}"
1347 add_to_preamble(document, [preamble])
1348 document.header[i] = "\\font_roman default"
1351 def revert_mathfonts(document):
1352 " Revert native math font definitions to LaTeX "
1354 i = find_token(document.header, "\\font_math", 0)
1357 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1358 val = get_value(document.header, "\\font_math", i)
1359 if val == "eulervm":
1360 add_to_preamble(document, "\\usepackage{eulervm}")
1361 elif val == "default":
1363 "lmodern": "\\renewcommand{\\rmdefault}{lmr}",
1364 "minionpro": "\\usepackage[onlytext,lf]{MinionPro}",
1365 "minionpro-osf": "\\usepackage[onlytext]{MinionPro}",
1366 "palatino": "\\renewcommand{\\rmdefault}{ppl}",
1367 "palatino-osf": "\\renewcommand{\\rmdefault}{pplj}",
1368 "times": "\\renewcommand{\\rmdefault}{ptm}",
1369 "utopia": "\\renewcommand{\\rmdefault}{futs}",
1370 "utopia-osf": "\\renewcommand{\\rmdefault}{futj}",
1372 j = find_token(document.header, "\\font_roman", 0)
1374 rm = get_value(document.header, "\\font_roman", j)
1375 k = find_token(document.header, "\\font_osf true", 0)
1378 if rm in mathfont_dict.keys():
1379 add_to_preamble(document, mathfont_dict[rm])
1380 document.header[j] = "\\font_roman default"
1382 document.header[k] = "\\font_osf false"
1383 del document.header[i]
1386 def revert_mdnomath(document):
1387 " Revert mathdesign and fourier without math "
1389 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1391 "md-charter": "mdbch",
1392 "md-utopia": "mdput",
1393 "md-garamond": "mdugm"
1395 i = find_token(document.header, "\\font_roman", 0)
1398 val = get_value(document.header, "\\font_roman", i)
1399 if val in mathdesign_dict.keys():
1400 j = find_token(document.header, "\\font_math", 0)
1402 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1403 mval = get_value(document.header, "\\font_math", j)
1404 if mval == "default":
1405 document.header[i] = "\\font_roman default"
1406 add_to_preamble(document, "\\renewcommand{\\rmdefault}{%s}" % mathdesign_dict[val])
1408 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1411 def convert_mdnomath(document):
1412 " Change mathdesign font name "
1414 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1416 "mdbch": "md-charter",
1417 "mdput": "md-utopia",
1418 "mdugm": "md-garamond"
1420 i = find_token(document.header, "\\font_roman", 0)
1423 val = get_value(document.header, "\\font_roman", i)
1424 if val in mathdesign_dict.keys():
1425 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1428 def revert_newtxmath(document):
1429 " Revert native newtxmath definitions to LaTeX "
1431 i = find_token(document.header, "\\font_math", 0)
1434 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1435 val = get_value(document.header, "\\font_math", i)
1437 "libertine-ntxm": "\\usepackage[libertine]{newtxmath}",
1438 "minion-ntxm": "\\usepackage[minion]{newtxmath}",
1439 "newtxmath": "\\usepackage{newtxmath}",
1441 if val in mathfont_dict.keys():
1442 add_to_preamble(document, mathfont_dict[val])
1443 document.header[i] = "\\font_math auto"
1446 def revert_biolinum(document):
1447 " Revert native biolinum font definition to LaTeX "
1449 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1450 i = find_token(document.header, "\\font_sans biolinum", 0)
1453 j = find_token(document.header, "\\font_osf true", 0)
1456 preamble = "\\usepackage"
1459 preamble += "{biolinum-type1}"
1460 add_to_preamble(document, [preamble])
1461 document.header[i] = "\\font_sans default"
1464 def revert_uop(document):
1465 " Revert native URW Classico (Optima) font definition to LaTeX "
1467 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1468 i = find_token(document.header, "\\font_sans uop", 0)
1470 preamble = "\\renewcommand{\\sfdefault}{uop}"
1471 add_to_preamble(document, [preamble])
1472 document.header[i] = "\\font_sans default"
1475 def convert_latexargs(document):
1476 " Convert InsetArgument to new syntax "
1478 if find_token(document.body, "\\begin_inset Argument", 0) == -1:
1482 # A list of layouts (document classes) with only optional or no arguments.
1483 # These can be safely converted to the new syntax
1484 # (I took the liberty to add some of my personal layouts/modules here; JSP)
1485 safe_layouts = ["aa", "aapaper", "aastex", "achemso", "acmsiggraph", "AEA",
1486 "agu-dtd", "agums", "agutex", "amsart", "amsbook", "apa",
1487 "arab-article", "armenian-article", "article-beamer", "article",
1488 "beamer", "book", "broadway", "chess", "cl2emult", "ctex-article",
1489 "ctex-book", "ctex-report", "dinbrief", "docbook-book", "docbook-chapter",
1490 "docbook", "docbook-section", "doublecol-new", "dtk", "ectaart", "egs",
1491 "elsarticle", "elsart", "entcs", "europecv", "extarticle", "extbook",
1492 "extletter", "extreport", "foils", "frletter", "g-brief2", "g-brief",
1493 "heb-article", "heb-letter", "hollywood", "IEEEtran", "ijmpc", "ijmpd",
1494 "iopart", "isprs", "jarticle", "jasatex", "jbook", "jgrga", "jreport",
1495 "jsarticle", "jsbeamer", "jsbook", "jss", "kluwer", "latex8", "letter", "lettre",
1496 "literate-article", "literate-book", "literate-report", "llncs", "ltugboat",
1497 "memoir", "moderncv", "mwart", "mwbk", "mwrep", "paper", "powerdot",
1498 "recipebook", "report", "revtex4", "revtex", "scrartcl", "scrarticle-beamer",
1499 "scrbook", "scrlettr", "scrlttr2", "scrreprt", "seminar", "siamltex",
1500 "sigplanconf", "simplecv", "singlecol", "singlecol-new", "slides", "spie",
1501 "svglobal3", "svglobal", "svjog", "svmono", "svmult", "svprobth", "tarticle",
1502 "tbook", "treport", "tufte-book", "tufte-handout"]
1503 # A list of "safe" modules, same as above
1504 safe_modules = ["biblatex", "beameraddons", "beamersession", "braille", "customHeadersFooters",
1505 "endnotes", "enumitem", "eqs-within-sections", "figs-within-sections", "fix-cm",
1506 "fixltx2e", "foottoend", "hanging", "jscharstyles", "knitr", "lilypond",
1507 "linguistics", "linguisticx", "logicalmkup", "minimalistic", "nomindex", "noweb",
1508 "pdfcomment", "sweave", "tabs-within-sections", "theorems-ams-bytype",
1509 "theorems-ams-extended-bytype", "theorems-ams-extended", "theorems-ams", "theorems-bytype",
1510 "theorems-chap-bytype", "theorems-chap", "theorems-named", "theorems-sec-bytype",
1511 "theorems-sec", "theorems-starred", "theorems-std", "todonotes"]
1512 # Modules we need to take care of
1513 caveat_modules = ["initials"]
1514 # information about the relevant styles in caveat_modules (number of opt and req args)
1515 # use this if we get more caveat_modules. For now, use hard coding (see below).
1516 # initials = [{'Layout' : 'Initial', 'opt' : 1, 'req' : 1}]
1518 # Is this a known safe layout?
1519 safe_layout = document.textclass in safe_layouts
1521 document.warning("Lyx2lyx knows nothing about textclass '%s'. "
1522 "Please check if short title insets have been converted correctly."
1523 % document.textclass)
1524 # Do we use unsafe or unknown modules
1525 mods = document.get_module_list()
1526 unknown_modules = False
1527 used_caveat_modules = list()
1529 if mod in safe_modules:
1531 if mod in caveat_modules:
1532 used_caveat_modules.append(mod)
1534 unknown_modules = True
1535 document.warning("Lyx2lyx knows nothing about module '%s'. "
1536 "Please check if short title insets have been converted correctly."
1541 i = find_token(document.body, "\\begin_inset Argument", i)
1545 if not safe_layout or unknown_modules:
1546 # We cannot do more here since we have no access to this layout.
1547 # InsetArgument itself will do the real work
1548 # (see InsetArgument::updateBuffer())
1549 document.body[i] = "\\begin_inset Argument 999"
1553 # Find containing paragraph layout
1554 parent = get_containing_layout(document.body, i)
1556 document.warning("Malformed LyX document: Can't find parent paragraph layout")
1563 if len(used_caveat_modules) > 0:
1564 # We know for now that this must be the initials module with the Initial layout
1565 # If we get more such modules, we need some automating.
1566 if parent[0] == "Initial":
1567 # Layout has 1 opt and 1 req arg.
1568 # Count the actual arguments
1570 for p in range(parbeg, parend):
1571 if document.body[p] == "\\begin_inset Argument":
1576 # Collect all arguments in this paragraph
1578 for p in range(parbeg, parend):
1579 if document.body[p] == "\\begin_inset Argument":
1581 if allowed_opts != -1:
1582 # We have less arguments than opt + required.
1583 # required must take precedence.
1584 if argnr > allowed_opts and argnr < first_req:
1586 document.body[p] = "\\begin_inset Argument %d" % argnr
1590 def revert_latexargs(document):
1591 " Revert InsetArgument to old syntax "
1594 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
1597 # Search for Argument insets
1598 i = find_token(document.body, "\\begin_inset Argument", i)
1601 m = rx.match(document.body[i])
1603 # No ID: inset already reverted
1606 # Find containing paragraph layout
1607 parent = get_containing_layout(document.body, i)
1609 document.warning("Malformed LyX document: Can't find parent paragraph layout")
1614 # Do not set realparbeg to parent[3], since this does not work if we
1615 # have another inset (e.g. label or index) before the first argument
1616 # inset (this is the case in the user guide of LyX 2.0.8)
1618 # Collect all arguments in this paragraph
1620 for p in range(parbeg, parend):
1621 m = rx.match(document.body[p])
1624 # This is the first argument inset
1626 val = int(m.group(1))
1627 j = find_end_of_inset(document.body, p)
1628 # Revert to old syntax
1629 document.body[p] = "\\begin_inset Argument"
1631 document.warning("Malformed LyX document: Can't find end of Argument inset")
1634 args[val] = document.body[p : j + 1]
1636 realparend = realparend - len(document.body[p : j + 1])
1637 # Remove arg inset at this position
1638 del document.body[p : j + 1]
1642 # No argument inset found
1643 realparbeg = parent[3]
1644 # Now sort the arg insets
1646 for f in sorted(args):
1649 # Insert the sorted arg insets at paragraph begin
1650 document.body[realparbeg : realparbeg] = subst
1652 i = realparbeg + 1 + len(subst)
1655 def revert_IEEEtran(document):
1657 Reverts InsetArgument of
1660 Biography without photo
1663 if document.textclass == "IEEEtran":
1670 i = find_token(document.body, "\\begin_layout Page headings", i)
1672 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1675 i2 = find_token(document.body, "\\begin_inset Flex Paragraph Start", i2)
1677 revert_Argument_to_TeX_brace(document, i2, 0, 1, 1, False, False)
1680 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1682 revert_Argument_to_TeX_brace(document, j, 0, 1, 1, True, False)
1685 k = find_token(document.body, "\\begin_layout Biography", k)
1686 kA = find_token(document.body, "\\begin_layout Biography without photo", k)
1687 if k == kA and k != -1:
1691 # start with the second argument, therefore 2
1692 revert_Argument_to_TeX_brace(document, k, 0, 2, 2, True, False)
1694 if i == -1 and i2 == -1 and j == -1 and k == -1:
1698 def revert_IEEEtran_2(document):
1700 Reverts Flex Paragraph Start to TeX-code
1702 if document.textclass == "IEEEtran":
1705 begin = find_token(document.body, "\\begin_inset Flex Paragraph Start", begin)
1708 end1 = find_end_of_inset(document.body, begin)
1709 document.body[end1 - 2 : end1 + 1] = put_cmd_in_ert("}")
1710 document.body[begin : begin + 4] = put_cmd_in_ert("\\IEEEPARstart{")
1714 def convert_IEEEtran(document):
1719 Biography without photo
1722 if document.textclass == "IEEEtran":
1728 i = find_token(document.body, "\\begin_layout Page headings", i)
1730 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1733 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1735 convert_TeX_brace_to_Argument(document, j, 1, 1, False, True, False)
1738 # assure that we don't handle Biography Biography without photo
1739 k = find_token(document.body, "\\begin_layout Biography", k)
1740 kA = find_token(document.body, "\\begin_layout Biography without photo", k - 1)
1741 if k == kA and k != -1:
1745 # the argument we want to convert is the second one
1746 convert_TeX_brace_to_Argument(document, k, 2, 2, False, True, False)
1748 if i == -1 and j == -1 and k == -1:
1752 def revert_AASTeX(document):
1753 " Reverts InsetArgument of Altaffilation to TeX-code "
1754 if document.textclass == "aastex":
1757 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1760 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1764 def convert_AASTeX(document):
1765 " Converts ERT of Altaffilation to InsetArgument "
1766 if document.textclass == "aastex":
1769 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1772 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1776 def revert_AGUTeX(document):
1777 " Reverts InsetArgument of Author affiliation to TeX-code "
1778 if document.textclass == "agutex":
1781 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1784 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1788 def convert_AGUTeX(document):
1789 " Converts ERT of Author affiliation to InsetArgument "
1790 if document.textclass == "agutex":
1793 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1796 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1800 def revert_IJMP(document):
1801 " Reverts InsetArgument of MarkBoth to TeX-code "
1802 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1805 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1808 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1812 def convert_IJMP(document):
1813 " Converts ERT of MarkBoth to InsetArgument "
1814 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1817 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1820 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1824 def revert_SIGPLAN(document):
1825 " Reverts InsetArguments of SIGPLAN to TeX-code "
1826 if document.textclass == "sigplanconf":
1831 i = find_token(document.body, "\\begin_layout Conference", i)
1833 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1836 j = find_token(document.body, "\\begin_layout Author", j)
1838 revert_Argument_to_TeX_brace(document, j, 0, 1, 2, False, False)
1840 if i == -1 and j == -1:
1844 def convert_SIGPLAN(document):
1845 " Converts ERT of SIGPLAN to InsetArgument "
1846 if document.textclass == "sigplanconf":
1851 i = find_token(document.body, "\\begin_layout Conference", i)
1853 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1856 j = find_token(document.body, "\\begin_layout Author", j)
1858 convert_TeX_brace_to_Argument(document, j, 1, 2, False, False, False)
1860 if i == -1 and j == -1:
1864 def revert_SIGGRAPH(document):
1865 " Reverts InsetArgument of Flex CRcat to TeX-code "
1866 if document.textclass == "acmsiggraph":
1869 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1872 revert_Argument_to_TeX_brace(document, i, 0, 1, 3, False, False)
1876 def convert_SIGGRAPH(document):
1877 " Converts ERT of Flex CRcat to InsetArgument "
1878 if document.textclass == "acmsiggraph":
1881 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1884 convert_TeX_brace_to_Argument(document, i, 1, 3, True, False, False)
1888 def revert_EuropeCV(document):
1889 " Reverts InsetArguments of europeCV to TeX-code "
1890 if document.textclass == "europecv":
1897 i = find_token(document.body, "\\begin_layout Item", i)
1899 revert_Argument_to_TeX_brace(document, i, 0, 2, 2, False, False)
1902 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1904 revert_Argument_to_TeX_brace(document, j, 0, 2, 2, False, False)
1907 k = find_token(document.body, "\\begin_layout Language", k)
1909 revert_Argument_to_TeX_brace(document, k, 0, 2, 6, False, False)
1912 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1914 revert_Argument_to_TeX_brace(document, m, 0, 2, 6, False, False)
1916 if i == -1 and j == -1 and k == -1 and m == -1:
1920 def convert_EuropeCV(document):
1921 " Converts ERT of europeCV to InsetArgument "
1922 if document.textclass == "europecv":
1929 i = find_token(document.body, "\\begin_layout Item", i)
1931 convert_TeX_brace_to_Argument(document, i, 2, 2, False, False, False)
1934 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1936 convert_TeX_brace_to_Argument(document, j, 2, 2, False, False, False)
1939 k = find_token(document.body, "\\begin_layout Language", k)
1941 convert_TeX_brace_to_Argument(document, k, 2, 6, False, False, False)
1944 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1946 convert_TeX_brace_to_Argument(document, m, 2, 6, False, False, False)
1948 if i == -1 and j == -1 and k == -1 and m == -1:
1952 def revert_ModernCV(document):
1953 " Reverts InsetArguments of modernCV to TeX-code "
1954 if document.textclass == "moderncv":
1962 j = find_token(document.body, "\\begin_layout Entry", j)
1964 revert_Argument_to_TeX_brace(document, j, 0, 1, 5, False, False)
1967 k = find_token(document.body, "\\begin_layout Item", k)
1969 revert_Argument_to_TeX_brace(document, k, 0, 1, 1, False, False)
1972 m = find_token(document.body, "\\begin_layout ItemWithComment", m)
1974 revert_Argument_to_TeX_brace(document, m, 0, 1, 2, False, False)
1975 document.body[m] = document.body[m].replace("\\begin_layout ItemWithComment", "\\begin_layout Language")
1978 o = find_token(document.body, "\\begin_layout DoubleItem", o)
1980 revert_Argument_to_TeX_brace(document, o, 0, 1, 3, False, False)
1981 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout Computer")
1984 p = find_token(document.body, "\\begin_layout Social", p)
1986 revert_Argument_to_TeX_brace(document, p, 0, 1, 1, False, True)
1988 if j == -1 and k == -1 and m == -1 and o == -1 and p == -1:
1992 def revert_ModernCV_2(document):
1993 " Reverts the Flex:Column inset of modernCV to TeX-code "
1994 if document.textclass == "moderncv":
1998 flex = find_token(document.body, "\\begin_inset Flex Column", flex)
2001 flexEnd = find_end_of_inset(document.body, flex)
2002 wasOpt = revert_Argument_to_TeX_brace(document, flex, flexEnd, 1, 1, False, True)
2003 revert_Argument_to_TeX_brace(document, flex, 0, 2, 2, False, False)
2004 flexEnd = find_end_of_inset(document.body, flex)
2006 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn")
2008 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn{")
2009 document.body[flexEnd + 4 : flexEnd + 7] = put_cmd_in_ert("}")
2013 def revert_ModernCV_3(document):
2014 " Reverts the Column style of modernCV to TeX-code "
2015 if document.textclass == "moderncv":
2016 # revert the layouts
2017 revert_ModernCV(document)
2019 # get the position of the end of the last column inset
2020 LastFlexEnd = revert_ModernCV_2(document)
2022 p = find_token(document.body, "\\begin_layout Columns", p)
2025 pEnd = find_end_of_layout(document.body, p)
2026 document.body[p] = document.body[p].replace("\\begin_layout Columns", "\\begin_layout Standard")
2027 if LastFlexEnd != -1:
2028 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\begin{cvcolumns}")
2029 document.body[LastFlexEnd + 24 : LastFlexEnd + 24] = put_cmd_in_ert("\\end{cvcolumns}")
2033 def revert_ModernCV_4(document):
2034 " Reverts the style Social to TeX-code "
2035 if document.textclass == "moderncv":
2036 # revert the layouts
2037 revert_ModernCV(document)
2040 p = find_token(document.body, "\\begin_layout Social", p)
2043 pEnd = find_end_of_layout(document.body, p)
2044 document.body[p] = document.body[p].replace("\\begin_layout Social", "\\begin_layout Standard")
2045 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\social")
2046 hasOpt = find_token(document.body, "[", p + 9)
2048 document.body[p + 30 : p + 30] = put_cmd_in_ert("{")
2049 document.body[p + 41 : p + 41] = put_cmd_in_ert("}")
2051 document.body[p + 11 : p + 11] = put_cmd_in_ert("{")
2052 document.body[p + 21 : p + 21] = put_cmd_in_ert("}")
2056 def convert_ModernCV(document):
2057 " Converts ERT of modernCV to InsetArgument "
2058 if document.textclass == "moderncv":
2066 i = find_token(document.body, "\\begin_layout DoubleItem", i)
2068 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
2069 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout DoubleListItem")
2072 j = find_token(document.body, "\\begin_layout Entry", j)
2074 convert_TeX_brace_to_Argument(document, j, 1, 5, False, False, False)
2077 k = find_token(document.body, "\\begin_layout Item", k)
2079 convert_TeX_brace_to_Argument(document, k, 1, 1, False, False, False)
2082 m = find_token(document.body, "\\begin_layout Language", m)
2084 convert_TeX_brace_to_Argument(document, m, 1, 2, False, False, False)
2086 if i == -1 and j == -1 and k == -1 and m == -1:
2090 def revert_Initials(document):
2091 " Reverts InsetArgument of Initial to TeX-code "
2094 i = find_token(document.body, "\\begin_layout Initial", i)
2097 # first arg (optional) and second arg (first mandatory) are supported in LyX 2.0.x
2098 revert_Argument_to_TeX_brace(document, i, 0, 3, 3, False, False)
2102 def convert_Initials(document):
2103 " Converts ERT of Initial to InsetArgument "
2106 i = find_token(document.body, "\\begin_layout Initial", i)
2109 convert_TeX_brace_to_Argument(document, i, 3, 3, False, False, False)
2113 def revert_literate(document):
2114 " Revert Literate document to old format "
2115 if del_token(document.header, "noweb", 0):
2116 document.textclass = "literate-" + document.textclass
2119 i = find_token(document.body, "\\begin_layout Chunk", i)
2122 document.body[i] = "\\begin_layout Scrap"
2126 def convert_literate(document):
2127 " Convert Literate document to new format"
2128 i = find_token(document.header, "\\textclass", 0)
2129 if (i != -1) and "literate-" in document.header[i]:
2130 document.textclass = document.header[i].replace("\\textclass literate-", "")
2131 j = find_token(document.header, "\\begin_modules", 0)
2133 document.header.insert(j + 1, "noweb")
2135 document.header.insert(i + 1, "\\end_modules")
2136 document.header.insert(i + 1, "noweb")
2137 document.header.insert(i + 1, "\\begin_modules")
2140 i = find_token(document.body, "\\begin_layout Scrap", i)
2143 document.body[i] = "\\begin_layout Chunk"
2147 def revert_itemargs(document):
2148 " Reverts \\item arguments to TeX-code "
2151 i = find_token(document.body, "\\begin_inset Argument item:", i)
2154 j = find_end_of_inset(document.body, i)
2155 # Find containing paragraph layout
2156 parent = get_containing_layout(document.body, i)
2158 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2162 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2163 endPlain = find_end_of_layout(document.body, beginPlain)
2164 content = document.body[beginPlain + 1 : endPlain]
2165 del document.body[i:j+1]
2166 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2167 document.body[parbeg : parbeg] = subst
2171 def revert_garamondx_newtxmath(document):
2172 " Revert native garamond newtxmath definition to LaTeX "
2174 i = find_token(document.header, "\\font_math", 0)
2177 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2178 val = get_value(document.header, "\\font_math", i)
2179 if val == "garamondx-ntxm":
2180 add_to_preamble(document, "\\usepackage[garamondx]{newtxmath}")
2181 document.header[i] = "\\font_math auto"
2184 def revert_garamondx(document):
2185 " Revert native garamond font definition to LaTeX "
2187 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2188 i = find_token(document.header, "\\font_roman garamondx", 0)
2191 j = find_token(document.header, "\\font_osf true", 0)
2194 preamble = "\\usepackage"
2196 preamble += "[osfI]"
2197 preamble += "{garamondx}"
2198 add_to_preamble(document, [preamble])
2199 document.header[i] = "\\font_roman default"
2202 def convert_beamerargs(document):
2203 " Converts beamer arguments to new layout "
2205 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2206 if document.textclass not in beamer_classes:
2209 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2210 list_layouts = ["Itemize", "Enumerate", "Description"]
2211 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
2215 i = find_token(document.body, "\\begin_inset Argument", i)
2218 # Find containing paragraph layout
2219 parent = get_containing_layout(document.body, i)
2221 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2226 layoutname = parent[0]
2227 for p in range(parbeg, parend):
2228 if layoutname in shifted_layouts:
2229 m = rx.match(document.body[p])
2231 argnr = int(m.group(1))
2233 document.body[p] = "\\begin_inset Argument %d" % argnr
2234 if layoutname == "AgainFrame":
2235 m = rx.match(document.body[p])
2237 document.body[p] = "\\begin_inset Argument 3"
2238 if document.body[p + 4] == "\\begin_inset ERT":
2239 if document.body[p + 9].startswith("<"):
2240 # This is an overlay specification
2242 document.body[p + 9] = document.body[p + 9][1:]
2243 if document.body[p + 9].endswith(">"):
2245 document.body[p + 9] = document.body[p + 9][:-1]
2247 document.body[p] = "\\begin_inset Argument 2"
2248 if layoutname in list_layouts:
2249 m = rx.match(document.body[p])
2251 if m.group(1) == "1":
2252 if document.body[p + 4] == "\\begin_inset ERT":
2253 if document.body[p + 9].startswith("<"):
2254 # This is an overlay specification
2256 document.body[p + 9] = document.body[p + 9][1:]
2257 if document.body[p + 9].endswith(">"):
2259 document.body[p + 9] = document.body[p + 9][:-1]
2260 elif document.body[p + 4].startswith("<"):
2261 # This is an overlay specification (without ERT)
2263 document.body[p + 4] = document.body[p + 4][1:]
2264 if document.body[p + 4].endswith(">"):
2266 document.body[p + 4] = document.body[p + 4][:-1]
2267 elif layoutname != "Itemize":
2269 document.body[p] = "\\begin_inset Argument 2"
2274 # Helper function for the frame conversion routines
2276 # FIXME: This method currently requires the arguments to be either
2277 # * In one (whole) ERT each: <ERT>[<arg1>]</ERT><ERT><arg2></ERT><ERT>[arg3]</ERT>
2278 # * Altogether in one whole ERT: <ERT>[<arg1>]<arg2>[arg3]</ERT>
2279 # If individual arguments mix ERT and non-ERT or are splitted
2280 # over several ERTs, the parsing fails.
2281 def convert_beamerframeargs(document, i, parbeg):
2284 if document.body[parbeg] != "\\begin_inset ERT":
2286 ertend = find_end_of_inset(document.body, parbeg)
2288 document.warning("Malformed LyX document: missing ERT \\end_inset")
2290 ertcont = parbeg + 5
2291 if document.body[ertcont].startswith("[<"):
2292 # This is a default overlay specification
2294 document.body[ertcont] = document.body[ertcont][2:]
2295 if document.body[ertcont].endswith(">]"):
2297 document.body[ertcont] = document.body[ertcont][:-2]
2298 elif document.body[ertcont].endswith("]"):
2300 tok = document.body[ertcont].find('>][')
2302 subst = [document.body[ertcont][:tok],
2303 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2304 'status collapsed', '', '\\begin_layout Plain Layout',
2305 document.body[ertcont][tok + 3:-1]]
2306 document.body[ertcont : ertcont + 1] = subst
2308 # Convert to ArgInset
2309 document.body[parbeg] = "\\begin_inset Argument 2"
2310 elif document.body[ertcont].startswith("<"):
2311 # This is an overlay specification
2313 document.body[ertcont] = document.body[ertcont][1:]
2314 if document.body[ertcont].endswith(">"):
2316 document.body[ertcont] = document.body[ertcont][:-1]
2317 # Convert to ArgInset
2318 document.body[parbeg] = "\\begin_inset Argument 1"
2319 elif document.body[ertcont].endswith(">]"):
2321 tok = document.body[ertcont].find('>[<')
2323 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2324 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2325 'status collapsed', '', '\\begin_layout Plain Layout',
2326 document.body[ertcont][tok + 3:-2]]
2327 # Convert to ArgInset
2328 document.body[parbeg] = "\\begin_inset Argument 1"
2330 elif document.body[ertcont].endswith("]"):
2332 tok = document.body[ertcont].find('>[<')
2335 tokk = document.body[ertcont].find('>][')
2337 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2338 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2339 'status collapsed', '', '\\begin_layout Plain Layout',
2340 document.body[ertcont][tok + 3:tokk],
2341 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2342 'status collapsed', '', '\\begin_layout Plain Layout',
2343 document.body[ertcont][tokk + 3:-1]]
2346 tokk = document.body[ertcont].find('>[')
2348 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tokk],
2349 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2350 'status collapsed', '', '\\begin_layout Plain Layout',
2351 document.body[ertcont][tokk + 2:-1]]
2353 # Convert to ArgInset
2354 document.body[parbeg] = "\\begin_inset Argument 1"
2355 elif document.body[ertcont].startswith("["):
2356 # This is an ERT option
2358 document.body[ertcont] = document.body[ertcont][1:]
2359 if document.body[ertcont].endswith("]"):
2361 document.body[ertcont] = document.body[ertcont][:-1]
2362 # Convert to ArgInset
2363 document.body[parbeg] = "\\begin_inset Argument 3"
2369 def convert_againframe_args(document):
2370 " Converts beamer AgainFrame to new layout "
2372 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2373 if document.textclass not in beamer_classes:
2378 i = find_token(document.body, "\\begin_layout AgainFrame", i)
2381 parent = get_containing_layout(document.body, i)
2383 document.warning("Wrong parent layout!")
2387 # Convert ERT arguments
2388 # FIXME: See restrictions in convert_beamerframeargs method
2389 ertend = convert_beamerframeargs(document, i, parbeg)
2395 def convert_corollary_args(document):
2396 " Converts beamer corrolary-style ERT arguments native InsetArgs "
2398 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2399 if document.textclass not in beamer_classes:
2402 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2403 for lay in corollary_layouts:
2406 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2409 parent = get_containing_layout(document.body, i)
2411 document.warning("Wrong parent layout!")
2415 if document.body[parbeg] == "\\begin_inset ERT":
2416 ertcontfirstline = parbeg + 5
2417 # Find the last ERT in this paragraph (which might also be the first)
2418 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
2419 if lastertbeg == -1:
2420 document.warning("Last ERT not found!")
2422 lastertend = find_end_of_inset(document.body, lastertbeg)
2423 if lastertend == -1:
2424 document.warning("End of last ERT not found!")
2426 ertcontlastline = lastertend - 3
2427 if document.body[ertcontfirstline].startswith("<"):
2428 # This is an overlay specification
2430 document.body[ertcontfirstline] = document.body[ertcontfirstline][1:]
2431 if document.body[ertcontlastline].endswith(">"):
2433 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
2434 if ertcontfirstline < ertcontlastline:
2435 # Multiline ERT. Might contain TeX code. Embrace in ERT.
2436 document.body[ertcontlastline : ertcontlastline + 1] = [
2437 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
2438 document.body[ertcontfirstline : ertcontfirstline + 1] = [
2439 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
2440 'status collapsed', '', '\\begin_layout Plain Layout',
2441 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
2442 document.body[ertcontfirstline]]
2444 # Convert to ArgInset
2445 document.body[parbeg] = "\\begin_inset Argument 1"
2446 elif document.body[ertcontlastline].endswith("]"):
2448 ertcontdivline = document.body[ertcontfirstline].find('>[')
2449 if ertcontdivline != -1:
2450 if ertcontfirstline < ertcontlastline:
2451 # Multiline ERT. Might contain TeX code. Embrace in ERT.
2452 document.body[ertcontlastline : ertcontlastline + 1] = [
2453 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
2454 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
2455 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2456 'status collapsed', '', '\\begin_layout Plain Layout',
2457 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
2458 document.body[ertcontdivline][tok + 2:]]
2460 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
2461 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2462 'status collapsed', '', '\\begin_layout Plain Layout',
2463 document.body[ertcontdivline][tok + 2:]]
2464 # Convert to ArgInset
2465 document.body[parbeg] = "\\begin_inset Argument 1"
2468 elif document.body[ertcontlastline].startswith("["):
2469 if document.body[ertcontlastline].endswith("]"):
2470 # This is an ERT option
2472 document.body[ertcontlastline] = document.body[ertcontlastline][1:]
2474 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
2475 # Convert to ArgInset
2476 document.body[parbeg] = "\\begin_inset Argument 2"
2478 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, True)
2485 def convert_quote_args(document):
2486 " Converts beamer quote style ERT args to native InsetArgs "
2488 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2489 if document.textclass not in beamer_classes:
2492 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2493 for lay in quote_layouts:
2496 i = find_token(document.body, "\\begin_layout " + lay, i)
2499 parent = get_containing_layout(document.body, i)
2501 document.warning("Wrong parent layout!")
2505 if document.body[parbeg] == "\\begin_inset ERT":
2506 if document.body[i + 6].startswith("<"):
2507 # This is an overlay specification
2509 document.body[i + 6] = document.body[i + 6][1:]
2510 if document.body[i + 6].endswith(">"):
2512 document.body[i + 6] = document.body[i + 6][:-1]
2513 # Convert to ArgInset
2514 document.body[i + 1] = "\\begin_inset Argument 1"
2518 def revert_beamerargs(document):
2519 " Reverts beamer arguments to old layout "
2521 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2522 if document.textclass not in beamer_classes:
2526 list_layouts = ["Itemize", "Enumerate", "Description"]
2527 headings = ["Part", "Section", "Section*", "Subsection", "Subsection*",
2528 "Subsubsection", "Subsubsection*", "FrameSubtitle", "NoteItem"]
2529 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2530 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2531 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2534 i = find_token(document.body, "\\begin_inset Argument", i)
2537 # Find containing paragraph layout
2538 parent = get_containing_layout(document.body, i)
2540 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2545 realparbeg = parent[3]
2546 layoutname = parent[0]
2548 for p in range(parbeg, parend):
2552 if layoutname in headings:
2553 m = rx.match(document.body[p])
2557 # Find containing paragraph layout
2558 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2559 endPlain = find_end_of_layout(document.body, beginPlain)
2560 endInset = find_end_of_inset(document.body, p)
2561 argcontent = document.body[beginPlain + 1 : endPlain]
2563 realparend = realparend - len(document.body[p : endInset + 1])
2565 del document.body[p : endInset + 1]
2566 if layoutname == "FrameSubtitle":
2567 pre = put_cmd_in_ert("\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2568 elif layoutname == "NoteItem":
2569 pre = put_cmd_in_ert("\\note<") + argcontent + put_cmd_in_ert(">[item]")
2570 elif layoutname.endswith('*'):
2571 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower()[:-1] + "<") + argcontent + put_cmd_in_ert(">*")
2573 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2574 secarg = find_token(document.body, "\\begin_inset Argument 2", parbeg, parend)
2576 # Find containing paragraph layout
2577 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", secarg)
2578 endPlain = find_end_of_layout(document.body, beginPlain)
2579 endInset = find_end_of_inset(document.body, secarg)
2580 argcontent = document.body[beginPlain + 1 : endPlain]
2582 realparend = realparend - len(document.body[secarg : endInset + 1])
2583 del document.body[secarg : endInset + 1]
2584 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2585 pre += put_cmd_in_ert("{")
2586 document.body[parbeg] = "\\begin_layout Standard"
2587 document.body[realparbeg : realparbeg] = pre
2588 pe = find_end_of_layout(document.body, parbeg)
2589 post = put_cmd_in_ert("}")
2590 document.body[pe : pe] = post
2591 realparend += len(pre) + len(post)
2592 if layoutname == "AgainFrame":
2593 m = rx.match(document.body[p])
2597 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2598 endPlain = find_end_of_layout(document.body, beginPlain)
2599 endInset = find_end_of_inset(document.body, p)
2600 content = document.body[beginPlain + 1 : endPlain]
2602 realparend = realparend - len(document.body[p : endInset + 1])
2604 del document.body[p : endInset + 1]
2605 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2606 document.body[realparbeg : realparbeg] = subst
2607 if layoutname == "Overprint":
2608 m = rx.match(document.body[p])
2612 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2613 endPlain = find_end_of_layout(document.body, beginPlain)
2614 endInset = find_end_of_inset(document.body, p)
2615 content = document.body[beginPlain + 1 : endPlain]
2617 realparend = realparend - len(document.body[p : endInset + 1])
2619 del document.body[p : endInset + 1]
2620 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2621 document.body[realparbeg : realparbeg] = subst
2622 if layoutname == "OverlayArea":
2623 m = rx.match(document.body[p])
2627 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2628 endPlain = find_end_of_layout(document.body, beginPlain)
2629 endInset = find_end_of_inset(document.body, p)
2630 content = document.body[beginPlain + 1 : endPlain]
2632 realparend = realparend - len(document.body[p : endInset + 1])
2634 del document.body[p : endInset + 1]
2635 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2636 document.body[realparbeg : realparbeg] = subst
2637 if layoutname in list_layouts:
2638 m = rx.match(document.body[p])
2642 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2643 endPlain = find_end_of_layout(document.body, beginPlain)
2644 endInset = find_end_of_inset(document.body, p)
2645 content = document.body[beginPlain + 1 : endPlain]
2646 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2647 realparend = realparend + len(subst) - len(content)
2648 document.body[beginPlain + 1 : endPlain] = subst
2649 elif argnr == "item:1":
2650 j = find_end_of_inset(document.body, i)
2651 # Find containing paragraph layout
2652 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2653 endPlain = find_end_of_layout(document.body, beginPlain)
2654 content = document.body[beginPlain + 1 : endPlain]
2655 del document.body[i:j+1]
2656 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2657 document.body[realparbeg : realparbeg] = subst
2658 elif argnr == "item:2":
2659 j = find_end_of_inset(document.body, i)
2660 # Find containing paragraph layout
2661 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2662 endPlain = find_end_of_layout(document.body, beginPlain)
2663 content = document.body[beginPlain + 1 : endPlain]
2664 del document.body[i:j+1]
2665 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2666 document.body[realparbeg : realparbeg] = subst
2667 if layoutname in quote_layouts:
2668 m = rx.match(document.body[p])
2672 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2673 endPlain = find_end_of_layout(document.body, beginPlain)
2674 endInset = find_end_of_inset(document.body, p)
2675 content = document.body[beginPlain + 1 : endPlain]
2677 realparend = realparend - len(document.body[p : endInset + 1])
2679 del document.body[p : endInset + 1]
2680 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2681 document.body[realparbeg : realparbeg] = subst
2682 if layoutname in corollary_layouts:
2683 m = rx.match(document.body[p])
2687 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2688 endPlain = find_end_of_layout(document.body, beginPlain)
2689 endInset = find_end_of_inset(document.body, p)
2690 content = document.body[beginPlain + 1 : endPlain]
2692 realparend = realparend - len(document.body[p : endInset + 1])
2694 del document.body[p : endInset + 1]
2695 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2696 document.body[realparbeg : realparbeg] = subst
2701 def revert_beamerargs2(document):
2702 " Reverts beamer arguments to old layout, step 2 "
2704 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2705 if document.textclass not in beamer_classes:
2709 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2710 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2711 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2714 i = find_token(document.body, "\\begin_inset Argument", i)
2717 # Find containing paragraph layout
2718 parent = get_containing_layout(document.body, i)
2720 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2725 realparbeg = parent[3]
2726 layoutname = parent[0]
2728 for p in range(parbeg, parend):
2732 if layoutname in shifted_layouts:
2733 m = rx.match(document.body[p])
2737 document.body[p] = "\\begin_inset Argument 1"
2738 if layoutname in corollary_layouts:
2739 m = rx.match(document.body[p])
2743 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2744 endPlain = find_end_of_layout(document.body, beginPlain)
2745 endInset = find_end_of_inset(document.body, p)
2746 content = document.body[beginPlain + 1 : endPlain]
2748 realparend = realparend - len(document.body[p : endInset + 1])
2750 del document.body[p : endInset + 1]
2751 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2752 document.body[realparbeg : realparbeg] = subst
2753 if layoutname == "OverlayArea":
2754 m = rx.match(document.body[p])
2758 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2759 endPlain = find_end_of_layout(document.body, beginPlain)
2760 endInset = find_end_of_inset(document.body, p)
2761 content = document.body[beginPlain + 1 : endPlain]
2763 realparend = realparend - len(document.body[p : endInset + 1])
2765 del document.body[p : endInset + 1]
2766 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2767 document.body[realparbeg : realparbeg] = subst
2768 if layoutname == "AgainFrame":
2769 m = rx.match(document.body[p])
2773 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2774 endPlain = find_end_of_layout(document.body, beginPlain)
2775 endInset = find_end_of_inset(document.body, p)
2776 content = document.body[beginPlain + 1 : endPlain]
2778 realparend = realparend - len(document.body[p : endInset + 1])
2780 del document.body[p : endInset + 1]
2781 subst = put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
2782 document.body[realparbeg : realparbeg] = subst
2786 def revert_beamerargs3(document):
2787 " Reverts beamer arguments to old layout, step 3 "
2789 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2790 if document.textclass not in beamer_classes:
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 == "AgainFrame":
2815 m = rx.match(document.body[p])
2819 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2820 endPlain = find_end_of_layout(document.body, beginPlain)
2821 endInset = find_end_of_inset(document.body, p)
2822 content = document.body[beginPlain + 1 : endPlain]
2824 realparend = realparend - len(document.body[p : endInset + 1])
2826 del document.body[p : endInset + 1]
2827 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2828 document.body[realparbeg : realparbeg] = subst
2832 def revert_beamerflex(document):
2833 " Reverts beamer Flex insets "
2835 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2836 if document.textclass not in beamer_classes:
2839 new_flexes = {"Bold" : "\\textbf", "Emphasize" : "\\emph", "Only" : "\\only",
2840 "Uncover" : "\\uncover", "Visible" : "\\visible",
2841 "Invisible" : "\\invisible", "Alternative" : "\\alt",
2842 "Beamer_Note" : "\\note"}
2843 old_flexes = {"Alert" : "\\alert", "Structure" : "\\structure"}
2844 rx = re.compile(r'^\\begin_inset Flex (.+)$')
2848 i = find_token(document.body, "\\begin_inset Flex", i)
2851 m = rx.match(document.body[i])
2853 flextype = m.group(1)
2854 z = find_end_of_inset(document.body, i)
2856 document.warning("Can't find end of Flex " + flextype + " inset.")
2859 if flextype in new_flexes:
2860 pre = put_cmd_in_ert(new_flexes[flextype])
2861 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2863 argend = find_end_of_inset(document.body, arg)
2865 document.warning("Can't find end of Argument!")
2868 # Find containing paragraph layout
2869 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2870 endPlain = find_end_of_layout(document.body, beginPlain)
2871 argcontent = document.body[beginPlain + 1 : endPlain]
2873 z = z - len(document.body[arg : argend + 1])
2875 del document.body[arg : argend + 1]
2876 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2877 arg = find_token(document.body, "\\begin_inset Argument 2", i, z)
2879 argend = find_end_of_inset(document.body, arg)
2881 document.warning("Can't find end of Argument!")
2884 # Find containing paragraph layout
2885 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2886 endPlain = find_end_of_layout(document.body, beginPlain)
2887 argcontent = document.body[beginPlain + 1 : endPlain]
2889 z = z - len(document.body[arg : argend + 1])
2891 del document.body[arg : argend + 1]
2892 if flextype == "Alternative":
2893 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
2895 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2896 pre += put_cmd_in_ert("{")
2897 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2898 endPlain = find_end_of_layout(document.body, beginPlain)
2900 z = z - len(document.body[i : beginPlain + 1])
2902 document.body[i : beginPlain + 1] = pre
2903 post = put_cmd_in_ert("}")
2904 document.body[z - 2 : z + 1] = post
2905 elif flextype in old_flexes:
2906 pre = put_cmd_in_ert(old_flexes[flextype])
2907 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2911 argend = find_end_of_inset(document.body, arg)
2913 document.warning("Can't find end of Argument!")
2916 # Find containing paragraph layout
2917 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2918 endPlain = find_end_of_layout(document.body, beginPlain)
2919 argcontent = document.body[beginPlain + 1 : endPlain]
2921 z = z - len(document.body[arg : argend + 1])
2923 del document.body[arg : argend + 1]
2924 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2925 pre += put_cmd_in_ert("{")
2926 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2927 endPlain = find_end_of_layout(document.body, beginPlain)
2929 z = z - len(document.body[i : beginPlain + 1])
2931 document.body[i : beginPlain + 1] = pre
2932 post = put_cmd_in_ert("}")
2933 document.body[z - 2 : z + 1] = post
2938 def revert_beamerblocks(document):
2939 " Reverts beamer block arguments to ERT "
2941 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2942 if document.textclass not in beamer_classes:
2945 blocks = ["Block", "ExampleBlock", "AlertBlock"]
2947 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2950 i = find_token(document.body, "\\begin_inset Argument", i)
2953 # Find containing paragraph layout
2954 parent = get_containing_layout(document.body, i)
2956 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2961 realparbeg = parent[3]
2962 layoutname = parent[0]
2964 for p in range(parbeg, parend):
2968 if layoutname in blocks:
2969 m = rx.match(document.body[p])
2973 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2974 endPlain = find_end_of_layout(document.body, beginPlain)
2975 endInset = find_end_of_inset(document.body, p)
2976 content = document.body[beginPlain + 1 : endPlain]
2978 realparend = realparend - len(document.body[p : endInset + 1])
2980 del document.body[p : endInset + 1]
2981 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2982 document.body[realparbeg : realparbeg] = subst
2984 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2985 endPlain = find_end_of_layout(document.body, beginPlain)
2986 endInset = find_end_of_inset(document.body, p)
2987 content = document.body[beginPlain + 1 : endPlain]
2989 realparend = realparend - len(document.body[p : endInset + 1])
2991 del document.body[p : endInset + 1]
2992 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2993 document.body[realparbeg : realparbeg] = subst
2998 def convert_beamerblocks(document):
2999 " Converts beamer block ERT args to native InsetArgs "
3001 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3002 if document.textclass not in beamer_classes:
3005 blocks = ["Block", "ExampleBlock", "AlertBlock"]
3009 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
3012 parent = get_containing_layout(document.body, i)
3013 if parent == False or parent[1] != i:
3014 document.warning("Wrong parent layout!")
3021 if document.body[parbeg] == "\\begin_inset ERT":
3022 ertcontfirstline = parbeg + 5
3023 # Find the last ERT in this paragraph (which might also be the first)
3024 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
3025 if lastertbeg == -1:
3026 document.warning("Last ERT not found!")
3028 lastertend = find_end_of_inset(document.body, lastertbeg)
3029 if lastertend == -1:
3030 document.warning("End of last ERT not found!")
3032 ertcontlastline = lastertend - 3
3034 if document.body[ertcontfirstline].lstrip().startswith("<"):
3035 # This is an overlay specification
3037 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3038 if document.body[ertcontlastline].rstrip().endswith(">"):
3040 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3041 # Convert to ArgInset
3042 document.body[parbeg] = "\\begin_inset Argument 1"
3043 elif document.body[ertcontlastline].rstrip().endswith("}"):
3045 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3047 ertcontdivline = ertcontfirstline
3048 tok = document.body[ertcontdivline].find('>{')
3050 regexp = re.compile(r'.*>\{', re.IGNORECASE)
3051 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, ertcontlastline)
3052 tok = document.body[ertcontdivline].find('>{')
3054 if ertcontfirstline < ertcontlastline:
3055 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3056 document.body[ertcontlastline : ertcontlastline + 1] = [
3057 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3058 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3059 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3060 'status collapsed', '', '\\begin_layout Plain Layout',
3061 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3062 document.body[ertcontdivline][tok + 2:]]
3064 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3065 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3066 'status collapsed', '', '\\begin_layout Plain Layout',
3067 document.body[ertcontdivline][tok + 2:]]
3069 # check if have delimiters in two different ERTs
3070 tok = document.body[ertcontdivline].find('>')
3072 regexp = re.compile(r'.*>', re.IGNORECASE)
3073 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, ertcontlastline)
3074 tok = document.body[ertcontdivline].find('>')
3076 tokk = document.body[ertcontdivline].find('{')
3078 regexp = re.compile(r'.*\{', re.IGNORECASE)
3079 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, ertcontlastline)
3080 tokk = document.body[ertcontdivlinetwo].find('{')
3082 if ertcontfirstline < ertcontlastline:
3083 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3084 document.body[ertcontlastline : ertcontlastline + 1] = [
3085 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3086 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3087 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3088 '\\end_inset', '', '', '\\begin_inset Argument 2',
3089 'status collapsed', '', '\\begin_layout Plain Layout',
3090 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3091 document.body[ertcontdivlinetwo][tokk + 1:]]
3093 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3094 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3095 'status collapsed', '', '\\begin_layout Plain Layout',
3096 document.body[ertcontdivlinetwo][tokk + 1:]]
3097 # Convert to ArgInset
3098 if ertcontfirstline < ertcontlastline:
3099 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3100 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 1',
3101 'status collapsed', '', '\\begin_layout Plain Layout',
3102 '\\begin_inset ERT', '']
3104 document.body[parbeg] = "\\begin_inset Argument 1"
3105 elif document.body[ertcontfirstline].lstrip().startswith("{"):
3106 # This is the block title
3107 if document.body[ertcontlastline].rstrip().endswith("}"):
3108 # strip off the braces
3109 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3110 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3111 if ertcontfirstline < ertcontlastline:
3112 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3113 document.body[parend : parend + 1] = [
3114 document.body[parend], '\\end_inset', '', '\\end_layout']
3115 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3116 'status collapsed', '', '\\begin_layout Plain Layout',
3117 '\\begin_inset ERT', '']
3119 # Convert to ArgInset
3120 document.body[parbeg] = "\\begin_inset Argument 2"
3121 # the overlay argument can also follow the title, so ...
3122 elif document.body[ertcontlastline].rstrip().endswith(">"):
3124 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3126 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3128 ertcontdivline = ertcontfirstline
3129 tok = document.body[ertcontdivline].find('}<')
3131 regexp = re.compile(r'.*\}<', re.IGNORECASE)
3132 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, ertcontlastline)
3133 tok = document.body[ertcontdivline].find('}<')
3135 if ertcontfirstline < ertcontlastline:
3136 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3137 document.body[ertcontlastline : ertcontlastline + 1] = [
3138 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3139 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3140 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3141 'status collapsed', '', '\\begin_layout Plain Layout',
3142 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3143 document.body[ertcontdivline][tok + 2:]]
3145 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3146 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3147 'status collapsed', '', '\\begin_layout Plain Layout',
3148 document.body[ertcontdivline][tok + 2:]]
3150 # check if have delimiters in two different ERTs
3151 tok = document.body[ertcontdivline].find('}')
3153 regexp = re.compile(r'.*\}', re.IGNORECASE)
3154 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, ertcontlastline)
3155 tok = document.body[ertcontdivline].find('}')
3157 tokk = document.body[ertcontdivline].find('<')
3159 regexp = re.compile(r'.*<', re.IGNORECASE)
3160 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, ertcontlastline)
3161 tokk = document.body[ertcontdivlinetwo].find('<')
3163 if ertcontfirstline < ertcontlastline:
3164 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3165 document.body[ertcontlastline : ertcontlastline + 1] = [
3166 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3167 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3168 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3169 '\\end_inset', '', '', '\\begin_inset Argument 1',
3170 'status collapsed', '', '\\begin_layout Plain Layout',
3171 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3172 document.body[ertcontdivlinetwo][tokk + 1:]]
3174 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3175 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3176 'status collapsed', '', '\\begin_layout Plain Layout',
3177 document.body[ertcontdivlinetwo][tokk + 1:]]
3178 # Convert to ArgInset
3179 if ertcontfirstline < ertcontlastline:
3180 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3181 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3182 'status collapsed', '', '\\begin_layout Plain Layout',
3183 '\\begin_inset ERT', '']
3185 document.body[parbeg] = "\\begin_inset Argument 2"
3186 elif count_pars_in_inset(document.body, ertcontfirstline) > 1:
3187 # Multipar ERT. Skip this.
3190 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, False)
3193 j = find_end_of_layout(document.body, i)
3195 document.warning("end of layout not found!")
3196 k = find_token(document.body, "\\begin_inset Argument", i, j)
3198 document.warning("InsetArgument not found!")
3200 l = find_end_of_inset(document.body, k)
3201 m = find_token(document.body, "\\begin_inset ERT", l, j)
3204 ertcontfirstline = m + 5
3209 def convert_overprint(document):
3210 " Convert old beamer overprint layouts to ERT "
3212 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3213 if document.textclass not in beamer_classes:
3218 i = find_token(document.body, "\\begin_layout Overprint", i)
3221 # Find end of sequence
3222 j = find_end_of_sequence(document.body, i)
3224 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3228 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3230 if document.body[j] == "\\end_deeper":
3231 esubst = ["", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3233 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3234 endseq = endseq + len(esubst) - len(document.body[j : j])
3235 document.body[j : j] = esubst
3236 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3238 argend = find_end_of_layout(document.body, argbeg)
3240 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3243 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3244 endPlain = find_end_of_layout(document.body, beginPlain)
3245 content = document.body[beginPlain + 1 : endPlain]
3247 endseq = endseq - len(document.body[argbeg : argend + 1])
3249 del document.body[argbeg : argend + 1]
3250 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3252 endseq = endseq - len(document.body[i : i])
3253 document.body[i : i] = subst + ["\\end_layout"]
3254 endseq += len(subst)
3256 for p in range(i, endseq):
3257 if document.body[p] == "\\begin_layout Overprint":
3258 document.body[p] = "\\begin_layout Standard"
3263 def revert_overprint(document):
3264 " Revert old beamer overprint layouts to ERT "
3266 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3267 if document.textclass not in beamer_classes:
3272 i = find_token(document.body, "\\begin_layout Overprint", i)
3275 # Find end of sequence
3276 j = find_end_of_sequence(document.body, i)
3278 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3282 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3283 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}")
3284 endseq = endseq + len(esubst) - len(document.body[j : j])
3285 if document.body[j] == "\\end_deeper":
3286 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3288 document.body[j : j] = ["\\end_layout", ""] + esubst
3291 if document.body[r] == "\\begin_deeper":
3292 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3294 document.body[r] = ""
3295 document.body[s] = ""
3299 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3301 # Is this really our argument?
3302 nested = find_token(document.body, "\\begin_deeper", i, argbeg)
3304 argend = find_end_of_inset(document.body, argbeg)
3306 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3309 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3310 endPlain = find_end_of_layout(document.body, beginPlain)
3311 content = document.body[beginPlain + 1 : endPlain]
3313 endseq = endseq - len(document.body[argbeg : argend])
3315 del document.body[argbeg : argend + 1]
3316 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3318 endseq = endseq - len(document.body[i : i])
3319 document.body[i : i] = subst + ["\\end_layout"]
3320 endseq += len(subst)
3326 if document.body[p] == "\\begin_layout Overprint":
3327 q = find_end_of_layout(document.body, p)
3329 document.warning("Malformed LyX document. Cannot find end of Overprint layout!")
3332 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\onslide")
3333 argbeg = find_token(document.body, "\\begin_inset Argument item:1", p, q)
3335 argend = find_end_of_inset(document.body, argbeg)
3337 document.warning("Malformed LyX document. Cannot find end of Overprint item argument!")
3340 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3341 endPlain = find_end_of_layout(document.body, beginPlain)
3342 content = document.body[beginPlain + 1 : endPlain]
3344 endseq = endseq - len(document.body[argbeg : argend + 1])
3346 del document.body[argbeg : argend + 1]
3347 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3348 endseq = endseq - len(document.body[p : p + 1]) + len(subst)
3349 document.body[p : p + 1] = subst
3355 def revert_frametitle(document):
3356 " Reverts beamer frametitle layout to ERT "
3358 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3359 if document.textclass not in beamer_classes:
3362 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3365 i = find_token(document.body, "\\begin_layout FrameTitle", i)
3368 j = find_end_of_layout(document.body, i)
3370 document.warning("Malformed LyX document: Can't find end of FrameTitle layout")
3374 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
3375 endlay += len(put_cmd_in_ert("}"))
3376 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\frametitle")
3377 for p in range(i, j):
3380 m = rx.match(document.body[p])
3384 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3385 endPlain = find_end_of_layout(document.body, beginPlain)
3386 endInset = find_end_of_inset(document.body, p)
3387 content = document.body[beginPlain + 1 : endPlain]
3389 endlay = endlay - len(document.body[p : endInset + 1])
3391 del document.body[p : endInset + 1]
3392 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3394 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3395 endPlain = find_end_of_layout(document.body, beginPlain)
3396 endInset = find_end_of_inset(document.body, p)
3397 content = document.body[beginPlain + 1 : endPlain]
3399 endlay = endlay - len(document.body[p : endInset + 1])
3401 del document.body[p : endInset + 1]
3402 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3404 subst += put_cmd_in_ert("{")
3405 document.body[i : i + 1] = subst
3409 def convert_epigraph(document):
3410 " Converts memoir epigraph to new syntax "
3412 if document.textclass != "memoir":
3417 i = find_token(document.body, "\\begin_layout Epigraph", i)
3420 j = find_end_of_layout(document.body, i)
3422 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3427 ert = find_token(document.body, "\\begin_inset ERT", i, j)
3429 endInset = find_end_of_inset(document.body, ert)
3430 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", ert)
3431 endPlain = find_end_of_layout(document.body, beginPlain)
3432 ertcont = beginPlain + 2
3433 if document.body[ertcont] == "}{":
3435 # Convert to ArgInset
3436 endlay = endlay - 2 * len(document.body[j])
3437 begsubst = ['\\begin_inset Argument post:1', 'status collapsed', '',
3438 '\\begin_layout Plain Layout']
3439 endsubst = ['\\end_layout', '', '\\end_inset', '', document.body[j]]
3440 document.body[j : j + 1] = endsubst
3441 document.body[endInset + 1 : endInset + 1] = begsubst
3443 endlay += len(begsubst) + len(endsubst)
3444 endlay = endlay - len(document.body[ert : endInset + 1])
3445 del document.body[ert : endInset + 1]
3450 def revert_epigraph(document):
3451 " Reverts memoir epigraph argument to ERT "
3453 if document.textclass != "memoir":
3458 i = find_token(document.body, "\\begin_layout Epigraph", i)
3461 j = find_end_of_layout(document.body, i)
3463 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3468 p = find_token(document.body, "\\begin_layout Argument post:1", i, j)
3470 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3471 endPlain = find_end_of_layout(document.body, beginPlain)
3472 endInset = find_end_of_inset(document.body, p)
3473 content = document.body[beginPlain + 1 : endPlain]
3475 endlay = endlay - len(document.body[p : endInset + 1])
3477 del document.body[p : endInset + 1]
3478 subst += put_cmd_in_ert("}{") + content
3480 subst += put_cmd_in_ert("}{")
3482 document.body[j : j] = subst + document.body[j : j]
3486 def convert_captioninsets(document):
3487 " Converts caption insets to new syntax "
3491 i = find_token(document.body, "\\begin_inset Caption", i)
3494 document.body[i] = "\\begin_inset Caption Standard"
3498 def revert_captioninsets(document):
3499 " Reverts caption insets to old syntax "
3503 i = find_token(document.body, "\\begin_inset Caption Standard", i)
3506 document.body[i] = "\\begin_inset Caption"
3510 def convert_captionlayouts(document):
3511 " Convert caption layouts to caption insets. "
3514 "Captionabove": "Above",
3515 "Captionbelow": "Below",
3516 "FigCaption" : "FigCaption",
3517 "Table_Caption" : "Table",
3518 "CenteredCaption" : "Centered",
3519 "Bicaption" : "Bicaption",
3524 i = find_token(document.body, "\\begin_layout", i)
3527 val = get_value(document.body, "\\begin_layout", i)
3528 if val in caption_dict.keys():
3529 j = find_end_of_layout(document.body, i)
3531 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3534 document.body[j:j] = ["\\end_layout", "", "\\end_inset", "", ""]
3535 document.body[i:i+1] = ["\\begin_layout %s" % document.default_layout,
3536 "\\begin_inset Caption %s" % caption_dict[val], "",
3537 "\\begin_layout %s" % document.default_layout]
3541 def revert_captionlayouts(document):
3542 " Revert caption insets to caption layouts. "
3545 "Above" : "Captionabove",
3546 "Below" : "Captionbelow",
3547 "FigCaption" : "FigCaption",
3548 "Table" : "Table_Caption",
3549 "Centered" : "CenteredCaption",
3550 "Bicaption" : "Bicaption",
3554 rx = re.compile(r'^\\begin_inset Caption (\S+)$')
3556 i = find_token(document.body, "\\begin_inset Caption", i)
3560 m = rx.match(document.body[i])
3564 if val not in caption_dict.keys():
3568 # We either need to delete the previous \begin_layout line, or we
3569 # need to end the previous layout if this inset is not in the first
3570 # position of the paragraph.
3571 layout_before = find_token_backwards(document.body, "\\begin_layout", i)
3572 if layout_before == -1:
3573 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3575 layout_line = document.body[layout_before]
3576 del_layout_before = True
3577 l = layout_before + 1
3579 if document.body[l] != "":
3580 del_layout_before = False
3583 if del_layout_before:
3584 del document.body[layout_before:i]
3587 document.body[i:i] = ["\\end_layout", ""]
3590 # Find start of layout in the inset and end of inset
3591 j = find_token(document.body, "\\begin_layout", i)
3593 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3595 k = find_end_of_inset(document.body, i)
3597 document.warning("Malformed LyX document: Missing `\\end_inset'.")
3600 # We either need to delete the following \end_layout line, or we need
3601 # to restart the old layout if this inset is not at the paragraph end.
3602 layout_after = find_token(document.body, "\\end_layout", k)
3603 if layout_after == -1:
3604 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3606 del_layout_after = True
3608 while l < layout_after:
3609 if document.body[l] != "":
3610 del_layout_after = False
3613 if del_layout_after:
3614 del document.body[k+1:layout_after+1]
3616 document.body[k+1:k+1] = [layout_line, ""]
3618 # delete \begin_layout and \end_inset and replace \begin_inset with
3619 # "\begin_layout XXX". This works because we can only have one
3620 # paragraph in the caption inset: The old \end_layout will be recycled.
3621 del document.body[k]
3622 if document.body[k] == "":
3623 del document.body[k]
3624 del document.body[j]
3625 if document.body[j] == "":
3626 del document.body[j]
3627 document.body[i] = "\\begin_layout %s" % caption_dict[val]
3628 if document.body[i+1] == "":
3629 del document.body[i+1]
3633 def revert_fragileframe(document):
3634 " Reverts beamer FragileFrame layout to ERT "
3636 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3637 if document.textclass not in beamer_classes:
3642 i = find_token(document.body, "\\begin_layout FragileFrame", i)
3645 # Find end of sequence
3646 j = find_end_of_sequence(document.body, i)
3648 document.warning("Malformed LyX document. Cannot find end of FragileFrame sequence!")
3652 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{frame}")
3653 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{frame}")
3654 endseq = endseq + len(esubst) - len(document.body[j : j])
3655 if document.body[j] == "\\end_deeper":
3656 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3658 document.body[j : j] = esubst
3659 for q in range(i, j):
3660 if document.body[q] == "\\begin_layout FragileFrame":
3661 document.body[q] = "\\begin_layout %s" % document.default_layout
3664 if document.body[r] == "\\begin_deeper":
3665 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3667 document.body[r] = ""
3668 document.body[s] = ""
3672 for p in range(1, 5):
3673 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, j)
3676 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3677 endPlain = find_end_of_layout(document.body, beginPlain)
3678 endInset = find_end_of_inset(document.body, arg)
3679 content = document.body[beginPlain + 1 : endPlain]
3681 j = j - len(document.body[arg : endInset + 1])
3683 del document.body[arg : endInset + 1]
3684 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3686 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3687 endPlain = find_end_of_layout(document.body, beginPlain)
3688 endInset = find_end_of_inset(document.body, arg)
3689 content = document.body[beginPlain + 1 : endPlain]
3691 j = j - len(document.body[arg : endInset + 1])
3693 del document.body[arg : endInset + 1]
3694 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3696 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3697 endPlain = find_end_of_layout(document.body, beginPlain)
3698 endInset = find_end_of_inset(document.body, arg)
3699 content = document.body[beginPlain + 1 : endPlain]
3701 j = j - len(document.body[arg : endInset + 1])
3703 del document.body[arg : endInset + 1]
3704 subst += put_cmd_in_ert("[fragile,") + content + put_cmd_in_ert("]")
3706 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3707 endPlain = find_end_of_layout(document.body, beginPlain)
3708 endInset = find_end_of_inset(document.body, arg)
3709 content = document.body[beginPlain + 1 : endPlain]
3711 j = j - len(document.body[arg : endInset + 1])
3713 del document.body[arg : endInset + 1]
3714 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3716 subst += put_cmd_in_ert("[fragile]")
3718 document.body[i : i + 1] = subst
3722 def revert_newframes(document):
3723 " Reverts beamer Frame and PlainFrame layouts to old forms "
3725 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3726 if document.textclass not in beamer_classes:
3730 "Frame" : "BeginFrame",
3731 "PlainFrame" : "BeginPlainFrame",
3734 rx = re.compile(r'^\\begin_layout (\S+)$')
3737 i = find_token(document.body, "\\begin_layout", i)
3741 m = rx.match(document.body[i])
3745 if val not in frame_dict.keys():
3748 # Find end of sequence
3749 j = find_end_of_sequence(document.body, i)
3751 document.warning("Malformed LyX document. Cannot find end of Frame sequence!")
3755 subst = ["\\begin_layout %s" % frame_dict[val]]
3756 esubst = ["\\begin_layout EndFrame", "", "\\end_layout"]
3757 endseq = endseq + len(esubst) - len(document.body[j : j])
3758 if document.body[j] == "\\end_deeper":
3759 document.body[j : j] = [""] + esubst
3761 document.body[j : j] = esubst
3762 for q in range(i, j):
3763 if document.body[q] == "\\begin_layout %s" % val:
3764 document.body[q] = "\\begin_layout %s" % document.default_layout
3767 if document.body[r] == "\\begin_deeper":
3768 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3770 document.body[r] = ""
3771 document.body[s] = ""
3775 l = find_end_of_layout(document.body, i)
3776 for p in range(1, 5):
3777 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, l)
3780 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3781 endPlain = find_end_of_layout(document.body, beginPlain)
3782 endInset = find_end_of_inset(document.body, arg)
3783 content = document.body[beginPlain + 1 : endPlain]
3785 l = l - len(document.body[arg : endInset + 1])
3787 del document.body[arg : endInset + 1]
3788 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3790 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3791 endPlain = find_end_of_layout(document.body, beginPlain)
3792 endInset = find_end_of_inset(document.body, arg)
3793 content = document.body[beginPlain + 1 : endPlain]
3795 l = l - len(document.body[arg : endInset + 1])
3797 del document.body[arg : endInset + 1]
3798 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3800 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3801 endPlain = find_end_of_layout(document.body, beginPlain)
3802 endInset = find_end_of_inset(document.body, arg)
3803 content = document.body[beginPlain + 1 : endPlain]
3805 l = l - len(document.body[arg : endInset + 1])
3807 del document.body[arg : endInset + 1]
3808 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3810 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3811 endPlain = find_end_of_layout(document.body, beginPlain)
3812 endInset = find_end_of_inset(document.body, arg)
3813 content = document.body[beginPlain + 1 : endPlain]
3815 l = l - len(document.body[arg : endInset + 1])
3817 del document.body[arg : endInset + 1]
3820 document.body[i : i + 1] = subst
3823 # known encodings that do not change their names (same LyX and LaTeX names)
3824 known_enc_tuple = ("auto", "default", "ansinew", "applemac", "armscii8", "ascii",
3825 "cp437", "cp437de", "cp850", "cp852", "cp855", "cp858", "cp862", "cp865", "cp866",
3826 "cp1250", "cp1251", "cp1252", "cp1255", "cp1256", "cp1257", "koi8-r", "koi8-u",
3827 "pt154", "pt254", "tis620-0", "utf8", "utf8x", "utf8-plain")
3829 def convert_encodings(document):
3830 "Use the LyX names of the encodings instead of the LaTeX names."
3831 LaTeX2LyX_enc_dict = {
3832 "8859-6": "iso8859-6",
3833 "8859-8": "iso8859-8",
3835 "euc": "euc-jp-platex",
3840 "iso88595": "iso8859-5",
3841 "iso-8859-7": "iso8859-7",
3843 "jis": "jis-platex",
3845 "l7xenc": "iso8859-13",
3846 "latin1": "iso8859-1",
3847 "latin2": "iso8859-2",
3848 "latin3": "iso8859-3",
3849 "latin4": "iso8859-4",
3850 "latin5": "iso8859-9",
3851 "latin9": "iso8859-15",
3852 "latin10": "iso8859-16",
3853 "SJIS": "shift-jis",
3854 "sjis": "shift-jis-platex",
3857 i = find_token(document.header, "\\inputencoding" , 0)
3860 val = get_value(document.header, "\\inputencoding", i)
3861 if val in LaTeX2LyX_enc_dict.keys():
3862 document.header[i] = "\\inputencoding %s" % LaTeX2LyX_enc_dict[val]
3863 elif val not in known_enc_tuple:
3864 document.warning("Ignoring unknown input encoding: `%s'" % val)
3867 def revert_encodings(document):
3868 """Revert to using the LaTeX names of the encodings instead of the LyX names.
3869 Also revert utf8-platex to sjis, the language default when using Japanese.
3871 LyX2LaTeX_enc_dict = {
3876 "euc-jp-platex": "euc",
3879 "iso8859-1": "latin1",
3880 "iso8859-2": "latin2",
3881 "iso8859-3": "latin3",
3882 "iso8859-4": "latin4",
3883 "iso8859-5": "iso88595",
3884 "iso8859-6": "8859-6",
3885 "iso8859-7": "iso-8859-7",
3886 "iso8859-8": "8859-8",
3887 "iso8859-9": "latin5",
3888 "iso8859-13": "l7xenc",
3889 "iso8859-15": "latin9",
3890 "iso8859-16": "latin10",
3892 "jis-platex": "jis",
3893 "shift-jis": "SJIS",
3894 "shift-jis-platex": "sjis",
3896 "utf8-platex": "sjis"
3898 i = find_token(document.header, "\\inputencoding" , 0)
3901 val = get_value(document.header, "\\inputencoding", i)
3902 if val in LyX2LaTeX_enc_dict.keys():
3903 document.header[i] = "\\inputencoding %s" % LyX2LaTeX_enc_dict[val]
3904 elif val not in known_enc_tuple:
3905 document.warning("Ignoring unknown input encoding: `%s'" % val)
3908 def revert_IEEEtran_3(document):
3910 Reverts Flex Insets to TeX-code
3912 if document.textclass == "IEEEtran":
3918 h = find_token(document.body, "\\begin_inset Flex Author Mark", h)
3920 endh = find_end_of_inset(document.body, h)
3921 document.body[endh - 2 : endh + 1] = put_cmd_in_ert("}")
3922 document.body[h : h + 4] = put_cmd_in_ert("\\IEEEauthorrefmark{")
3925 i = find_token(document.body, "\\begin_inset Flex Author Name", i)
3927 endi = find_end_of_inset(document.body, i)
3928 document.body[endi - 2 : endi + 1] = put_cmd_in_ert("}")
3929 document.body[i : i + 4] = put_cmd_in_ert("\\IEEEauthorblockN{")
3932 j = find_token(document.body, "\\begin_inset Flex Author Affiliation", j)
3934 endj = find_end_of_inset(document.body, j)
3935 document.body[endj - 2 : endj + 1] = put_cmd_in_ert("}")
3936 document.body[j : j + 4] = put_cmd_in_ert("\\IEEEauthorblockA{")
3938 if i == -1 and j == -1 and h == -1:
3942 def revert_kurier_fonts(document):
3943 " Revert kurier font definition to LaTeX "
3945 i = find_token(document.header, "\\font_math", 0)
3947 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
3948 val = get_value(document.header, "\\font_math", i)
3949 if val == "kurier-math":
3950 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
3951 "\\usepackage[math]{kurier}\n" \
3952 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
3953 document.header[i] = "\\font_math auto"
3955 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
3956 kurier_fonts = ["kurier", "kurierc", "kurierl", "kurierlc"]
3957 k = find_token(document.header, "\\font_sans kurier", 0)
3959 sf = get_value(document.header, "\\font_sans", k)
3960 if sf in kurier_fonts:
3961 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
3962 document.header[k] = "\\font_sans default"
3964 def revert_iwona_fonts(document):
3965 " Revert iwona font definition to LaTeX "
3967 i = find_token(document.header, "\\font_math", 0)
3969 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
3970 val = get_value(document.header, "\\font_math", i)
3971 if val == "iwona-math":
3972 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
3973 "\\usepackage[math]{iwona}\n" \
3974 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
3975 document.header[i] = "\\font_math auto"
3977 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
3978 iwona_fonts = ["iwona", "iwonac", "iwonal", "iwonalc"]
3979 k = find_token(document.header, "\\font_sans iwona", 0)
3981 sf = get_value(document.header, "\\font_sans", k)
3982 if sf in iwona_fonts:
3983 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
3984 document.header[k] = "\\font_sans default"
3987 def revert_new_libertines(document):
3988 " Revert new libertine font definition to LaTeX "
3990 if find_token(document.header, "\\use_non_tex_fonts true", 0) != -1:
3993 i = find_token(document.header, "\\font_typewriter libertine-mono", 0)
3995 preamble = "\\usepackage"
3996 sc = find_token(document.header, "\\font_tt_scale", 0)
3998 scval = get_value(document.header, "\\font_tt_scale", sc)
4000 preamble += "[scale=%f]" % (float(scval) / 100)
4001 document.header[sc] = "\\font_tt_scale 100"
4002 preamble += "{libertineMono-type1}"
4003 add_to_preamble(document, [preamble])
4004 document.header[i] = "\\font_typewriter default"
4006 k = find_token(document.header, "\\font_sans biolinum", 0)
4008 preamble = "\\usepackage"
4010 j = find_token(document.header, "\\font_osf true", 0)
4015 sc = find_token(document.header, "\\font_sf_scale", 0)
4017 scval = get_value(document.header, "\\font_sf_scale", sc)
4019 options += ",scale=%f" % (float(scval) / 100)
4020 document.header[sc] = "\\font_sf_scale 100"
4022 preamble += "[" + options +"]"
4023 preamble += "{biolinum-type1}"
4024 add_to_preamble(document, [preamble])
4025 document.header[k] = "\\font_sans default"
4028 def convert_lyxframes(document):
4029 " Converts old beamer frames to new style "
4031 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4032 if document.textclass not in beamer_classes:
4035 framebeg = ["BeginFrame", "BeginPlainFrame"]
4036 frameend = ["Frame", "PlainFrame", "EndFrame", "BeginFrame", "BeginPlainFrame", "AgainFrame",
4037 "Section", "Section*", "Subsection", "Subsection*", "Subsubsection", "Subsubsection*"]
4038 for lay in framebeg:
4041 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
4044 parent = get_containing_layout(document.body, i)
4045 if parent == False or parent[1] != i:
4046 document.warning("Wrong parent layout!")
4049 frametype = parent[0]
4053 # Step I: Convert ERT arguments
4054 # FIXME: See restrictions in convert_beamerframeargs method
4055 ertend = convert_beamerframeargs(document, i, parbeg)
4058 # Step II: Now rename the layout and convert the title to an argument
4059 j = find_end_of_layout(document.body, i)
4060 document.body[j : j + 1] = ['\\end_layout', '', '\\end_inset', '', '\\end_layout']
4061 if lay == "BeginFrame":
4062 document.body[i] = "\\begin_layout Frame"
4064 document.body[i] = "\\begin_layout PlainFrame"
4065 document.body[ertend + 1 : ertend + 1] = ['\\begin_inset Argument 4',
4066 'status open', '', '\\begin_layout Plain Layout']
4067 # Step III: find real frame end
4071 fend = find_token(document.body, "\\begin_layout", jj)
4073 document.warning("Malformed LyX document: No real frame end!")
4075 val = get_value(document.body, "\\begin_layout", fend)
4076 if val not in frameend:
4079 old = document.body[fend]
4080 if val == frametype:
4081 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4082 # consider explicit EndFrames between two identical frame types
4083 elif val == "EndFrame":
4084 nextlayout = find_token(document.body, "\\begin_layout", fend + 1)
4085 if nextlayout != -1 and get_value(document.body, "\\begin_layout", nextlayout) == frametype:
4086 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4088 document.body[fend : fend] = ['\\end_deeper']
4090 document.body[fend : fend] = ['\\end_deeper']
4091 document.body[j + 1 : j + 1] = ['', '\\begin_deeper']
4096 def remove_endframes(document):
4097 " Remove deprecated beamer endframes "
4099 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4100 if document.textclass not in beamer_classes:
4105 i = find_token_exact(document.body, "\\begin_layout EndFrame", i)
4108 j = find_end_of_layout(document.body, i)
4110 document.warning("Malformed LyX document: Missing \\end_layout to EndFrame")
4113 del document.body[i : j + 1]
4116 def revert_powerdot_flexes(document):
4117 " Reverts powerdot flex insets "
4119 if document.textclass != "powerdot":
4122 flexes = {"Onslide" : "\\onslide",
4123 "Onslide*" : "\\onslide*",
4124 "Onslide+" : "\\onslide+"}
4125 rx = re.compile(r'^\\begin_inset Flex (.+)$')
4129 i = find_token(document.body, "\\begin_inset Flex", i)
4132 m = rx.match(document.body[i])
4134 flextype = m.group(1)
4135 z = find_end_of_inset(document.body, i)
4137 document.warning("Can't find end of Flex " + flextype + " inset.")
4140 if flextype in flexes:
4141 pre = put_cmd_in_ert(flexes[flextype])
4142 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
4144 argend = find_end_of_inset(document.body, arg)
4146 document.warning("Can't find end of Argument!")
4149 # Find containing paragraph layout
4150 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
4151 endPlain = find_end_of_layout(document.body, beginPlain)
4152 argcontent = document.body[beginPlain + 1 : endPlain]
4154 z = z - len(document.body[arg : argend + 1])
4156 del document.body[arg : argend + 1]
4157 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
4158 pre += put_cmd_in_ert("{")
4159 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4160 endPlain = find_end_of_layout(document.body, beginPlain)
4162 z = z - len(document.body[i : beginPlain + 1])
4164 document.body[i : beginPlain + 1] = pre
4165 post = put_cmd_in_ert("}")
4166 document.body[z - 2 : z + 1] = post
4170 def revert_powerdot_pause(document):
4171 " Reverts powerdot pause layout to ERT "
4173 if document.textclass != "powerdot":
4178 i = find_token(document.body, "\\begin_layout Pause", i)
4181 j = find_end_of_layout(document.body, i)
4183 document.warning("Malformed LyX document: Can't find end of Pause layout")
4187 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\pause")
4188 for p in range(i, j):
4191 arg = find_token(document.body, "\\begin_inset Argument 1", i, j)
4193 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4194 endPlain = find_end_of_layout(document.body, beginPlain)
4195 endInset = find_end_of_inset(document.body, p)
4196 content = document.body[beginPlain + 1 : endPlain]
4198 endlay = endlay - len(document.body[p : endInset + 1])
4200 del document.body[p : endInset + 1]
4201 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4203 document.body[i : i + 1] = subst
4207 def revert_powerdot_itemargs(document):
4208 " Reverts powerdot item arguments to ERT "
4210 if document.textclass != "powerdot":
4214 list_layouts = ["Itemize", "ItemizeType1", "Enumerate", "EnumerateType1"]
4215 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4218 i = find_token(document.body, "\\begin_inset Argument", i)
4221 # Find containing paragraph layout
4222 parent = get_containing_layout(document.body, i)
4224 document.warning("Malformed LyX document: Can't find parent paragraph layout")
4229 realparbeg = parent[3]
4230 layoutname = parent[0]
4232 for p in range(parbeg, parend):
4236 if layoutname in list_layouts:
4237 m = rx.match(document.body[p])
4240 if argnr == "item:1":
4241 j = find_end_of_inset(document.body, i)
4242 # Find containing paragraph layout
4243 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4244 endPlain = find_end_of_layout(document.body, beginPlain)
4245 content = document.body[beginPlain + 1 : endPlain]
4246 del document.body[i:j+1]
4247 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4248 document.body[realparbeg : realparbeg] = subst
4249 elif argnr == "item:2":
4250 j = find_end_of_inset(document.body, i)
4251 # Find containing paragraph layout
4252 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4253 endPlain = find_end_of_layout(document.body, beginPlain)
4254 content = document.body[beginPlain + 1 : endPlain]
4255 del document.body[i:j+1]
4256 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
4257 document.body[realparbeg : realparbeg] = subst
4262 def revert_powerdot_columns(document):
4263 " Reverts powerdot twocolumn to TeX-code "
4264 if document.textclass != "powerdot":
4267 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4270 i = find_token(document.body, "\\begin_layout Twocolumn", i)
4273 j = find_end_of_layout(document.body, i)
4275 document.warning("Malformed LyX document: Can't find end of Twocolumn layout")
4279 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
4280 endlay += len(put_cmd_in_ert("}"))
4281 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\twocolumn")
4282 for p in range(i, j):
4285 m = rx.match(document.body[p])
4289 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4290 endPlain = find_end_of_layout(document.body, beginPlain)
4291 endInset = find_end_of_inset(document.body, p)
4292 content = document.body[beginPlain + 1 : endPlain]
4294 endlay = endlay - len(document.body[p : endInset + 1])
4296 del document.body[p : endInset + 1]
4297 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4299 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4300 endPlain = find_end_of_layout(document.body, beginPlain)
4301 endInset = find_end_of_inset(document.body, p)
4302 content = document.body[beginPlain + 1 : endPlain]
4304 endlay = endlay - len(document.body[p : endInset + 1])
4306 del document.body[p : endInset + 1]
4307 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
4309 subst += put_cmd_in_ert("{")
4310 document.body[i : i + 1] = subst
4314 def revert_mbox_fbox(document):
4315 'Convert revert mbox/fbox boxes to TeX-code'
4318 i = find_token(document.body, "\\begin_inset Box", i)
4321 j = find_token(document.body, "width", i)
4323 document.warning("Malformed LyX document: Can't find box width")
4325 width = get_value(document.body, "width", j)
4326 k = find_end_of_inset(document.body, j)
4328 document.warning("Malformed LyX document: Can't find end of box inset")
4331 BeginLayout = find_token(document.body, "\\begin_layout Plain Layout", j)
4332 EndLayout = find_token(document.body, "\\end_layout", BeginLayout)
4333 # replace if width is ""
4335 document.body[EndLayout:k + 1] = put_cmd_in_ert("}")
4336 if document.body[i] == "\\begin_inset Box Frameless":
4337 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\mbox{")
4338 if document.body[i] == "\\begin_inset Box Boxed":
4339 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\fbox{")
4343 def revert_starred_caption(document):
4344 " Reverts unnumbered longtable caption insets "
4348 i = find_token(document.body, "\\begin_inset Caption LongTableNoNumber", i)
4351 # This is not equivalent, but since the caption inset is a full blown
4352 # text inset a true conversion to ERT is too difficult.
4353 document.body[i] = "\\begin_inset Caption Standard"
4357 def revert_forced_local_layout(document):
4360 i = find_token(document.header, "\\begin_forced_local_layout", i)
4363 j = find_end_of(document.header, i, "\\begin_forced_local_layout", "\\end_forced_local_layout")
4365 # this should not happen
4367 regexp = re.compile(r'\s*forcelocal', re.IGNORECASE)
4368 k = find_re(document.header, regexp, i, j)
4370 del document.header[k]
4372 k = find_re(document.header, regexp, i, j)
4373 k = find_token(document.header, "\\begin_local_layout", 0)
4375 document.header[i] = "\\begin_local_layout"
4376 document.header[j] = "\\end_local_layout"
4378 l = find_end_of(document.header, k, "\\begin_local_layout", "\\end_local_layout")
4380 # this should not happen
4382 lines = document.header[i+1 : j]
4384 document.header[k+1 : k+1] = lines
4385 document.header[i : j ] = []
4387 document.header[i : j ] = []
4388 document.header[k+1 : k+1] = lines
4391 def revert_aa1(document):
4392 " Reverts InsetArguments of aa to TeX-code "
4393 if document.textclass == "aa":
4397 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4399 revert_Argument_to_TeX_brace(document, i, 0, 1, 4, False, False)
4405 def revert_aa2(document):
4406 " Reverts InsetArguments of aa to TeX-code "
4407 if document.textclass == "aa":
4411 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4413 document.body[i] = "\\begin_layout Abstract"
4419 def revert_tibetan(document):
4420 "Set the document language for Tibetan to English"
4422 if document.language == "tibetan":
4423 document.language = "english"
4424 i = find_token(document.header, "\\language", 0)
4426 document.header[i] = "\\language english"
4428 while j < len(document.body):
4429 j = find_token(document.body, "\\lang tibetan", j)
4431 document.body[j] = document.body[j].replace("\\lang tibetan", "\\lang english")
4434 j = len(document.body)
4443 # The idea here is that we will have a sequence of chunk paragraphs.
4444 # We want to convert them to paragraphs in one or several chunk insets.
4445 # Individual chunks are terminated by the character @ on the last line.
4446 # This line will be discarded, and following lines are treated as new
4447 # chunks, which go into their own insets.
4448 # The first line of a chunk should look like: <<CONTENT>>=
4449 # We will discard the delimiters, and put the CONTENT into the
4450 # optional argument of the inset, if the CONTENT is non-empty.
4451 def convert_chunks(document):
4452 first_re = re.compile(r'<<(.*)>>=(.*)')
4455 # find start of a block of chunks
4456 i = find_token(document.body, "\\begin_layout Chunk", file_pos)
4462 chunk_started = False
4465 # process the one we just found
4466 j = find_end_of_layout(document.body, i)
4468 document.warning("Malformed LyX documents. Can't find end of Chunk layout!")
4469 # there is no point continuing, as we will run into the same error again.
4471 this_chunk = "".join(document.body[i + 1:j])
4473 # there may be empty lines between chunks
4474 # we just skip them.
4475 if not chunk_started:
4476 if this_chunk != "":
4478 chunk_started = True
4481 contents.append(document.body[i + 1:j])
4483 # look for potential chunk terminator
4484 # on the last line of the chunk paragraph
4485 if document.body[j - 1] == "@":
4488 # look for subsequent chunk paragraph
4489 i = find_token(document.body, "\\begin_layout", j)
4493 if get_value(document.body, "\\begin_layout", i) != "Chunk":
4496 file_pos = end = j + 1
4498 # The last chunk should simply have an "@" in it
4499 # or at least end with "@" (can happen if @ is
4500 # preceded by a newline)
4501 lastpar = ''.join(contents[-1])
4502 if not lastpar.endswith("@"):
4503 document.warning("Unexpected chunk content: chunk not terminated by '@'!")
4507 # chunk par only contains "@". Just drop it.
4510 # chunk par contains more. Only drop the "@".
4513 # The first line should look like: <<CONTENT>>=
4514 # We want the CONTENT
4515 optarg = ' '.join(contents[0])
4517 # We can already have real chunk content in
4518 # the first par (separated from the options by a newline).
4519 # We collect such stuff to re-insert it later.
4522 match = first_re.search(optarg)
4524 optarg = match.groups()[0]
4525 if match.groups()[1] != "":
4527 for c in contents[0]:
4528 if c.endswith(">>="):
4532 postoptstuff.append(c)
4533 # We have stripped everything. This can be deleted.
4536 newstuff = ['\\begin_layout Standard',
4537 '\\begin_inset Flex Chunk',
4539 '\\begin_layout Plain Layout', '']
4541 # If we have a non-empty optional argument, insert it.
4542 if match and optarg != "":
4544 ['\\begin_inset Argument 1',
4546 '\\begin_layout Plain Layout',
4551 # Since we already opened a Plain layout, the first paragraph
4552 # does not need to do that.
4555 newstuff.extend(postoptstuff)
4556 newstuff.append('\\end_layout')
4560 newstuff.extend(['', '\\begin_layout Plain Layout', ''])
4564 newstuff.append('\\end_layout')
4566 newstuff.extend(['', '\\end_inset', '', '\\end_layout', ''])
4568 document.body[start:end] = newstuff
4570 file_pos += len(newstuff) - (end - start)
4573 def revert_chunks(document):
4576 i = find_token(document.body, "\\begin_inset Flex Chunk", i)
4580 iend = find_end_of_inset(document.body, i)
4582 document.warning("Can't find end of Chunk!")
4586 # Look for optional argument
4588 ostart = find_token(document.body, "\\begin_inset Argument 1", i, iend)
4590 oend = find_end_of_inset(document.body, ostart)
4591 k = find_token(document.body, "\\begin_layout Plain Layout", ostart, oend)
4593 document.warning("Malformed LyX document: Can't find argument contents!")
4595 m = find_end_of_layout(document.body, k)
4596 optarg = "".join(document.body[k+1:m])
4599 # We now remove the optional argument, so we have something
4600 # uniform on which to work
4601 document.body[ostart : oend + 1] = []
4602 # iend is now invalid
4603 iend = find_end_of_inset(document.body, i)
4605 retval = get_containing_layout(document.body, i)
4607 document.warning("Can't find containing layout for Chunk!")
4610 (lname, lstart, lend, pstart) = retval
4611 # we now want to work through the various paragraphs, and collect their contents
4615 k = find_token(document.body, "\\begin_layout Plain Layout", k, lend)
4618 j = find_end_of_layout(document.body, k)
4620 document.warning("Can't find end of layout inside chunk!")
4622 parlist.append(document.body[k+1:j])
4624 # we now need to wrap all of these paragraphs in chunks
4627 newlines.extend(["\\begin_layout Chunk", "", "<<" + optarg + ">>=", "\\end_layout", ""])
4628 for stuff in parlist:
4629 newlines.extend(["\\begin_layout Chunk"] + stuff + ["\\end_layout", ""])
4630 newlines.extend(["\\begin_layout Chunk", "", "@", "\\end_layout", ""])
4631 # replace old content with new content
4632 document.body[lstart : lend + 1] = newlines
4633 i = lstart + len(newlines)
4640 supported_versions = ["2.1.0","2.1"]
4643 [415, [convert_undertilde]],
4645 [417, [convert_japanese_encodings]],
4646 [418, [convert_justification]],
4648 [420, [convert_biblio_style]],
4649 [421, [convert_longtable_captions]],
4650 [422, [convert_use_packages]],
4651 [423, [convert_use_mathtools]],
4652 [424, [convert_cite_engine_type]],
4653 # No convert_cancel, since cancel will be loaded automatically
4654 # in format 425 without any possibility to switch it off.
4655 # This has been fixed in format 464.
4659 [428, [convert_cell_rotation]],
4660 [429, [convert_table_rotation]],
4661 [430, [convert_listoflistings]],
4662 [431, [convert_use_amssymb]],
4664 [433, [convert_armenian]],
4672 [441, [convert_mdnomath]],
4677 [446, [convert_latexargs]],
4678 [447, [convert_IEEEtran, convert_AASTeX, convert_AGUTeX, convert_IJMP, convert_SIGPLAN, convert_SIGGRAPH, convert_EuropeCV, convert_Initials, convert_ModernCV]],
4679 [448, [convert_literate]],
4682 [451, [convert_beamerargs, convert_againframe_args, convert_corollary_args, convert_quote_args]],
4683 [452, [convert_beamerblocks]],
4684 [453, [convert_use_stmaryrd]],
4685 [454, [convert_overprint]],
4687 [456, [convert_epigraph]],
4688 [457, [convert_use_stackrel]],
4689 [458, [convert_captioninsets, convert_captionlayouts]],
4694 [463, [convert_encodings]],
4695 [464, [convert_use_cancel]],
4696 [465, [convert_lyxframes, remove_endframes]],
4702 [471, [convert_cite_engine_type_default]],
4705 [474, [convert_chunks]],
4709 [473, [revert_chunks]],
4710 [472, [revert_tibetan]],
4711 [471, [revert_aa1,revert_aa2]],
4712 [470, [revert_cite_engine_type_default]],
4713 [469, [revert_forced_local_layout]],
4714 [468, [revert_starred_caption]],
4715 [467, [revert_mbox_fbox]],
4716 [466, [revert_iwona_fonts]],
4717 [465, [revert_powerdot_flexes, revert_powerdot_pause, revert_powerdot_itemargs, revert_powerdot_columns]],
4719 [463, [revert_use_cancel]],
4720 [462, [revert_encodings]],
4721 [461, [revert_new_libertines]],
4722 [460, [revert_kurier_fonts]],
4723 [459, [revert_IEEEtran_3]],
4724 [458, [revert_fragileframe, revert_newframes]],
4725 [457, [revert_captioninsets, revert_captionlayouts]],
4726 [456, [revert_use_stackrel]],
4727 [455, [revert_epigraph]],
4728 [454, [revert_frametitle]],
4729 [453, [revert_overprint]],
4730 [452, [revert_use_stmaryrd]],
4731 [451, [revert_beamerblocks]],
4732 [450, [revert_beamerargs, revert_beamerargs2, revert_beamerargs3, revert_beamerflex]],
4733 [449, [revert_garamondx, revert_garamondx_newtxmath]],
4734 [448, [revert_itemargs]],
4735 [447, [revert_literate]],
4736 [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]],
4737 [445, [revert_latexargs]],
4738 [444, [revert_uop]],
4739 [443, [revert_biolinum]],
4741 [441, [revert_newtxmath]],
4742 [440, [revert_mdnomath]],
4743 [439, [revert_mathfonts]],
4744 [438, [revert_minionpro]],
4745 [437, [revert_ipadeco, revert_ipachar]],
4746 [436, [revert_texgyre]],
4747 [435, [revert_mathdesign]],
4748 [434, [revert_txtt]],
4749 [433, [revert_libertine]],
4750 [432, [revert_armenian]],
4751 [431, [revert_languages, revert_ancientgreek]],
4752 [430, [revert_use_amssymb]],
4753 [429, [revert_listoflistings]],
4754 [428, [revert_table_rotation]],
4755 [427, [revert_cell_rotation]],
4756 [426, [revert_tipa]],
4757 [425, [revert_verbatim]],
4758 [424, [revert_cancel]],
4759 [423, [revert_cite_engine_type]],
4760 [422, [revert_use_mathtools]],
4761 [421, [revert_use_packages]],
4762 [420, [revert_longtable_captions]],
4763 [419, [revert_biblio_style]],
4764 [418, [revert_australian]],
4765 [417, [revert_justification]],
4766 [416, [revert_japanese_encodings]],
4767 [415, [revert_negative_space, revert_math_spaces]],
4768 [414, [revert_undertilde]],
4769 [413, [revert_visible_space]]
4773 if __name__ == "__main__":