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 cleanup_beamerargs(document):
2519 " Clean up empty ERTs (conversion artefacts) "
2521 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2522 if document.textclass not in beamer_classes:
2527 i = find_token(document.body, "\\begin_inset Argument", i)
2530 j = find_end_of_inset(document.body, i)
2532 document.warning("Malformed LyX document: Can't find end of Argument inset")
2536 ertbeg = find_token(document.body, "\\begin_inset ERT", i, j)
2539 ertend = find_end_of_inset(document.body, ertbeg)
2541 document.warning("Malformed LyX document: Can't find end of ERT inset")
2543 stripped = [line for line in document.body[ertbeg : ertend + 1] if line.strip()]
2544 if len(stripped) == 5:
2545 # This is an empty ERT
2546 offset = len(document.body[ertbeg : ertend + 1])
2547 del document.body[ertbeg : ertend + 1]
2554 def revert_beamerargs(document):
2555 " Reverts beamer arguments to old layout "
2557 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2558 if document.textclass not in beamer_classes:
2562 list_layouts = ["Itemize", "Enumerate", "Description"]
2563 headings = ["Part", "Section", "Section*", "Subsection", "Subsection*",
2564 "Subsubsection", "Subsubsection*", "FrameSubtitle", "NoteItem"]
2565 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2566 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2567 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2570 i = find_token(document.body, "\\begin_inset Argument", i)
2573 # Find containing paragraph layout
2574 parent = get_containing_layout(document.body, i)
2576 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2581 realparbeg = parent[3]
2582 layoutname = parent[0]
2584 for p in range(parbeg, parend):
2588 if layoutname in headings:
2589 m = rx.match(document.body[p])
2593 # Find containing paragraph layout
2594 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2595 endPlain = find_end_of_layout(document.body, beginPlain)
2596 endInset = find_end_of_inset(document.body, p)
2597 argcontent = document.body[beginPlain + 1 : endPlain]
2599 realparend = realparend - len(document.body[p : endInset + 1])
2601 del document.body[p : endInset + 1]
2602 if layoutname == "FrameSubtitle":
2603 pre = put_cmd_in_ert("\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2604 elif layoutname == "NoteItem":
2605 pre = put_cmd_in_ert("\\note<") + argcontent + put_cmd_in_ert(">[item]")
2606 elif layoutname.endswith('*'):
2607 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower()[:-1] + "<") + argcontent + put_cmd_in_ert(">*")
2609 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2610 secarg = find_token(document.body, "\\begin_inset Argument 2", parbeg, parend)
2612 # Find containing paragraph layout
2613 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", secarg)
2614 endPlain = find_end_of_layout(document.body, beginPlain)
2615 endInset = find_end_of_inset(document.body, secarg)
2616 argcontent = document.body[beginPlain + 1 : endPlain]
2618 realparend = realparend - len(document.body[secarg : endInset + 1])
2619 del document.body[secarg : endInset + 1]
2620 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2621 pre += put_cmd_in_ert("{")
2622 document.body[parbeg] = "\\begin_layout Standard"
2623 document.body[realparbeg : realparbeg] = pre
2624 pe = find_end_of_layout(document.body, parbeg)
2625 post = put_cmd_in_ert("}")
2626 document.body[pe : pe] = post
2627 realparend += len(pre) + len(post)
2628 if layoutname == "AgainFrame":
2629 m = rx.match(document.body[p])
2633 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2634 endPlain = find_end_of_layout(document.body, beginPlain)
2635 endInset = find_end_of_inset(document.body, p)
2636 content = document.body[beginPlain + 1 : endPlain]
2638 realparend = realparend - len(document.body[p : endInset + 1])
2640 del document.body[p : endInset + 1]
2641 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2642 document.body[realparbeg : realparbeg] = subst
2643 if layoutname == "Overprint":
2644 m = rx.match(document.body[p])
2648 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2649 endPlain = find_end_of_layout(document.body, beginPlain)
2650 endInset = find_end_of_inset(document.body, p)
2651 content = document.body[beginPlain + 1 : endPlain]
2653 realparend = realparend - len(document.body[p : endInset + 1])
2655 del document.body[p : endInset + 1]
2656 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2657 document.body[realparbeg : realparbeg] = subst
2658 if layoutname == "OverlayArea":
2659 m = rx.match(document.body[p])
2663 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2664 endPlain = find_end_of_layout(document.body, beginPlain)
2665 endInset = find_end_of_inset(document.body, p)
2666 content = document.body[beginPlain + 1 : endPlain]
2668 realparend = realparend - len(document.body[p : endInset + 1])
2670 del document.body[p : endInset + 1]
2671 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2672 document.body[realparbeg : realparbeg] = subst
2673 if layoutname in list_layouts:
2674 m = rx.match(document.body[p])
2678 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2679 endPlain = find_end_of_layout(document.body, beginPlain)
2680 endInset = find_end_of_inset(document.body, p)
2681 content = document.body[beginPlain + 1 : endPlain]
2682 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2683 realparend = realparend + len(subst) - len(content)
2684 document.body[beginPlain + 1 : endPlain] = subst
2685 elif argnr == "item:1":
2686 j = find_end_of_inset(document.body, i)
2687 # Find containing paragraph layout
2688 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2689 endPlain = find_end_of_layout(document.body, beginPlain)
2690 content = document.body[beginPlain + 1 : endPlain]
2691 del document.body[i:j+1]
2692 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2693 document.body[realparbeg : realparbeg] = subst
2694 elif argnr == "item:2":
2695 j = find_end_of_inset(document.body, i)
2696 # Find containing paragraph layout
2697 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2698 endPlain = find_end_of_layout(document.body, beginPlain)
2699 content = document.body[beginPlain + 1 : endPlain]
2700 del document.body[i:j+1]
2701 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2702 document.body[realparbeg : realparbeg] = subst
2703 if layoutname in quote_layouts:
2704 m = rx.match(document.body[p])
2708 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2709 endPlain = find_end_of_layout(document.body, beginPlain)
2710 endInset = find_end_of_inset(document.body, p)
2711 content = document.body[beginPlain + 1 : endPlain]
2713 realparend = realparend - len(document.body[p : endInset + 1])
2715 del document.body[p : endInset + 1]
2716 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2717 document.body[realparbeg : realparbeg] = subst
2718 if layoutname in corollary_layouts:
2719 m = rx.match(document.body[p])
2723 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2724 endPlain = find_end_of_layout(document.body, beginPlain)
2725 endInset = find_end_of_inset(document.body, p)
2726 content = document.body[beginPlain + 1 : endPlain]
2728 realparend = realparend - len(document.body[p : endInset + 1])
2730 del document.body[p : endInset + 1]
2731 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2732 document.body[realparbeg : realparbeg] = subst
2737 def revert_beamerargs2(document):
2738 " Reverts beamer arguments to old layout, step 2 "
2740 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2741 if document.textclass not in beamer_classes:
2745 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2746 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2747 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2750 i = find_token(document.body, "\\begin_inset Argument", i)
2753 # Find containing paragraph layout
2754 parent = get_containing_layout(document.body, i)
2756 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2761 realparbeg = parent[3]
2762 layoutname = parent[0]
2764 for p in range(parbeg, parend):
2768 if layoutname in shifted_layouts:
2769 m = rx.match(document.body[p])
2773 document.body[p] = "\\begin_inset Argument 1"
2774 if layoutname in corollary_layouts:
2775 m = rx.match(document.body[p])
2779 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2780 endPlain = find_end_of_layout(document.body, beginPlain)
2781 endInset = find_end_of_inset(document.body, p)
2782 content = document.body[beginPlain + 1 : endPlain]
2784 realparend = realparend - len(document.body[p : endInset + 1])
2786 del document.body[p : endInset + 1]
2787 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2788 document.body[realparbeg : realparbeg] = subst
2789 if layoutname == "OverlayArea":
2790 m = rx.match(document.body[p])
2794 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2795 endPlain = find_end_of_layout(document.body, beginPlain)
2796 endInset = find_end_of_inset(document.body, p)
2797 content = document.body[beginPlain + 1 : endPlain]
2799 realparend = realparend - len(document.body[p : endInset + 1])
2801 del document.body[p : endInset + 1]
2802 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2803 document.body[realparbeg : realparbeg] = subst
2804 if layoutname == "AgainFrame":
2805 m = rx.match(document.body[p])
2809 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2810 endPlain = find_end_of_layout(document.body, beginPlain)
2811 endInset = find_end_of_inset(document.body, p)
2812 content = document.body[beginPlain + 1 : endPlain]
2814 realparend = realparend - len(document.body[p : endInset + 1])
2816 del document.body[p : endInset + 1]
2817 subst = put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
2818 document.body[realparbeg : realparbeg] = subst
2822 def revert_beamerargs3(document):
2823 " Reverts beamer arguments to old layout, step 3 "
2825 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2826 if document.textclass not in beamer_classes:
2829 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2832 i = find_token(document.body, "\\begin_inset Argument", i)
2835 # Find containing paragraph layout
2836 parent = get_containing_layout(document.body, i)
2838 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2843 realparbeg = parent[3]
2844 layoutname = parent[0]
2846 for p in range(parbeg, parend):
2850 if layoutname == "AgainFrame":
2851 m = rx.match(document.body[p])
2855 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2856 endPlain = find_end_of_layout(document.body, beginPlain)
2857 endInset = find_end_of_inset(document.body, p)
2858 content = document.body[beginPlain + 1 : endPlain]
2860 realparend = realparend - len(document.body[p : endInset + 1])
2862 del document.body[p : endInset + 1]
2863 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2864 document.body[realparbeg : realparbeg] = subst
2868 def revert_beamerflex(document):
2869 " Reverts beamer Flex insets "
2871 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2872 if document.textclass not in beamer_classes:
2875 new_flexes = {"Bold" : "\\textbf", "Emphasize" : "\\emph", "Only" : "\\only",
2876 "Uncover" : "\\uncover", "Visible" : "\\visible",
2877 "Invisible" : "\\invisible", "Alternative" : "\\alt",
2878 "Beamer_Note" : "\\note"}
2879 old_flexes = {"Alert" : "\\alert", "Structure" : "\\structure"}
2880 rx = re.compile(r'^\\begin_inset Flex (.+)$')
2884 i = find_token(document.body, "\\begin_inset Flex", i)
2887 m = rx.match(document.body[i])
2889 flextype = m.group(1)
2890 z = find_end_of_inset(document.body, i)
2892 document.warning("Can't find end of Flex " + flextype + " inset.")
2895 if flextype in new_flexes:
2896 pre = put_cmd_in_ert(new_flexes[flextype])
2897 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2899 argend = find_end_of_inset(document.body, arg)
2901 document.warning("Can't find end of Argument!")
2904 # Find containing paragraph layout
2905 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2906 endPlain = find_end_of_layout(document.body, beginPlain)
2907 argcontent = document.body[beginPlain + 1 : endPlain]
2909 z = z - len(document.body[arg : argend + 1])
2911 del document.body[arg : argend + 1]
2912 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2913 arg = find_token(document.body, "\\begin_inset Argument 2", i, z)
2915 argend = find_end_of_inset(document.body, arg)
2917 document.warning("Can't find end of Argument!")
2920 # Find containing paragraph layout
2921 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2922 endPlain = find_end_of_layout(document.body, beginPlain)
2923 argcontent = document.body[beginPlain + 1 : endPlain]
2925 z = z - len(document.body[arg : argend + 1])
2927 del document.body[arg : argend + 1]
2928 if flextype == "Alternative":
2929 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
2931 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2932 pre += put_cmd_in_ert("{")
2933 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2934 endPlain = find_end_of_layout(document.body, beginPlain)
2936 z = z - len(document.body[i : beginPlain + 1])
2938 document.body[i : beginPlain + 1] = pre
2939 post = put_cmd_in_ert("}")
2940 document.body[z - 2 : z + 1] = post
2941 elif flextype in old_flexes:
2942 pre = put_cmd_in_ert(old_flexes[flextype])
2943 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2947 argend = find_end_of_inset(document.body, arg)
2949 document.warning("Can't find end of Argument!")
2952 # Find containing paragraph layout
2953 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2954 endPlain = find_end_of_layout(document.body, beginPlain)
2955 argcontent = document.body[beginPlain + 1 : endPlain]
2957 z = z - len(document.body[arg : argend + 1])
2959 del document.body[arg : argend + 1]
2960 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2961 pre += put_cmd_in_ert("{")
2962 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2963 endPlain = find_end_of_layout(document.body, beginPlain)
2965 z = z - len(document.body[i : beginPlain + 1])
2967 document.body[i : beginPlain + 1] = pre
2968 post = put_cmd_in_ert("}")
2969 document.body[z - 2 : z + 1] = post
2974 def revert_beamerblocks(document):
2975 " Reverts beamer block arguments to ERT "
2977 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2978 if document.textclass not in beamer_classes:
2981 blocks = ["Block", "ExampleBlock", "AlertBlock"]
2983 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2986 i = find_token(document.body, "\\begin_inset Argument", i)
2989 # Find containing paragraph layout
2990 parent = get_containing_layout(document.body, i)
2992 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2997 realparbeg = parent[3]
2998 layoutname = parent[0]
3000 for p in range(parbeg, parend):
3004 if layoutname in blocks:
3005 m = rx.match(document.body[p])
3009 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3010 endPlain = find_end_of_layout(document.body, beginPlain)
3011 endInset = find_end_of_inset(document.body, p)
3012 content = document.body[beginPlain + 1 : endPlain]
3014 realparend = realparend - len(document.body[p : endInset + 1])
3016 del document.body[p : endInset + 1]
3017 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3018 document.body[realparbeg : realparbeg] = subst
3020 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3021 endPlain = find_end_of_layout(document.body, beginPlain)
3022 endInset = find_end_of_inset(document.body, p)
3023 content = document.body[beginPlain + 1 : endPlain]
3025 realparend = realparend - len(document.body[p : endInset + 1])
3027 del document.body[p : endInset + 1]
3028 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3029 document.body[realparbeg : realparbeg] = subst
3034 def convert_beamerblocks(document):
3035 " Converts beamer block ERT args to native InsetArgs "
3037 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3038 if document.textclass not in beamer_classes:
3041 blocks = ["Block", "ExampleBlock", "AlertBlock"]
3045 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
3048 parent = get_containing_layout(document.body, i)
3049 if parent == False or parent[1] != i:
3050 document.warning("Wrong parent layout!")
3057 if document.body[parbeg] == "\\begin_inset ERT":
3058 ertcontfirstline = parbeg + 5
3059 # Find the last ERT in this paragraph (which might also be the first)
3060 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
3061 if lastertbeg == -1:
3062 document.warning("Last ERT not found!")
3064 lastertend = find_end_of_inset(document.body, lastertbeg)
3065 if lastertend == -1:
3066 document.warning("End of last ERT not found!")
3068 ertcontlastline = lastertend - 3
3070 if document.body[ertcontfirstline].lstrip().startswith("<"):
3071 # This is an overlay specification
3073 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3074 if document.body[ertcontlastline].rstrip().endswith(">"):
3076 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3077 # Convert to ArgInset
3078 document.body[parbeg] = "\\begin_inset Argument 1"
3079 elif document.body[ertcontlastline].rstrip().endswith("}"):
3081 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3083 ertcontdivline = ertcontfirstline
3084 tok = document.body[ertcontdivline].find('>{')
3086 regexp = re.compile(r'.*>\{', re.IGNORECASE)
3087 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, ertcontlastline)
3088 tok = document.body[ertcontdivline].find('>{')
3090 if ertcontfirstline < ertcontlastline:
3091 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3092 document.body[ertcontlastline : ertcontlastline + 1] = [
3093 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3094 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3095 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3096 'status collapsed', '', '\\begin_layout Plain Layout',
3097 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3098 document.body[ertcontdivline][tok + 2:]]
3100 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3101 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3102 'status collapsed', '', '\\begin_layout Plain Layout',
3103 document.body[ertcontdivline][tok + 2:]]
3105 # check if have delimiters in two different ERTs
3106 tok = document.body[ertcontdivline].find('>')
3108 regexp = re.compile(r'.*>', re.IGNORECASE)
3109 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, ertcontlastline)
3110 tok = document.body[ertcontdivline].find('>')
3112 tokk = document.body[ertcontdivline].find('{')
3114 regexp = re.compile(r'.*\{', re.IGNORECASE)
3115 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, ertcontlastline)
3116 tokk = document.body[ertcontdivlinetwo].find('{')
3118 if ertcontfirstline < ertcontlastline:
3119 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3120 document.body[ertcontlastline : ertcontlastline + 1] = [
3121 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3122 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3123 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3124 '\\end_inset', '', '', '\\begin_inset Argument 2',
3125 'status collapsed', '', '\\begin_layout Plain Layout',
3126 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3127 document.body[ertcontdivlinetwo][tokk + 1:]]
3129 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3130 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3131 'status collapsed', '', '\\begin_layout Plain Layout',
3132 document.body[ertcontdivlinetwo][tokk + 1:]]
3133 # Convert to ArgInset
3134 if ertcontfirstline < ertcontlastline:
3135 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3136 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 1',
3137 'status collapsed', '', '\\begin_layout Plain Layout',
3138 '\\begin_inset ERT', '']
3140 document.body[parbeg] = "\\begin_inset Argument 1"
3141 elif document.body[ertcontfirstline].lstrip().startswith("{"):
3142 # This is the block title
3143 if document.body[ertcontlastline].rstrip().endswith("}"):
3144 # strip off the braces
3145 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3146 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3147 if ertcontfirstline < ertcontlastline:
3148 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3149 document.body[parend : parend + 1] = [
3150 document.body[parend], '\\end_inset', '', '\\end_layout']
3151 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3152 'status collapsed', '', '\\begin_layout Plain Layout',
3153 '\\begin_inset ERT', '']
3155 # Convert to ArgInset
3156 document.body[parbeg] = "\\begin_inset Argument 2"
3157 # the overlay argument can also follow the title, so ...
3158 elif document.body[ertcontlastline].rstrip().endswith(">"):
3160 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3162 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3164 ertcontdivline = ertcontfirstline
3165 tok = document.body[ertcontdivline].find('}<')
3167 regexp = re.compile(r'.*\}<', re.IGNORECASE)
3168 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, ertcontlastline)
3169 tok = document.body[ertcontdivline].find('}<')
3171 if ertcontfirstline < ertcontlastline:
3172 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3173 document.body[ertcontlastline : ertcontlastline + 1] = [
3174 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3175 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3176 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3177 'status collapsed', '', '\\begin_layout Plain Layout',
3178 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3179 document.body[ertcontdivline][tok + 2:]]
3181 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3182 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3183 'status collapsed', '', '\\begin_layout Plain Layout',
3184 document.body[ertcontdivline][tok + 2:]]
3186 # check if have delimiters in two different ERTs
3187 tok = document.body[ertcontdivline].find('}')
3189 regexp = re.compile(r'.*\}', re.IGNORECASE)
3190 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, ertcontlastline)
3191 tok = document.body[ertcontdivline].find('}')
3193 tokk = document.body[ertcontdivline].find('<')
3195 regexp = re.compile(r'.*<', re.IGNORECASE)
3196 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, ertcontlastline)
3197 tokk = document.body[ertcontdivlinetwo].find('<')
3199 if ertcontfirstline < ertcontlastline:
3200 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3201 document.body[ertcontlastline : ertcontlastline + 1] = [
3202 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3203 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3204 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3205 '\\end_inset', '', '', '\\begin_inset Argument 1',
3206 'status collapsed', '', '\\begin_layout Plain Layout',
3207 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3208 document.body[ertcontdivlinetwo][tokk + 1:]]
3210 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3211 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3212 'status collapsed', '', '\\begin_layout Plain Layout',
3213 document.body[ertcontdivlinetwo][tokk + 1:]]
3214 # Convert to ArgInset
3215 if ertcontfirstline < ertcontlastline:
3216 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3217 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3218 'status collapsed', '', '\\begin_layout Plain Layout',
3219 '\\begin_inset ERT', '']
3221 document.body[parbeg] = "\\begin_inset Argument 2"
3222 elif count_pars_in_inset(document.body, ertcontfirstline) > 1:
3223 # Multipar ERT. Skip this.
3226 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, False)
3229 j = find_end_of_layout(document.body, i)
3231 document.warning("end of layout not found!")
3232 k = find_token(document.body, "\\begin_inset Argument", i, j)
3234 document.warning("InsetArgument not found!")
3236 l = find_end_of_inset(document.body, k)
3237 m = find_token(document.body, "\\begin_inset ERT", l, j)
3240 ertcontfirstline = m + 5
3245 def convert_overprint(document):
3246 " Convert old beamer overprint layouts to ERT "
3248 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3249 if document.textclass not in beamer_classes:
3254 i = find_token(document.body, "\\begin_layout Overprint", i)
3257 # Find end of sequence
3258 j = find_end_of_sequence(document.body, i)
3260 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3264 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3266 if document.body[j] == "\\end_deeper":
3267 esubst = ["", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3269 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3270 endseq = endseq + len(esubst) - len(document.body[j : j])
3271 document.body[j : j] = esubst
3272 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3274 argend = find_end_of_layout(document.body, argbeg)
3276 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3279 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3280 endPlain = find_end_of_layout(document.body, beginPlain)
3281 content = document.body[beginPlain + 1 : endPlain]
3283 endseq = endseq - len(document.body[argbeg : argend + 1])
3285 del document.body[argbeg : argend + 1]
3286 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3288 endseq = endseq - len(document.body[i : i])
3289 document.body[i : i] = subst + ["\\end_layout"]
3290 endseq += len(subst)
3292 for p in range(i, endseq):
3293 if document.body[p] == "\\begin_layout Overprint":
3294 document.body[p] = "\\begin_layout Standard"
3299 def revert_overprint(document):
3300 " Revert old beamer overprint layouts to ERT "
3302 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3303 if document.textclass not in beamer_classes:
3308 i = find_token(document.body, "\\begin_layout Overprint", i)
3311 # Find end of sequence
3312 j = find_end_of_sequence(document.body, i)
3314 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3318 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3319 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}")
3320 endseq = endseq + len(esubst) - len(document.body[j : j])
3321 if document.body[j] == "\\end_deeper":
3322 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3324 document.body[j : j] = ["\\end_layout", ""] + esubst
3327 if document.body[r] == "\\begin_deeper":
3328 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3330 document.body[r] = ""
3331 document.body[s] = ""
3335 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3337 # Is this really our argument?
3338 nested = find_token(document.body, "\\begin_deeper", i, argbeg)
3340 argend = find_end_of_inset(document.body, argbeg)
3342 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3345 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3346 endPlain = find_end_of_layout(document.body, beginPlain)
3347 content = document.body[beginPlain + 1 : endPlain]
3349 endseq = endseq - len(document.body[argbeg : argend])
3351 del document.body[argbeg : argend + 1]
3352 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3354 endseq = endseq - len(document.body[i : i])
3355 document.body[i : i] = subst + ["\\end_layout"]
3356 endseq += len(subst)
3362 if document.body[p] == "\\begin_layout Overprint":
3363 q = find_end_of_layout(document.body, p)
3365 document.warning("Malformed LyX document. Cannot find end of Overprint layout!")
3368 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\onslide")
3369 argbeg = find_token(document.body, "\\begin_inset Argument item:1", p, q)
3371 argend = find_end_of_inset(document.body, argbeg)
3373 document.warning("Malformed LyX document. Cannot find end of Overprint item argument!")
3376 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3377 endPlain = find_end_of_layout(document.body, beginPlain)
3378 content = document.body[beginPlain + 1 : endPlain]
3380 endseq = endseq - len(document.body[argbeg : argend + 1])
3382 del document.body[argbeg : argend + 1]
3383 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3384 endseq = endseq - len(document.body[p : p + 1]) + len(subst)
3385 document.body[p : p + 1] = subst
3391 def revert_frametitle(document):
3392 " Reverts beamer frametitle layout to ERT "
3394 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3395 if document.textclass not in beamer_classes:
3398 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3401 i = find_token(document.body, "\\begin_layout FrameTitle", i)
3404 j = find_end_of_layout(document.body, i)
3406 document.warning("Malformed LyX document: Can't find end of FrameTitle layout")
3410 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
3411 endlay += len(put_cmd_in_ert("}"))
3412 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\frametitle")
3413 for p in range(i, j):
3416 m = rx.match(document.body[p])
3420 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3421 endPlain = find_end_of_layout(document.body, beginPlain)
3422 endInset = find_end_of_inset(document.body, p)
3423 content = document.body[beginPlain + 1 : endPlain]
3425 endlay = endlay - len(document.body[p : endInset + 1])
3427 del document.body[p : endInset + 1]
3428 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3430 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3431 endPlain = find_end_of_layout(document.body, beginPlain)
3432 endInset = find_end_of_inset(document.body, p)
3433 content = document.body[beginPlain + 1 : endPlain]
3435 endlay = endlay - len(document.body[p : endInset + 1])
3437 del document.body[p : endInset + 1]
3438 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3440 subst += put_cmd_in_ert("{")
3441 document.body[i : i + 1] = subst
3445 def convert_epigraph(document):
3446 " Converts memoir epigraph to new syntax "
3448 if document.textclass != "memoir":
3453 i = find_token(document.body, "\\begin_layout Epigraph", i)
3456 j = find_end_of_layout(document.body, i)
3458 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3463 ert = find_token(document.body, "\\begin_inset ERT", i, j)
3465 endInset = find_end_of_inset(document.body, ert)
3466 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", ert)
3467 endPlain = find_end_of_layout(document.body, beginPlain)
3468 ertcont = beginPlain + 2
3469 if document.body[ertcont] == "}{":
3471 # Convert to ArgInset
3472 endlay = endlay - 2 * len(document.body[j])
3473 begsubst = ['\\begin_inset Argument post:1', 'status collapsed', '',
3474 '\\begin_layout Plain Layout']
3475 endsubst = ['\\end_layout', '', '\\end_inset', '', document.body[j]]
3476 document.body[j : j + 1] = endsubst
3477 document.body[endInset + 1 : endInset + 1] = begsubst
3479 endlay += len(begsubst) + len(endsubst)
3480 endlay = endlay - len(document.body[ert : endInset + 1])
3481 del document.body[ert : endInset + 1]
3486 def revert_epigraph(document):
3487 " Reverts memoir epigraph argument to ERT "
3489 if document.textclass != "memoir":
3494 i = find_token(document.body, "\\begin_layout Epigraph", i)
3497 j = find_end_of_layout(document.body, i)
3499 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3504 p = find_token(document.body, "\\begin_layout Argument post:1", i, j)
3506 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3507 endPlain = find_end_of_layout(document.body, beginPlain)
3508 endInset = find_end_of_inset(document.body, p)
3509 content = document.body[beginPlain + 1 : endPlain]
3511 endlay = endlay - len(document.body[p : endInset + 1])
3513 del document.body[p : endInset + 1]
3514 subst += put_cmd_in_ert("}{") + content
3516 subst += put_cmd_in_ert("}{")
3518 document.body[j : j] = subst + document.body[j : j]
3522 def convert_captioninsets(document):
3523 " Converts caption insets to new syntax "
3527 i = find_token(document.body, "\\begin_inset Caption", i)
3530 document.body[i] = "\\begin_inset Caption Standard"
3534 def revert_captioninsets(document):
3535 " Reverts caption insets to old syntax "
3539 i = find_token(document.body, "\\begin_inset Caption Standard", i)
3542 document.body[i] = "\\begin_inset Caption"
3546 def convert_captionlayouts(document):
3547 " Convert caption layouts to caption insets. "
3550 "Captionabove": "Above",
3551 "Captionbelow": "Below",
3552 "FigCaption" : "FigCaption",
3553 "Table_Caption" : "Table",
3554 "CenteredCaption" : "Centered",
3555 "Bicaption" : "Bicaption",
3560 i = find_token(document.body, "\\begin_layout", i)
3563 val = get_value(document.body, "\\begin_layout", i)
3564 if val in caption_dict.keys():
3565 j = find_end_of_layout(document.body, i)
3567 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3570 document.body[j:j] = ["\\end_layout", "", "\\end_inset", "", ""]
3571 document.body[i:i+1] = ["\\begin_layout %s" % document.default_layout,
3572 "\\begin_inset Caption %s" % caption_dict[val], "",
3573 "\\begin_layout %s" % document.default_layout]
3577 def revert_captionlayouts(document):
3578 " Revert caption insets to caption layouts. "
3581 "Above" : "Captionabove",
3582 "Below" : "Captionbelow",
3583 "FigCaption" : "FigCaption",
3584 "Table" : "Table_Caption",
3585 "Centered" : "CenteredCaption",
3586 "Bicaption" : "Bicaption",
3590 rx = re.compile(r'^\\begin_inset Caption (\S+)$')
3592 i = find_token(document.body, "\\begin_inset Caption", i)
3596 m = rx.match(document.body[i])
3600 if val not in caption_dict.keys():
3604 # We either need to delete the previous \begin_layout line, or we
3605 # need to end the previous layout if this inset is not in the first
3606 # position of the paragraph.
3607 layout_before = find_token_backwards(document.body, "\\begin_layout", i)
3608 if layout_before == -1:
3609 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3611 layout_line = document.body[layout_before]
3612 del_layout_before = True
3613 l = layout_before + 1
3615 if document.body[l] != "":
3616 del_layout_before = False
3619 if del_layout_before:
3620 del document.body[layout_before:i]
3623 document.body[i:i] = ["\\end_layout", ""]
3626 # Find start of layout in the inset and end of inset
3627 j = find_token(document.body, "\\begin_layout", i)
3629 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3631 k = find_end_of_inset(document.body, i)
3633 document.warning("Malformed LyX document: Missing `\\end_inset'.")
3636 # We either need to delete the following \end_layout line, or we need
3637 # to restart the old layout if this inset is not at the paragraph end.
3638 layout_after = find_token(document.body, "\\end_layout", k)
3639 if layout_after == -1:
3640 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3642 del_layout_after = True
3644 while l < layout_after:
3645 if document.body[l] != "":
3646 del_layout_after = False
3649 if del_layout_after:
3650 del document.body[k+1:layout_after+1]
3652 document.body[k+1:k+1] = [layout_line, ""]
3654 # delete \begin_layout and \end_inset and replace \begin_inset with
3655 # "\begin_layout XXX". This works because we can only have one
3656 # paragraph in the caption inset: The old \end_layout will be recycled.
3657 del document.body[k]
3658 if document.body[k] == "":
3659 del document.body[k]
3660 del document.body[j]
3661 if document.body[j] == "":
3662 del document.body[j]
3663 document.body[i] = "\\begin_layout %s" % caption_dict[val]
3664 if document.body[i+1] == "":
3665 del document.body[i+1]
3669 def revert_fragileframe(document):
3670 " Reverts beamer FragileFrame layout to ERT "
3672 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3673 if document.textclass not in beamer_classes:
3678 i = find_token(document.body, "\\begin_layout FragileFrame", i)
3681 # Find end of sequence
3682 j = find_end_of_sequence(document.body, i)
3684 document.warning("Malformed LyX document. Cannot find end of FragileFrame sequence!")
3688 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{frame}")
3689 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{frame}")
3690 endseq = endseq + len(esubst) - len(document.body[j : j])
3691 if document.body[j] == "\\end_deeper":
3692 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3694 document.body[j : j] = esubst
3695 for q in range(i, j):
3696 if document.body[q] == "\\begin_layout FragileFrame":
3697 document.body[q] = "\\begin_layout %s" % document.default_layout
3700 if document.body[r] == "\\begin_deeper":
3701 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3703 document.body[r] = ""
3704 document.body[s] = ""
3708 for p in range(1, 5):
3709 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, j)
3712 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3713 endPlain = find_end_of_layout(document.body, beginPlain)
3714 endInset = find_end_of_inset(document.body, arg)
3715 content = document.body[beginPlain + 1 : endPlain]
3717 j = j - len(document.body[arg : endInset + 1])
3719 del document.body[arg : endInset + 1]
3720 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3722 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3723 endPlain = find_end_of_layout(document.body, beginPlain)
3724 endInset = find_end_of_inset(document.body, arg)
3725 content = document.body[beginPlain + 1 : endPlain]
3727 j = j - len(document.body[arg : endInset + 1])
3729 del document.body[arg : endInset + 1]
3730 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3732 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3733 endPlain = find_end_of_layout(document.body, beginPlain)
3734 endInset = find_end_of_inset(document.body, arg)
3735 content = document.body[beginPlain + 1 : endPlain]
3737 j = j - len(document.body[arg : endInset + 1])
3739 del document.body[arg : endInset + 1]
3740 subst += put_cmd_in_ert("[fragile,") + content + put_cmd_in_ert("]")
3742 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3743 endPlain = find_end_of_layout(document.body, beginPlain)
3744 endInset = find_end_of_inset(document.body, arg)
3745 content = document.body[beginPlain + 1 : endPlain]
3747 j = j - len(document.body[arg : endInset + 1])
3749 del document.body[arg : endInset + 1]
3750 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3752 subst += put_cmd_in_ert("[fragile]")
3754 document.body[i : i + 1] = subst
3758 def revert_newframes(document):
3759 " Reverts beamer Frame and PlainFrame layouts to old forms "
3761 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3762 if document.textclass not in beamer_classes:
3766 "Frame" : "BeginFrame",
3767 "PlainFrame" : "BeginPlainFrame",
3770 rx = re.compile(r'^\\begin_layout (\S+)$')
3773 i = find_token(document.body, "\\begin_layout", i)
3777 m = rx.match(document.body[i])
3781 if val not in frame_dict.keys():
3784 # Find end of sequence
3785 j = find_end_of_sequence(document.body, i)
3787 document.warning("Malformed LyX document. Cannot find end of Frame sequence!")
3791 subst = ["\\begin_layout %s" % frame_dict[val]]
3792 esubst = ["", "\\begin_layout EndFrame", "", "\\end_layout"]
3793 endseq = endseq + len(esubst) - len(document.body[j : j])
3794 if document.body[j] == "\\end_deeper":
3795 document.body[j : j] = esubst
3797 document.body[j+1 : j+1] = esubst
3798 for q in range(i, j):
3799 if document.body[q] == "\\begin_layout %s" % val:
3800 document.body[q] = "\\begin_layout %s" % document.default_layout
3803 if document.body[r] == "\\begin_deeper":
3804 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3806 document.body[r] = ""
3807 document.body[s] = ""
3811 l = find_end_of_layout(document.body, i)
3812 for p in range(1, 5):
3813 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, l)
3816 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3817 endPlain = find_end_of_layout(document.body, beginPlain)
3818 endInset = find_end_of_inset(document.body, arg)
3819 content = document.body[beginPlain + 1 : endPlain]
3821 l = l - len(document.body[arg : endInset + 1])
3823 del document.body[arg : endInset + 1]
3824 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3826 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3827 endPlain = find_end_of_layout(document.body, beginPlain)
3828 endInset = find_end_of_inset(document.body, arg)
3829 content = document.body[beginPlain + 1 : endPlain]
3831 l = l - len(document.body[arg : endInset + 1])
3833 del document.body[arg : endInset + 1]
3834 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3836 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3837 endPlain = find_end_of_layout(document.body, beginPlain)
3838 endInset = find_end_of_inset(document.body, arg)
3839 content = document.body[beginPlain + 1 : endPlain]
3841 l = l - len(document.body[arg : endInset + 1])
3843 del document.body[arg : endInset + 1]
3844 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3846 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3847 endPlain = find_end_of_layout(document.body, beginPlain)
3848 endInset = find_end_of_inset(document.body, arg)
3849 content = document.body[beginPlain + 1 : endPlain]
3851 l = l - len(document.body[arg : endInset + 1])
3853 del document.body[arg : endInset + 1]
3856 document.body[i : i + 1] = subst
3859 # known encodings that do not change their names (same LyX and LaTeX names)
3860 known_enc_tuple = ("auto", "default", "ansinew", "applemac", "armscii8", "ascii",
3861 "cp437", "cp437de", "cp850", "cp852", "cp855", "cp858", "cp862", "cp865", "cp866",
3862 "cp1250", "cp1251", "cp1252", "cp1255", "cp1256", "cp1257", "koi8-r", "koi8-u",
3863 "pt154", "pt254", "tis620-0", "utf8", "utf8x", "utf8-plain")
3865 def convert_encodings(document):
3866 "Use the LyX names of the encodings instead of the LaTeX names."
3867 LaTeX2LyX_enc_dict = {
3868 "8859-6": "iso8859-6",
3869 "8859-8": "iso8859-8",
3871 "euc": "euc-jp-platex",
3876 "iso88595": "iso8859-5",
3877 "iso-8859-7": "iso8859-7",
3879 "jis": "jis-platex",
3881 "l7xenc": "iso8859-13",
3882 "latin1": "iso8859-1",
3883 "latin2": "iso8859-2",
3884 "latin3": "iso8859-3",
3885 "latin4": "iso8859-4",
3886 "latin5": "iso8859-9",
3887 "latin9": "iso8859-15",
3888 "latin10": "iso8859-16",
3889 "SJIS": "shift-jis",
3890 "sjis": "shift-jis-platex",
3893 i = find_token(document.header, "\\inputencoding" , 0)
3896 val = get_value(document.header, "\\inputencoding", i)
3897 if val in LaTeX2LyX_enc_dict.keys():
3898 document.header[i] = "\\inputencoding %s" % LaTeX2LyX_enc_dict[val]
3899 elif val not in known_enc_tuple:
3900 document.warning("Ignoring unknown input encoding: `%s'" % val)
3903 def revert_encodings(document):
3904 """Revert to using the LaTeX names of the encodings instead of the LyX names.
3905 Also revert utf8-platex to sjis, the language default when using Japanese.
3907 LyX2LaTeX_enc_dict = {
3912 "euc-jp-platex": "euc",
3915 "iso8859-1": "latin1",
3916 "iso8859-2": "latin2",
3917 "iso8859-3": "latin3",
3918 "iso8859-4": "latin4",
3919 "iso8859-5": "iso88595",
3920 "iso8859-6": "8859-6",
3921 "iso8859-7": "iso-8859-7",
3922 "iso8859-8": "8859-8",
3923 "iso8859-9": "latin5",
3924 "iso8859-13": "l7xenc",
3925 "iso8859-15": "latin9",
3926 "iso8859-16": "latin10",
3928 "jis-platex": "jis",
3929 "shift-jis": "SJIS",
3930 "shift-jis-platex": "sjis",
3932 "utf8-platex": "sjis"
3934 i = find_token(document.header, "\\inputencoding" , 0)
3937 val = get_value(document.header, "\\inputencoding", i)
3938 if val in LyX2LaTeX_enc_dict.keys():
3939 document.header[i] = "\\inputencoding %s" % LyX2LaTeX_enc_dict[val]
3940 elif val not in known_enc_tuple:
3941 document.warning("Ignoring unknown input encoding: `%s'" % val)
3944 def revert_IEEEtran_3(document):
3946 Reverts Flex Insets to TeX-code
3948 if document.textclass == "IEEEtran":
3954 h = find_token(document.body, "\\begin_inset Flex Author Mark", h)
3956 endh = find_end_of_inset(document.body, h)
3957 document.body[endh - 2 : endh + 1] = put_cmd_in_ert("}")
3958 document.body[h : h + 4] = put_cmd_in_ert("\\IEEEauthorrefmark{")
3961 i = find_token(document.body, "\\begin_inset Flex Author Name", i)
3963 endi = find_end_of_inset(document.body, i)
3964 document.body[endi - 2 : endi + 1] = put_cmd_in_ert("}")
3965 document.body[i : i + 4] = put_cmd_in_ert("\\IEEEauthorblockN{")
3968 j = find_token(document.body, "\\begin_inset Flex Author Affiliation", j)
3970 endj = find_end_of_inset(document.body, j)
3971 document.body[endj - 2 : endj + 1] = put_cmd_in_ert("}")
3972 document.body[j : j + 4] = put_cmd_in_ert("\\IEEEauthorblockA{")
3974 if i == -1 and j == -1 and h == -1:
3978 def revert_kurier_fonts(document):
3979 " Revert kurier font definition to LaTeX "
3981 i = find_token(document.header, "\\font_math", 0)
3983 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
3984 val = get_value(document.header, "\\font_math", i)
3985 if val == "kurier-math":
3986 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
3987 "\\usepackage[math]{kurier}\n" \
3988 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
3989 document.header[i] = "\\font_math auto"
3991 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
3992 kurier_fonts = ["kurier", "kurierc", "kurierl", "kurierlc"]
3993 k = find_token(document.header, "\\font_sans kurier", 0)
3995 sf = get_value(document.header, "\\font_sans", k)
3996 if sf in kurier_fonts:
3997 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
3998 document.header[k] = "\\font_sans default"
4000 def revert_iwona_fonts(document):
4001 " Revert iwona font definition to LaTeX "
4003 i = find_token(document.header, "\\font_math", 0)
4005 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4006 val = get_value(document.header, "\\font_math", i)
4007 if val == "iwona-math":
4008 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
4009 "\\usepackage[math]{iwona}\n" \
4010 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
4011 document.header[i] = "\\font_math auto"
4013 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4014 iwona_fonts = ["iwona", "iwonac", "iwonal", "iwonalc"]
4015 k = find_token(document.header, "\\font_sans iwona", 0)
4017 sf = get_value(document.header, "\\font_sans", k)
4018 if sf in iwona_fonts:
4019 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4020 document.header[k] = "\\font_sans default"
4023 def revert_new_libertines(document):
4024 " Revert new libertine font definition to LaTeX "
4026 if find_token(document.header, "\\use_non_tex_fonts true", 0) != -1:
4029 i = find_token(document.header, "\\font_typewriter libertine-mono", 0)
4031 preamble = "\\usepackage"
4032 sc = find_token(document.header, "\\font_tt_scale", 0)
4034 scval = get_value(document.header, "\\font_tt_scale", sc)
4036 preamble += "[scale=%f]" % (float(scval) / 100)
4037 document.header[sc] = "\\font_tt_scale 100"
4038 preamble += "{libertineMono-type1}"
4039 add_to_preamble(document, [preamble])
4040 document.header[i] = "\\font_typewriter default"
4042 k = find_token(document.header, "\\font_sans biolinum", 0)
4044 preamble = "\\usepackage"
4046 j = find_token(document.header, "\\font_osf true", 0)
4051 sc = find_token(document.header, "\\font_sf_scale", 0)
4053 scval = get_value(document.header, "\\font_sf_scale", sc)
4055 options += ",scale=%f" % (float(scval) / 100)
4056 document.header[sc] = "\\font_sf_scale 100"
4058 preamble += "[" + options +"]"
4059 preamble += "{biolinum-type1}"
4060 add_to_preamble(document, [preamble])
4061 document.header[k] = "\\font_sans default"
4064 def convert_lyxframes(document):
4065 " Converts old beamer frames to new style "
4067 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4068 if document.textclass not in beamer_classes:
4071 framebeg = ["BeginFrame", "BeginPlainFrame"]
4072 frameend = ["Frame", "PlainFrame", "EndFrame", "BeginFrame", "BeginPlainFrame", "AgainFrame",
4073 "Section", "Section*", "Subsection", "Subsection*", "Subsubsection", "Subsubsection*"]
4074 for lay in framebeg:
4077 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
4080 parent = get_containing_layout(document.body, i)
4081 if parent == False or parent[1] != i:
4082 document.warning("Wrong parent layout!")
4085 frametype = parent[0]
4089 # Step I: Convert ERT arguments
4090 # FIXME: See restrictions in convert_beamerframeargs method
4091 ertend = convert_beamerframeargs(document, i, parbeg)
4094 # Step II: Now rename the layout and convert the title to an argument
4095 j = find_end_of_layout(document.body, i)
4096 document.body[j : j + 1] = ['\\end_layout', '', '\\end_inset', '', '\\end_layout']
4097 if lay == "BeginFrame":
4098 document.body[i] = "\\begin_layout Frame"
4100 document.body[i] = "\\begin_layout PlainFrame"
4101 document.body[ertend + 1 : ertend + 1] = ['\\begin_inset Argument 4',
4102 'status open', '', '\\begin_layout Plain Layout']
4103 # Step III: find real frame end
4107 fend = find_token(document.body, "\\begin_layout", jj)
4109 document.warning("Malformed LyX document: No real frame end!")
4111 val = get_value(document.body, "\\begin_layout", fend)
4112 if val not in frameend:
4115 old = document.body[fend]
4116 if val == frametype:
4117 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4118 # consider explicit EndFrames between two identical frame types
4119 elif val == "EndFrame":
4120 nextlayout = find_token(document.body, "\\begin_layout", fend + 1)
4121 if nextlayout != -1 and get_value(document.body, "\\begin_layout", nextlayout) == frametype:
4122 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4124 document.body[fend : fend] = ['\\end_deeper']
4126 document.body[fend : fend] = ['\\end_deeper']
4127 document.body[j + 1 : j + 1] = ['', '\\begin_deeper']
4132 def remove_endframes(document):
4133 " Remove deprecated beamer endframes "
4135 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4136 if document.textclass not in beamer_classes:
4141 i = find_token_exact(document.body, "\\begin_layout EndFrame", i)
4144 j = find_end_of_layout(document.body, i)
4146 document.warning("Malformed LyX document: Missing \\end_layout to EndFrame")
4149 del document.body[i : j + 1]
4152 def revert_powerdot_flexes(document):
4153 " Reverts powerdot flex insets "
4155 if document.textclass != "powerdot":
4158 flexes = {"Onslide" : "\\onslide",
4159 "Onslide*" : "\\onslide*",
4160 "Onslide+" : "\\onslide+"}
4161 rx = re.compile(r'^\\begin_inset Flex (.+)$')
4165 i = find_token(document.body, "\\begin_inset Flex", i)
4168 m = rx.match(document.body[i])
4170 flextype = m.group(1)
4171 z = find_end_of_inset(document.body, i)
4173 document.warning("Can't find end of Flex " + flextype + " inset.")
4176 if flextype in flexes:
4177 pre = put_cmd_in_ert(flexes[flextype])
4178 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
4180 argend = find_end_of_inset(document.body, arg)
4182 document.warning("Can't find end of Argument!")
4185 # Find containing paragraph layout
4186 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
4187 endPlain = find_end_of_layout(document.body, beginPlain)
4188 argcontent = document.body[beginPlain + 1 : endPlain]
4190 z = z - len(document.body[arg : argend + 1])
4192 del document.body[arg : argend + 1]
4193 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
4194 pre += put_cmd_in_ert("{")
4195 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4196 endPlain = find_end_of_layout(document.body, beginPlain)
4198 z = z - len(document.body[i : beginPlain + 1])
4200 document.body[i : beginPlain + 1] = pre
4201 post = put_cmd_in_ert("}")
4202 document.body[z - 2 : z + 1] = post
4206 def revert_powerdot_pause(document):
4207 " Reverts powerdot pause layout to ERT "
4209 if document.textclass != "powerdot":
4214 i = find_token(document.body, "\\begin_layout Pause", i)
4217 j = find_end_of_layout(document.body, i)
4219 document.warning("Malformed LyX document: Can't find end of Pause layout")
4223 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\pause")
4224 for p in range(i, j):
4227 arg = find_token(document.body, "\\begin_inset Argument 1", i, j)
4229 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4230 endPlain = find_end_of_layout(document.body, beginPlain)
4231 endInset = find_end_of_inset(document.body, p)
4232 content = document.body[beginPlain + 1 : endPlain]
4234 endlay = endlay - len(document.body[p : endInset + 1])
4236 del document.body[p : endInset + 1]
4237 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4239 document.body[i : i + 1] = subst
4243 def revert_powerdot_itemargs(document):
4244 " Reverts powerdot item arguments to ERT "
4246 if document.textclass != "powerdot":
4250 list_layouts = ["Itemize", "ItemizeType1", "Enumerate", "EnumerateType1"]
4251 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4254 i = find_token(document.body, "\\begin_inset Argument", i)
4257 # Find containing paragraph layout
4258 parent = get_containing_layout(document.body, i)
4260 document.warning("Malformed LyX document: Can't find parent paragraph layout")
4265 realparbeg = parent[3]
4266 layoutname = parent[0]
4268 for p in range(parbeg, parend):
4272 if layoutname in list_layouts:
4273 m = rx.match(document.body[p])
4276 if argnr == "item:1":
4277 j = find_end_of_inset(document.body, i)
4278 # Find containing paragraph layout
4279 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4280 endPlain = find_end_of_layout(document.body, beginPlain)
4281 content = document.body[beginPlain + 1 : endPlain]
4282 del document.body[i:j+1]
4283 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4284 document.body[realparbeg : realparbeg] = subst
4285 elif argnr == "item:2":
4286 j = find_end_of_inset(document.body, i)
4287 # Find containing paragraph layout
4288 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4289 endPlain = find_end_of_layout(document.body, beginPlain)
4290 content = document.body[beginPlain + 1 : endPlain]
4291 del document.body[i:j+1]
4292 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
4293 document.body[realparbeg : realparbeg] = subst
4298 def revert_powerdot_columns(document):
4299 " Reverts powerdot twocolumn to TeX-code "
4300 if document.textclass != "powerdot":
4303 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4306 i = find_token(document.body, "\\begin_layout Twocolumn", i)
4309 j = find_end_of_layout(document.body, i)
4311 document.warning("Malformed LyX document: Can't find end of Twocolumn layout")
4315 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
4316 endlay += len(put_cmd_in_ert("}"))
4317 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\twocolumn")
4318 for p in range(i, j):
4321 m = rx.match(document.body[p])
4325 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4326 endPlain = find_end_of_layout(document.body, beginPlain)
4327 endInset = find_end_of_inset(document.body, p)
4328 content = document.body[beginPlain + 1 : endPlain]
4330 endlay = endlay - len(document.body[p : endInset + 1])
4332 del document.body[p : endInset + 1]
4333 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4335 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4336 endPlain = find_end_of_layout(document.body, beginPlain)
4337 endInset = find_end_of_inset(document.body, p)
4338 content = document.body[beginPlain + 1 : endPlain]
4340 endlay = endlay - len(document.body[p : endInset + 1])
4342 del document.body[p : endInset + 1]
4343 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
4345 subst += put_cmd_in_ert("{")
4346 document.body[i : i + 1] = subst
4350 def revert_mbox_fbox(document):
4351 'Convert revert mbox/fbox boxes to TeX-code'
4354 i = find_token(document.body, "\\begin_inset Box", i)
4357 j = find_token(document.body, "width", i)
4359 document.warning("Malformed LyX document: Can't find box width")
4361 width = get_value(document.body, "width", j)
4362 k = find_end_of_inset(document.body, j)
4364 document.warning("Malformed LyX document: Can't find end of box inset")
4367 BeginLayout = find_token(document.body, "\\begin_layout Plain Layout", j)
4368 EndLayout = find_end_of_layout(document.body, BeginLayout)
4369 # replace if width is ""
4371 document.body[EndLayout:k + 1] = put_cmd_in_ert("}")
4372 if document.body[i] == "\\begin_inset Box Frameless":
4373 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\mbox{")
4374 if document.body[i] == "\\begin_inset Box Boxed":
4375 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\fbox{")
4379 def revert_starred_caption(document):
4380 " Reverts unnumbered longtable caption insets "
4384 i = find_token(document.body, "\\begin_inset Caption LongTableNoNumber", i)
4387 # This is not equivalent, but since the caption inset is a full blown
4388 # text inset a true conversion to ERT is too difficult.
4389 document.body[i] = "\\begin_inset Caption Standard"
4393 def revert_forced_local_layout(document):
4396 i = find_token(document.header, "\\begin_forced_local_layout", i)
4399 j = find_end_of(document.header, i, "\\begin_forced_local_layout", "\\end_forced_local_layout")
4401 # this should not happen
4403 regexp = re.compile(r'\s*forcelocal', re.IGNORECASE)
4404 k = find_re(document.header, regexp, i, j)
4406 del document.header[k]
4408 k = find_re(document.header, regexp, i, j)
4409 k = find_token(document.header, "\\begin_local_layout", 0)
4411 document.header[i] = "\\begin_local_layout"
4412 document.header[j] = "\\end_local_layout"
4414 l = find_end_of(document.header, k, "\\begin_local_layout", "\\end_local_layout")
4416 # this should not happen
4418 lines = document.header[i+1 : j]
4420 document.header[k+1 : k+1] = lines
4421 document.header[i : j ] = []
4423 document.header[i : j ] = []
4424 document.header[k+1 : k+1] = lines
4427 def revert_aa1(document):
4428 " Reverts InsetArguments of aa to TeX-code "
4429 if document.textclass == "aa":
4433 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4435 revert_Argument_to_TeX_brace(document, i, 0, 1, 4, False, False)
4441 def revert_aa2(document):
4442 " Reverts InsetArguments of aa to TeX-code "
4443 if document.textclass == "aa":
4447 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4449 document.body[i] = "\\begin_layout Abstract"
4455 def revert_tibetan(document):
4456 "Set the document language for Tibetan to English"
4458 if document.language == "tibetan":
4459 document.language = "english"
4460 i = find_token(document.header, "\\language", 0)
4462 document.header[i] = "\\language english"
4464 while j < len(document.body):
4465 j = find_token(document.body, "\\lang tibetan", j)
4467 document.body[j] = document.body[j].replace("\\lang tibetan", "\\lang english")
4470 j = len(document.body)
4479 # The idea here is that we will have a sequence of chunk paragraphs.
4480 # We want to convert them to paragraphs in one or several chunk insets.
4481 # Individual chunks are terminated by the character @ on the last line.
4482 # This line will be discarded, and following lines are treated as new
4483 # chunks, which go into their own insets.
4484 # The first line of a chunk should look like: <<CONTENT>>=
4485 # We will discard the delimiters, and put the CONTENT into the
4486 # optional argument of the inset, if the CONTENT is non-empty.
4487 def convert_chunks(document):
4488 first_re = re.compile(r'<<(.*)>>=(.*)')
4491 # find start of a block of chunks
4492 i = find_token(document.body, "\\begin_layout Chunk", file_pos)
4498 chunk_started = False
4501 # process the one we just found
4502 j = find_end_of_layout(document.body, i)
4504 document.warning("Malformed LyX documents. Can't find end of Chunk layout!")
4505 # there is no point continuing, as we will run into the same error again.
4507 this_chunk = "".join(document.body[i + 1:j])
4509 # there may be empty lines between chunks
4510 # we just skip them.
4511 if not chunk_started:
4512 if this_chunk != "":
4514 chunk_started = True
4517 contents.append(document.body[i + 1:j])
4519 # look for potential chunk terminator
4520 # on the last line of the chunk paragraph
4521 if document.body[j - 1] == "@":
4524 # look for subsequent chunk paragraph
4525 i = find_token(document.body, "\\begin_layout", j)
4529 if get_value(document.body, "\\begin_layout", i) != "Chunk":
4532 file_pos = end = j + 1
4534 # The last chunk should simply have an "@" in it
4535 # or at least end with "@" (can happen if @ is
4536 # preceded by a newline)
4537 lastpar = ''.join(contents[-1])
4538 if not lastpar.endswith("@"):
4539 document.warning("Unexpected chunk content: chunk not terminated by '@'!")
4543 # chunk par only contains "@". Just drop it.
4546 # chunk par contains more. Only drop the "@".
4549 # The first line should look like: <<CONTENT>>=
4550 # We want the CONTENT
4551 optarg = ' '.join(contents[0])
4553 # We can already have real chunk content in
4554 # the first par (separated from the options by a newline).
4555 # We collect such stuff to re-insert it later.
4558 match = first_re.search(optarg)
4560 optarg = match.groups()[0]
4561 if match.groups()[1] != "":
4563 for c in contents[0]:
4564 if c.endswith(">>="):
4568 postoptstuff.append(c)
4569 # We have stripped everything. This can be deleted.
4572 newstuff = ['\\begin_layout Standard',
4573 '\\begin_inset Flex Chunk',
4575 '\\begin_layout Plain Layout', '']
4577 # If we have a non-empty optional argument, insert it.
4578 if match and optarg != "":
4580 ['\\begin_inset Argument 1',
4582 '\\begin_layout Plain Layout',
4587 # Since we already opened a Plain layout, the first paragraph
4588 # does not need to do that.
4591 newstuff.extend(postoptstuff)
4592 newstuff.append('\\end_layout')
4596 newstuff.extend(['', '\\begin_layout Plain Layout', ''])
4600 newstuff.append('\\end_layout')
4602 newstuff.extend(['', '\\end_inset', '', '\\end_layout', ''])
4604 document.body[start:end] = newstuff
4606 file_pos += len(newstuff) - (end - start)
4609 def revert_chunks(document):
4612 i = find_token(document.body, "\\begin_inset Flex Chunk", i)
4616 iend = find_end_of_inset(document.body, i)
4618 document.warning("Can't find end of Chunk!")
4622 # Look for optional argument
4624 ostart = find_token(document.body, "\\begin_inset Argument 1", i, iend)
4626 oend = find_end_of_inset(document.body, ostart)
4627 k = find_token(document.body, "\\begin_layout Plain Layout", ostart, oend)
4629 document.warning("Malformed LyX document: Can't find argument contents!")
4631 m = find_end_of_layout(document.body, k)
4632 optarg = "".join(document.body[k+1:m])
4635 # We now remove the optional argument, so we have something
4636 # uniform on which to work
4637 document.body[ostart : oend + 1] = []
4638 # iend is now invalid
4639 iend = find_end_of_inset(document.body, i)
4641 retval = get_containing_layout(document.body, i)
4643 document.warning("Can't find containing layout for Chunk!")
4646 (lname, lstart, lend, pstart) = retval
4647 # we now want to work through the various paragraphs, and collect their contents
4651 k = find_token(document.body, "\\begin_layout Plain Layout", k, lend)
4654 j = find_end_of_layout(document.body, k)
4656 document.warning("Can't find end of layout inside chunk!")
4658 parlist.append(document.body[k+1:j])
4660 # we now need to wrap all of these paragraphs in chunks
4663 newlines.extend(["\\begin_layout Chunk", "", "<<" + optarg + ">>=", "\\end_layout", ""])
4664 for stuff in parlist:
4665 newlines.extend(["\\begin_layout Chunk"] + stuff + ["\\end_layout", ""])
4666 newlines.extend(["\\begin_layout Chunk", "", "@", "\\end_layout", ""])
4667 # replace old content with new content
4668 document.body[lstart : lend + 1] = newlines
4669 i = lstart + len(newlines)
4676 supported_versions = ["2.1.0","2.1"]
4679 [415, [convert_undertilde]],
4681 [417, [convert_japanese_encodings]],
4682 [418, [convert_justification]],
4684 [420, [convert_biblio_style]],
4685 [421, [convert_longtable_captions]],
4686 [422, [convert_use_packages]],
4687 [423, [convert_use_mathtools]],
4688 [424, [convert_cite_engine_type]],
4689 # No convert_cancel, since cancel will be loaded automatically
4690 # in format 425 without any possibility to switch it off.
4691 # This has been fixed in format 464.
4695 [428, [convert_cell_rotation]],
4696 [429, [convert_table_rotation]],
4697 [430, [convert_listoflistings]],
4698 [431, [convert_use_amssymb]],
4700 [433, [convert_armenian]],
4708 [441, [convert_mdnomath]],
4713 [446, [convert_latexargs]],
4714 [447, [convert_IEEEtran, convert_AASTeX, convert_AGUTeX, convert_IJMP, convert_SIGPLAN, convert_SIGGRAPH, convert_EuropeCV, convert_Initials, convert_ModernCV]],
4715 [448, [convert_literate]],
4718 [451, [convert_beamerargs, convert_againframe_args, convert_corollary_args, convert_quote_args]],
4719 [452, [convert_beamerblocks]],
4720 [453, [convert_use_stmaryrd]],
4721 [454, [convert_overprint]],
4723 [456, [convert_epigraph]],
4724 [457, [convert_use_stackrel]],
4725 [458, [convert_captioninsets, convert_captionlayouts]],
4730 [463, [convert_encodings]],
4731 [464, [convert_use_cancel]],
4732 [465, [convert_lyxframes, remove_endframes]],
4738 [471, [convert_cite_engine_type_default]],
4741 [474, [convert_chunks, cleanup_beamerargs]],
4745 [473, [revert_chunks]],
4746 [472, [revert_tibetan]],
4747 [471, [revert_aa1,revert_aa2]],
4748 [470, [revert_cite_engine_type_default]],
4749 [469, [revert_forced_local_layout]],
4750 [468, [revert_starred_caption]],
4751 [467, [revert_mbox_fbox]],
4752 [466, [revert_iwona_fonts]],
4753 [465, [revert_powerdot_flexes, revert_powerdot_pause, revert_powerdot_itemargs, revert_powerdot_columns]],
4755 [463, [revert_use_cancel]],
4756 [462, [revert_encodings]],
4757 [461, [revert_new_libertines]],
4758 [460, [revert_kurier_fonts]],
4759 [459, [revert_IEEEtran_3]],
4760 [458, [revert_fragileframe, revert_newframes]],
4761 [457, [revert_captioninsets, revert_captionlayouts]],
4762 [456, [revert_use_stackrel]],
4763 [455, [revert_epigraph]],
4764 [454, [revert_frametitle]],
4765 [453, [revert_overprint]],
4766 [452, [revert_use_stmaryrd]],
4767 [451, [revert_beamerblocks]],
4768 [450, [revert_beamerargs, revert_beamerargs2, revert_beamerargs3, revert_beamerflex]],
4769 [449, [revert_garamondx, revert_garamondx_newtxmath]],
4770 [448, [revert_itemargs]],
4771 [447, [revert_literate]],
4772 [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]],
4773 [445, [revert_latexargs]],
4774 [444, [revert_uop]],
4775 [443, [revert_biolinum]],
4777 [441, [revert_newtxmath]],
4778 [440, [revert_mdnomath]],
4779 [439, [revert_mathfonts]],
4780 [438, [revert_minionpro]],
4781 [437, [revert_ipadeco, revert_ipachar]],
4782 [436, [revert_texgyre]],
4783 [435, [revert_mathdesign]],
4784 [434, [revert_txtt]],
4785 [433, [revert_libertine]],
4786 [432, [revert_armenian]],
4787 [431, [revert_languages, revert_ancientgreek]],
4788 [430, [revert_use_amssymb]],
4789 [429, [revert_listoflistings]],
4790 [428, [revert_table_rotation]],
4791 [427, [revert_cell_rotation]],
4792 [426, [revert_tipa]],
4793 [425, [revert_verbatim]],
4794 [424, [revert_cancel]],
4795 [423, [revert_cite_engine_type]],
4796 [422, [revert_use_mathtools]],
4797 [421, [revert_use_packages]],
4798 [420, [revert_longtable_captions]],
4799 [419, [revert_biblio_style]],
4800 [418, [revert_australian]],
4801 [417, [revert_justification]],
4802 [416, [revert_japanese_encodings]],
4803 [415, [revert_negative_space, revert_math_spaces]],
4804 [414, [revert_undertilde]],
4805 [413, [revert_visible_space]]
4809 if __name__ == "__main__":