1 # -*- coding: utf-8 -*-
2 # This file is part of lyx2lyx
3 # -*- coding: utf-8 -*-
4 # Copyright (C) 2011 The LyX team
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 """ Convert files to the file format generated by LyX 2.1"""
26 # Uncomment only what you need to import, please.
28 from parser_tools import count_pars_in_inset, del_token, find_token, find_token_exact, \
29 find_token_backwards, find_end_of, find_end_of_inset, find_end_of_layout, \
30 find_end_of_sequence, find_re, get_option_value, get_containing_layout, \
31 get_containing_inset, get_value, get_quoted_value, set_option_value
33 #from parser_tools import find_token, find_end_of, find_tokens, \
34 #find_end_of_inset, find_end_of_layout, \
35 #is_in_inset, del_token, check_token
37 from lyx2lyx_tools import add_to_preamble, put_cmd_in_ert, get_ert
39 #from lyx2lyx_tools import insert_to_preamble, \
40 # lyx2latex, latex_length, revert_flex_inset, \
41 # revert_font_attrs, hex2ratio, str2bool
43 ####################################################################
44 # Private helper functions
46 #def remove_option(lines, m, option):
47 #''' removes option from line m. returns whether we did anything '''
48 #l = lines[m].find(option)
51 #val = lines[m][l:].split('"')[1]
52 #lines[m] = lines[m][:l - 1] + lines[m][l+len(option + '="' + val + '"'):]
56 def revert_Argument_to_TeX_brace(document, line, endline, n, nmax, environment, opt):
58 Reverts an InsetArgument to TeX-code
60 revert_Argument_to_TeX_brace(document, LineOfBegin, LineOfEnd, StartArgument, EndArgument, isEnvironment, isOpt)
61 LineOfBegin is the line of the \begin_layout or \begin_inset statement
62 LineOfEnd is the line of the \end_layout or \end_inset statement, if "0" is given, the end of the file is used instead
63 StartArgument is the number of the first argument that needs to be converted
64 EndArgument is the number of the last argument that needs to be converted or the last defined one
65 isEnvironment must be true, if the layout is for a LaTeX environment
66 isOpt must be true, if the argument is an optional one
70 while lineArg != -1 and n < nmax + 1:
71 lineArg = find_token(document.body, "\\begin_inset Argument " + str(n), line)
72 if lineArg > endline and endline != 0:
75 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", lineArg)
76 # we have to assure that no other inset is in the Argument
77 beginInset = find_token(document.body, "\\begin_inset", beginPlain)
78 endInset = find_token(document.body, "\\end_inset", beginPlain)
81 while beginInset < endInset and beginInset != -1:
82 beginInset = find_token(document.body, "\\begin_inset", k)
83 endInset = find_token(document.body, "\\end_inset", l)
86 if environment == False:
88 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}{")
89 del(document.body[lineArg : beginPlain + 1])
92 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("]")
93 document.body[lineArg : beginPlain + 1] = put_cmd_in_ert("[")
96 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}")
97 document.body[lineArg : beginPlain + 1] = put_cmd_in_ert("{")
103 def convert_TeX_brace_to_Argument(document, line, n, nmax, inset, environment, opt):
105 Converts TeX code for mandatory arguments to an InsetArgument
106 The conversion of TeX code for optional arguments must be done with another routine
107 !!! Be careful if the braces are different in your case as expected here:
108 - "}{" separates mandatory arguments of commands
109 - "}" + "{" separates mandatory arguments of commands
110 - "}" + " " + "{" separates mandatory arguments of commands
111 - { and } surround a mandatory argument of an environment
113 convert_TeX_brace_to_Argument(document, LineOfBeginLayout/Inset, StartArgument, EndArgument, isInset, isEnvironment, isOpt)
114 LineOfBeginLayout/Inset is the line of the \begin_layout or \begin_inset statement
115 StartArgument is the number of the first ERT that needs to be converted
116 EndArgument is the number of the last ERT that needs to be converted
117 isInset must be true, if braces inside an InsetLayout needs to be converted
118 isEnvironment must be true, if the layout is for a LaTeX environment
119 isOpt must be true, if the argument is an optional one
121 Todo: this routine can currently handle only one mandatory argument of environments
124 end_layout = find_end_of_layout(document.body, line)
129 lineERT = find_token(document.body, "\\begin_inset ERT", lineERT, end_layout)
132 if environment == False:
133 end_ERT = find_end_of_inset(document.body, lineERT)
135 document.warning("Can't find end of ERT!!")
137 # Note that this only checks for ][ or }{ at the beginning of a line
139 bracePair = find_token(document.body, "][", lineERT, end_ERT)
141 bracePair = find_token(document.body, "}{", lineERT, end_ERT)
143 end = find_token(document.body, "\\end_inset", bracePair)
144 document.body[lineERT : end_ERT + 1] = ["\\end_layout", "", "\\end_inset"]
146 # in the case that n > 1 we have optional arguments before
147 # therefore detect them if any
149 # first check if there is an argument
150 lineArg = find_token(document.body, "\\begin_inset Argument", line)
151 if lineArg < lineERT and lineArg != -1:
152 # we have an argument, so now search backwards for its end
153 # we must now assure that we don't find other insets like e.g. a newline
154 endInsetArg = lineERT
155 endLayoutArg = endInsetArg
156 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
157 endInsetArg = endInsetArg - 1
158 endLayoutArg = endInsetArg
159 endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
160 endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
161 line = endInsetArg + 1
163 document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
165 document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
167 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
172 # no brace pair found
173 # now check the case that we have "}" + "{" in two ERTs
175 endBrace = find_token(document.body, "]", lineERT, end_layout)
177 endBrace = find_token(document.body, "}", lineERT, end_layout)
178 if endBrace == lineERT + 5:
180 beginBrace = find_token(document.body, "[", endBrace, end_layout)
182 beginBrace = find_token(document.body, "{", endBrace, end_layout)
183 # assure that the ERTs are consecutive (11 or 12 depending if there is a space between the ERTs or not)
184 if beginBrace == endBrace + 11 or beginBrace == endBrace + 12:
185 end = find_token(document.body, "\\end_inset", beginBrace)
186 document.body[lineERT : end + 1] = ["\\end_layout", "", "\\end_inset"]
188 # in the case that n > 1 we have optional arguments before
189 # therefore detect them if any
191 # first check if there is an argument
192 lineArg = find_token(document.body, "\\begin_inset Argument", line)
193 if lineArg < lineERT and lineArg != -1:
194 # we have an argument, so now search backwards for its end
195 # we must now assure that we don't find other insets like e.g. a newline
196 endInsetArg = lineERT
197 endLayoutArg = endInsetArg
198 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
199 endInsetArg = endInsetArg - 1
200 endLayoutArg = endInsetArg
201 endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
202 endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
203 line = endInsetArg + 1
205 document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
207 document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
209 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
212 # set the line where the next argument will be inserted
213 if beginBrace == endBrace + 11:
221 if environment == True:
222 end_ERT = find_end_of_inset(document.body, lineERT)
224 document.warning("Can't find end of ERT!!")
226 # Note that this only checks for [ or { at the beginning of a line
228 opening = find_token(document.body, "[", lineERT, end_ERT)
230 opening = find_token(document.body, "{", lineERT, end_ERT)
232 lineERT2 = find_token(document.body, "\\begin_inset ERT", end_ERT, end_layout)
234 # argument in a single ERT
235 # strip off the opening bracket
236 document.body[opening] = document.body[opening][1:]
237 ertcontlastline = end_ERT - 3
238 if (opt and document.body[ertcontlastline].endswith("]")) or document.body[ertcontlastline].endswith("}"):
239 # strip off the closing bracket
240 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
241 end2 = find_token(document.body, "\\end_inset", ertcontlastline)
242 document.body[lineERT : lineERT + 1] = ["\\begin_inset Argument " + str(n)]
244 end_ERT2 = find_end_of_inset(document.body, lineERT2)
246 document.warning("Can't find end of second ERT!!")
249 closing = find_token(document.body, "]", lineERT2, end_ERT2)
251 closing = find_token(document.body, "}", lineERT2, end_ERT2)
252 if closing != -1: # assure that the "}" is in this ERT
253 end2 = find_token(document.body, "\\end_inset", closing)
254 document.body[lineERT2 : end2 + 1] = ["\\end_layout", "", "\\end_inset"]
255 document.body[lineERT : end_ERT + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
259 ###############################################################################
261 ### Conversion and reversion routines
263 ###############################################################################
265 def revert_visible_space(document):
266 "Revert InsetSpace visible into its ERT counterpart"
269 i = find_token(document.body, "\\begin_inset space \\textvisiblespace{}", i)
272 end = find_end_of_inset(document.body, i)
273 subst = put_cmd_in_ert("\\textvisiblespace{}")
274 document.body[i:end + 1] = subst
277 undertilde_commands = ["utilde"]
278 def convert_undertilde(document):
279 " Load undertilde automatically "
280 i = find_token(document.header, "\\use_mathdots" , 0)
282 i = find_token(document.header, "\\use_mhchem" , 0)
284 i = find_token(document.header, "\\use_esint" , 0)
286 document.warning("Malformed LyX document: Can't find \\use_mathdots.")
288 j = find_token(document.preamble, "\\usepackage{undertilde}", 0)
290 # package was loaded in the preamble, convert this to header setting for round trip
291 document.header.insert(i + 1, "\\use_undertilde 2") # on
292 del document.preamble[j]
296 j = find_token(document.body, '\\begin_inset Formula', j)
299 k = find_end_of_inset(document.body, j)
301 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(j))
304 code = "\n".join(document.body[j:k])
305 for c in undertilde_commands:
306 if code.find("\\%s" % c) != -1:
307 # at least one of the commands was found - need to switch package off
308 document.header.insert(i + 1, "\\use_undertilde 0") # off
311 # no command was found - set to auto (bug 9069)
312 document.header.insert(i + 1, "\\use_undertilde 1") # auto
316 def revert_undertilde(document):
317 " Load undertilde if used in the document "
318 regexp = re.compile(r'(\\use_undertilde)')
319 i = find_re(document.header, regexp, 0)
320 value = "1" # default is auto
322 value = get_value(document.header, "\\use_undertilde" , i).split()[0]
323 del document.header[i]
324 if value == "2": # on
325 add_to_preamble(document, ["\\usepackage{undertilde}"])
326 elif value == "1": # auto
329 i = find_token(document.body, '\\begin_inset Formula', i)
332 j = find_end_of_inset(document.body, i)
334 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
337 code = "\n".join(document.body[i:j])
338 for c in undertilde_commands:
339 if code.find("\\%s" % c) != -1:
340 add_to_preamble(document, ["\\usepackage{undertilde}"])
345 def revert_negative_space(document):
346 "Revert InsetSpace negmedspace and negthickspace into its TeX-code counterpart"
351 i = find_token(document.body, "\\begin_inset space \\negmedspace{}", i)
353 j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
355 # load amsmath in the preamble if not already loaded if we are at the end of checking
357 i = find_token(document.header, "\\use_amsmath 2", 0)
359 add_to_preamble(document, ["\\@ifundefined{negthickspace}{\\usepackage{amsmath}}"])
363 end = find_end_of_inset(document.body, i)
364 subst = put_cmd_in_ert("\\negmedspace{}")
365 document.body[i:end + 1] = subst
366 j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
369 end = find_end_of_inset(document.body, j)
370 subst = put_cmd_in_ert("\\negthickspace{}")
371 document.body[j:end + 1] = subst
375 def revert_math_spaces(document):
376 "Revert formulas with protected custom space and protected hfills to TeX-code"
379 i = find_token(document.body, "\\begin_inset Formula", i)
382 j = document.body[i].find("\\hspace*")
384 end = find_end_of_inset(document.body, i)
385 subst = put_cmd_in_ert(document.body[i][21:])
386 document.body[i:end + 1] = subst
390 def convert_japanese_encodings(document):
391 " Rename the japanese encodings to names understood by platex "
393 "EUC-JP-pLaTeX": "euc",
395 "SJIS-pLaTeX": "sjis"
397 i = find_token(document.header, "\\inputencoding" , 0)
400 val = get_value(document.header, "\\inputencoding", i)
401 if val in jap_enc_dict.keys():
402 document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
405 def revert_japanese_encodings(document):
406 " Revert the japanese encodings name changes "
408 "euc": "EUC-JP-pLaTeX",
410 "sjis": "SJIS-pLaTeX"
412 i = find_token(document.header, "\\inputencoding" , 0)
415 val = get_value(document.header, "\\inputencoding", i)
416 if val in jap_enc_dict.keys():
417 document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
420 def convert_justification(document):
421 " Add the \\justification buffer param"
422 i = find_token(document.header, "\\suppress_date" , 0)
424 i = find_token(document.header, "\\paperorientation" , 0)
426 i = find_token(document.header, "\\use_indices" , 0)
428 i = find_token(document.header, "\\use_bibtopic" , 0)
430 document.warning("Malformed LyX document: Missing \\suppress_date.")
432 document.header.insert(i + 1, "\\justification true")
435 def revert_justification(document):
436 " Revert the \\justification buffer param"
437 if not del_token(document.header, '\\justification', 0):
438 document.warning("Malformed LyX document: Missing \\justification.")
441 def revert_australian(document):
442 "Set English language variants Australian and Newzealand to English"
444 if document.language == "australian" or document.language == "newzealand":
445 document.language = "english"
446 i = find_token(document.header, "\\language", 0)
448 document.header[i] = "\\language english"
451 j = find_token(document.body, "\\lang australian", j)
453 j = find_token(document.body, "\\lang newzealand", 0)
457 document.body[j] = document.body[j].replace("\\lang newzealand", "\\lang english")
459 document.body[j] = document.body[j].replace("\\lang australian", "\\lang english")
463 def convert_biblio_style(document):
464 "Add a sensible default for \\biblio_style based on the citation engine."
465 i = find_token(document.header, "\\cite_engine", 0)
467 engine = get_value(document.header, "\\cite_engine", i).split("_")[0]
468 style = {"basic": "plain", "natbib": "plainnat", "jurabib": "jurabib"}
469 document.header.insert(i + 1, "\\biblio_style " + style[engine])
472 def revert_biblio_style(document):
473 "BibTeX insets with default option use the style defined by \\biblio_style."
474 i = find_token(document.header, "\\biblio_style" , 0)
476 document.warning("No \\biblio_style line. Nothing to do.")
479 default_style = get_value(document.header, "\\biblio_style", i)
480 del document.header[i]
482 # We are looking for bibtex insets having the default option
485 i = find_token(document.body, "\\begin_inset CommandInset bibtex", i)
488 j = find_end_of_inset(document.body, i)
490 document.warning("Malformed LyX document: Can't find end of bibtex inset at line " + str(i))
493 k = find_token(document.body, "options", i, j)
495 options = get_quoted_value(document.body, "options", k)
496 if "default" in options.split(","):
497 document.body[k] = 'options "%s"' \
498 % options.replace("default", default_style)
502 def handle_longtable_captions(document, forward):
505 begin_table = find_token(document.body, '<lyxtabular version=', begin_table)
506 if begin_table == -1:
508 end_table = find_end_of(document.body, begin_table, '<lyxtabular', '</lyxtabular>')
510 document.warning("Malformed LyX document: Could not find end of table.")
513 fline = find_token(document.body, "<features", begin_table, end_table)
515 document.warning("Can't find features for inset at line " + str(begin_table))
518 p = document.body[fline].find("islongtable")
523 numrows = get_option_value(document.body[begin_table], "rows")
525 numrows = int(numrows)
527 document.warning(document.body[begin_table])
528 document.warning("Unable to determine rows!")
529 begin_table = end_table
531 begin_row = begin_table
532 for row in range(numrows):
533 begin_row = find_token(document.body, '<row', begin_row, end_table)
535 document.warning("Can't find row " + str(row + 1))
537 end_row = find_end_of(document.body, begin_row, '<row', '</row>')
539 document.warning("Can't find end of row " + str(row + 1))
542 if (get_option_value(document.body[begin_row], 'caption') == 'true' and
543 get_option_value(document.body[begin_row], 'endfirsthead') != 'true' and
544 get_option_value(document.body[begin_row], 'endhead') != 'true' and
545 get_option_value(document.body[begin_row], 'endfoot') != 'true' and
546 get_option_value(document.body[begin_row], 'endlastfoot') != 'true'):
547 document.body[begin_row] = set_option_value(document.body[begin_row], 'caption', 'true", endfirsthead="true')
548 elif get_option_value(document.body[begin_row], 'caption') == 'true':
549 if get_option_value(document.body[begin_row], 'endfirsthead') == 'true':
550 document.body[begin_row] = set_option_value(document.body[begin_row], 'endfirsthead', 'false')
551 if get_option_value(document.body[begin_row], 'endhead') == 'true':
552 document.body[begin_row] = set_option_value(document.body[begin_row], 'endhead', 'false')
553 if get_option_value(document.body[begin_row], 'endfoot') == 'true':
554 document.body[begin_row] = set_option_value(document.body[begin_row], 'endfoot', 'false')
555 if get_option_value(document.body[begin_row], 'endlastfoot') == 'true':
556 document.body[begin_row] = set_option_value(document.body[begin_row], 'endlastfoot', 'false')
558 # since there could be a tabular inside this one, we
559 # cannot jump to end.
563 def convert_longtable_captions(document):
564 "Add a firsthead flag to caption rows"
565 handle_longtable_captions(document, True)
568 def revert_longtable_captions(document):
569 "remove head/foot flag from caption rows"
570 handle_longtable_captions(document, False)
573 def convert_use_packages(document):
574 "use_xxx yyy => use_package xxx yyy"
575 packages = ["amsmath", "esint", "mathdots", "mhchem", "undertilde"]
577 i = find_token(document.header, "\\use_%s" % p, 0)
579 value = get_value(document.header, "\\use_%s" % p, i)
580 document.header[i] = "\\use_package %s %s" % (p, value)
583 def revert_use_packages(document):
584 "use_package xxx yyy => use_xxx yyy"
585 packages = ["amsmath", "esint", "mhchem", "mathdots", "undertilde"]
586 # the order is arbitrary for the use_package version, and not all packages need to be given.
587 # Ensure a complete list and correct order (important for older LyX versions and especially lyx2lyx)
588 # first loop: find line with first package
591 regexp = re.compile(r'(\\use_package\s+%s)' % p)
592 i = find_re(document.header, regexp, 0)
593 if i != -1 and (j < 0 or i < j):
595 # second loop: replace or insert packages in front of all existing ones
597 regexp = re.compile(r'(\\use_package\s+%s)' % p)
598 i = find_re(document.header, regexp, 0)
600 value = get_value(document.header, "\\use_package %s" % p, i).split()[1]
601 del document.header[i]
602 document.header.insert(j, "\\use_%s %s" % (p, value))
604 document.header.insert(j, "\\use_%s 1" % p)
608 def convert_use_package(document, pkg, commands, oldauto):
609 # oldauto defines how the version we are converting from behaves:
610 # if it is true, the old version uses the package automatically.
611 # if it is false, the old version never uses the package.
612 i = find_token(document.header, "\\use_package", 0)
614 document.warning("Malformed LyX document: Can't find \\use_package.")
616 j = find_token(document.preamble, "\\usepackage{" + pkg + "}", 0)
618 # package was loaded in the preamble, convert this to header setting for round trip
619 document.header.insert(i + 1, "\\use_package " + pkg + " 2") # on
620 del document.preamble[j]
621 # If oldauto is true we have two options:
622 # We can either set the package to auto - this is correct for files in
623 # format 425 to 463, and may create a conflict for older files which use
624 # any command in commands with a different definition.
625 # Or we can look whether any command in commands is used, and set it to
626 # auto if not and to off if yes. This will not create a conflict, but will
627 # create uncompilable documents for files in format 425 to 463, which use
628 # any command in commands.
629 # We choose the first option since its error is less likely.
631 document.header.insert(i + 1, "\\use_package " + pkg + " 1") # auto
635 j = find_token(document.body, '\\begin_inset Formula', j)
638 k = find_end_of_inset(document.body, j)
640 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(j))
643 code = "\n".join(document.body[j:k])
645 if code.find("\\%s" % c) != -1:
646 # at least one of the commands was found - need to switch package off
647 document.header.insert(i + 1, "\\use_package " + pkg + " 0") # off
650 # no command was found - set to auto (bug 9069)
651 document.header.insert(i + 1, "\\use_package " + pkg + " 1") # auto
654 def revert_use_package(document, pkg, commands, oldauto):
655 # oldauto defines how the version we are reverting to behaves:
656 # if it is true, the old version uses the package automatically.
657 # if it is false, the old version never uses the package.
658 regexp = re.compile(r'(\\use_package\s+%s)' % pkg)
659 i = find_re(document.header, regexp, 0)
660 value = "1" # default is auto
662 value = get_value(document.header, "\\use_package" , i).split()[1]
663 del document.header[i]
664 if value == "2": # on
665 add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
666 elif value == "1" and not oldauto: # auto
669 i = find_token(document.body, '\\begin_inset Formula', i)
672 j = find_end_of_inset(document.body, i)
674 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
677 code = "\n".join(document.body[i:j])
679 if code.find("\\%s" % c) != -1:
680 add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
685 mathtools_commands = ["mathclap", "mathllap", "mathrlap", \
686 "lgathered", "rgathered", "vcentcolon", "dblcolon", \
687 "coloneqq", "Coloneqq", "coloneq", "Coloneq", "eqqcolon", \
688 "Eqqcolon", "eqcolon", "Eqcolon", "colonapprox", \
689 "Colonapprox", "colonsim", "Colonsim"]
690 def convert_use_mathtools(document):
691 "insert use_package mathtools"
692 convert_use_package(document, "mathtools", mathtools_commands, False)
695 def revert_use_mathtools(document):
696 "remove use_package mathtools"
697 revert_use_package(document, "mathtools", mathtools_commands, False)
700 # commands provided by stmaryrd.sty but LyX uses other packages:
701 # boxdot lightning, bigtriangledown, bigtriangleup
702 stmaryrd_commands = ["shortleftarrow", "shortrightarrow", "shortuparrow", \
703 "shortdownarrow", "Yup", "Ydown", "Yleft", "Yright", \
704 "varcurlyvee", "varcurlywedge", "minuso", "baro", \
705 "sslash", "bbslash", "moo", "varotimes", "varoast", \
706 "varobar", "varodot", "varoslash", "varobslash", \
707 "varocircle", "varoplus", "varominus", "boxast", \
708 "boxbar", "boxslash", "boxbslash", "boxcircle", \
709 "boxbox", "boxempty", "merge", "vartimes", \
710 "fatsemi", "sswarrow", "ssearrow", "curlywedgeuparrow", \
711 "curlywedgedownarrow", "fatslash", "fatbslash", "lbag", \
712 "rbag", "varbigcirc", "leftrightarroweq", \
713 "curlyveedownarrow", "curlyveeuparrow", "nnwarrow", \
714 "nnearrow", "leftslice", "rightslice", "varolessthan", \
715 "varogreaterthan", "varovee", "varowedge", "talloblong", \
716 "interleave", "obar", "obslash", "olessthan", \
717 "ogreaterthan", "ovee", "owedge", "oblong", "inplus", \
718 "niplus", "nplus", "subsetplus", "supsetplus", \
719 "subsetpluseq", "supsetpluseq", "Lbag", "Rbag", \
720 "llbracket", "rrbracket", "llparenthesis", \
721 "rrparenthesis", "binampersand", "bindnasrepma", \
722 "trianglelefteqslant", "trianglerighteqslant", \
723 "ntrianglelefteqslant", "ntrianglerighteqslant", \
724 "llfloor", "rrfloor", "llceil", "rrceil", "arrownot", \
725 "Arrownot", "Mapstochar", "mapsfromchar", "Mapsfromchar", \
726 "leftrightarrowtriangle", "leftarrowtriangle", \
727 "rightarrowtriangle", \
728 "bigcurlyvee", "bigcurlywedge", "bigsqcap", "bigbox", \
729 "bigparallel", "biginterleave", "bignplus", \
730 "varcopyright", "longarrownot", "Longarrownot", \
731 "Mapsto", "mapsfrom", "Mapsfrom" "Longmapsto", \
732 "longmapsfrom", "Longmapsfrom"]
733 def convert_use_stmaryrd(document):
734 "insert use_package stmaryrd"
735 convert_use_package(document, "stmaryrd", stmaryrd_commands, False)
738 def revert_use_stmaryrd(document):
739 "remove use_package stmaryrd"
740 revert_use_package(document, "stmaryrd", stmaryrd_commands, False)
743 stackrel_commands = ["stackrel"]
744 def convert_use_stackrel(document):
745 "insert use_package stackrel"
746 convert_use_package(document, "stackrel", stackrel_commands, False)
749 def revert_use_stackrel(document):
750 "remove use_package stackrel"
751 revert_use_package(document, "stackrel", stackrel_commands, False)
754 def convert_cite_engine_type(document):
755 "Determine the \\cite_engine_type from the citation engine."
756 i = find_token(document.header, "\\cite_engine", 0)
759 engine = get_value(document.header, "\\cite_engine", i)
761 engine, type = engine.split("_")
763 type = {"basic": "numerical", "jurabib": "authoryear"}[engine]
764 document.header[i] = "\\cite_engine " + engine
765 document.header.insert(i + 1, "\\cite_engine_type " + type)
768 def revert_cite_engine_type(document):
769 "Natbib had the type appended with an underscore."
770 engine_type = "numerical"
771 i = find_token(document.header, "\\cite_engine_type" , 0)
773 document.warning("No \\cite_engine_type line. Assuming numerical.")
775 engine_type = get_value(document.header, "\\cite_engine_type", i)
776 del document.header[i]
778 # We are looking for the natbib citation engine
779 i = find_token(document.header, "\\cite_engine natbib", 0)
782 document.header[i] = "\\cite_engine natbib_" + engine_type
785 def convert_cite_engine_type_default(document):
786 "Convert \\cite_engine_type to default for the basic citation engine."
787 i = find_token(document.header, "\\cite_engine basic", 0)
790 i = find_token(document.header, "\\cite_engine_type" , 0)
793 document.header[i] = "\\cite_engine_type default"
796 def revert_cite_engine_type_default(document):
797 """Revert \\cite_engine_type default.
799 Revert to numerical for the basic cite engine, otherwise to authoryear."""
800 engine_type = "authoryear"
801 i = find_token(document.header, "\\cite_engine_type default" , 0)
804 j = find_token(document.header, "\\cite_engine basic", 0)
806 engine_type = "numerical"
807 document.header[i] = "\\cite_engine_type " + engine_type
810 cancel_commands = ["cancel", "bcancel", "xcancel", "cancelto"]
811 # this is the same, as revert_use_cancel() except for the default
812 def revert_cancel(document):
813 "add cancel to the preamble if necessary"
814 revert_use_package(document, "cancel", cancel_commands, False)
817 def revert_verbatim(document):
818 " Revert verbatim einvironments completely to TeX-code. "
821 subst_end = ['\end_layout', '', '\\begin_layout Plain Layout',
823 '\\begin_layout Plain Layout', '', '',
826 '\\end_layout', '', '\\end_inset',
827 '', '', '\\end_layout']
828 subst_begin = ['\\begin_layout Standard', '\\noindent',
829 '\\begin_inset ERT', 'status open', '',
830 '\\begin_layout Plain Layout', '', '', '\\backslash',
832 '\\end_layout', '', '\\begin_layout Plain Layout', '']
835 i = find_token(document.body, "\\begin_layout Verbatim", i)
838 j = find_end_of_layout(document.body, i)
840 document.warning("Malformed LyX document: Can't find end of Verbatim layout")
843 # delete all line breaks insets (there are no other insets)
846 n = find_token(document.body, "\\begin_inset Newline newline", l, j)
848 n = find_token(document.body, "\\begin_inset Newline linebreak", l, j)
851 m = find_end_of_inset(document.body, n)
852 del(document.body[m:m+1])
853 document.body[n:n+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
855 # we deleted a line, so the end of the inset moved forward.
857 # consecutive verbatim environments need to be connected
858 k = find_token(document.body, "\\begin_layout Verbatim", j)
859 if k == j + 2 and consecutive == False:
861 document.body[j:j+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
862 document.body[i:i+1] = subst_begin
864 if k == j + 2 and consecutive == True:
865 document.body[j:j+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
866 del(document.body[i:i+1])
868 if k != j + 2 and consecutive == True:
869 document.body[j:j+1] = subst_end
870 # the next paragraph must not be indented
871 document.body[j+19:j+19] = ['\\noindent']
872 del(document.body[i:i+1])
876 document.body[j:j+1] = subst_end
877 # the next paragraph must not be indented
878 document.body[j+19:j+19] = ['\\noindent']
879 document.body[i:i+1] = subst_begin
882 def revert_tipa(document):
883 " Revert native TIPA insets to mathed or ERT. "
886 i = find_token(document.body, "\\begin_inset IPA", i)
889 j = find_end_of_inset(document.body, i)
891 document.warning("Malformed LyX document: Can't find end of IPA inset")
895 n = find_token(document.body, "\\begin_layout", i, j)
897 document.warning("Malformed LyX document: IPA inset has no embedded layout")
900 m = find_end_of_layout(document.body, n)
902 document.warning("Malformed LyX document: Can't find end of embedded layout")
905 content = document.body[n+1:m]
906 p = find_token(document.body, "\\begin_layout", m, j)
907 if p != -1 or len(content) > 1:
909 content = document.body[i+1:j]
911 # IPA insets with multiple pars need to be wrapped by \begin{IPA}...\end{IPA}
912 document.body[i:j+1] = ['\\end_layout', '', '\\begin_layout Standard'] + put_cmd_in_ert("\\begin{IPA}") + ['\\end_layout'] + content + ['\\begin_layout Standard'] + put_cmd_in_ert("\\end{IPA}")
913 add_to_preamble(document, ["\\usepackage{tipa,tipx}"])
915 # single-par IPA insets can be reverted to mathed
916 document.body[i:j+1] = ["\\begin_inset Formula $\\text{\\textipa{" + content[0] + "}}$", "\\end_inset"]
920 def revert_cell_rotation(document):
921 "Revert cell rotations to TeX-code"
923 load_rotating = False
927 # first, let's find out if we need to do anything
928 i = find_token(document.body, '<cell ', i)
931 j = document.body[i].find('rotate="')
933 k = document.body[i].find('"', j + 8)
934 value = document.body[i][j + 8 : k]
936 rgx = re.compile(r' rotate="[^"]+?"')
937 # remove rotate option
938 document.body[i] = rgx.sub('', document.body[i])
940 rgx = re.compile(r' rotate="[^"]+?"')
941 document.body[i] = rgx.sub(' rotate="true"', document.body[i])
943 rgx = re.compile(r' rotate="[^"]+?"')
945 # remove rotate option
946 document.body[i] = rgx.sub('', document.body[i])
948 document.body[i + 5 : i + 5] = \
949 put_cmd_in_ert("\\end{turn}")
950 document.body[i + 4 : i + 4] = \
951 put_cmd_in_ert("\\begin{turn}{" + value + "}")
957 add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"])
960 def convert_cell_rotation(document):
961 'Convert cell rotation statements from "true" to "90"'
965 # first, let's find out if we need to do anything
966 i = find_token(document.body, '<cell ', i)
969 j = document.body[i].find('rotate="true"')
971 rgx = re.compile(r'rotate="[^"]+?"')
972 # convert "true" to "90"
973 document.body[i] = rgx.sub('rotate="90"', document.body[i])
978 def revert_table_rotation(document):
979 "Revert table rotations to TeX-code"
981 load_rotating = False
985 # first, let's find out if we need to do anything
986 i = find_token(document.body, '<features ', i)
989 j = document.body[i].find('rotate="')
991 end_table = find_token(document.body, '</lyxtabular>', j)
992 k = document.body[i].find('"', j + 8)
993 value = document.body[i][j + 8 : k]
995 rgx = re.compile(r' rotate="[^"]+?"')
996 # remove rotate option
997 document.body[i] = rgx.sub('', document.body[i])
999 rgx = re.compile(r'rotate="[^"]+?"')
1000 document.body[i] = rgx.sub('rotate="true"', document.body[i])
1002 rgx = re.compile(r' rotate="[^"]+?"')
1003 load_rotating = True
1004 # remove rotate option
1005 document.body[i] = rgx.sub('', document.body[i])
1007 document.body[end_table + 3 : end_table + 3] = \
1008 put_cmd_in_ert("\\end{turn}")
1009 document.body[i - 2 : i - 2] = \
1010 put_cmd_in_ert("\\begin{turn}{" + value + "}")
1016 add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"])
1019 def convert_table_rotation(document):
1020 'Convert table rotation statements from "true" to "90"'
1024 # first, let's find out if we need to do anything
1025 i = find_token(document.body, '<features ', i)
1028 j = document.body[i].find('rotate="true"')
1030 rgx = re.compile(r'rotate="[^"]+?"')
1031 # convert "true" to "90"
1032 document.body[i] = rgx.sub('rotate="90"', document.body[i])
1037 def convert_listoflistings(document):
1038 'Convert ERT \lstlistoflistings to TOC lstlistoflistings inset'
1039 # We can support roundtrip because the command is so simple
1042 i = find_token(document.body, "\\begin_inset ERT", i)
1045 j = find_end_of_inset(document.body, i)
1047 document.warning("Malformed LyX document: Can't find end of ERT inset")
1050 ert = get_ert(document.body, i)
1051 if ert == "\\lstlistoflistings{}":
1052 document.body[i:j] = ["\\begin_inset CommandInset toc", "LatexCommand lstlistoflistings", ""]
1058 def revert_listoflistings(document):
1059 'Convert TOC lstlistoflistings inset to ERT lstlistoflistings'
1062 i = find_token(document.body, "\\begin_inset CommandInset toc", i)
1065 if document.body[i+1] == "LatexCommand lstlistoflistings":
1066 j = find_end_of_inset(document.body, i)
1068 document.warning("Malformed LyX document: Can't find end of TOC inset")
1071 subst = put_cmd_in_ert("\\lstlistoflistings{}")
1072 document.body[i:j+1] = subst
1073 add_to_preamble(document, ["\\usepackage{listings}"])
1077 def convert_use_amssymb(document):
1078 "insert use_package amssymb"
1079 regexp = re.compile(r'(\\use_package\s+amsmath)')
1080 i = find_re(document.header, regexp, 0)
1082 document.warning("Malformed LyX document: Can't find \\use_package amsmath.")
1084 value = get_value(document.header, "\\use_package" , i).split()[1]
1087 useamsmath = int(value)
1089 document.warning("Invalid \\use_package amsmath: " + value + ". Assuming auto.")
1091 j = find_token(document.preamble, "\\usepackage{amssymb}", 0)
1093 document.header.insert(i + 1, "\\use_package amssymb %d" % useamsmath)
1095 document.header.insert(i + 1, "\\use_package amssymb 2")
1096 del document.preamble[j]
1099 def revert_use_amssymb(document):
1100 "remove use_package amssymb"
1101 regexp1 = re.compile(r'(\\use_package\s+amsmath)')
1102 regexp2 = re.compile(r'(\\use_package\s+amssymb)')
1103 i = find_re(document.header, regexp1, 0)
1104 j = find_re(document.header, regexp2, 0)
1105 value1 = "1" # default is auto
1106 value2 = "1" # default is auto
1108 value1 = get_value(document.header, "\\use_package" , i).split()[1]
1110 value2 = get_value(document.header, "\\use_package" , j).split()[1]
1111 del document.header[j]
1112 if value1 != value2 and value2 == "2": # on
1113 add_to_preamble(document, ["\\usepackage{amssymb}"])
1116 def convert_use_cancel(document):
1117 "insert use_package cancel"
1118 convert_use_package(document, "cancel", cancel_commands, True)
1121 def revert_use_cancel(document):
1122 "remove use_package cancel"
1123 revert_use_package(document, "cancel", cancel_commands, True)
1126 def revert_ancientgreek(document):
1127 "Set the document language for ancientgreek to greek"
1129 if document.language == "ancientgreek":
1130 document.language = "greek"
1131 i = find_token(document.header, "\\language", 0)
1133 document.header[i] = "\\language greek"
1136 j = find_token(document.body, "\\lang ancientgreek", j)
1140 document.body[j] = document.body[j].replace("\\lang ancientgreek", "\\lang greek")
1144 def revert_languages(document):
1145 "Set the document language for new supported languages to English"
1148 "coptic", "divehi", "hindi", "kurmanji", "lao", "marathi", "occitan", "sanskrit",
1149 "syriac", "tamil", "telugu", "urdu"
1151 for n in range(len(languages)):
1152 if document.language == languages[n]:
1153 document.language = "english"
1154 i = find_token(document.header, "\\language", 0)
1156 document.header[i] = "\\language english"
1158 while j < len(document.body):
1159 j = find_token(document.body, "\\lang " + languages[n], j)
1161 document.body[j] = document.body[j].replace("\\lang " + languages[n], "\\lang english")
1164 j = len(document.body)
1167 def convert_armenian(document):
1168 "Use polyglossia and thus non-TeX fonts for Armenian"
1170 if document.language == "armenian":
1171 i = find_token(document.header, "\\use_non_tex_fonts", 0)
1173 document.header[i] = "\\use_non_tex_fonts true"
1176 def revert_armenian(document):
1177 "Use ArmTeX and thus TeX fonts for Armenian"
1179 if document.language == "armenian":
1180 i = find_token(document.header, "\\use_non_tex_fonts", 0)
1182 document.header[i] = "\\use_non_tex_fonts false"
1185 def revert_libertine(document):
1186 " Revert native libertine font definition to LaTeX "
1188 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1189 i = find_token(document.header, "\\font_roman libertine", 0)
1192 j = find_token(document.header, "\\font_osf true", 0)
1195 preamble = "\\usepackage"
1197 document.header[j] = "\\font_osf false"
1200 preamble += "[lining]"
1201 preamble += "{libertine-type1}"
1202 add_to_preamble(document, [preamble])
1203 document.header[i] = "\\font_roman default"
1206 def revert_txtt(document):
1207 " Revert native txtt font definition to LaTeX "
1209 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1210 i = find_token(document.header, "\\font_typewriter txtt", 0)
1212 preamble = "\\renewcommand{\\ttdefault}{txtt}"
1213 add_to_preamble(document, [preamble])
1214 document.header[i] = "\\font_typewriter default"
1217 def revert_mathdesign(document):
1218 " Revert native mathdesign font definition to LaTeX "
1220 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1226 i = find_token(document.header, "\\font_roman", 0)
1229 val = get_value(document.header, "\\font_roman", i)
1230 if val in mathdesign_dict.keys():
1231 preamble = "\\usepackage[%s" % mathdesign_dict[val]
1233 j = find_token(document.header, "\\font_osf true", 0)
1236 document.header[j] = "\\font_osf false"
1237 l = find_token(document.header, "\\font_sc true", 0)
1240 document.header[l] = "\\font_sc false"
1242 preamble += ",expert"
1243 preamble += "]{mathdesign}"
1244 add_to_preamble(document, [preamble])
1245 document.header[i] = "\\font_roman default"
1248 def revert_texgyre(document):
1249 " Revert native TeXGyre font definition to LaTeX "
1251 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1252 texgyre_fonts = ["tgadventor", "tgbonum", "tgchorus", "tgcursor", \
1253 "tgheros", "tgpagella", "tgschola", "tgtermes"]
1254 i = find_token(document.header, "\\font_roman", 0)
1256 val = get_value(document.header, "\\font_roman", i)
1257 if val in texgyre_fonts:
1258 preamble = "\\usepackage{%s}" % val
1259 add_to_preamble(document, [preamble])
1260 document.header[i] = "\\font_roman default"
1261 i = find_token(document.header, "\\font_sans", 0)
1263 val = get_value(document.header, "\\font_sans", i)
1264 if val in texgyre_fonts:
1265 preamble = "\\usepackage{%s}" % val
1266 add_to_preamble(document, [preamble])
1267 document.header[i] = "\\font_sans default"
1268 i = find_token(document.header, "\\font_typewriter", 0)
1270 val = get_value(document.header, "\\font_typewriter", i)
1271 if val in texgyre_fonts:
1272 preamble = "\\usepackage{%s}" % val
1273 add_to_preamble(document, [preamble])
1274 document.header[i] = "\\font_typewriter default"
1277 def revert_ipadeco(document):
1278 " Revert IPA decorations to ERT "
1281 i = find_token(document.body, "\\begin_inset IPADeco", i)
1284 end = find_end_of_inset(document.body, i)
1286 document.warning("Can't find end of inset at line " + str(i))
1289 line = document.body[i]
1290 rx = re.compile(r'\\begin_inset IPADeco (.*)$')
1292 decotype = m.group(1)
1293 if decotype != "toptiebar" and decotype != "bottomtiebar":
1294 document.warning("Invalid IPADeco type: " + decotype)
1297 blay = find_token(document.body, "\\begin_layout Plain Layout", i, end)
1299 document.warning("Can't find layout for inset at line " + str(i))
1302 bend = find_end_of_layout(document.body, blay)
1304 document.warning("Malformed LyX document: Could not find end of IPADeco inset's layout.")
1307 substi = ["\\begin_inset ERT", "status collapsed", "",
1308 "\\begin_layout Plain Layout", "", "", "\\backslash",
1309 decotype + "{", "\\end_layout", "", "\\end_inset"]
1310 substj = ["\\size default", "", "\\begin_inset ERT", "status collapsed", "",
1311 "\\begin_layout Plain Layout", "", "}", "\\end_layout", "", "\\end_inset"]
1312 # do the later one first so as not to mess up the numbering
1313 document.body[bend:end + 1] = substj
1314 document.body[i:blay + 1] = substi
1315 i = end + len(substi) + len(substj) - (end - bend) - (blay - i) - 2
1316 add_to_preamble(document, "\\usepackage{tipa}")
1319 def revert_ipachar(document):
1320 ' Revert \\IPAChar to ERT '
1323 while i < len(document.body):
1324 m = re.match(r'(.*)\\IPAChar \\(\w+\{\w+\})(.*)', document.body[i])
1328 ipachar = m.group(2)
1331 '\\begin_inset ERT',
1332 'status collapsed', '',
1333 '\\begin_layout Standard',
1334 '', '', '\\backslash',
1339 document.body[i: i+1] = subst
1344 add_to_preamble(document, "\\usepackage{tone}")
1347 def revert_minionpro(document):
1348 " Revert native MinionPro font definition to LaTeX "
1350 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1351 i = find_token(document.header, "\\font_roman minionpro", 0)
1354 j = find_token(document.header, "\\font_osf true", 0)
1357 preamble = "\\usepackage"
1359 document.header[j] = "\\font_osf false"
1362 preamble += "{MinionPro}"
1363 add_to_preamble(document, [preamble])
1364 document.header[i] = "\\font_roman default"
1367 def revert_mathfonts(document):
1368 " Revert native math font definitions to LaTeX "
1370 i = find_token(document.header, "\\font_math", 0)
1373 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1374 val = get_value(document.header, "\\font_math", i)
1375 if val == "eulervm":
1376 add_to_preamble(document, "\\usepackage{eulervm}")
1377 elif val == "default":
1379 "lmodern": "\\renewcommand{\\rmdefault}{lmr}",
1380 "minionpro": "\\usepackage[onlytext,lf]{MinionPro}",
1381 "minionpro-osf": "\\usepackage[onlytext]{MinionPro}",
1382 "palatino": "\\renewcommand{\\rmdefault}{ppl}",
1383 "palatino-osf": "\\renewcommand{\\rmdefault}{pplj}",
1384 "times": "\\renewcommand{\\rmdefault}{ptm}",
1385 "utopia": "\\renewcommand{\\rmdefault}{futs}",
1386 "utopia-osf": "\\renewcommand{\\rmdefault}{futj}",
1388 j = find_token(document.header, "\\font_roman", 0)
1390 rm = get_value(document.header, "\\font_roman", j)
1391 k = find_token(document.header, "\\font_osf true", 0)
1394 if rm in mathfont_dict.keys():
1395 add_to_preamble(document, mathfont_dict[rm])
1396 document.header[j] = "\\font_roman default"
1398 document.header[k] = "\\font_osf false"
1399 del document.header[i]
1402 def revert_mdnomath(document):
1403 " Revert mathdesign and fourier without math "
1405 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1407 "md-charter": "mdbch",
1408 "md-utopia": "mdput",
1409 "md-garamond": "mdugm"
1411 i = find_token(document.header, "\\font_roman", 0)
1414 val = get_value(document.header, "\\font_roman", i)
1415 if val in mathdesign_dict.keys():
1416 j = find_token(document.header, "\\font_math", 0)
1418 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1419 mval = get_value(document.header, "\\font_math", j)
1420 if mval == "default":
1421 document.header[i] = "\\font_roman default"
1422 add_to_preamble(document, "\\renewcommand{\\rmdefault}{%s}" % mathdesign_dict[val])
1424 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1427 def convert_mdnomath(document):
1428 " Change mathdesign font name "
1430 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1432 "mdbch": "md-charter",
1433 "mdput": "md-utopia",
1434 "mdugm": "md-garamond"
1436 i = find_token(document.header, "\\font_roman", 0)
1439 val = get_value(document.header, "\\font_roman", i)
1440 if val in mathdesign_dict.keys():
1441 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1444 def revert_newtxmath(document):
1445 " Revert native newtxmath definitions to LaTeX "
1447 i = find_token(document.header, "\\font_math", 0)
1450 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1451 val = get_value(document.header, "\\font_math", i)
1453 "libertine-ntxm": "\\usepackage[libertine]{newtxmath}",
1454 "minion-ntxm": "\\usepackage[minion]{newtxmath}",
1455 "newtxmath": "\\usepackage{newtxmath}",
1457 if val in mathfont_dict.keys():
1458 add_to_preamble(document, mathfont_dict[val])
1459 document.header[i] = "\\font_math auto"
1462 def revert_biolinum(document):
1463 " Revert native biolinum font definition to LaTeX "
1465 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1466 i = find_token(document.header, "\\font_sans biolinum", 0)
1469 j = find_token(document.header, "\\font_osf true", 0)
1472 preamble = "\\usepackage"
1475 preamble += "{biolinum-type1}"
1476 add_to_preamble(document, [preamble])
1477 document.header[i] = "\\font_sans default"
1480 def revert_uop(document):
1481 " Revert native URW Classico (Optima) font definition to LaTeX "
1483 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1484 i = find_token(document.header, "\\font_sans uop", 0)
1486 preamble = "\\renewcommand{\\sfdefault}{uop}"
1487 add_to_preamble(document, [preamble])
1488 document.header[i] = "\\font_sans default"
1491 def convert_latexargs(document):
1492 " Convert InsetArgument to new syntax "
1494 if find_token(document.body, "\\begin_inset Argument", 0) == -1:
1498 # A list of layouts (document classes) with only optional or no arguments.
1499 # These can be safely converted to the new syntax
1500 # (I took the liberty to add some of my personal layouts/modules here; JSP)
1501 safe_layouts = ["aa", "aapaper", "aastex", "achemso", "acmsiggraph", "AEA",
1502 "agu-dtd", "agums", "agutex", "amsart", "amsbook", "apa",
1503 "arab-article", "armenian-article", "article-beamer", "article",
1504 "beamer", "book", "broadway", "chess", "cl2emult", "ctex-article",
1505 "ctex-book", "ctex-report", "dinbrief", "docbook-book", "docbook-chapter",
1506 "docbook", "docbook-section", "doublecol-new", "dtk", "ectaart", "egs",
1507 "elsarticle", "elsart", "entcs", "europecv", "extarticle", "extbook",
1508 "extletter", "extreport", "foils", "frletter", "g-brief2", "g-brief",
1509 "heb-article", "heb-letter", "hollywood", "IEEEtran", "ijmpc", "ijmpd",
1510 "iopart", "isprs", "jarticle", "jasatex", "jbook", "jgrga", "jreport",
1511 "jsarticle", "jsbeamer", "jsbook", "jss", "kluwer", "latex8", "letter", "lettre",
1512 "literate-article", "literate-book", "literate-report", "llncs", "ltugboat",
1513 "memoir", "moderncv", "mwart", "mwbk", "mwrep", "paper", "powerdot",
1514 "recipebook", "report", "revtex4", "revtex", "scrartcl", "scrarticle-beamer",
1515 "scrbook", "scrlettr", "scrlttr2", "scrreprt", "seminar", "siamltex",
1516 "sigplanconf", "simplecv", "singlecol", "singlecol-new", "slides", "spie",
1517 "svglobal3", "svglobal", "svjog", "svmono", "svmult", "svprobth", "tarticle",
1518 "tbook", "treport", "tufte-book", "tufte-handout"]
1519 # A list of "safe" modules, same as above
1520 safe_modules = ["biblatex", "beameraddons", "beamer-resenumerate", "beamersession", "braille",
1521 "customHeadersFooters", "endnotes", "enumitem", "eqs-within-sections", "figs-within-sections",
1522 "fix-cm", "fixltx2e", "foottoend", "hanging", "jscharstyles", "knitr", "lilypond",
1523 "linguistics", "linguisticx", "logicalmkup", "minimalistic", "nomindex", "noweb",
1524 "pdfcomment", "sweave", "tabs-within-sections", "theorems-ams-bytype",
1525 "theorems-ams-extended-bytype", "theorems-ams-extended", "theorems-ams", "theorems-bytype",
1526 "theorems-chap-bytype", "theorems-chap", "theorems-named", "theorems-sec-bytype",
1527 "theorems-sec", "theorems-starred", "theorems-std", "todonotes"]
1528 # Modules we need to take care of
1529 caveat_modules = ["initials"]
1530 # information about the relevant styles in caveat_modules (number of opt and req args)
1531 # use this if we get more caveat_modules. For now, use hard coding (see below).
1532 # initials = [{'Layout' : 'Initial', 'opt' : 1, 'req' : 1}]
1534 # Is this a known safe layout?
1535 safe_layout = document.textclass in safe_layouts
1537 document.warning("Lyx2lyx knows nothing about textclass '%s'. "
1538 "Please check if short title insets have been converted correctly."
1539 % document.textclass)
1540 # Do we use unsafe or unknown modules
1541 mods = document.get_module_list()
1542 unknown_modules = False
1543 used_caveat_modules = list()
1545 if mod in safe_modules:
1547 if mod in caveat_modules:
1548 used_caveat_modules.append(mod)
1550 unknown_modules = True
1551 document.warning("Lyx2lyx knows nothing about module '%s'. "
1552 "Please check if short title insets have been converted correctly."
1557 i = find_token(document.body, "\\begin_inset Argument", i)
1561 if not safe_layout or unknown_modules:
1562 # We cannot do more here since we have no access to this layout.
1563 # InsetArgument itself will do the real work
1564 # (see InsetArgument::updateBuffer())
1565 document.body[i] = "\\begin_inset Argument 999"
1569 # Find containing paragraph layout
1570 parent = get_containing_layout(document.body, i)
1572 document.warning("Malformed LyX document: Can't find parent paragraph layout")
1579 if len(used_caveat_modules) > 0:
1580 # We know for now that this must be the initials module with the Initial layout
1581 # If we get more such modules, we need some automating.
1582 if parent[0] == "Initial":
1583 # Layout has 1 opt and 1 req arg.
1584 # Count the actual arguments
1586 for p in range(parbeg, parend):
1587 if document.body[p] == "\\begin_inset Argument":
1592 # Collect all arguments in this paragraph
1594 for p in range(parbeg, parend):
1595 if document.body[p] == "\\begin_inset Argument":
1597 if allowed_opts != -1:
1598 # We have less arguments than opt + required.
1599 # required must take precedence.
1600 if argnr > allowed_opts and argnr < first_req:
1602 document.body[p] = "\\begin_inset Argument %d" % argnr
1606 def revert_latexargs(document):
1607 " Revert InsetArgument to old syntax "
1610 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
1613 # Search for Argument insets
1614 i = find_token(document.body, "\\begin_inset Argument", i)
1617 m = rx.match(document.body[i])
1619 # No ID: inset already reverted
1622 # Find containing paragraph layout
1623 parent = get_containing_layout(document.body, i)
1625 document.warning("Malformed LyX document: Can't find parent paragraph layout")
1630 # Do not set realparbeg to parent[3], since this does not work if we
1631 # have another inset (e.g. label or index) before the first argument
1632 # inset (this is the case in the user guide of LyX 2.0.8)
1634 # Collect all arguments in this paragraph
1636 for p in range(parbeg, parend):
1637 m = rx.match(document.body[p])
1640 # This is the first argument inset
1642 val = int(m.group(1))
1643 j = find_end_of_inset(document.body, p)
1644 # Revert to old syntax
1645 document.body[p] = "\\begin_inset Argument"
1647 document.warning("Malformed LyX document: Can't find end of Argument inset")
1650 args[val] = document.body[p : j + 1]
1652 realparend = realparend - len(document.body[p : j + 1])
1653 # Remove arg inset at this position
1654 del document.body[p : j + 1]
1658 # No argument inset found
1659 realparbeg = parent[3]
1660 # Now sort the arg insets
1662 for f in sorted(args):
1665 # Insert the sorted arg insets at paragraph begin
1666 document.body[realparbeg : realparbeg] = subst
1668 i = realparbeg + 1 + len(subst)
1671 def revert_IEEEtran(document):
1673 Reverts InsetArgument of
1676 Biography without photo
1679 if document.textclass == "IEEEtran":
1686 i = find_token(document.body, "\\begin_layout Page headings", i)
1688 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1691 i2 = find_token(document.body, "\\begin_inset Flex Paragraph Start", i2)
1693 revert_Argument_to_TeX_brace(document, i2, 0, 1, 1, False, False)
1696 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1698 revert_Argument_to_TeX_brace(document, j, 0, 1, 1, True, False)
1701 k = find_token(document.body, "\\begin_layout Biography", k)
1702 kA = find_token(document.body, "\\begin_layout Biography without photo", k)
1703 if k == kA and k != -1:
1707 # start with the second argument, therefore 2
1708 revert_Argument_to_TeX_brace(document, k, 0, 2, 2, True, False)
1710 if i == -1 and i2 == -1 and j == -1 and k == -1:
1714 def revert_IEEEtran_2(document):
1716 Reverts Flex Paragraph Start to TeX-code
1718 if document.textclass == "IEEEtran":
1721 begin = find_token(document.body, "\\begin_inset Flex Paragraph Start", begin)
1724 end1 = find_end_of_inset(document.body, begin)
1725 document.body[end1 - 2 : end1 + 1] = put_cmd_in_ert("}")
1726 document.body[begin : begin + 4] = put_cmd_in_ert("\\IEEEPARstart{")
1730 def convert_IEEEtran(document):
1735 Biography without photo
1738 if document.textclass == "IEEEtran":
1744 i = find_token(document.body, "\\begin_layout Page headings", i)
1746 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1749 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1751 convert_TeX_brace_to_Argument(document, j, 1, 1, False, True, False)
1754 # assure that we don't handle Biography Biography without photo
1755 k = find_token(document.body, "\\begin_layout Biography", k)
1756 kA = find_token(document.body, "\\begin_layout Biography without photo", k - 1)
1757 if k == kA and k != -1:
1761 # the argument we want to convert is the second one
1762 convert_TeX_brace_to_Argument(document, k, 2, 2, False, True, False)
1764 if i == -1 and j == -1 and k == -1:
1768 def revert_AASTeX(document):
1769 " Reverts InsetArgument of Altaffilation to TeX-code "
1770 if document.textclass == "aastex":
1773 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1776 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1780 def convert_AASTeX(document):
1781 " Converts ERT of Altaffilation to InsetArgument "
1782 if document.textclass == "aastex":
1785 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1788 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1792 def revert_AGUTeX(document):
1793 " Reverts InsetArgument of Author affiliation to TeX-code "
1794 if document.textclass == "agutex":
1797 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1800 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1804 def convert_AGUTeX(document):
1805 " Converts ERT of Author affiliation to InsetArgument "
1806 if document.textclass == "agutex":
1809 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1812 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1816 def revert_IJMP(document):
1817 " Reverts InsetArgument of MarkBoth to TeX-code "
1818 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1821 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1824 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1828 def convert_IJMP(document):
1829 " Converts ERT of MarkBoth to InsetArgument "
1830 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1833 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1836 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1840 def revert_SIGPLAN(document):
1841 " Reverts InsetArguments of SIGPLAN to TeX-code "
1842 if document.textclass == "sigplanconf":
1847 i = find_token(document.body, "\\begin_layout Conference", i)
1849 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1852 j = find_token(document.body, "\\begin_layout Author", j)
1854 revert_Argument_to_TeX_brace(document, j, 0, 1, 2, False, False)
1856 if i == -1 and j == -1:
1860 def convert_SIGPLAN(document):
1861 " Converts ERT of SIGPLAN to InsetArgument "
1862 if document.textclass == "sigplanconf":
1867 i = find_token(document.body, "\\begin_layout Conference", i)
1869 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1872 j = find_token(document.body, "\\begin_layout Author", j)
1874 convert_TeX_brace_to_Argument(document, j, 1, 2, False, False, False)
1876 if i == -1 and j == -1:
1880 def revert_SIGGRAPH(document):
1881 " Reverts InsetArgument of Flex CRcat to TeX-code "
1882 if document.textclass == "acmsiggraph":
1885 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1888 revert_Argument_to_TeX_brace(document, i, 0, 1, 3, False, False)
1892 def convert_SIGGRAPH(document):
1893 " Converts ERT of Flex CRcat to InsetArgument "
1894 if document.textclass == "acmsiggraph":
1897 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1900 convert_TeX_brace_to_Argument(document, i, 1, 3, True, False, False)
1904 def revert_EuropeCV(document):
1905 " Reverts InsetArguments of europeCV to TeX-code "
1906 if document.textclass == "europecv":
1913 i = find_token(document.body, "\\begin_layout Item", i)
1915 revert_Argument_to_TeX_brace(document, i, 0, 2, 2, False, False)
1918 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1920 revert_Argument_to_TeX_brace(document, j, 0, 2, 2, False, False)
1923 k = find_token(document.body, "\\begin_layout Language", k)
1925 revert_Argument_to_TeX_brace(document, k, 0, 2, 6, False, False)
1928 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1930 revert_Argument_to_TeX_brace(document, m, 0, 2, 6, False, False)
1932 if i == -1 and j == -1 and k == -1 and m == -1:
1936 def convert_EuropeCV(document):
1937 " Converts ERT of europeCV to InsetArgument "
1938 if document.textclass == "europecv":
1945 i = find_token(document.body, "\\begin_layout Item", i)
1947 convert_TeX_brace_to_Argument(document, i, 2, 2, False, False, False)
1950 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1952 convert_TeX_brace_to_Argument(document, j, 2, 2, False, False, False)
1955 k = find_token(document.body, "\\begin_layout Language", k)
1957 convert_TeX_brace_to_Argument(document, k, 2, 6, False, False, False)
1960 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1962 convert_TeX_brace_to_Argument(document, m, 2, 6, False, False, False)
1964 if i == -1 and j == -1 and k == -1 and m == -1:
1968 def revert_ModernCV(document):
1969 " Reverts InsetArguments of modernCV to TeX-code "
1970 if document.textclass == "moderncv":
1978 j = find_token(document.body, "\\begin_layout Entry", j)
1980 revert_Argument_to_TeX_brace(document, j, 0, 1, 5, False, False)
1983 k = find_token(document.body, "\\begin_layout Item", k)
1985 revert_Argument_to_TeX_brace(document, k, 0, 1, 1, False, False)
1988 m = find_token(document.body, "\\begin_layout ItemWithComment", m)
1990 revert_Argument_to_TeX_brace(document, m, 0, 1, 2, False, False)
1991 document.body[m] = document.body[m].replace("\\begin_layout ItemWithComment", "\\begin_layout Language")
1994 o = find_token(document.body, "\\begin_layout DoubleItem", o)
1996 revert_Argument_to_TeX_brace(document, o, 0, 1, 3, False, False)
1997 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout Computer")
2000 p = find_token(document.body, "\\begin_layout Social", p)
2002 revert_Argument_to_TeX_brace(document, p, 0, 1, 1, False, True)
2004 if j == -1 and k == -1 and m == -1 and o == -1 and p == -1:
2008 def revert_ModernCV_2(document):
2009 " Reverts the Flex:Column inset of modernCV to TeX-code "
2010 if document.textclass == "moderncv":
2014 flex = find_token(document.body, "\\begin_inset Flex Column", flex)
2017 flexEnd = find_end_of_inset(document.body, flex)
2018 wasOpt = revert_Argument_to_TeX_brace(document, flex, flexEnd, 1, 1, False, True)
2019 revert_Argument_to_TeX_brace(document, flex, 0, 2, 2, False, False)
2020 flexEnd = find_end_of_inset(document.body, flex)
2022 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn")
2024 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn{")
2025 document.body[flexEnd + 4 : flexEnd + 7] = put_cmd_in_ert("}")
2029 def revert_ModernCV_3(document):
2030 " Reverts the Column style of modernCV to TeX-code "
2031 if document.textclass == "moderncv":
2032 # revert the layouts
2033 revert_ModernCV(document)
2035 # get the position of the end of the last column inset
2036 LastFlexEnd = revert_ModernCV_2(document)
2038 p = find_token(document.body, "\\begin_layout Columns", p)
2041 pEnd = find_end_of_layout(document.body, p)
2042 document.body[p] = document.body[p].replace("\\begin_layout Columns", "\\begin_layout Standard")
2043 if LastFlexEnd != -1:
2044 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\begin{cvcolumns}")
2045 document.body[LastFlexEnd + 24 : LastFlexEnd + 24] = put_cmd_in_ert("\\end{cvcolumns}")
2049 def revert_ModernCV_4(document):
2050 " Reverts the style Social to TeX-code "
2051 if document.textclass == "moderncv":
2052 # revert the layouts
2053 revert_ModernCV(document)
2056 p = find_token(document.body, "\\begin_layout Social", p)
2059 pEnd = find_end_of_layout(document.body, p)
2060 document.body[p] = document.body[p].replace("\\begin_layout Social", "\\begin_layout Standard")
2061 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\social")
2062 hasOpt = find_token(document.body, "[", p + 9)
2064 document.body[p + 30 : p + 30] = put_cmd_in_ert("{")
2065 document.body[p + 41 : p + 41] = put_cmd_in_ert("}")
2067 document.body[p + 11 : p + 11] = put_cmd_in_ert("{")
2068 document.body[p + 21 : p + 21] = put_cmd_in_ert("}")
2072 def convert_ModernCV(document):
2073 " Converts ERT of modernCV to InsetArgument "
2074 if document.textclass == "moderncv":
2082 i = find_token(document.body, "\\begin_layout DoubleItem", i)
2084 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
2085 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout DoubleListItem")
2088 j = find_token(document.body, "\\begin_layout Entry", j)
2090 convert_TeX_brace_to_Argument(document, j, 1, 5, False, False, False)
2093 k = find_token(document.body, "\\begin_layout Item", k)
2095 convert_TeX_brace_to_Argument(document, k, 1, 1, False, False, False)
2098 m = find_token(document.body, "\\begin_layout Language", m)
2100 convert_TeX_brace_to_Argument(document, m, 1, 2, False, False, False)
2102 if i == -1 and j == -1 and k == -1 and m == -1:
2106 def revert_Initials(document):
2107 " Reverts InsetArgument of Initial to TeX-code "
2110 i = find_token(document.body, "\\begin_layout Initial", i)
2113 # first arg (optional) and second arg (first mandatory) are supported in LyX 2.0.x
2114 revert_Argument_to_TeX_brace(document, i, 0, 3, 3, False, False)
2118 def convert_Initials(document):
2119 " Converts ERT of Initial to InsetArgument "
2122 i = find_token(document.body, "\\begin_layout Initial", i)
2125 convert_TeX_brace_to_Argument(document, i, 3, 3, False, False, False)
2129 def revert_literate(document):
2130 " Revert Literate document to old format "
2131 if del_token(document.header, "noweb", 0):
2132 document.textclass = "literate-" + document.textclass
2135 i = find_token(document.body, "\\begin_layout Chunk", i)
2138 document.body[i] = "\\begin_layout Scrap"
2142 def convert_literate(document):
2143 " Convert Literate document to new format"
2144 i = find_token(document.header, "\\textclass", 0)
2145 if (i != -1) and "literate-" in document.header[i]:
2146 document.textclass = document.header[i].replace("\\textclass literate-", "")
2147 j = find_token(document.header, "\\begin_modules", 0)
2149 document.header.insert(j + 1, "noweb")
2151 document.header.insert(i + 1, "\\end_modules")
2152 document.header.insert(i + 1, "noweb")
2153 document.header.insert(i + 1, "\\begin_modules")
2156 i = find_token(document.body, "\\begin_layout Scrap", i)
2159 document.body[i] = "\\begin_layout Chunk"
2163 def revert_itemargs(document):
2164 " Reverts \\item arguments to TeX-code "
2167 i = find_token(document.body, "\\begin_inset Argument item:", i)
2170 j = find_end_of_inset(document.body, i)
2171 # Find containing paragraph layout
2172 parent = get_containing_layout(document.body, i)
2174 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2178 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2179 endPlain = find_end_of_layout(document.body, beginPlain)
2180 content = document.body[beginPlain + 1 : endPlain]
2181 del document.body[i:j+1]
2182 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2183 document.body[parbeg : parbeg] = subst
2187 def revert_garamondx_newtxmath(document):
2188 " Revert native garamond newtxmath definition to LaTeX "
2190 i = find_token(document.header, "\\font_math", 0)
2193 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2194 val = get_value(document.header, "\\font_math", i)
2195 if val == "garamondx-ntxm":
2196 add_to_preamble(document, "\\usepackage[garamondx]{newtxmath}")
2197 document.header[i] = "\\font_math auto"
2200 def revert_garamondx(document):
2201 " Revert native garamond font definition to LaTeX "
2203 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2204 i = find_token(document.header, "\\font_roman garamondx", 0)
2207 j = find_token(document.header, "\\font_osf true", 0)
2210 preamble = "\\usepackage"
2212 preamble += "[osfI]"
2213 preamble += "{garamondx}"
2214 add_to_preamble(document, [preamble])
2215 document.header[i] = "\\font_roman default"
2218 def convert_beamerargs(document):
2219 " Converts beamer arguments to new layout "
2221 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2222 if document.textclass not in beamer_classes:
2225 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2226 list_layouts = ["Itemize", "Enumerate", "Description"]
2227 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
2231 i = find_token(document.body, "\\begin_inset Argument", i)
2234 # Find containing paragraph layout
2235 parent = get_containing_layout(document.body, i)
2237 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2242 layoutname = parent[0]
2243 for p in range(parbeg, parend):
2244 if layoutname in shifted_layouts:
2245 m = rx.match(document.body[p])
2247 argnr = int(m.group(1))
2249 document.body[p] = "\\begin_inset Argument %d" % argnr
2250 if layoutname == "AgainFrame":
2251 m = rx.match(document.body[p])
2253 document.body[p] = "\\begin_inset Argument 3"
2254 if document.body[p + 4] == "\\begin_inset ERT":
2255 if document.body[p + 9].startswith("<"):
2256 # This is an overlay specification
2258 document.body[p + 9] = document.body[p + 9][1:]
2259 if document.body[p + 9].endswith(">"):
2261 document.body[p + 9] = document.body[p + 9][:-1]
2263 document.body[p] = "\\begin_inset Argument 2"
2264 if layoutname in list_layouts:
2265 m = rx.match(document.body[p])
2267 if m.group(1) == "1":
2268 if document.body[p + 4] == "\\begin_inset ERT":
2269 if document.body[p + 9].startswith("<"):
2270 # This is an overlay specification
2272 document.body[p + 9] = document.body[p + 9][1:]
2273 if document.body[p + 9].endswith(">"):
2275 document.body[p + 9] = document.body[p + 9][:-1]
2276 elif document.body[p + 4].startswith("<"):
2277 # This is an overlay specification (without ERT)
2279 document.body[p + 4] = document.body[p + 4][1:]
2280 if document.body[p + 4].endswith(">"):
2282 document.body[p + 4] = document.body[p + 4][:-1]
2283 elif layoutname != "Itemize":
2285 document.body[p] = "\\begin_inset Argument 2"
2290 # Helper function for the frame conversion routines
2292 # FIXME: This method currently requires the arguments to be either
2293 # * In one (whole) ERT each: <ERT>[<arg1>]</ERT><ERT><arg2></ERT><ERT>[arg3]</ERT>
2294 # * Altogether in one whole ERT: <ERT>[<arg1>]<arg2>[arg3]</ERT>
2295 # If individual arguments mix ERT and non-ERT or are splitted
2296 # over several ERTs, the parsing fails.
2297 def convert_beamerframeargs(document, i, parbeg):
2300 if document.body[parbeg] != "\\begin_inset ERT":
2302 ertend = find_end_of_inset(document.body, parbeg)
2304 document.warning("Malformed LyX document: missing ERT \\end_inset")
2306 ertcont = parbeg + 5
2307 if document.body[ertcont].startswith("[<"):
2308 # This is a default overlay specification
2310 document.body[ertcont] = document.body[ertcont][2:]
2311 if document.body[ertcont].endswith(">]"):
2313 document.body[ertcont] = document.body[ertcont][:-2]
2314 elif document.body[ertcont].endswith("]"):
2316 tok = document.body[ertcont].find('>][')
2318 subst = [document.body[ertcont][:tok],
2319 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2320 'status collapsed', '', '\\begin_layout Plain Layout',
2321 document.body[ertcont][tok + 3:-1]]
2322 document.body[ertcont : ertcont + 1] = subst
2324 # Convert to ArgInset
2325 document.body[parbeg] = "\\begin_inset Argument 2"
2326 elif document.body[ertcont].startswith("<"):
2327 # This is an overlay specification
2329 document.body[ertcont] = document.body[ertcont][1:]
2330 if document.body[ertcont].endswith(">"):
2332 document.body[ertcont] = document.body[ertcont][:-1]
2333 # Convert to ArgInset
2334 document.body[parbeg] = "\\begin_inset Argument 1"
2335 elif document.body[ertcont].endswith(">]"):
2337 tok = document.body[ertcont].find('>[<')
2339 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2340 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2341 'status collapsed', '', '\\begin_layout Plain Layout',
2342 document.body[ertcont][tok + 3:-2]]
2343 # Convert to ArgInset
2344 document.body[parbeg] = "\\begin_inset Argument 1"
2346 elif document.body[ertcont].endswith("]"):
2348 tok = document.body[ertcont].find('>[<')
2351 tokk = document.body[ertcont].find('>][')
2353 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2354 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2355 'status collapsed', '', '\\begin_layout Plain Layout',
2356 document.body[ertcont][tok + 3:tokk],
2357 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2358 'status collapsed', '', '\\begin_layout Plain Layout',
2359 document.body[ertcont][tokk + 3:-1]]
2362 tokk = document.body[ertcont].find('>[')
2364 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tokk],
2365 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2366 'status collapsed', '', '\\begin_layout Plain Layout',
2367 document.body[ertcont][tokk + 2:-1]]
2369 # Convert to ArgInset
2370 document.body[parbeg] = "\\begin_inset Argument 1"
2371 elif document.body[ertcont].startswith("["):
2372 # This is an ERT option
2374 document.body[ertcont] = document.body[ertcont][1:]
2375 if document.body[ertcont].endswith("]"):
2377 document.body[ertcont] = document.body[ertcont][:-1]
2378 # Convert to ArgInset
2379 document.body[parbeg] = "\\begin_inset Argument 3"
2385 def convert_againframe_args(document):
2386 " Converts beamer AgainFrame to new layout "
2388 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2389 if document.textclass not in beamer_classes:
2394 i = find_token(document.body, "\\begin_layout AgainFrame", i)
2397 parent = get_containing_layout(document.body, i)
2399 document.warning("Wrong parent layout!")
2403 # Convert ERT arguments
2404 # FIXME: See restrictions in convert_beamerframeargs method
2405 ertend = convert_beamerframeargs(document, i, parbeg)
2411 def convert_corollary_args(document):
2412 " Converts beamer corrolary-style ERT arguments native InsetArgs "
2414 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2415 if document.textclass not in beamer_classes:
2418 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2419 for lay in corollary_layouts:
2422 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2425 parent = get_containing_layout(document.body, i)
2427 document.warning("Wrong parent layout!")
2431 if document.body[parbeg] == "\\begin_inset ERT":
2432 ertcontfirstline = parbeg + 5
2433 # Find the last ERT in this paragraph (which might also be the first)
2434 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
2435 if lastertbeg == -1:
2436 document.warning("Last ERT not found!")
2438 lastertend = find_end_of_inset(document.body, lastertbeg)
2439 if lastertend == -1:
2440 document.warning("End of last ERT not found!")
2442 ertcontlastline = lastertend - 3
2443 if document.body[ertcontfirstline].startswith("<"):
2444 # This is an overlay specification
2446 document.body[ertcontfirstline] = document.body[ertcontfirstline][1:]
2447 if document.body[ertcontlastline].endswith(">"):
2449 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
2450 if ertcontfirstline < ertcontlastline:
2451 # Multiline ERT. Might contain TeX code. Embrace in ERT.
2452 document.body[ertcontlastline : ertcontlastline + 1] = [
2453 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
2454 document.body[ertcontfirstline : ertcontfirstline + 1] = [
2455 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
2456 'status collapsed', '', '\\begin_layout Plain Layout',
2457 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
2458 document.body[ertcontfirstline]]
2460 # Convert to ArgInset
2461 document.body[parbeg] = "\\begin_inset Argument 1"
2462 elif document.body[ertcontlastline].endswith("]"):
2464 ertcontdivline = document.body[ertcontfirstline].find('>[')
2465 if ertcontdivline != -1:
2466 if ertcontfirstline < ertcontlastline:
2467 # Multiline ERT. Might contain TeX code. Embrace in ERT.
2468 document.body[ertcontlastline : ertcontlastline + 1] = [
2469 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
2470 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
2471 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2472 'status collapsed', '', '\\begin_layout Plain Layout',
2473 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
2474 document.body[ertcontdivline][tok + 2:]]
2476 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
2477 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2478 'status collapsed', '', '\\begin_layout Plain Layout',
2479 document.body[ertcontdivline][tok + 2:]]
2480 # Convert to ArgInset
2481 document.body[parbeg] = "\\begin_inset Argument 1"
2484 elif document.body[ertcontlastline].startswith("["):
2485 if document.body[ertcontlastline].endswith("]"):
2486 # This is an ERT option
2488 document.body[ertcontlastline] = document.body[ertcontlastline][1:]
2490 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
2491 # Convert to ArgInset
2492 document.body[parbeg] = "\\begin_inset Argument 2"
2494 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, True)
2501 def convert_quote_args(document):
2502 " Converts beamer quote style ERT args to native InsetArgs "
2504 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2505 if document.textclass not in beamer_classes:
2508 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2509 for lay in quote_layouts:
2512 i = find_token(document.body, "\\begin_layout " + lay, i)
2515 parent = get_containing_layout(document.body, i)
2517 document.warning("Wrong parent layout!")
2521 if document.body[parbeg] == "\\begin_inset ERT":
2522 if document.body[i + 6].startswith("<"):
2523 # This is an overlay specification
2525 document.body[i + 6] = document.body[i + 6][1:]
2526 if document.body[i + 6].endswith(">"):
2528 document.body[i + 6] = document.body[i + 6][:-1]
2529 # Convert to ArgInset
2530 document.body[i + 1] = "\\begin_inset Argument 1"
2534 def cleanup_beamerargs(document):
2535 " Clean up empty ERTs (conversion artefacts) "
2537 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2538 if document.textclass not in beamer_classes:
2543 i = find_token(document.body, "\\begin_inset Argument", i)
2546 j = find_end_of_inset(document.body, i)
2548 document.warning("Malformed LyX document: Can't find end of Argument inset")
2552 ertbeg = find_token(document.body, "\\begin_inset ERT", i, j)
2555 ertend = find_end_of_inset(document.body, ertbeg)
2557 document.warning("Malformed LyX document: Can't find end of ERT inset")
2559 stripped = [line for line in document.body[ertbeg : ertend + 1] if line.strip()]
2560 if len(stripped) == 5:
2561 # This is an empty ERT
2562 offset = len(document.body[ertbeg : ertend + 1])
2563 del document.body[ertbeg : ertend + 1]
2570 def revert_beamerargs(document):
2571 " Reverts beamer arguments to old layout "
2573 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2574 if document.textclass not in beamer_classes:
2578 list_layouts = ["Itemize", "Enumerate", "Description"]
2579 headings = ["Part", "Section", "Section*", "Subsection", "Subsection*",
2580 "Subsubsection", "Subsubsection*", "FrameSubtitle", "NoteItem"]
2581 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2582 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2583 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2586 i = find_token(document.body, "\\begin_inset Argument", i)
2589 # Find containing paragraph layout
2590 parent = get_containing_layout(document.body, i)
2592 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2597 realparbeg = parent[3]
2598 layoutname = parent[0]
2600 for p in range(parbeg, parend):
2604 if layoutname in headings:
2605 m = rx.match(document.body[p])
2609 # Find containing paragraph layout
2610 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2611 endPlain = find_end_of_layout(document.body, beginPlain)
2612 endInset = find_end_of_inset(document.body, p)
2613 argcontent = document.body[beginPlain + 1 : endPlain]
2615 realparend = realparend - len(document.body[p : endInset + 1])
2617 del document.body[p : endInset + 1]
2618 if layoutname == "FrameSubtitle":
2619 pre = put_cmd_in_ert("\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2620 elif layoutname == "NoteItem":
2621 pre = put_cmd_in_ert("\\note<") + argcontent + put_cmd_in_ert(">[item]")
2622 elif layoutname.endswith('*'):
2623 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower()[:-1] + "<") + argcontent + put_cmd_in_ert(">*")
2625 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2626 secarg = find_token(document.body, "\\begin_inset Argument 2", parbeg, parend)
2628 # Find containing paragraph layout
2629 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", secarg)
2630 endPlain = find_end_of_layout(document.body, beginPlain)
2631 endInset = find_end_of_inset(document.body, secarg)
2632 argcontent = document.body[beginPlain + 1 : endPlain]
2634 realparend = realparend - len(document.body[secarg : endInset + 1])
2635 del document.body[secarg : endInset + 1]
2636 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2637 pre += put_cmd_in_ert("{")
2638 document.body[parbeg] = "\\begin_layout Standard"
2639 document.body[realparbeg : realparbeg] = pre
2640 pe = find_end_of_layout(document.body, parbeg)
2641 post = put_cmd_in_ert("}")
2642 document.body[pe : pe] = post
2643 realparend += len(pre) + len(post)
2644 if layoutname == "AgainFrame":
2645 m = rx.match(document.body[p])
2649 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2650 endPlain = find_end_of_layout(document.body, beginPlain)
2651 endInset = find_end_of_inset(document.body, p)
2652 content = document.body[beginPlain + 1 : endPlain]
2654 realparend = realparend - len(document.body[p : endInset + 1])
2656 del document.body[p : endInset + 1]
2657 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2658 document.body[realparbeg : realparbeg] = subst
2659 if layoutname == "Overprint":
2660 m = rx.match(document.body[p])
2664 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2665 endPlain = find_end_of_layout(document.body, beginPlain)
2666 endInset = find_end_of_inset(document.body, p)
2667 content = document.body[beginPlain + 1 : endPlain]
2669 realparend = realparend - len(document.body[p : endInset + 1])
2671 del document.body[p : endInset + 1]
2672 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2673 document.body[realparbeg : realparbeg] = subst
2674 if layoutname == "OverlayArea":
2675 m = rx.match(document.body[p])
2679 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2680 endPlain = find_end_of_layout(document.body, beginPlain)
2681 endInset = find_end_of_inset(document.body, p)
2682 content = document.body[beginPlain + 1 : endPlain]
2684 realparend = realparend - len(document.body[p : endInset + 1])
2686 del document.body[p : endInset + 1]
2687 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2688 document.body[realparbeg : realparbeg] = subst
2689 if layoutname in list_layouts:
2690 m = rx.match(document.body[p])
2694 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2695 endPlain = find_end_of_layout(document.body, beginPlain)
2696 endInset = find_end_of_inset(document.body, p)
2697 content = document.body[beginPlain + 1 : endPlain]
2698 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2699 realparend = realparend + len(subst) - len(content)
2700 document.body[beginPlain + 1 : endPlain] = subst
2701 elif argnr == "item:1":
2702 j = find_end_of_inset(document.body, i)
2703 # Find containing paragraph layout
2704 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2705 endPlain = find_end_of_layout(document.body, beginPlain)
2706 content = document.body[beginPlain + 1 : endPlain]
2707 del document.body[i:j+1]
2708 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2709 document.body[realparbeg : realparbeg] = subst
2710 elif argnr == "item:2":
2711 j = find_end_of_inset(document.body, i)
2712 # Find containing paragraph layout
2713 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2714 endPlain = find_end_of_layout(document.body, beginPlain)
2715 content = document.body[beginPlain + 1 : endPlain]
2716 del document.body[i:j+1]
2717 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2718 document.body[realparbeg : realparbeg] = subst
2719 if layoutname in quote_layouts:
2720 m = rx.match(document.body[p])
2724 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2725 endPlain = find_end_of_layout(document.body, beginPlain)
2726 endInset = find_end_of_inset(document.body, p)
2727 content = document.body[beginPlain + 1 : endPlain]
2729 realparend = realparend - len(document.body[p : endInset + 1])
2731 del document.body[p : endInset + 1]
2732 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2733 document.body[realparbeg : realparbeg] = subst
2734 if layoutname in corollary_layouts:
2735 m = rx.match(document.body[p])
2739 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2740 endPlain = find_end_of_layout(document.body, beginPlain)
2741 endInset = find_end_of_inset(document.body, p)
2742 content = document.body[beginPlain + 1 : endPlain]
2744 realparend = realparend - len(document.body[p : endInset + 1])
2746 del document.body[p : endInset + 1]
2747 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2748 document.body[realparbeg : realparbeg] = subst
2753 def revert_beamerargs2(document):
2754 " Reverts beamer arguments to old layout, step 2 "
2756 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2757 if document.textclass not in beamer_classes:
2761 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2762 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2763 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2766 i = find_token(document.body, "\\begin_inset Argument", i)
2769 # Find containing paragraph layout
2770 parent = get_containing_layout(document.body, i)
2772 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2777 realparbeg = parent[3]
2778 layoutname = parent[0]
2780 for p in range(parbeg, parend):
2784 if layoutname in shifted_layouts:
2785 m = rx.match(document.body[p])
2789 document.body[p] = "\\begin_inset Argument 1"
2790 if layoutname in corollary_layouts:
2791 m = rx.match(document.body[p])
2795 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2796 endPlain = find_end_of_layout(document.body, beginPlain)
2797 endInset = find_end_of_inset(document.body, p)
2798 content = document.body[beginPlain + 1 : endPlain]
2800 realparend = realparend - len(document.body[p : endInset + 1])
2802 del document.body[p : endInset + 1]
2803 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2804 document.body[realparbeg : realparbeg] = subst
2805 if layoutname == "OverlayArea":
2806 m = rx.match(document.body[p])
2810 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2811 endPlain = find_end_of_layout(document.body, beginPlain)
2812 endInset = find_end_of_inset(document.body, p)
2813 content = document.body[beginPlain + 1 : endPlain]
2815 realparend = realparend - len(document.body[p : endInset + 1])
2817 del document.body[p : endInset + 1]
2818 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2819 document.body[realparbeg : realparbeg] = subst
2820 if layoutname == "AgainFrame":
2821 m = rx.match(document.body[p])
2825 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2826 endPlain = find_end_of_layout(document.body, beginPlain)
2827 endInset = find_end_of_inset(document.body, p)
2828 content = document.body[beginPlain + 1 : endPlain]
2830 realparend = realparend - len(document.body[p : endInset + 1])
2832 del document.body[p : endInset + 1]
2833 subst = put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
2834 document.body[realparbeg : realparbeg] = subst
2838 def revert_beamerargs3(document):
2839 " Reverts beamer arguments to old layout, step 3 "
2841 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2842 if document.textclass not in beamer_classes:
2845 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2848 i = find_token(document.body, "\\begin_inset Argument", i)
2851 # Find containing paragraph layout
2852 parent = get_containing_layout(document.body, i)
2854 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2859 realparbeg = parent[3]
2860 layoutname = parent[0]
2862 for p in range(parbeg, parend):
2866 if layoutname == "AgainFrame":
2867 m = rx.match(document.body[p])
2871 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2872 endPlain = find_end_of_layout(document.body, beginPlain)
2873 endInset = find_end_of_inset(document.body, p)
2874 content = document.body[beginPlain + 1 : endPlain]
2876 realparend = realparend - len(document.body[p : endInset + 1])
2878 del document.body[p : endInset + 1]
2879 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2880 document.body[realparbeg : realparbeg] = subst
2884 def revert_beamerflex(document):
2885 " Reverts beamer Flex insets "
2887 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2888 if document.textclass not in beamer_classes:
2891 new_flexes = {"Bold" : "\\textbf", "Emphasize" : "\\emph", "Only" : "\\only",
2892 "Uncover" : "\\uncover", "Visible" : "\\visible",
2893 "Invisible" : "\\invisible", "Alternative" : "\\alt",
2894 "Beamer_Note" : "\\note"}
2895 old_flexes = {"Alert" : "\\alert", "Structure" : "\\structure"}
2896 rx = re.compile(r'^\\begin_inset Flex (.+)$')
2900 i = find_token(document.body, "\\begin_inset Flex", i)
2903 m = rx.match(document.body[i])
2905 flextype = m.group(1)
2906 z = find_end_of_inset(document.body, i)
2908 document.warning("Can't find end of Flex " + flextype + " inset.")
2911 if flextype in new_flexes:
2912 pre = put_cmd_in_ert(new_flexes[flextype])
2913 arg = find_token(document.body, "\\begin_inset Argument 1", 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 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2929 arg = find_token(document.body, "\\begin_inset Argument 2", i, z)
2931 argend = find_end_of_inset(document.body, arg)
2933 document.warning("Can't find end of Argument!")
2936 # Find containing paragraph layout
2937 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2938 endPlain = find_end_of_layout(document.body, beginPlain)
2939 argcontent = document.body[beginPlain + 1 : endPlain]
2941 z = z - len(document.body[arg : argend + 1])
2943 del document.body[arg : argend + 1]
2944 if flextype == "Alternative":
2945 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
2947 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2948 pre += put_cmd_in_ert("{")
2949 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2950 endPlain = find_end_of_layout(document.body, beginPlain)
2952 z = z - len(document.body[i : beginPlain + 1])
2954 document.body[i : beginPlain + 1] = pre
2955 post = put_cmd_in_ert("}")
2956 document.body[z - 2 : z + 1] = post
2957 elif flextype in old_flexes:
2958 pre = put_cmd_in_ert(old_flexes[flextype])
2959 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2963 argend = find_end_of_inset(document.body, arg)
2965 document.warning("Can't find end of Argument!")
2968 # Find containing paragraph layout
2969 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2970 endPlain = find_end_of_layout(document.body, beginPlain)
2971 argcontent = document.body[beginPlain + 1 : endPlain]
2973 z = z - len(document.body[arg : argend + 1])
2975 del document.body[arg : argend + 1]
2976 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2977 pre += put_cmd_in_ert("{")
2978 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2979 endPlain = find_end_of_layout(document.body, beginPlain)
2981 z = z - len(document.body[i : beginPlain + 1])
2983 document.body[i : beginPlain + 1] = pre
2984 post = put_cmd_in_ert("}")
2985 document.body[z - 2 : z + 1] = post
2990 def revert_beamerblocks(document):
2991 " Reverts beamer block arguments to ERT "
2993 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2994 if document.textclass not in beamer_classes:
2997 blocks = ["Block", "ExampleBlock", "AlertBlock"]
2999 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3002 i = find_token(document.body, "\\begin_inset Argument", i)
3005 # Find containing paragraph layout
3006 parent = get_containing_layout(document.body, i)
3008 document.warning("Malformed LyX document: Can't find parent paragraph layout")
3013 realparbeg = parent[3]
3014 layoutname = parent[0]
3016 for p in range(parbeg, parend):
3020 if layoutname in blocks:
3021 m = rx.match(document.body[p])
3025 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3026 endPlain = find_end_of_layout(document.body, beginPlain)
3027 endInset = find_end_of_inset(document.body, p)
3028 content = document.body[beginPlain + 1 : endPlain]
3030 realparend = realparend - len(document.body[p : endInset + 1])
3032 del document.body[p : endInset + 1]
3033 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3034 document.body[realparbeg : realparbeg] = subst
3036 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3037 endPlain = find_end_of_layout(document.body, beginPlain)
3038 endInset = find_end_of_inset(document.body, p)
3039 content = document.body[beginPlain + 1 : endPlain]
3041 realparend = realparend - len(document.body[p : endInset + 1])
3043 del document.body[p : endInset + 1]
3044 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3045 document.body[realparbeg : realparbeg] = subst
3050 def convert_beamerblocks(document):
3051 " Converts beamer block ERT args to native InsetArgs "
3053 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3054 if document.textclass not in beamer_classes:
3057 blocks = ["Block", "ExampleBlock", "AlertBlock"]
3061 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
3064 parent = get_containing_layout(document.body, i)
3065 if parent == False or parent[1] != i:
3066 document.warning("Wrong parent layout!")
3073 # If the paragraph starts with a language switch, adjust parbeg
3074 if len(document.body[parbeg]) == 0 and parbeg < parend \
3075 and document.body[parbeg + 1].startswith("\\lang"):
3077 if document.body[parbeg] == "\\begin_inset ERT":
3078 ertcontfirstline = parbeg + 5
3082 # Find the last ERT in this paragraph used for arguments
3083 # (which might also be the first)
3084 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
3085 if lastertbeg == -1:
3086 document.warning("Last ERT not found!")
3088 lastertend = find_end_of_inset(document.body, lastertbeg)
3089 if lastertend == -1:
3090 document.warning("End of last ERT not found!")
3092 # Is this ERT really used for an argument?
3093 # Note: This will fail when non-argument ERTs actually use brackets
3095 regexp = re.compile(r'.*[>\]\}]', re.IGNORECASE)
3096 cbracket = find_re(document.body, regexp, lastertbeg, lastertend)
3099 if lastertbeg == parbeg:
3102 if lastertbeg == -1 or lastertend == -1:
3104 ertcontlastline = lastertend - 3
3106 if document.body[ertcontfirstline].lstrip().startswith("<"):
3107 # This is an overlay specification
3109 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3110 if document.body[ertcontlastline].rstrip().endswith(">"):
3112 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3113 # Convert to ArgInset
3114 document.body[parbeg] = "\\begin_inset Argument 1"
3115 elif document.body[ertcontlastline].rstrip().endswith("}"):
3117 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3119 ertcontdivline = ertcontfirstline
3120 tok = document.body[ertcontdivline].find('>{')
3122 regexp = re.compile(r'.*>\{', re.IGNORECASE)
3123 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3124 tok = document.body[ertcontdivline].find('>{')
3126 if ertcontfirstline < ertcontlastline:
3127 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3128 document.body[ertcontlastline : ertcontlastline + 1] = [
3129 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3130 if ertcontdivline == ertcontfirstline:
3131 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3132 '\\end_layout', '', '\\end_inset', '',
3133 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3134 'status collapsed', '', '\\begin_layout Plain Layout',
3135 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3136 document.body[ertcontdivline][tok + 2:]]
3138 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3139 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3140 'status collapsed', '', '\\begin_layout Plain Layout',
3141 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3142 document.body[ertcontdivline][tok + 2:]]
3144 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3145 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3146 'status collapsed', '', '\\begin_layout Plain Layout',
3147 document.body[ertcontdivline][tok + 2:]]
3149 # check if have delimiters in two different ERTs
3150 tok = document.body[ertcontdivline].find('>')
3152 regexp = re.compile(r'.*>', re.IGNORECASE)
3153 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3154 tok = document.body[ertcontdivline].find('>')
3156 tokk = document.body[ertcontdivline].find('{')
3158 regexp = re.compile(r'.*\{', re.IGNORECASE)
3159 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, lastertend)
3160 tokk = document.body[ertcontdivlinetwo].find('{')
3162 if ertcontfirstline < ertcontlastline:
3163 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3164 document.body[ertcontlastline : ertcontlastline + 1] = [
3165 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3166 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3167 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3168 '\\end_inset', '', '', '\\begin_inset Argument 2',
3169 'status collapsed', '', '\\begin_layout Plain Layout',
3170 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3171 document.body[ertcontdivlinetwo][tokk + 1:]]
3173 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3174 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3175 'status collapsed', '', '\\begin_layout Plain Layout',
3176 document.body[ertcontdivlinetwo][tokk + 1:]]
3177 # Convert to ArgInset
3178 if ertcontfirstline < ertcontlastline:
3179 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3180 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 1',
3181 'status collapsed', '', '\\begin_layout Plain Layout',
3182 '\\begin_inset ERT', '']
3184 document.body[parbeg] = "\\begin_inset Argument 1"
3185 elif document.body[ertcontfirstline].lstrip().startswith("{"):
3186 # This is the block title
3187 if document.body[ertcontlastline].rstrip().endswith("}"):
3188 # strip off the braces
3189 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3190 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3191 if ertcontfirstline < ertcontlastline:
3192 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3193 document.body[parend : parend + 1] = [
3194 document.body[parend], '\\end_inset', '', '\\end_layout']
3195 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3196 'status collapsed', '', '\\begin_layout Plain Layout',
3197 '\\begin_inset ERT', '']
3199 # Convert to ArgInset
3200 document.body[parbeg] = "\\begin_inset Argument 2"
3201 # the overlay argument can also follow the title, so ...
3202 elif document.body[ertcontlastline].rstrip().endswith(">"):
3204 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3206 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3208 ertcontdivline = ertcontfirstline
3209 tok = document.body[ertcontdivline].find('}<')
3211 regexp = re.compile(r'.*\}<', re.IGNORECASE)
3212 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3213 tok = document.body[ertcontdivline].find('}<')
3215 if ertcontfirstline < ertcontlastline:
3216 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3217 document.body[ertcontlastline : ertcontlastline + 1] = [
3218 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3219 if ertcontdivline == ertcontfirstline:
3220 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3221 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3222 'status collapsed', '', '\\begin_layout Plain Layout',
3223 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3224 document.body[ertcontdivline][tok + 2:]]
3226 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3227 '\\end_layout', '', '\\end_inset', '',
3228 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3229 'status collapsed', '', '\\begin_layout Plain Layout',
3230 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3231 document.body[ertcontdivline][tok + 2:]]
3233 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3234 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3235 'status collapsed', '', '\\begin_layout Plain Layout',
3236 document.body[ertcontdivline][tok + 2:]]
3238 # check if have delimiters in two different ERTs
3239 tok = document.body[ertcontdivline].find('}')
3241 regexp = re.compile(r'.*\}', re.IGNORECASE)
3242 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3243 tok = document.body[ertcontdivline].find('}')
3245 tokk = document.body[ertcontdivline].find('<')
3247 regexp = re.compile(r'.*<', re.IGNORECASE)
3248 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, lastertend)
3249 tokk = document.body[ertcontdivlinetwo].find('<')
3251 if ertcontfirstline < ertcontlastline:
3252 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3253 document.body[ertcontlastline : ertcontlastline + 1] = [
3254 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3255 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3256 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3257 '\\end_inset', '', '', '\\begin_inset Argument 1',
3258 'status collapsed', '', '\\begin_layout Plain Layout',
3259 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3260 document.body[ertcontdivlinetwo][tokk + 1:]]
3262 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3263 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3264 'status collapsed', '', '\\begin_layout Plain Layout',
3265 document.body[ertcontdivlinetwo][tokk + 1:]]
3266 # Convert to ArgInset
3267 if ertcontfirstline < ertcontlastline:
3268 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3269 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3270 'status collapsed', '', '\\begin_layout Plain Layout',
3271 '\\begin_inset ERT', '']
3273 document.body[parbeg] = "\\begin_inset Argument 2"
3274 elif count_pars_in_inset(document.body, ertcontfirstline) > 1:
3275 # Multipar ERT. Skip this.
3278 # ERT has contents after the closing bracket. We cannot convert this.
3279 # convert_TeX_brace_to_Argument cannot either.
3280 #convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, False)
3284 j = find_end_of_layout(document.body, i)
3286 document.warning("end of layout not found!")
3287 k = find_token(document.body, "\\begin_inset Argument", i, j)
3289 document.warning("InsetArgument not found!")
3291 l = find_end_of_inset(document.body, k)
3292 m = find_token(document.body, "\\begin_inset ERT", l, j)
3295 ertcontfirstline = m + 5
3300 def convert_overprint(document):
3301 " Convert old beamer overprint layouts to ERT "
3303 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3304 if document.textclass not in beamer_classes:
3309 i = find_token(document.body, "\\begin_layout Overprint", i)
3312 # Find end of sequence
3313 j = find_end_of_sequence(document.body, i)
3315 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3319 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3321 if document.body[j] == "\\end_deeper":
3322 esubst = ["", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3324 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3325 endseq = endseq + len(esubst) - len(document.body[j : j])
3326 document.body[j : j] = esubst
3327 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3329 argend = find_end_of_layout(document.body, argbeg)
3331 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3334 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3335 endPlain = find_end_of_layout(document.body, beginPlain)
3336 content = document.body[beginPlain + 1 : endPlain]
3338 endseq = endseq - len(document.body[argbeg : argend + 1])
3340 del document.body[argbeg : argend + 1]
3341 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3343 endseq = endseq - len(document.body[i : i])
3344 document.body[i : i] = subst + ["\\end_layout"]
3345 endseq += len(subst)
3347 for p in range(i, endseq):
3348 if document.body[p] == "\\begin_layout Overprint":
3349 document.body[p] = "\\begin_layout Standard"
3354 def revert_overprint(document):
3355 " Revert old beamer overprint layouts to ERT "
3357 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3358 if document.textclass not in beamer_classes:
3363 i = find_token(document.body, "\\begin_layout Overprint", i)
3366 # Find end of sequence
3367 j = find_end_of_sequence(document.body, i)
3369 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3373 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3374 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}")
3375 endseq = endseq + len(esubst) - len(document.body[j : j])
3376 if document.body[j] == "\\end_deeper":
3377 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3379 document.body[j : j] = ["\\end_layout", ""] + esubst
3382 if document.body[r] == "\\begin_deeper":
3383 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3385 document.body[r] = ""
3386 document.body[s] = ""
3390 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3392 # Is this really our argument?
3393 nested = find_token(document.body, "\\begin_deeper", i, argbeg)
3395 argend = find_end_of_inset(document.body, argbeg)
3397 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3400 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3401 endPlain = find_end_of_layout(document.body, beginPlain)
3402 content = document.body[beginPlain + 1 : endPlain]
3404 endseq = endseq - len(document.body[argbeg : argend])
3406 del document.body[argbeg : argend + 1]
3407 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3409 endseq = endseq - len(document.body[i : i])
3410 document.body[i : i] = subst + ["\\end_layout"]
3411 endseq += len(subst)
3417 if document.body[p] == "\\begin_layout Overprint":
3418 q = find_end_of_layout(document.body, p)
3420 document.warning("Malformed LyX document. Cannot find end of Overprint layout!")
3423 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\onslide")
3424 argbeg = find_token(document.body, "\\begin_inset Argument item:1", p, q)
3426 argend = find_end_of_inset(document.body, argbeg)
3428 document.warning("Malformed LyX document. Cannot find end of Overprint item argument!")
3431 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3432 endPlain = find_end_of_layout(document.body, beginPlain)
3433 content = document.body[beginPlain + 1 : endPlain]
3435 endseq = endseq - len(document.body[argbeg : argend + 1])
3437 del document.body[argbeg : argend + 1]
3438 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3439 endseq = endseq - len(document.body[p : p + 1]) + len(subst)
3440 document.body[p : p + 1] = subst
3446 def revert_frametitle(document):
3447 " Reverts beamer frametitle layout to ERT "
3449 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3450 if document.textclass not in beamer_classes:
3453 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3456 i = find_token(document.body, "\\begin_layout FrameTitle", i)
3459 j = find_end_of_layout(document.body, i)
3461 document.warning("Malformed LyX document: Can't find end of FrameTitle layout")
3465 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
3466 endlay += len(put_cmd_in_ert("}"))
3467 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\frametitle")
3468 for p in range(i, j):
3471 m = rx.match(document.body[p])
3475 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3476 endPlain = find_end_of_layout(document.body, beginPlain)
3477 endInset = find_end_of_inset(document.body, p)
3478 content = document.body[beginPlain + 1 : endPlain]
3480 endlay = endlay - len(document.body[p : endInset + 1])
3482 del document.body[p : endInset + 1]
3483 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3485 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3486 endPlain = find_end_of_layout(document.body, beginPlain)
3487 endInset = find_end_of_inset(document.body, p)
3488 content = document.body[beginPlain + 1 : endPlain]
3490 endlay = endlay - len(document.body[p : endInset + 1])
3492 del document.body[p : endInset + 1]
3493 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3495 subst += put_cmd_in_ert("{")
3496 document.body[i : i + 1] = subst
3500 def convert_epigraph(document):
3501 " Converts memoir epigraph to new syntax "
3503 if document.textclass != "memoir":
3508 i = find_token(document.body, "\\begin_layout Epigraph", i)
3511 j = find_end_of_layout(document.body, i)
3513 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3518 ert = find_token(document.body, "\\begin_inset ERT", i, j)
3520 endInset = find_end_of_inset(document.body, ert)
3521 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", ert)
3522 endPlain = find_end_of_layout(document.body, beginPlain)
3523 ertcont = beginPlain + 2
3524 if document.body[ertcont] == "}{":
3526 # Convert to ArgInset
3527 endlay = endlay - 2 * len(document.body[j])
3528 begsubst = ['\\begin_inset Argument post:1', 'status collapsed', '',
3529 '\\begin_layout Plain Layout']
3530 endsubst = ['\\end_layout', '', '\\end_inset', '', document.body[j]]
3531 document.body[j : j + 1] = endsubst
3532 document.body[endInset + 1 : endInset + 1] = begsubst
3534 endlay += len(begsubst) + len(endsubst)
3535 endlay = endlay - len(document.body[ert : endInset + 1])
3536 del document.body[ert : endInset + 1]
3541 def revert_epigraph(document):
3542 " Reverts memoir epigraph argument to ERT "
3544 if document.textclass != "memoir":
3549 i = find_token(document.body, "\\begin_layout Epigraph", i)
3552 j = find_end_of_layout(document.body, i)
3554 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3559 p = find_token(document.body, "\\begin_layout Argument post:1", i, j)
3561 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3562 endPlain = find_end_of_layout(document.body, beginPlain)
3563 endInset = find_end_of_inset(document.body, p)
3564 content = document.body[beginPlain + 1 : endPlain]
3566 endlay = endlay - len(document.body[p : endInset + 1])
3568 del document.body[p : endInset + 1]
3569 subst += put_cmd_in_ert("}{") + content
3571 subst += put_cmd_in_ert("}{")
3573 document.body[j : j] = subst + document.body[j : j]
3577 def convert_captioninsets(document):
3578 " Converts caption insets to new syntax "
3582 i = find_token(document.body, "\\begin_inset Caption", i)
3585 document.body[i] = "\\begin_inset Caption Standard"
3589 def revert_captioninsets(document):
3590 " Reverts caption insets to old syntax "
3594 i = find_token(document.body, "\\begin_inset Caption Standard", i)
3597 document.body[i] = "\\begin_inset Caption"
3601 def convert_captionlayouts(document):
3602 " Convert caption layouts to caption insets. "
3605 "Captionabove": "Above",
3606 "Captionbelow": "Below",
3607 "FigCaption" : "FigCaption",
3608 "Table_Caption" : "Table",
3609 "CenteredCaption" : "Centered",
3610 "Bicaption" : "Bicaption",
3615 i = find_token(document.body, "\\begin_layout", i)
3618 val = get_value(document.body, "\\begin_layout", i)
3619 if val in caption_dict.keys():
3620 j = find_end_of_layout(document.body, i)
3622 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3625 document.body[j:j] = ["\\end_layout", "", "\\end_inset", "", ""]
3626 document.body[i:i+1] = ["\\begin_layout %s" % document.default_layout,
3627 "\\begin_inset Caption %s" % caption_dict[val], "",
3628 "\\begin_layout %s" % document.default_layout]
3632 def revert_captionlayouts(document):
3633 " Revert caption insets to caption layouts. "
3636 "Above" : "Captionabove",
3637 "Below" : "Captionbelow",
3638 "FigCaption" : "FigCaption",
3639 "Table" : "Table_Caption",
3640 "Centered" : "CenteredCaption",
3641 "Bicaption" : "Bicaption",
3645 rx = re.compile(r'^\\begin_inset Caption (\S+)$')
3647 i = find_token(document.body, "\\begin_inset Caption", i)
3651 m = rx.match(document.body[i])
3655 if val not in caption_dict.keys():
3659 # We either need to delete the previous \begin_layout line, or we
3660 # need to end the previous layout if this inset is not in the first
3661 # position of the paragraph.
3662 layout_before = find_token_backwards(document.body, "\\begin_layout", i)
3663 if layout_before == -1:
3664 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3666 layout_line = document.body[layout_before]
3667 del_layout_before = True
3668 l = layout_before + 1
3670 if document.body[l] != "":
3671 del_layout_before = False
3674 if del_layout_before:
3675 del document.body[layout_before:i]
3678 document.body[i:i] = ["\\end_layout", ""]
3681 # Find start of layout in the inset and end of inset
3682 j = find_token(document.body, "\\begin_layout", i)
3684 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3686 k = find_end_of_inset(document.body, i)
3688 document.warning("Malformed LyX document: Missing `\\end_inset'.")
3691 # We either need to delete the following \end_layout line, or we need
3692 # to restart the old layout if this inset is not at the paragraph end.
3693 layout_after = find_token(document.body, "\\end_layout", k)
3694 if layout_after == -1:
3695 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3697 del_layout_after = True
3699 while l < layout_after:
3700 if document.body[l] != "":
3701 del_layout_after = False
3704 if del_layout_after:
3705 del document.body[k+1:layout_after+1]
3707 document.body[k+1:k+1] = [layout_line, ""]
3709 # delete \begin_layout and \end_inset and replace \begin_inset with
3710 # "\begin_layout XXX". This works because we can only have one
3711 # paragraph in the caption inset: The old \end_layout will be recycled.
3712 del document.body[k]
3713 if document.body[k] == "":
3714 del document.body[k]
3715 del document.body[j]
3716 if document.body[j] == "":
3717 del document.body[j]
3718 document.body[i] = "\\begin_layout %s" % caption_dict[val]
3719 if document.body[i+1] == "":
3720 del document.body[i+1]
3724 def revert_fragileframe(document):
3725 " Reverts beamer FragileFrame layout to ERT "
3727 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3728 if document.textclass not in beamer_classes:
3733 i = find_token(document.body, "\\begin_layout FragileFrame", i)
3736 # Find end of sequence
3737 j = find_end_of_sequence(document.body, i)
3739 document.warning("Malformed LyX document. Cannot find end of FragileFrame sequence!")
3743 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{frame}")
3744 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{frame}")
3745 endseq = endseq + len(esubst) - len(document.body[j : j])
3746 if document.body[j] == "\\end_deeper":
3747 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3749 document.body[j : j] = esubst
3750 for q in range(i, j):
3751 if document.body[q] == "\\begin_layout FragileFrame":
3752 document.body[q] = "\\begin_layout %s" % document.default_layout
3755 if document.body[r] == "\\begin_deeper":
3756 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3758 document.body[r] = ""
3759 document.body[s] = ""
3763 for p in range(1, 5):
3764 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, j)
3767 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3768 endPlain = find_end_of_layout(document.body, beginPlain)
3769 endInset = find_end_of_inset(document.body, arg)
3770 content = document.body[beginPlain + 1 : endPlain]
3772 j = j - len(document.body[arg : endInset + 1])
3774 del document.body[arg : endInset + 1]
3775 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3777 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3778 endPlain = find_end_of_layout(document.body, beginPlain)
3779 endInset = find_end_of_inset(document.body, arg)
3780 content = document.body[beginPlain + 1 : endPlain]
3782 j = j - len(document.body[arg : endInset + 1])
3784 del document.body[arg : endInset + 1]
3785 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3787 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3788 endPlain = find_end_of_layout(document.body, beginPlain)
3789 endInset = find_end_of_inset(document.body, arg)
3790 content = document.body[beginPlain + 1 : endPlain]
3792 j = j - len(document.body[arg : endInset + 1])
3794 del document.body[arg : endInset + 1]
3795 subst += put_cmd_in_ert("[fragile,") + content + put_cmd_in_ert("]")
3797 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3798 endPlain = find_end_of_layout(document.body, beginPlain)
3799 endInset = find_end_of_inset(document.body, arg)
3800 content = document.body[beginPlain + 1 : endPlain]
3802 j = j - len(document.body[arg : endInset + 1])
3804 del document.body[arg : endInset + 1]
3805 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3807 subst += put_cmd_in_ert("[fragile]")
3809 document.body[i : i + 1] = subst
3813 def revert_newframes(document):
3814 " Reverts beamer Frame and PlainFrame layouts to old forms "
3816 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3817 if document.textclass not in beamer_classes:
3821 "Frame" : "BeginFrame",
3822 "PlainFrame" : "BeginPlainFrame",
3825 rx = re.compile(r'^\\begin_layout (\S+)$')
3828 i = find_token(document.body, "\\begin_layout", i)
3832 m = rx.match(document.body[i])
3836 if val not in frame_dict.keys():
3839 # Find end of sequence
3840 j = find_end_of_sequence(document.body, i)
3842 document.warning("Malformed LyX document. Cannot find end of Frame sequence!")
3846 subst = ["\\begin_layout %s" % frame_dict[val]]
3847 esubst = ["", "\\begin_layout EndFrame", "", "\\end_layout"]
3848 endseq = endseq + len(esubst) - len(document.body[j : j])
3849 if document.body[j] == "\\end_deeper":
3850 document.body[j : j] = esubst
3852 document.body[j+1 : j+1] = esubst
3853 for q in range(i, j):
3854 if document.body[q] == "\\begin_layout %s" % val:
3855 document.body[q] = "\\begin_layout %s" % document.default_layout
3858 if document.body[r] == "\\begin_deeper":
3859 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3861 document.body[r] = ""
3862 document.body[s] = ""
3866 l = find_end_of_layout(document.body, i)
3867 for p in range(1, 5):
3868 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, l)
3871 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3872 endPlain = find_end_of_layout(document.body, beginPlain)
3873 endInset = find_end_of_inset(document.body, arg)
3874 content = document.body[beginPlain + 1 : endPlain]
3876 l = l - len(document.body[arg : endInset + 1])
3878 del document.body[arg : endInset + 1]
3879 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3881 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3882 endPlain = find_end_of_layout(document.body, beginPlain)
3883 endInset = find_end_of_inset(document.body, arg)
3884 content = document.body[beginPlain + 1 : endPlain]
3886 l = l - len(document.body[arg : endInset + 1])
3888 del document.body[arg : endInset + 1]
3889 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3891 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3892 endPlain = find_end_of_layout(document.body, beginPlain)
3893 endInset = find_end_of_inset(document.body, arg)
3894 content = document.body[beginPlain + 1 : endPlain]
3896 l = l - len(document.body[arg : endInset + 1])
3898 del document.body[arg : endInset + 1]
3899 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3901 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3902 endPlain = find_end_of_layout(document.body, beginPlain)
3903 endInset = find_end_of_inset(document.body, arg)
3904 content = document.body[beginPlain + 1 : endPlain]
3906 l = l - len(document.body[arg : endInset + 1])
3908 del document.body[arg : endInset + 1]
3911 document.body[i : i + 1] = subst
3914 # known encodings that do not change their names (same LyX and LaTeX names)
3915 known_enc_tuple = ("auto", "default", "ansinew", "applemac", "armscii8", "ascii",
3916 "cp437", "cp437de", "cp850", "cp852", "cp855", "cp858", "cp862", "cp865", "cp866",
3917 "cp1250", "cp1251", "cp1252", "cp1255", "cp1256", "cp1257", "koi8-r", "koi8-u",
3918 "pt154", "pt254", "tis620-0", "utf8", "utf8x", "utf8-plain")
3920 def convert_encodings(document):
3921 "Use the LyX names of the encodings instead of the LaTeX names."
3922 LaTeX2LyX_enc_dict = {
3923 "8859-6": "iso8859-6",
3924 "8859-8": "iso8859-8",
3926 "euc": "euc-jp-platex",
3931 "iso88595": "iso8859-5",
3932 "iso-8859-7": "iso8859-7",
3934 "jis": "jis-platex",
3936 "l7xenc": "iso8859-13",
3937 "latin1": "iso8859-1",
3938 "latin2": "iso8859-2",
3939 "latin3": "iso8859-3",
3940 "latin4": "iso8859-4",
3941 "latin5": "iso8859-9",
3942 "latin9": "iso8859-15",
3943 "latin10": "iso8859-16",
3944 "SJIS": "shift-jis",
3945 "sjis": "shift-jis-platex",
3948 i = find_token(document.header, "\\inputencoding" , 0)
3951 val = get_value(document.header, "\\inputencoding", i)
3952 if val in LaTeX2LyX_enc_dict.keys():
3953 document.header[i] = "\\inputencoding %s" % LaTeX2LyX_enc_dict[val]
3954 elif val not in known_enc_tuple:
3955 document.warning("Ignoring unknown input encoding: `%s'" % val)
3958 def revert_encodings(document):
3959 """Revert to using the LaTeX names of the encodings instead of the LyX names.
3960 Also revert utf8-platex to sjis, the language default when using Japanese.
3962 LyX2LaTeX_enc_dict = {
3967 "euc-jp-platex": "euc",
3970 "iso8859-1": "latin1",
3971 "iso8859-2": "latin2",
3972 "iso8859-3": "latin3",
3973 "iso8859-4": "latin4",
3974 "iso8859-5": "iso88595",
3975 "iso8859-6": "8859-6",
3976 "iso8859-7": "iso-8859-7",
3977 "iso8859-8": "8859-8",
3978 "iso8859-9": "latin5",
3979 "iso8859-13": "l7xenc",
3980 "iso8859-15": "latin9",
3981 "iso8859-16": "latin10",
3983 "jis-platex": "jis",
3984 "shift-jis": "SJIS",
3985 "shift-jis-platex": "sjis",
3987 "utf8-platex": "sjis"
3989 i = find_token(document.header, "\\inputencoding" , 0)
3992 val = get_value(document.header, "\\inputencoding", i)
3993 if val in LyX2LaTeX_enc_dict.keys():
3994 document.header[i] = "\\inputencoding %s" % LyX2LaTeX_enc_dict[val]
3995 elif val not in known_enc_tuple:
3996 document.warning("Ignoring unknown input encoding: `%s'" % val)
3999 def revert_IEEEtran_3(document):
4001 Reverts Flex Insets to TeX-code
4003 if document.textclass == "IEEEtran":
4009 h = find_token(document.body, "\\begin_inset Flex Author Mark", h)
4011 endh = find_end_of_inset(document.body, h)
4012 document.body[endh - 2 : endh + 1] = put_cmd_in_ert("}")
4013 document.body[h : h + 4] = put_cmd_in_ert("\\IEEEauthorrefmark{")
4016 i = find_token(document.body, "\\begin_inset Flex Author Name", i)
4018 endi = find_end_of_inset(document.body, i)
4019 document.body[endi - 2 : endi + 1] = put_cmd_in_ert("}")
4020 document.body[i : i + 4] = put_cmd_in_ert("\\IEEEauthorblockN{")
4023 j = find_token(document.body, "\\begin_inset Flex Author Affiliation", j)
4025 endj = find_end_of_inset(document.body, j)
4026 document.body[endj - 2 : endj + 1] = put_cmd_in_ert("}")
4027 document.body[j : j + 4] = put_cmd_in_ert("\\IEEEauthorblockA{")
4029 if i == -1 and j == -1 and h == -1:
4033 def revert_kurier_fonts(document):
4034 " Revert kurier font definition to LaTeX "
4036 i = find_token(document.header, "\\font_math", 0)
4038 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4039 val = get_value(document.header, "\\font_math", i)
4040 if val == "kurier-math":
4041 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
4042 "\\usepackage[math]{kurier}\n" \
4043 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
4044 document.header[i] = "\\font_math auto"
4046 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4047 kurier_fonts = ["kurier", "kurierc", "kurierl", "kurierlc"]
4048 k = find_token(document.header, "\\font_sans kurier", 0)
4050 sf = get_value(document.header, "\\font_sans", k)
4051 if sf in kurier_fonts:
4052 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4053 document.header[k] = "\\font_sans default"
4055 def revert_iwona_fonts(document):
4056 " Revert iwona font definition to LaTeX "
4058 i = find_token(document.header, "\\font_math", 0)
4060 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4061 val = get_value(document.header, "\\font_math", i)
4062 if val == "iwona-math":
4063 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
4064 "\\usepackage[math]{iwona}\n" \
4065 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
4066 document.header[i] = "\\font_math auto"
4068 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4069 iwona_fonts = ["iwona", "iwonac", "iwonal", "iwonalc"]
4070 k = find_token(document.header, "\\font_sans iwona", 0)
4072 sf = get_value(document.header, "\\font_sans", k)
4073 if sf in iwona_fonts:
4074 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4075 document.header[k] = "\\font_sans default"
4078 def revert_new_libertines(document):
4079 " Revert new libertine font definition to LaTeX "
4081 if find_token(document.header, "\\use_non_tex_fonts true", 0) != -1:
4084 i = find_token(document.header, "\\font_typewriter libertine-mono", 0)
4086 preamble = "\\usepackage"
4087 sc = find_token(document.header, "\\font_tt_scale", 0)
4089 scval = get_value(document.header, "\\font_tt_scale", sc)
4091 preamble += "[scale=%f]" % (float(scval) / 100)
4092 document.header[sc] = "\\font_tt_scale 100"
4093 preamble += "{libertineMono-type1}"
4094 add_to_preamble(document, [preamble])
4095 document.header[i] = "\\font_typewriter default"
4097 k = find_token(document.header, "\\font_sans biolinum", 0)
4099 preamble = "\\usepackage"
4101 j = find_token(document.header, "\\font_osf true", 0)
4106 sc = find_token(document.header, "\\font_sf_scale", 0)
4108 scval = get_value(document.header, "\\font_sf_scale", sc)
4110 options += ",scale=%f" % (float(scval) / 100)
4111 document.header[sc] = "\\font_sf_scale 100"
4113 preamble += "[" + options +"]"
4114 preamble += "{biolinum-type1}"
4115 add_to_preamble(document, [preamble])
4116 document.header[k] = "\\font_sans default"
4119 def convert_lyxframes(document):
4120 " Converts old beamer frames to new style "
4122 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4123 if document.textclass not in beamer_classes:
4126 framebeg = ["BeginFrame", "BeginPlainFrame"]
4127 frameend = ["Frame", "PlainFrame", "EndFrame", "BeginFrame", "BeginPlainFrame", "AgainFrame",
4128 "Section", "Section*", "Subsection", "Subsection*", "Subsubsection", "Subsubsection*"]
4129 for lay in framebeg:
4132 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
4135 parent = get_containing_layout(document.body, i)
4136 if parent == False or parent[1] != i:
4137 document.warning("Wrong parent layout!")
4140 frametype = parent[0]
4144 # Step I: Convert ERT arguments
4145 # FIXME: See restrictions in convert_beamerframeargs method
4146 ertend = convert_beamerframeargs(document, i, parbeg)
4149 # Step II: Now rename the layout and convert the title to an argument
4150 j = find_end_of_layout(document.body, i)
4151 document.body[j : j + 1] = ['\\end_layout', '', '\\end_inset', '', '\\end_layout']
4152 if lay == "BeginFrame":
4153 document.body[i] = "\\begin_layout Frame"
4155 document.body[i] = "\\begin_layout PlainFrame"
4156 document.body[ertend + 1 : ertend + 1] = ['\\begin_inset Argument 4',
4157 'status open', '', '\\begin_layout Plain Layout']
4158 # Step III: find real frame end
4161 inInset = get_containing_inset(document.body, i)
4163 fend = find_token(document.body, "\\begin_layout", jj)
4165 document.warning("Malformed LyX document: No real frame end!")
4167 val = get_value(document.body, "\\begin_layout", fend)
4168 if val not in frameend:
4171 # is this frame nested in an inset (e.g., Note)?
4172 if inInset != False:
4173 # if so, end the frame inside the inset
4174 if inInset[2] < fend:
4176 if val == frametype:
4177 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4178 # consider explicit EndFrames between two identical frame types
4179 elif val == "EndFrame":
4180 nextlayout = find_token(document.body, "\\begin_layout", fend + 1)
4181 if nextlayout != -1 and get_value(document.body, "\\begin_layout", nextlayout) == frametype:
4182 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4184 document.body[fend : fend] = ['\\end_deeper']
4186 document.body[fend : fend] = ['\\end_deeper']
4187 document.body[j + 1 : j + 1] = ['', '\\begin_deeper']
4192 def remove_endframes(document):
4193 " Remove deprecated beamer endframes "
4195 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4196 if document.textclass not in beamer_classes:
4201 i = find_token_exact(document.body, "\\begin_layout EndFrame", i)
4204 j = find_end_of_layout(document.body, i)
4206 document.warning("Malformed LyX document: Missing \\end_layout to EndFrame")
4209 del document.body[i : j + 1]
4212 def revert_powerdot_flexes(document):
4213 " Reverts powerdot flex insets "
4215 if document.textclass != "powerdot":
4218 flexes = {"Onslide" : "\\onslide",
4219 "Onslide*" : "\\onslide*",
4220 "Onslide+" : "\\onslide+"}
4221 rx = re.compile(r'^\\begin_inset Flex (.+)$')
4225 i = find_token(document.body, "\\begin_inset Flex", i)
4228 m = rx.match(document.body[i])
4230 flextype = m.group(1)
4231 z = find_end_of_inset(document.body, i)
4233 document.warning("Can't find end of Flex " + flextype + " inset.")
4236 if flextype in flexes:
4237 pre = put_cmd_in_ert(flexes[flextype])
4238 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
4240 argend = find_end_of_inset(document.body, arg)
4242 document.warning("Can't find end of Argument!")
4245 # Find containing paragraph layout
4246 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
4247 endPlain = find_end_of_layout(document.body, beginPlain)
4248 argcontent = document.body[beginPlain + 1 : endPlain]
4250 z = z - len(document.body[arg : argend + 1])
4252 del document.body[arg : argend + 1]
4253 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
4254 pre += put_cmd_in_ert("{")
4255 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4256 endPlain = find_end_of_layout(document.body, beginPlain)
4258 z = z - len(document.body[i : beginPlain + 1])
4260 document.body[i : beginPlain + 1] = pre
4261 post = put_cmd_in_ert("}")
4262 document.body[z - 2 : z + 1] = post
4266 def revert_powerdot_pause(document):
4267 " Reverts powerdot pause layout to ERT "
4269 if document.textclass != "powerdot":
4274 i = find_token(document.body, "\\begin_layout Pause", i)
4277 j = find_end_of_layout(document.body, i)
4279 document.warning("Malformed LyX document: Can't find end of Pause layout")
4283 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\pause")
4284 for p in range(i, j):
4287 arg = find_token(document.body, "\\begin_inset Argument 1", i, j)
4289 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4290 endPlain = find_end_of_layout(document.body, beginPlain)
4291 endInset = find_end_of_inset(document.body, p)
4292 content = document.body[beginPlain + 1 : endPlain]
4294 endlay = endlay - len(document.body[p : endInset + 1])
4296 del document.body[p : endInset + 1]
4297 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4299 document.body[i : i + 1] = subst
4303 def revert_powerdot_itemargs(document):
4304 " Reverts powerdot item arguments to ERT "
4306 if document.textclass != "powerdot":
4310 list_layouts = ["Itemize", "ItemizeType1", "Enumerate", "EnumerateType1"]
4311 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4314 i = find_token(document.body, "\\begin_inset Argument", i)
4317 # Find containing paragraph layout
4318 parent = get_containing_layout(document.body, i)
4320 document.warning("Malformed LyX document: Can't find parent paragraph layout")
4325 realparbeg = parent[3]
4326 layoutname = parent[0]
4328 for p in range(parbeg, parend):
4332 if layoutname in list_layouts:
4333 m = rx.match(document.body[p])
4336 if argnr == "item:1":
4337 j = find_end_of_inset(document.body, i)
4338 # Find containing paragraph layout
4339 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4340 endPlain = find_end_of_layout(document.body, beginPlain)
4341 content = document.body[beginPlain + 1 : endPlain]
4342 del document.body[i:j+1]
4343 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4344 document.body[realparbeg : realparbeg] = subst
4345 elif argnr == "item:2":
4346 j = find_end_of_inset(document.body, i)
4347 # Find containing paragraph layout
4348 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4349 endPlain = find_end_of_layout(document.body, beginPlain)
4350 content = document.body[beginPlain + 1 : endPlain]
4351 del document.body[i:j+1]
4352 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
4353 document.body[realparbeg : realparbeg] = subst
4358 def revert_powerdot_columns(document):
4359 " Reverts powerdot twocolumn to TeX-code "
4360 if document.textclass != "powerdot":
4363 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4366 i = find_token(document.body, "\\begin_layout Twocolumn", i)
4369 j = find_end_of_layout(document.body, i)
4371 document.warning("Malformed LyX document: Can't find end of Twocolumn layout")
4375 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
4376 endlay += len(put_cmd_in_ert("}"))
4377 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\twocolumn")
4378 for p in range(i, j):
4381 m = rx.match(document.body[p])
4385 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4386 endPlain = find_end_of_layout(document.body, beginPlain)
4387 endInset = find_end_of_inset(document.body, p)
4388 content = document.body[beginPlain + 1 : endPlain]
4390 endlay = endlay - len(document.body[p : endInset + 1])
4392 del document.body[p : endInset + 1]
4393 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4395 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4396 endPlain = find_end_of_layout(document.body, beginPlain)
4397 endInset = find_end_of_inset(document.body, p)
4398 content = document.body[beginPlain + 1 : endPlain]
4400 endlay = endlay - len(document.body[p : endInset + 1])
4402 del document.body[p : endInset + 1]
4403 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
4405 subst += put_cmd_in_ert("{")
4406 document.body[i : i + 1] = subst
4410 def revert_mbox_fbox(document):
4411 'Convert revert mbox/fbox boxes to TeX-code'
4414 i = find_token(document.body, "\\begin_inset Box", i)
4417 j = find_token(document.body, "width", i)
4419 document.warning("Malformed LyX document: Can't find box width")
4421 width = get_value(document.body, "width", j)
4422 k = find_end_of_inset(document.body, j)
4424 document.warning("Malformed LyX document: Can't find end of box inset")
4427 BeginLayout = find_token(document.body, "\\begin_layout Plain Layout", j)
4428 EndLayout = find_end_of_layout(document.body, BeginLayout)
4429 # replace if width is ""
4431 document.body[EndLayout:k + 1] = put_cmd_in_ert("}")
4432 if document.body[i] == "\\begin_inset Box Frameless":
4433 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\mbox{")
4434 if document.body[i] == "\\begin_inset Box Boxed":
4435 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\fbox{")
4439 def revert_starred_caption(document):
4440 " Reverts unnumbered longtable caption insets "
4444 i = find_token(document.body, "\\begin_inset Caption LongTableNoNumber", i)
4447 # This is not equivalent, but since the caption inset is a full blown
4448 # text inset a true conversion to ERT is too difficult.
4449 document.body[i] = "\\begin_inset Caption Standard"
4453 def revert_forced_local_layout(document):
4456 i = find_token(document.header, "\\begin_forced_local_layout", i)
4459 j = find_end_of(document.header, i, "\\begin_forced_local_layout", "\\end_forced_local_layout")
4461 # this should not happen
4463 regexp = re.compile(r'\s*forcelocal', re.IGNORECASE)
4464 k = find_re(document.header, regexp, i, j)
4466 del document.header[k]
4468 k = find_re(document.header, regexp, i, j)
4469 k = find_token(document.header, "\\begin_local_layout", 0)
4471 document.header[i] = "\\begin_local_layout"
4472 document.header[j] = "\\end_local_layout"
4474 l = find_end_of(document.header, k, "\\begin_local_layout", "\\end_local_layout")
4476 # this should not happen
4478 lines = document.header[i+1 : j]
4480 document.header[k+1 : k+1] = lines
4481 document.header[i : j ] = []
4483 document.header[i : j ] = []
4484 document.header[k+1 : k+1] = lines
4487 def revert_aa1(document):
4488 " Reverts InsetArguments of aa to TeX-code "
4489 if document.textclass == "aa":
4493 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4495 revert_Argument_to_TeX_brace(document, i, 0, 1, 4, False, False)
4501 def revert_aa2(document):
4502 " Reverts InsetArguments of aa to TeX-code "
4503 if document.textclass == "aa":
4507 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4509 document.body[i] = "\\begin_layout Abstract"
4515 def revert_tibetan(document):
4516 "Set the document language for Tibetan to English"
4518 if document.language == "tibetan":
4519 document.language = "english"
4520 i = find_token(document.header, "\\language", 0)
4522 document.header[i] = "\\language english"
4524 while j < len(document.body):
4525 j = find_token(document.body, "\\lang tibetan", j)
4527 document.body[j] = document.body[j].replace("\\lang tibetan", "\\lang english")
4530 j = len(document.body)
4539 # The idea here is that we will have a sequence of chunk paragraphs.
4540 # We want to convert them to paragraphs in one or several chunk insets.
4541 # Individual chunks are terminated by the character @ on the last line.
4542 # This line will be discarded, and following lines are treated as new
4543 # chunks, which go into their own insets.
4544 # The first line of a chunk should look like: <<CONTENT>>=
4545 # We will discard the delimiters, and put the CONTENT into the
4546 # optional argument of the inset, if the CONTENT is non-empty.
4547 def convert_chunks(document):
4548 first_re = re.compile(r'<<(.*)>>=(.*)')
4551 # find start of a block of chunks
4552 i = find_token(document.body, "\\begin_layout Chunk", file_pos)
4558 chunk_started = False
4561 # process the one we just found
4562 j = find_end_of_layout(document.body, i)
4564 document.warning("Malformed LyX documents. Can't find end of Chunk layout!")
4565 # there is no point continuing, as we will run into the same error again.
4567 this_chunk = "".join(document.body[i + 1:j])
4569 # there may be empty lines between chunks
4570 # we just skip them.
4571 if not chunk_started:
4572 if this_chunk != "":
4574 chunk_started = True
4577 contents.append(document.body[i + 1:j])
4579 # look for potential chunk terminator
4580 # on the last line of the chunk paragraph
4581 if document.body[j - 1] == "@":
4584 # look for subsequent chunk paragraph
4585 i = find_token(document.body, "\\begin_layout", j)
4589 if get_value(document.body, "\\begin_layout", i) != "Chunk":
4592 file_pos = end = j + 1
4594 # The last chunk should simply have an "@" in it
4595 # or at least end with "@" (can happen if @ is
4596 # preceded by a newline)
4598 if len(contents) > 0:
4599 lastpar = ''.join(contents[-1])
4600 if not lastpar.endswith("@"):
4601 document.warning("Unexpected chunk content: chunk not terminated by '@'!")
4602 if len(contents) == 0:
4603 # convert empty chunk layouts to Standard
4604 document.body[start] = "\\begin_layout Standard"
4608 # chunk par only contains "@". Just drop it.
4611 # chunk par contains more. Only drop the "@".
4614 # The first line should look like: <<CONTENT>>=
4615 # We want the CONTENT
4616 optarg = ' '.join(contents[0])
4618 # We can already have real chunk content in
4619 # the first par (separated from the options by a newline).
4620 # We collect such stuff to re-insert it later.
4623 match = first_re.search(optarg)
4625 optarg = match.groups()[0]
4626 if match.groups()[1] != "":
4628 for c in contents[0]:
4629 if c.endswith(">>="):
4633 postoptstuff.append(c)
4634 # We have stripped everything. This can be deleted.
4637 newstuff = ['\\begin_layout Standard']
4639 # Maintain paragraph parameters
4640 par_params = ["\\noindent", "\\indent", "\\indent-toggle", "\\leftindent",
4641 "\\start_of_appendix", "\\paragraph_spacing", "\\align",
4642 "\\labelwidthstring"]
4645 if document.body[parms].split(' ', 1)[0] not in par_params:
4647 newstuff.extend([document.body[parms]])
4651 ['\\begin_inset Flex Chunk',
4653 '\\begin_layout Plain Layout', ''])
4655 # If we have a non-empty optional argument, insert it.
4656 if match and optarg != "":
4658 ['\\begin_inset Argument 1',
4660 '\\begin_layout Plain Layout',
4665 # Since we already opened a Plain layout, the first paragraph
4666 # does not need to do that.
4669 # we need to replace newlines with new layouts
4671 started_text = False
4672 for lno in range(0,len(postoptstuff)):
4673 if postoptstuff[lno].startswith("\\begin_inset Newline newline"):
4675 elif start_newline != -1:
4676 if postoptstuff[lno].startswith("\\end_inset"):
4677 # replace that bit, but only if we already have some text
4678 # and we're not at the end except for a blank line
4679 if started_text and \
4680 (lno != len(postoptstuff) - 2 or postoptstuff[-1] != ""):
4681 newstuff.extend(['\\end_layout', '\n', '\\begin_layout Plain Layout', '\n'])
4685 newstuff.extend([postoptstuff[lno]])
4686 newstuff.append('\\end_layout')
4690 newstuff.extend(['', '\\begin_layout Plain Layout', ''])
4694 newstuff.append('\\end_layout')
4696 newstuff.extend(['', '\\end_inset', '', '\\end_layout', ''])
4698 document.body[start:end] = newstuff
4700 file_pos += len(newstuff) - (end - start)
4703 def revert_chunks(document):
4706 i = find_token(document.body, "\\begin_inset Flex Chunk", i)
4710 iend = find_end_of_inset(document.body, i)
4712 document.warning("Can't find end of Chunk!")
4716 # Look for optional argument
4718 ostart = find_token(document.body, "\\begin_inset Argument 1", i, iend)
4720 oend = find_end_of_inset(document.body, ostart)
4721 k = find_token(document.body, "\\begin_layout Plain Layout", ostart, oend)
4723 document.warning("Malformed LyX document: Can't find argument contents!")
4725 m = find_end_of_layout(document.body, k)
4726 optarg = "".join(document.body[k+1:m])
4728 # We now remove the optional argument, so we have something
4729 # uniform on which to work
4730 document.body[ostart : oend + 1] = []
4731 # iend is now invalid
4732 iend = find_end_of_inset(document.body, i)
4734 retval = get_containing_layout(document.body, i)
4736 document.warning("Can't find containing layout for Chunk!")
4739 (lname, lstart, lend, pstart) = retval
4740 # we now want to work through the various paragraphs, and collect their contents
4744 k = find_token(document.body, "\\begin_layout Plain Layout", k, lend)
4747 j = find_end_of_layout(document.body, k)
4749 document.warning("Can't find end of layout inside chunk!")
4751 parlist.append(document.body[k+1:j])
4753 # we now need to wrap all of these paragraphs in chunks
4755 newlines.extend(["\\begin_layout Chunk", "", "<<" + optarg + ">>=", "\\end_layout", ""])
4756 for stuff in parlist:
4757 newlines.extend(["\\begin_layout Chunk"] + stuff + ["\\end_layout", ""])
4758 newlines.extend(["\\begin_layout Chunk", "", "@", "\\end_layout", ""])
4759 # replace old content with new content
4760 document.body[lstart : lend + 1] = newlines
4761 i = lstart + len(newlines)
4768 supported_versions = ["2.1.0","2.1"]
4771 [415, [convert_undertilde]],
4773 [417, [convert_japanese_encodings]],
4774 [418, [convert_justification]],
4776 [420, [convert_biblio_style]],
4777 [421, [convert_longtable_captions]],
4778 [422, [convert_use_packages]],
4779 [423, [convert_use_mathtools]],
4780 [424, [convert_cite_engine_type]],
4781 # No convert_cancel, since cancel will be loaded automatically
4782 # in format 425 without any possibility to switch it off.
4783 # This has been fixed in format 464.
4787 [428, [convert_cell_rotation]],
4788 [429, [convert_table_rotation]],
4789 [430, [convert_listoflistings]],
4790 [431, [convert_use_amssymb]],
4792 [433, [convert_armenian]],
4800 [441, [convert_mdnomath]],
4805 [446, [convert_latexargs]],
4806 [447, [convert_IEEEtran, convert_AASTeX, convert_AGUTeX, convert_IJMP, convert_SIGPLAN, convert_SIGGRAPH, convert_EuropeCV, convert_Initials, convert_ModernCV]],
4807 [448, [convert_literate]],
4810 [451, [convert_beamerargs, convert_againframe_args, convert_corollary_args, convert_quote_args]],
4811 [452, [convert_beamerblocks]],
4812 [453, [convert_use_stmaryrd]],
4813 [454, [convert_overprint]],
4815 [456, [convert_epigraph]],
4816 [457, [convert_use_stackrel]],
4817 [458, [convert_captioninsets, convert_captionlayouts]],
4822 [463, [convert_encodings]],
4823 [464, [convert_use_cancel]],
4824 [465, [convert_lyxframes, remove_endframes]],
4830 [471, [convert_cite_engine_type_default]],
4833 [474, [convert_chunks, cleanup_beamerargs]],
4837 [473, [revert_chunks]],
4838 [472, [revert_tibetan]],
4839 [471, [revert_aa1,revert_aa2]],
4840 [470, [revert_cite_engine_type_default]],
4841 [469, [revert_forced_local_layout]],
4842 [468, [revert_starred_caption]],
4843 [467, [revert_mbox_fbox]],
4844 [466, [revert_iwona_fonts]],
4845 [465, [revert_powerdot_flexes, revert_powerdot_pause, revert_powerdot_itemargs, revert_powerdot_columns]],
4847 [463, [revert_use_cancel]],
4848 [462, [revert_encodings]],
4849 [461, [revert_new_libertines]],
4850 [460, [revert_kurier_fonts]],
4851 [459, [revert_IEEEtran_3]],
4852 [458, [revert_fragileframe, revert_newframes]],
4853 [457, [revert_captioninsets, revert_captionlayouts]],
4854 [456, [revert_use_stackrel]],
4855 [455, [revert_epigraph]],
4856 [454, [revert_frametitle]],
4857 [453, [revert_overprint]],
4858 [452, [revert_use_stmaryrd]],
4859 [451, [revert_beamerblocks]],
4860 [450, [revert_beamerargs, revert_beamerargs2, revert_beamerargs3, revert_beamerflex]],
4861 [449, [revert_garamondx, revert_garamondx_newtxmath]],
4862 [448, [revert_itemargs]],
4863 [447, [revert_literate]],
4864 [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]],
4865 [445, [revert_latexargs]],
4866 [444, [revert_uop]],
4867 [443, [revert_biolinum]],
4869 [441, [revert_newtxmath]],
4870 [440, [revert_mdnomath]],
4871 [439, [revert_mathfonts]],
4872 [438, [revert_minionpro]],
4873 [437, [revert_ipadeco, revert_ipachar]],
4874 [436, [revert_texgyre]],
4875 [435, [revert_mathdesign]],
4876 [434, [revert_txtt]],
4877 [433, [revert_libertine]],
4878 [432, [revert_armenian]],
4879 [431, [revert_languages, revert_ancientgreek]],
4880 [430, [revert_use_amssymb]],
4881 [429, [revert_listoflistings]],
4882 [428, [revert_table_rotation]],
4883 [427, [revert_cell_rotation]],
4884 [426, [revert_tipa]],
4885 [425, [revert_verbatim]],
4886 [424, [revert_cancel]],
4887 [423, [revert_cite_engine_type]],
4888 [422, [revert_use_mathtools]],
4889 [421, [revert_use_packages]],
4890 [420, [revert_longtable_captions]],
4891 [419, [revert_biblio_style]],
4892 [418, [revert_australian]],
4893 [417, [revert_justification]],
4894 [416, [revert_japanese_encodings]],
4895 [415, [revert_negative_space, revert_math_spaces]],
4896 [414, [revert_undertilde]],
4897 [413, [revert_visible_space]]
4901 if __name__ == "__main__":