1 # -*- coding: utf-8 -*-
2 # This file is part of lyx2lyx
3 # -*- coding: utf-8 -*-
4 # Copyright (C) 2011 The LyX team
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 """ Convert files to the file format generated by LyX 2.1"""
26 # Uncomment only what you need to import, please.
28 from parser_tools import count_pars_in_inset, del_token, find_token, find_token_exact, \
29 find_token_backwards, find_end_of, find_end_of_inset, find_end_of_layout, \
30 find_end_of_sequence, find_re, get_option_value, get_containing_layout, \
31 get_value, get_quoted_value, set_option_value
33 #from parser_tools import find_token, find_end_of, find_tokens, \
34 #find_end_of_inset, find_end_of_layout, \
35 #is_in_inset, del_token, check_token
37 from lyx2lyx_tools import add_to_preamble, put_cmd_in_ert, get_ert
39 #from lyx2lyx_tools import insert_to_preamble, \
40 # lyx2latex, latex_length, revert_flex_inset, \
41 # revert_font_attrs, hex2ratio, str2bool
43 ####################################################################
44 # Private helper functions
46 #def remove_option(lines, m, option):
47 #''' removes option from line m. returns whether we did anything '''
48 #l = lines[m].find(option)
51 #val = lines[m][l:].split('"')[1]
52 #lines[m] = lines[m][:l - 1] + lines[m][l+len(option + '="' + val + '"'):]
56 def revert_Argument_to_TeX_brace(document, line, endline, n, nmax, environment, opt):
58 Reverts an InsetArgument to TeX-code
60 revert_Argument_to_TeX_brace(document, LineOfBegin, LineOfEnd, StartArgument, EndArgument, isEnvironment, isOpt)
61 LineOfBegin is the line of the \begin_layout or \begin_inset statement
62 LineOfEnd is the line of the \end_layout or \end_inset statement, if "0" is given, the end of the file is used instead
63 StartArgument is the number of the first argument that needs to be converted
64 EndArgument is the number of the last argument that needs to be converted or the last defined one
65 isEnvironment must be true, if the layout is for a LaTeX environment
66 isOpt must be true, if the argument is an optional one
70 while lineArg != -1 and n < nmax + 1:
71 lineArg = find_token(document.body, "\\begin_inset Argument " + str(n), line)
72 if lineArg > endline and endline != 0:
75 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", lineArg)
76 # we have to assure that no other inset is in the Argument
77 beginInset = find_token(document.body, "\\begin_inset", beginPlain)
78 endInset = find_token(document.body, "\\end_inset", beginPlain)
81 while beginInset < endInset and beginInset != -1:
82 beginInset = find_token(document.body, "\\begin_inset", k)
83 endInset = find_token(document.body, "\\end_inset", l)
86 if environment == False:
88 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}{")
89 del(document.body[lineArg : beginPlain + 1])
92 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("]")
93 document.body[lineArg : beginPlain + 1] = put_cmd_in_ert("[")
96 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}")
97 document.body[lineArg : beginPlain + 1] = put_cmd_in_ert("{")
103 def convert_TeX_brace_to_Argument(document, line, n, nmax, inset, environment, opt):
105 Converts TeX code for mandatory arguments to an InsetArgument
106 The conversion of TeX code for optional arguments must be done with another routine
107 !!! Be careful if the braces are different in your case as expected here:
108 - "}{" separates mandatory arguments of commands
109 - "}" + "{" separates mandatory arguments of commands
110 - "}" + " " + "{" separates mandatory arguments of commands
111 - { and } surround a mandatory argument of an environment
113 convert_TeX_brace_to_Argument(document, LineOfBeginLayout/Inset, StartArgument, EndArgument, isInset, isEnvironment, isOpt)
114 LineOfBeginLayout/Inset is the line of the \begin_layout or \begin_inset statement
115 StartArgument is the number of the first ERT that needs to be converted
116 EndArgument is the number of the last ERT that needs to be converted
117 isInset must be true, if braces inside an InsetLayout needs to be converted
118 isEnvironment must be true, if the layout is for a LaTeX environment
119 isOpt must be true, if the argument is an optional one
121 Todo: this routine can currently handle only one mandatory argument of environments
124 end_layout = find_end_of_layout(document.body, line)
129 lineERT = find_token(document.body, "\\begin_inset ERT", lineERT, end_layout)
132 if environment == False:
133 end_ERT = find_end_of_inset(document.body, lineERT)
135 document.warning("Can't find end of ERT!!")
137 # Note that this only checks for ][ or }{ at the beginning of a line
139 bracePair = find_token(document.body, "][", lineERT, end_ERT)
141 bracePair = find_token(document.body, "}{", lineERT, end_ERT)
143 end = find_token(document.body, "\\end_inset", bracePair)
144 document.body[lineERT : end_ERT + 1] = ["\\end_layout", "", "\\end_inset"]
146 # in the case that n > 1 we have optional arguments before
147 # therefore detect them if any
149 # first check if there is an argument
150 lineArg = find_token(document.body, "\\begin_inset Argument", line)
151 if lineArg < lineERT and lineArg != -1:
152 # we have an argument, so now search backwards for its end
153 # we must now assure that we don't find other insets like e.g. a newline
154 endInsetArg = lineERT
155 endLayoutArg = endInsetArg
156 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
157 endInsetArg = endInsetArg - 1
158 endLayoutArg = endInsetArg
159 endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
160 endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
161 line = endInsetArg + 1
163 document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
165 document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
167 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
172 # no brace pair found
173 # now check the case that we have "}" + "{" in two ERTs
175 endBrace = find_token(document.body, "]", lineERT, end_layout)
177 endBrace = find_token(document.body, "}", lineERT, end_layout)
178 if endBrace == lineERT + 5:
180 beginBrace = find_token(document.body, "[", endBrace, end_layout)
182 beginBrace = find_token(document.body, "{", endBrace, end_layout)
183 # assure that the ERTs are consecutive (11 or 12 depending if there is a space between the ERTs or not)
184 if beginBrace == endBrace + 11 or beginBrace == endBrace + 12:
185 end = find_token(document.body, "\\end_inset", beginBrace)
186 document.body[lineERT : end + 1] = ["\\end_layout", "", "\\end_inset"]
188 # in the case that n > 1 we have optional arguments before
189 # therefore detect them if any
191 # first check if there is an argument
192 lineArg = find_token(document.body, "\\begin_inset Argument", line)
193 if lineArg < lineERT and lineArg != -1:
194 # we have an argument, so now search backwards for its end
195 # we must now assure that we don't find other insets like e.g. a newline
196 endInsetArg = lineERT
197 endLayoutArg = endInsetArg
198 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
199 endInsetArg = endInsetArg - 1
200 endLayoutArg = endInsetArg
201 endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
202 endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
203 line = endInsetArg + 1
205 document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
207 document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
209 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
212 # set the line where the next argument will be inserted
213 if beginBrace == endBrace + 11:
221 if environment == True:
222 end_ERT = find_end_of_inset(document.body, lineERT)
224 document.warning("Can't find end of ERT!!")
226 # Note that this only checks for [ or { at the beginning of a line
228 opening = find_token(document.body, "[", lineERT, end_ERT)
230 opening = find_token(document.body, "{", lineERT, end_ERT)
232 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 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3220 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3221 'status collapsed', '', '\\begin_layout Plain Layout',
3222 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3223 document.body[ertcontdivline][tok + 2:]]
3225 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3226 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3227 'status collapsed', '', '\\begin_layout Plain Layout',
3228 document.body[ertcontdivline][tok + 2:]]
3230 # check if have delimiters in two different ERTs
3231 tok = document.body[ertcontdivline].find('}')
3233 regexp = re.compile(r'.*\}', re.IGNORECASE)
3234 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3235 tok = document.body[ertcontdivline].find('}')
3237 tokk = document.body[ertcontdivline].find('<')
3239 regexp = re.compile(r'.*<', re.IGNORECASE)
3240 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, lastertend)
3241 tokk = document.body[ertcontdivlinetwo].find('<')
3243 if ertcontfirstline < ertcontlastline:
3244 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3245 document.body[ertcontlastline : ertcontlastline + 1] = [
3246 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3247 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3248 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3249 '\\end_inset', '', '', '\\begin_inset Argument 1',
3250 'status collapsed', '', '\\begin_layout Plain Layout',
3251 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3252 document.body[ertcontdivlinetwo][tokk + 1:]]
3254 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3255 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3256 'status collapsed', '', '\\begin_layout Plain Layout',
3257 document.body[ertcontdivlinetwo][tokk + 1:]]
3258 # Convert to ArgInset
3259 if ertcontfirstline < ertcontlastline:
3260 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3261 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3262 'status collapsed', '', '\\begin_layout Plain Layout',
3263 '\\begin_inset ERT', '']
3265 document.body[parbeg] = "\\begin_inset Argument 2"
3266 elif count_pars_in_inset(document.body, ertcontfirstline) > 1:
3267 # Multipar ERT. Skip this.
3270 # ERT has contents after the closing bracket. We cannot convert this.
3271 # convert_TeX_brace_to_Argument cannot either.
3272 #convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, False)
3276 j = find_end_of_layout(document.body, i)
3278 document.warning("end of layout not found!")
3279 k = find_token(document.body, "\\begin_inset Argument", i, j)
3281 document.warning("InsetArgument not found!")
3283 l = find_end_of_inset(document.body, k)
3284 m = find_token(document.body, "\\begin_inset ERT", l, j)
3287 ertcontfirstline = m + 5
3292 def convert_overprint(document):
3293 " Convert old beamer overprint layouts to ERT "
3295 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3296 if document.textclass not in beamer_classes:
3301 i = find_token(document.body, "\\begin_layout Overprint", i)
3304 # Find end of sequence
3305 j = find_end_of_sequence(document.body, i)
3307 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3311 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3313 if document.body[j] == "\\end_deeper":
3314 esubst = ["", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3316 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3317 endseq = endseq + len(esubst) - len(document.body[j : j])
3318 document.body[j : j] = esubst
3319 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3321 argend = find_end_of_layout(document.body, argbeg)
3323 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3326 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3327 endPlain = find_end_of_layout(document.body, beginPlain)
3328 content = document.body[beginPlain + 1 : endPlain]
3330 endseq = endseq - len(document.body[argbeg : argend + 1])
3332 del document.body[argbeg : argend + 1]
3333 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3335 endseq = endseq - len(document.body[i : i])
3336 document.body[i : i] = subst + ["\\end_layout"]
3337 endseq += len(subst)
3339 for p in range(i, endseq):
3340 if document.body[p] == "\\begin_layout Overprint":
3341 document.body[p] = "\\begin_layout Standard"
3346 def revert_overprint(document):
3347 " Revert old beamer overprint layouts to ERT "
3349 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3350 if document.textclass not in beamer_classes:
3355 i = find_token(document.body, "\\begin_layout Overprint", i)
3358 # Find end of sequence
3359 j = find_end_of_sequence(document.body, i)
3361 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3365 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3366 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}")
3367 endseq = endseq + len(esubst) - len(document.body[j : j])
3368 if document.body[j] == "\\end_deeper":
3369 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3371 document.body[j : j] = ["\\end_layout", ""] + esubst
3374 if document.body[r] == "\\begin_deeper":
3375 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3377 document.body[r] = ""
3378 document.body[s] = ""
3382 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3384 # Is this really our argument?
3385 nested = find_token(document.body, "\\begin_deeper", i, argbeg)
3387 argend = find_end_of_inset(document.body, argbeg)
3389 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3392 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3393 endPlain = find_end_of_layout(document.body, beginPlain)
3394 content = document.body[beginPlain + 1 : endPlain]
3396 endseq = endseq - len(document.body[argbeg : argend])
3398 del document.body[argbeg : argend + 1]
3399 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3401 endseq = endseq - len(document.body[i : i])
3402 document.body[i : i] = subst + ["\\end_layout"]
3403 endseq += len(subst)
3409 if document.body[p] == "\\begin_layout Overprint":
3410 q = find_end_of_layout(document.body, p)
3412 document.warning("Malformed LyX document. Cannot find end of Overprint layout!")
3415 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\onslide")
3416 argbeg = find_token(document.body, "\\begin_inset Argument item:1", p, q)
3418 argend = find_end_of_inset(document.body, argbeg)
3420 document.warning("Malformed LyX document. Cannot find end of Overprint item argument!")
3423 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3424 endPlain = find_end_of_layout(document.body, beginPlain)
3425 content = document.body[beginPlain + 1 : endPlain]
3427 endseq = endseq - len(document.body[argbeg : argend + 1])
3429 del document.body[argbeg : argend + 1]
3430 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3431 endseq = endseq - len(document.body[p : p + 1]) + len(subst)
3432 document.body[p : p + 1] = subst
3438 def revert_frametitle(document):
3439 " Reverts beamer frametitle layout to ERT "
3441 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3442 if document.textclass not in beamer_classes:
3445 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3448 i = find_token(document.body, "\\begin_layout FrameTitle", i)
3451 j = find_end_of_layout(document.body, i)
3453 document.warning("Malformed LyX document: Can't find end of FrameTitle layout")
3457 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
3458 endlay += len(put_cmd_in_ert("}"))
3459 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\frametitle")
3460 for p in range(i, j):
3463 m = rx.match(document.body[p])
3467 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3468 endPlain = find_end_of_layout(document.body, beginPlain)
3469 endInset = find_end_of_inset(document.body, p)
3470 content = document.body[beginPlain + 1 : endPlain]
3472 endlay = endlay - len(document.body[p : endInset + 1])
3474 del document.body[p : endInset + 1]
3475 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3477 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3478 endPlain = find_end_of_layout(document.body, beginPlain)
3479 endInset = find_end_of_inset(document.body, p)
3480 content = document.body[beginPlain + 1 : endPlain]
3482 endlay = endlay - len(document.body[p : endInset + 1])
3484 del document.body[p : endInset + 1]
3485 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3487 subst += put_cmd_in_ert("{")
3488 document.body[i : i + 1] = subst
3492 def convert_epigraph(document):
3493 " Converts memoir epigraph to new syntax "
3495 if document.textclass != "memoir":
3500 i = find_token(document.body, "\\begin_layout Epigraph", i)
3503 j = find_end_of_layout(document.body, i)
3505 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3510 ert = find_token(document.body, "\\begin_inset ERT", i, j)
3512 endInset = find_end_of_inset(document.body, ert)
3513 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", ert)
3514 endPlain = find_end_of_layout(document.body, beginPlain)
3515 ertcont = beginPlain + 2
3516 if document.body[ertcont] == "}{":
3518 # Convert to ArgInset
3519 endlay = endlay - 2 * len(document.body[j])
3520 begsubst = ['\\begin_inset Argument post:1', 'status collapsed', '',
3521 '\\begin_layout Plain Layout']
3522 endsubst = ['\\end_layout', '', '\\end_inset', '', document.body[j]]
3523 document.body[j : j + 1] = endsubst
3524 document.body[endInset + 1 : endInset + 1] = begsubst
3526 endlay += len(begsubst) + len(endsubst)
3527 endlay = endlay - len(document.body[ert : endInset + 1])
3528 del document.body[ert : endInset + 1]
3533 def revert_epigraph(document):
3534 " Reverts memoir epigraph argument to ERT "
3536 if document.textclass != "memoir":
3541 i = find_token(document.body, "\\begin_layout Epigraph", i)
3544 j = find_end_of_layout(document.body, i)
3546 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3551 p = find_token(document.body, "\\begin_layout Argument post:1", i, j)
3553 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3554 endPlain = find_end_of_layout(document.body, beginPlain)
3555 endInset = find_end_of_inset(document.body, p)
3556 content = document.body[beginPlain + 1 : endPlain]
3558 endlay = endlay - len(document.body[p : endInset + 1])
3560 del document.body[p : endInset + 1]
3561 subst += put_cmd_in_ert("}{") + content
3563 subst += put_cmd_in_ert("}{")
3565 document.body[j : j] = subst + document.body[j : j]
3569 def convert_captioninsets(document):
3570 " Converts caption insets to new syntax "
3574 i = find_token(document.body, "\\begin_inset Caption", i)
3577 document.body[i] = "\\begin_inset Caption Standard"
3581 def revert_captioninsets(document):
3582 " Reverts caption insets to old syntax "
3586 i = find_token(document.body, "\\begin_inset Caption Standard", i)
3589 document.body[i] = "\\begin_inset Caption"
3593 def convert_captionlayouts(document):
3594 " Convert caption layouts to caption insets. "
3597 "Captionabove": "Above",
3598 "Captionbelow": "Below",
3599 "FigCaption" : "FigCaption",
3600 "Table_Caption" : "Table",
3601 "CenteredCaption" : "Centered",
3602 "Bicaption" : "Bicaption",
3607 i = find_token(document.body, "\\begin_layout", i)
3610 val = get_value(document.body, "\\begin_layout", i)
3611 if val in caption_dict.keys():
3612 j = find_end_of_layout(document.body, i)
3614 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3617 document.body[j:j] = ["\\end_layout", "", "\\end_inset", "", ""]
3618 document.body[i:i+1] = ["\\begin_layout %s" % document.default_layout,
3619 "\\begin_inset Caption %s" % caption_dict[val], "",
3620 "\\begin_layout %s" % document.default_layout]
3624 def revert_captionlayouts(document):
3625 " Revert caption insets to caption layouts. "
3628 "Above" : "Captionabove",
3629 "Below" : "Captionbelow",
3630 "FigCaption" : "FigCaption",
3631 "Table" : "Table_Caption",
3632 "Centered" : "CenteredCaption",
3633 "Bicaption" : "Bicaption",
3637 rx = re.compile(r'^\\begin_inset Caption (\S+)$')
3639 i = find_token(document.body, "\\begin_inset Caption", i)
3643 m = rx.match(document.body[i])
3647 if val not in caption_dict.keys():
3651 # We either need to delete the previous \begin_layout line, or we
3652 # need to end the previous layout if this inset is not in the first
3653 # position of the paragraph.
3654 layout_before = find_token_backwards(document.body, "\\begin_layout", i)
3655 if layout_before == -1:
3656 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3658 layout_line = document.body[layout_before]
3659 del_layout_before = True
3660 l = layout_before + 1
3662 if document.body[l] != "":
3663 del_layout_before = False
3666 if del_layout_before:
3667 del document.body[layout_before:i]
3670 document.body[i:i] = ["\\end_layout", ""]
3673 # Find start of layout in the inset and end of inset
3674 j = find_token(document.body, "\\begin_layout", i)
3676 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3678 k = find_end_of_inset(document.body, i)
3680 document.warning("Malformed LyX document: Missing `\\end_inset'.")
3683 # We either need to delete the following \end_layout line, or we need
3684 # to restart the old layout if this inset is not at the paragraph end.
3685 layout_after = find_token(document.body, "\\end_layout", k)
3686 if layout_after == -1:
3687 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3689 del_layout_after = True
3691 while l < layout_after:
3692 if document.body[l] != "":
3693 del_layout_after = False
3696 if del_layout_after:
3697 del document.body[k+1:layout_after+1]
3699 document.body[k+1:k+1] = [layout_line, ""]
3701 # delete \begin_layout and \end_inset and replace \begin_inset with
3702 # "\begin_layout XXX". This works because we can only have one
3703 # paragraph in the caption inset: The old \end_layout will be recycled.
3704 del document.body[k]
3705 if document.body[k] == "":
3706 del document.body[k]
3707 del document.body[j]
3708 if document.body[j] == "":
3709 del document.body[j]
3710 document.body[i] = "\\begin_layout %s" % caption_dict[val]
3711 if document.body[i+1] == "":
3712 del document.body[i+1]
3716 def revert_fragileframe(document):
3717 " Reverts beamer FragileFrame layout to ERT "
3719 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3720 if document.textclass not in beamer_classes:
3725 i = find_token(document.body, "\\begin_layout FragileFrame", i)
3728 # Find end of sequence
3729 j = find_end_of_sequence(document.body, i)
3731 document.warning("Malformed LyX document. Cannot find end of FragileFrame sequence!")
3735 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{frame}")
3736 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{frame}")
3737 endseq = endseq + len(esubst) - len(document.body[j : j])
3738 if document.body[j] == "\\end_deeper":
3739 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3741 document.body[j : j] = esubst
3742 for q in range(i, j):
3743 if document.body[q] == "\\begin_layout FragileFrame":
3744 document.body[q] = "\\begin_layout %s" % document.default_layout
3747 if document.body[r] == "\\begin_deeper":
3748 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3750 document.body[r] = ""
3751 document.body[s] = ""
3755 for p in range(1, 5):
3756 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, j)
3759 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3760 endPlain = find_end_of_layout(document.body, beginPlain)
3761 endInset = find_end_of_inset(document.body, arg)
3762 content = document.body[beginPlain + 1 : endPlain]
3764 j = j - len(document.body[arg : endInset + 1])
3766 del document.body[arg : endInset + 1]
3767 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3769 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3770 endPlain = find_end_of_layout(document.body, beginPlain)
3771 endInset = find_end_of_inset(document.body, arg)
3772 content = document.body[beginPlain + 1 : endPlain]
3774 j = j - len(document.body[arg : endInset + 1])
3776 del document.body[arg : endInset + 1]
3777 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3779 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3780 endPlain = find_end_of_layout(document.body, beginPlain)
3781 endInset = find_end_of_inset(document.body, arg)
3782 content = document.body[beginPlain + 1 : endPlain]
3784 j = j - len(document.body[arg : endInset + 1])
3786 del document.body[arg : endInset + 1]
3787 subst += put_cmd_in_ert("[fragile,") + content + put_cmd_in_ert("]")
3789 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3790 endPlain = find_end_of_layout(document.body, beginPlain)
3791 endInset = find_end_of_inset(document.body, arg)
3792 content = document.body[beginPlain + 1 : endPlain]
3794 j = j - len(document.body[arg : endInset + 1])
3796 del document.body[arg : endInset + 1]
3797 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3799 subst += put_cmd_in_ert("[fragile]")
3801 document.body[i : i + 1] = subst
3805 def revert_newframes(document):
3806 " Reverts beamer Frame and PlainFrame layouts to old forms "
3808 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3809 if document.textclass not in beamer_classes:
3813 "Frame" : "BeginFrame",
3814 "PlainFrame" : "BeginPlainFrame",
3817 rx = re.compile(r'^\\begin_layout (\S+)$')
3820 i = find_token(document.body, "\\begin_layout", i)
3824 m = rx.match(document.body[i])
3828 if val not in frame_dict.keys():
3831 # Find end of sequence
3832 j = find_end_of_sequence(document.body, i)
3834 document.warning("Malformed LyX document. Cannot find end of Frame sequence!")
3838 subst = ["\\begin_layout %s" % frame_dict[val]]
3839 esubst = ["", "\\begin_layout EndFrame", "", "\\end_layout"]
3840 endseq = endseq + len(esubst) - len(document.body[j : j])
3841 if document.body[j] == "\\end_deeper":
3842 document.body[j : j] = esubst
3844 document.body[j+1 : j+1] = esubst
3845 for q in range(i, j):
3846 if document.body[q] == "\\begin_layout %s" % val:
3847 document.body[q] = "\\begin_layout %s" % document.default_layout
3850 if document.body[r] == "\\begin_deeper":
3851 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3853 document.body[r] = ""
3854 document.body[s] = ""
3858 l = find_end_of_layout(document.body, i)
3859 for p in range(1, 5):
3860 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, l)
3863 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3864 endPlain = find_end_of_layout(document.body, beginPlain)
3865 endInset = find_end_of_inset(document.body, arg)
3866 content = document.body[beginPlain + 1 : endPlain]
3868 l = l - len(document.body[arg : endInset + 1])
3870 del document.body[arg : endInset + 1]
3871 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3873 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3874 endPlain = find_end_of_layout(document.body, beginPlain)
3875 endInset = find_end_of_inset(document.body, arg)
3876 content = document.body[beginPlain + 1 : endPlain]
3878 l = l - len(document.body[arg : endInset + 1])
3880 del document.body[arg : endInset + 1]
3881 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3883 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3884 endPlain = find_end_of_layout(document.body, beginPlain)
3885 endInset = find_end_of_inset(document.body, arg)
3886 content = document.body[beginPlain + 1 : endPlain]
3888 l = l - len(document.body[arg : endInset + 1])
3890 del document.body[arg : endInset + 1]
3891 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3893 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3894 endPlain = find_end_of_layout(document.body, beginPlain)
3895 endInset = find_end_of_inset(document.body, arg)
3896 content = document.body[beginPlain + 1 : endPlain]
3898 l = l - len(document.body[arg : endInset + 1])
3900 del document.body[arg : endInset + 1]
3903 document.body[i : i + 1] = subst
3906 # known encodings that do not change their names (same LyX and LaTeX names)
3907 known_enc_tuple = ("auto", "default", "ansinew", "applemac", "armscii8", "ascii",
3908 "cp437", "cp437de", "cp850", "cp852", "cp855", "cp858", "cp862", "cp865", "cp866",
3909 "cp1250", "cp1251", "cp1252", "cp1255", "cp1256", "cp1257", "koi8-r", "koi8-u",
3910 "pt154", "pt254", "tis620-0", "utf8", "utf8x", "utf8-plain")
3912 def convert_encodings(document):
3913 "Use the LyX names of the encodings instead of the LaTeX names."
3914 LaTeX2LyX_enc_dict = {
3915 "8859-6": "iso8859-6",
3916 "8859-8": "iso8859-8",
3918 "euc": "euc-jp-platex",
3923 "iso88595": "iso8859-5",
3924 "iso-8859-7": "iso8859-7",
3926 "jis": "jis-platex",
3928 "l7xenc": "iso8859-13",
3929 "latin1": "iso8859-1",
3930 "latin2": "iso8859-2",
3931 "latin3": "iso8859-3",
3932 "latin4": "iso8859-4",
3933 "latin5": "iso8859-9",
3934 "latin9": "iso8859-15",
3935 "latin10": "iso8859-16",
3936 "SJIS": "shift-jis",
3937 "sjis": "shift-jis-platex",
3940 i = find_token(document.header, "\\inputencoding" , 0)
3943 val = get_value(document.header, "\\inputencoding", i)
3944 if val in LaTeX2LyX_enc_dict.keys():
3945 document.header[i] = "\\inputencoding %s" % LaTeX2LyX_enc_dict[val]
3946 elif val not in known_enc_tuple:
3947 document.warning("Ignoring unknown input encoding: `%s'" % val)
3950 def revert_encodings(document):
3951 """Revert to using the LaTeX names of the encodings instead of the LyX names.
3952 Also revert utf8-platex to sjis, the language default when using Japanese.
3954 LyX2LaTeX_enc_dict = {
3959 "euc-jp-platex": "euc",
3962 "iso8859-1": "latin1",
3963 "iso8859-2": "latin2",
3964 "iso8859-3": "latin3",
3965 "iso8859-4": "latin4",
3966 "iso8859-5": "iso88595",
3967 "iso8859-6": "8859-6",
3968 "iso8859-7": "iso-8859-7",
3969 "iso8859-8": "8859-8",
3970 "iso8859-9": "latin5",
3971 "iso8859-13": "l7xenc",
3972 "iso8859-15": "latin9",
3973 "iso8859-16": "latin10",
3975 "jis-platex": "jis",
3976 "shift-jis": "SJIS",
3977 "shift-jis-platex": "sjis",
3979 "utf8-platex": "sjis"
3981 i = find_token(document.header, "\\inputencoding" , 0)
3984 val = get_value(document.header, "\\inputencoding", i)
3985 if val in LyX2LaTeX_enc_dict.keys():
3986 document.header[i] = "\\inputencoding %s" % LyX2LaTeX_enc_dict[val]
3987 elif val not in known_enc_tuple:
3988 document.warning("Ignoring unknown input encoding: `%s'" % val)
3991 def revert_IEEEtran_3(document):
3993 Reverts Flex Insets to TeX-code
3995 if document.textclass == "IEEEtran":
4001 h = find_token(document.body, "\\begin_inset Flex Author Mark", h)
4003 endh = find_end_of_inset(document.body, h)
4004 document.body[endh - 2 : endh + 1] = put_cmd_in_ert("}")
4005 document.body[h : h + 4] = put_cmd_in_ert("\\IEEEauthorrefmark{")
4008 i = find_token(document.body, "\\begin_inset Flex Author Name", i)
4010 endi = find_end_of_inset(document.body, i)
4011 document.body[endi - 2 : endi + 1] = put_cmd_in_ert("}")
4012 document.body[i : i + 4] = put_cmd_in_ert("\\IEEEauthorblockN{")
4015 j = find_token(document.body, "\\begin_inset Flex Author Affiliation", j)
4017 endj = find_end_of_inset(document.body, j)
4018 document.body[endj - 2 : endj + 1] = put_cmd_in_ert("}")
4019 document.body[j : j + 4] = put_cmd_in_ert("\\IEEEauthorblockA{")
4021 if i == -1 and j == -1 and h == -1:
4025 def revert_kurier_fonts(document):
4026 " Revert kurier font definition to LaTeX "
4028 i = find_token(document.header, "\\font_math", 0)
4030 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4031 val = get_value(document.header, "\\font_math", i)
4032 if val == "kurier-math":
4033 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
4034 "\\usepackage[math]{kurier}\n" \
4035 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
4036 document.header[i] = "\\font_math auto"
4038 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4039 kurier_fonts = ["kurier", "kurierc", "kurierl", "kurierlc"]
4040 k = find_token(document.header, "\\font_sans kurier", 0)
4042 sf = get_value(document.header, "\\font_sans", k)
4043 if sf in kurier_fonts:
4044 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4045 document.header[k] = "\\font_sans default"
4047 def revert_iwona_fonts(document):
4048 " Revert iwona font definition to LaTeX "
4050 i = find_token(document.header, "\\font_math", 0)
4052 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4053 val = get_value(document.header, "\\font_math", i)
4054 if val == "iwona-math":
4055 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
4056 "\\usepackage[math]{iwona}\n" \
4057 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
4058 document.header[i] = "\\font_math auto"
4060 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4061 iwona_fonts = ["iwona", "iwonac", "iwonal", "iwonalc"]
4062 k = find_token(document.header, "\\font_sans iwona", 0)
4064 sf = get_value(document.header, "\\font_sans", k)
4065 if sf in iwona_fonts:
4066 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4067 document.header[k] = "\\font_sans default"
4070 def revert_new_libertines(document):
4071 " Revert new libertine font definition to LaTeX "
4073 if find_token(document.header, "\\use_non_tex_fonts true", 0) != -1:
4076 i = find_token(document.header, "\\font_typewriter libertine-mono", 0)
4078 preamble = "\\usepackage"
4079 sc = find_token(document.header, "\\font_tt_scale", 0)
4081 scval = get_value(document.header, "\\font_tt_scale", sc)
4083 preamble += "[scale=%f]" % (float(scval) / 100)
4084 document.header[sc] = "\\font_tt_scale 100"
4085 preamble += "{libertineMono-type1}"
4086 add_to_preamble(document, [preamble])
4087 document.header[i] = "\\font_typewriter default"
4089 k = find_token(document.header, "\\font_sans biolinum", 0)
4091 preamble = "\\usepackage"
4093 j = find_token(document.header, "\\font_osf true", 0)
4098 sc = find_token(document.header, "\\font_sf_scale", 0)
4100 scval = get_value(document.header, "\\font_sf_scale", sc)
4102 options += ",scale=%f" % (float(scval) / 100)
4103 document.header[sc] = "\\font_sf_scale 100"
4105 preamble += "[" + options +"]"
4106 preamble += "{biolinum-type1}"
4107 add_to_preamble(document, [preamble])
4108 document.header[k] = "\\font_sans default"
4111 def convert_lyxframes(document):
4112 " Converts old beamer frames to new style "
4114 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4115 if document.textclass not in beamer_classes:
4118 framebeg = ["BeginFrame", "BeginPlainFrame"]
4119 frameend = ["Frame", "PlainFrame", "EndFrame", "BeginFrame", "BeginPlainFrame", "AgainFrame",
4120 "Section", "Section*", "Subsection", "Subsection*", "Subsubsection", "Subsubsection*"]
4121 for lay in framebeg:
4124 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
4127 parent = get_containing_layout(document.body, i)
4128 if parent == False or parent[1] != i:
4129 document.warning("Wrong parent layout!")
4132 frametype = parent[0]
4136 # Step I: Convert ERT arguments
4137 # FIXME: See restrictions in convert_beamerframeargs method
4138 ertend = convert_beamerframeargs(document, i, parbeg)
4141 # Step II: Now rename the layout and convert the title to an argument
4142 j = find_end_of_layout(document.body, i)
4143 document.body[j : j + 1] = ['\\end_layout', '', '\\end_inset', '', '\\end_layout']
4144 if lay == "BeginFrame":
4145 document.body[i] = "\\begin_layout Frame"
4147 document.body[i] = "\\begin_layout PlainFrame"
4148 document.body[ertend + 1 : ertend + 1] = ['\\begin_inset Argument 4',
4149 'status open', '', '\\begin_layout Plain Layout']
4150 # Step III: find real frame end
4154 fend = find_token(document.body, "\\begin_layout", jj)
4156 document.warning("Malformed LyX document: No real frame end!")
4158 val = get_value(document.body, "\\begin_layout", fend)
4159 if val not in frameend:
4162 old = document.body[fend]
4163 if val == frametype:
4164 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4165 # consider explicit EndFrames between two identical frame types
4166 elif val == "EndFrame":
4167 nextlayout = find_token(document.body, "\\begin_layout", fend + 1)
4168 if nextlayout != -1 and get_value(document.body, "\\begin_layout", nextlayout) == frametype:
4169 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4171 document.body[fend : fend] = ['\\end_deeper']
4173 document.body[fend : fend] = ['\\end_deeper']
4174 document.body[j + 1 : j + 1] = ['', '\\begin_deeper']
4179 def remove_endframes(document):
4180 " Remove deprecated beamer endframes "
4182 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4183 if document.textclass not in beamer_classes:
4188 i = find_token_exact(document.body, "\\begin_layout EndFrame", i)
4191 j = find_end_of_layout(document.body, i)
4193 document.warning("Malformed LyX document: Missing \\end_layout to EndFrame")
4196 del document.body[i : j + 1]
4199 def revert_powerdot_flexes(document):
4200 " Reverts powerdot flex insets "
4202 if document.textclass != "powerdot":
4205 flexes = {"Onslide" : "\\onslide",
4206 "Onslide*" : "\\onslide*",
4207 "Onslide+" : "\\onslide+"}
4208 rx = re.compile(r'^\\begin_inset Flex (.+)$')
4212 i = find_token(document.body, "\\begin_inset Flex", i)
4215 m = rx.match(document.body[i])
4217 flextype = m.group(1)
4218 z = find_end_of_inset(document.body, i)
4220 document.warning("Can't find end of Flex " + flextype + " inset.")
4223 if flextype in flexes:
4224 pre = put_cmd_in_ert(flexes[flextype])
4225 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
4227 argend = find_end_of_inset(document.body, arg)
4229 document.warning("Can't find end of Argument!")
4232 # Find containing paragraph layout
4233 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
4234 endPlain = find_end_of_layout(document.body, beginPlain)
4235 argcontent = document.body[beginPlain + 1 : endPlain]
4237 z = z - len(document.body[arg : argend + 1])
4239 del document.body[arg : argend + 1]
4240 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
4241 pre += put_cmd_in_ert("{")
4242 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4243 endPlain = find_end_of_layout(document.body, beginPlain)
4245 z = z - len(document.body[i : beginPlain + 1])
4247 document.body[i : beginPlain + 1] = pre
4248 post = put_cmd_in_ert("}")
4249 document.body[z - 2 : z + 1] = post
4253 def revert_powerdot_pause(document):
4254 " Reverts powerdot pause layout to ERT "
4256 if document.textclass != "powerdot":
4261 i = find_token(document.body, "\\begin_layout Pause", i)
4264 j = find_end_of_layout(document.body, i)
4266 document.warning("Malformed LyX document: Can't find end of Pause layout")
4270 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\pause")
4271 for p in range(i, j):
4274 arg = find_token(document.body, "\\begin_inset Argument 1", i, j)
4276 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4277 endPlain = find_end_of_layout(document.body, beginPlain)
4278 endInset = find_end_of_inset(document.body, p)
4279 content = document.body[beginPlain + 1 : endPlain]
4281 endlay = endlay - len(document.body[p : endInset + 1])
4283 del document.body[p : endInset + 1]
4284 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4286 document.body[i : i + 1] = subst
4290 def revert_powerdot_itemargs(document):
4291 " Reverts powerdot item arguments to ERT "
4293 if document.textclass != "powerdot":
4297 list_layouts = ["Itemize", "ItemizeType1", "Enumerate", "EnumerateType1"]
4298 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4301 i = find_token(document.body, "\\begin_inset Argument", i)
4304 # Find containing paragraph layout
4305 parent = get_containing_layout(document.body, i)
4307 document.warning("Malformed LyX document: Can't find parent paragraph layout")
4312 realparbeg = parent[3]
4313 layoutname = parent[0]
4315 for p in range(parbeg, parend):
4319 if layoutname in list_layouts:
4320 m = rx.match(document.body[p])
4323 if argnr == "item:1":
4324 j = find_end_of_inset(document.body, i)
4325 # Find containing paragraph layout
4326 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4327 endPlain = find_end_of_layout(document.body, beginPlain)
4328 content = document.body[beginPlain + 1 : endPlain]
4329 del document.body[i:j+1]
4330 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4331 document.body[realparbeg : realparbeg] = subst
4332 elif argnr == "item:2":
4333 j = find_end_of_inset(document.body, i)
4334 # Find containing paragraph layout
4335 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4336 endPlain = find_end_of_layout(document.body, beginPlain)
4337 content = document.body[beginPlain + 1 : endPlain]
4338 del document.body[i:j+1]
4339 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
4340 document.body[realparbeg : realparbeg] = subst
4345 def revert_powerdot_columns(document):
4346 " Reverts powerdot twocolumn to TeX-code "
4347 if document.textclass != "powerdot":
4350 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4353 i = find_token(document.body, "\\begin_layout Twocolumn", i)
4356 j = find_end_of_layout(document.body, i)
4358 document.warning("Malformed LyX document: Can't find end of Twocolumn layout")
4362 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
4363 endlay += len(put_cmd_in_ert("}"))
4364 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\twocolumn")
4365 for p in range(i, j):
4368 m = rx.match(document.body[p])
4372 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4373 endPlain = find_end_of_layout(document.body, beginPlain)
4374 endInset = find_end_of_inset(document.body, p)
4375 content = document.body[beginPlain + 1 : endPlain]
4377 endlay = endlay - len(document.body[p : endInset + 1])
4379 del document.body[p : endInset + 1]
4380 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4382 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4383 endPlain = find_end_of_layout(document.body, beginPlain)
4384 endInset = find_end_of_inset(document.body, p)
4385 content = document.body[beginPlain + 1 : endPlain]
4387 endlay = endlay - len(document.body[p : endInset + 1])
4389 del document.body[p : endInset + 1]
4390 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
4392 subst += put_cmd_in_ert("{")
4393 document.body[i : i + 1] = subst
4397 def revert_mbox_fbox(document):
4398 'Convert revert mbox/fbox boxes to TeX-code'
4401 i = find_token(document.body, "\\begin_inset Box", i)
4404 j = find_token(document.body, "width", i)
4406 document.warning("Malformed LyX document: Can't find box width")
4408 width = get_value(document.body, "width", j)
4409 k = find_end_of_inset(document.body, j)
4411 document.warning("Malformed LyX document: Can't find end of box inset")
4414 BeginLayout = find_token(document.body, "\\begin_layout Plain Layout", j)
4415 EndLayout = find_end_of_layout(document.body, BeginLayout)
4416 # replace if width is ""
4418 document.body[EndLayout:k + 1] = put_cmd_in_ert("}")
4419 if document.body[i] == "\\begin_inset Box Frameless":
4420 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\mbox{")
4421 if document.body[i] == "\\begin_inset Box Boxed":
4422 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\fbox{")
4426 def revert_starred_caption(document):
4427 " Reverts unnumbered longtable caption insets "
4431 i = find_token(document.body, "\\begin_inset Caption LongTableNoNumber", i)
4434 # This is not equivalent, but since the caption inset is a full blown
4435 # text inset a true conversion to ERT is too difficult.
4436 document.body[i] = "\\begin_inset Caption Standard"
4440 def revert_forced_local_layout(document):
4443 i = find_token(document.header, "\\begin_forced_local_layout", i)
4446 j = find_end_of(document.header, i, "\\begin_forced_local_layout", "\\end_forced_local_layout")
4448 # this should not happen
4450 regexp = re.compile(r'\s*forcelocal', re.IGNORECASE)
4451 k = find_re(document.header, regexp, i, j)
4453 del document.header[k]
4455 k = find_re(document.header, regexp, i, j)
4456 k = find_token(document.header, "\\begin_local_layout", 0)
4458 document.header[i] = "\\begin_local_layout"
4459 document.header[j] = "\\end_local_layout"
4461 l = find_end_of(document.header, k, "\\begin_local_layout", "\\end_local_layout")
4463 # this should not happen
4465 lines = document.header[i+1 : j]
4467 document.header[k+1 : k+1] = lines
4468 document.header[i : j ] = []
4470 document.header[i : j ] = []
4471 document.header[k+1 : k+1] = lines
4474 def revert_aa1(document):
4475 " Reverts InsetArguments of aa to TeX-code "
4476 if document.textclass == "aa":
4480 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4482 revert_Argument_to_TeX_brace(document, i, 0, 1, 4, False, False)
4488 def revert_aa2(document):
4489 " Reverts InsetArguments of aa to TeX-code "
4490 if document.textclass == "aa":
4494 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4496 document.body[i] = "\\begin_layout Abstract"
4502 def revert_tibetan(document):
4503 "Set the document language for Tibetan to English"
4505 if document.language == "tibetan":
4506 document.language = "english"
4507 i = find_token(document.header, "\\language", 0)
4509 document.header[i] = "\\language english"
4511 while j < len(document.body):
4512 j = find_token(document.body, "\\lang tibetan", j)
4514 document.body[j] = document.body[j].replace("\\lang tibetan", "\\lang english")
4517 j = len(document.body)
4526 # The idea here is that we will have a sequence of chunk paragraphs.
4527 # We want to convert them to paragraphs in one or several chunk insets.
4528 # Individual chunks are terminated by the character @ on the last line.
4529 # This line will be discarded, and following lines are treated as new
4530 # chunks, which go into their own insets.
4531 # The first line of a chunk should look like: <<CONTENT>>=
4532 # We will discard the delimiters, and put the CONTENT into the
4533 # optional argument of the inset, if the CONTENT is non-empty.
4534 def convert_chunks(document):
4535 first_re = re.compile(r'<<(.*)>>=(.*)')
4538 # find start of a block of chunks
4539 i = find_token(document.body, "\\begin_layout Chunk", file_pos)
4545 chunk_started = False
4548 # process the one we just found
4549 j = find_end_of_layout(document.body, i)
4551 document.warning("Malformed LyX documents. Can't find end of Chunk layout!")
4552 # there is no point continuing, as we will run into the same error again.
4554 this_chunk = "".join(document.body[i + 1:j])
4556 # there may be empty lines between chunks
4557 # we just skip them.
4558 if not chunk_started:
4559 if this_chunk != "":
4561 chunk_started = True
4564 contents.append(document.body[i + 1:j])
4566 # look for potential chunk terminator
4567 # on the last line of the chunk paragraph
4568 if document.body[j - 1] == "@":
4571 # look for subsequent chunk paragraph
4572 i = find_token(document.body, "\\begin_layout", j)
4576 if get_value(document.body, "\\begin_layout", i) != "Chunk":
4579 file_pos = end = j + 1
4581 # The last chunk should simply have an "@" in it
4582 # or at least end with "@" (can happen if @ is
4583 # preceded by a newline)
4585 if len(contents) > 0:
4586 lastpar = ''.join(contents[-1])
4587 if not lastpar.endswith("@"):
4588 document.warning("Unexpected chunk content: chunk not terminated by '@'!")
4589 if len(contents) == 0:
4590 # convert empty chunk layouts to Standard
4591 document.body[start] = "\\begin_layout Standard"
4595 # chunk par only contains "@". Just drop it.
4598 # chunk par contains more. Only drop the "@".
4601 # The first line should look like: <<CONTENT>>=
4602 # We want the CONTENT
4603 optarg = ' '.join(contents[0])
4605 # We can already have real chunk content in
4606 # the first par (separated from the options by a newline).
4607 # We collect such stuff to re-insert it later.
4610 match = first_re.search(optarg)
4612 optarg = match.groups()[0]
4613 if match.groups()[1] != "":
4615 for c in contents[0]:
4616 if c.endswith(">>="):
4620 postoptstuff.append(c)
4621 # We have stripped everything. This can be deleted.
4624 newstuff = ['\\begin_layout Standard']
4626 # Maintain paragraph parameters
4627 par_params = ["\\noindent", "\\indent", "\\indent-toggle", "\\leftindent",
4628 "\\start_of_appendix", "\\paragraph_spacing", "\\align",
4629 "\\labelwidthstring"]
4632 if document.body[parms].split(' ', 1)[0] not in par_params:
4634 newstuff.extend([document.body[parms]])
4638 ['\\begin_inset Flex Chunk',
4640 '\\begin_layout Plain Layout', ''])
4642 # If we have a non-empty optional argument, insert it.
4643 if match and optarg != "":
4645 ['\\begin_inset Argument 1',
4647 '\\begin_layout Plain Layout',
4652 # Since we already opened a Plain layout, the first paragraph
4653 # does not need to do that.
4656 # we need to replace newlines with new layouts
4658 started_text = False
4659 for lno in range(0,len(postoptstuff)):
4660 if postoptstuff[lno].startswith("\\begin_inset Newline newline"):
4662 elif start_newline != -1:
4663 if postoptstuff[lno].startswith("\\end_inset"):
4664 # replace that bit, but only if we already have some text
4665 # and we're not at the end except for a blank line
4666 if started_text and \
4667 (lno != len(postoptstuff) - 2 or postoptstuff[-1] != ""):
4668 newstuff.extend(['\\end_layout', '\n', '\\begin_layout Plain Layout', '\n'])
4672 newstuff.extend([postoptstuff[lno]])
4673 newstuff.append('\\end_layout')
4677 newstuff.extend(['', '\\begin_layout Plain Layout', ''])
4681 newstuff.append('\\end_layout')
4683 newstuff.extend(['', '\\end_inset', '', '\\end_layout', ''])
4685 document.body[start:end] = newstuff
4687 file_pos += len(newstuff) - (end - start)
4690 def revert_chunks(document):
4693 i = find_token(document.body, "\\begin_inset Flex Chunk", i)
4697 iend = find_end_of_inset(document.body, i)
4699 document.warning("Can't find end of Chunk!")
4703 # Look for optional argument
4705 ostart = find_token(document.body, "\\begin_inset Argument 1", i, iend)
4707 oend = find_end_of_inset(document.body, ostart)
4708 k = find_token(document.body, "\\begin_layout Plain Layout", ostart, oend)
4710 document.warning("Malformed LyX document: Can't find argument contents!")
4712 m = find_end_of_layout(document.body, k)
4713 optarg = "".join(document.body[k+1:m])
4715 # We now remove the optional argument, so we have something
4716 # uniform on which to work
4717 document.body[ostart : oend + 1] = []
4718 # iend is now invalid
4719 iend = find_end_of_inset(document.body, i)
4721 retval = get_containing_layout(document.body, i)
4723 document.warning("Can't find containing layout for Chunk!")
4726 (lname, lstart, lend, pstart) = retval
4727 # we now want to work through the various paragraphs, and collect their contents
4731 k = find_token(document.body, "\\begin_layout Plain Layout", k, lend)
4734 j = find_end_of_layout(document.body, k)
4736 document.warning("Can't find end of layout inside chunk!")
4738 parlist.append(document.body[k+1:j])
4740 # we now need to wrap all of these paragraphs in chunks
4742 newlines.extend(["\\begin_layout Chunk", "", "<<" + optarg + ">>=", "\\end_layout", ""])
4743 for stuff in parlist:
4744 newlines.extend(["\\begin_layout Chunk"] + stuff + ["\\end_layout", ""])
4745 newlines.extend(["\\begin_layout Chunk", "", "@", "\\end_layout", ""])
4746 # replace old content with new content
4747 document.body[lstart : lend + 1] = newlines
4748 i = lstart + len(newlines)
4755 supported_versions = ["2.1.0","2.1"]
4758 [415, [convert_undertilde]],
4760 [417, [convert_japanese_encodings]],
4761 [418, [convert_justification]],
4763 [420, [convert_biblio_style]],
4764 [421, [convert_longtable_captions]],
4765 [422, [convert_use_packages]],
4766 [423, [convert_use_mathtools]],
4767 [424, [convert_cite_engine_type]],
4768 # No convert_cancel, since cancel will be loaded automatically
4769 # in format 425 without any possibility to switch it off.
4770 # This has been fixed in format 464.
4774 [428, [convert_cell_rotation]],
4775 [429, [convert_table_rotation]],
4776 [430, [convert_listoflistings]],
4777 [431, [convert_use_amssymb]],
4779 [433, [convert_armenian]],
4787 [441, [convert_mdnomath]],
4792 [446, [convert_latexargs]],
4793 [447, [convert_IEEEtran, convert_AASTeX, convert_AGUTeX, convert_IJMP, convert_SIGPLAN, convert_SIGGRAPH, convert_EuropeCV, convert_Initials, convert_ModernCV]],
4794 [448, [convert_literate]],
4797 [451, [convert_beamerargs, convert_againframe_args, convert_corollary_args, convert_quote_args]],
4798 [452, [convert_beamerblocks]],
4799 [453, [convert_use_stmaryrd]],
4800 [454, [convert_overprint]],
4802 [456, [convert_epigraph]],
4803 [457, [convert_use_stackrel]],
4804 [458, [convert_captioninsets, convert_captionlayouts]],
4809 [463, [convert_encodings]],
4810 [464, [convert_use_cancel]],
4811 [465, [convert_lyxframes, remove_endframes]],
4817 [471, [convert_cite_engine_type_default]],
4820 [474, [convert_chunks, cleanup_beamerargs]],
4824 [473, [revert_chunks]],
4825 [472, [revert_tibetan]],
4826 [471, [revert_aa1,revert_aa2]],
4827 [470, [revert_cite_engine_type_default]],
4828 [469, [revert_forced_local_layout]],
4829 [468, [revert_starred_caption]],
4830 [467, [revert_mbox_fbox]],
4831 [466, [revert_iwona_fonts]],
4832 [465, [revert_powerdot_flexes, revert_powerdot_pause, revert_powerdot_itemargs, revert_powerdot_columns]],
4834 [463, [revert_use_cancel]],
4835 [462, [revert_encodings]],
4836 [461, [revert_new_libertines]],
4837 [460, [revert_kurier_fonts]],
4838 [459, [revert_IEEEtran_3]],
4839 [458, [revert_fragileframe, revert_newframes]],
4840 [457, [revert_captioninsets, revert_captionlayouts]],
4841 [456, [revert_use_stackrel]],
4842 [455, [revert_epigraph]],
4843 [454, [revert_frametitle]],
4844 [453, [revert_overprint]],
4845 [452, [revert_use_stmaryrd]],
4846 [451, [revert_beamerblocks]],
4847 [450, [revert_beamerargs, revert_beamerargs2, revert_beamerargs3, revert_beamerflex]],
4848 [449, [revert_garamondx, revert_garamondx_newtxmath]],
4849 [448, [revert_itemargs]],
4850 [447, [revert_literate]],
4851 [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]],
4852 [445, [revert_latexargs]],
4853 [444, [revert_uop]],
4854 [443, [revert_biolinum]],
4856 [441, [revert_newtxmath]],
4857 [440, [revert_mdnomath]],
4858 [439, [revert_mathfonts]],
4859 [438, [revert_minionpro]],
4860 [437, [revert_ipadeco, revert_ipachar]],
4861 [436, [revert_texgyre]],
4862 [435, [revert_mathdesign]],
4863 [434, [revert_txtt]],
4864 [433, [revert_libertine]],
4865 [432, [revert_armenian]],
4866 [431, [revert_languages, revert_ancientgreek]],
4867 [430, [revert_use_amssymb]],
4868 [429, [revert_listoflistings]],
4869 [428, [revert_table_rotation]],
4870 [427, [revert_cell_rotation]],
4871 [426, [revert_tipa]],
4872 [425, [revert_verbatim]],
4873 [424, [revert_cancel]],
4874 [423, [revert_cite_engine_type]],
4875 [422, [revert_use_mathtools]],
4876 [421, [revert_use_packages]],
4877 [420, [revert_longtable_captions]],
4878 [419, [revert_biblio_style]],
4879 [418, [revert_australian]],
4880 [417, [revert_justification]],
4881 [416, [revert_japanese_encodings]],
4882 [415, [revert_negative_space, revert_math_spaces]],
4883 [414, [revert_undertilde]],
4884 [413, [revert_visible_space]]
4888 if __name__ == "__main__":