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 document.body[parbeg] == "\\begin_inset ERT":
3074 ertcontfirstline = parbeg + 5
3078 # Find the last ERT in this paragraph used for arguments
3079 # (which might also be the first)
3080 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
3081 if lastertbeg == -1:
3082 document.warning("Last ERT not found!")
3084 lastertend = find_end_of_inset(document.body, lastertbeg)
3085 if lastertend == -1:
3086 document.warning("End of last ERT not found!")
3088 # Is this ERT really used for an argument?
3089 # Note: This will fail when non-argument ERTs actually use brackets
3091 regexp = re.compile(r'.*[>\]\}]', re.IGNORECASE)
3092 cbracket = find_re(document.body, regexp, lastertbeg, lastertend)
3095 if lastertbeg == parbeg:
3098 if lastertbeg == -1 or lastertend == -1:
3100 ertcontlastline = lastertend - 3
3102 if document.body[ertcontfirstline].lstrip().startswith("<"):
3103 # This is an overlay specification
3105 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3106 if document.body[ertcontlastline].rstrip().endswith(">"):
3108 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3109 # Convert to ArgInset
3110 document.body[parbeg] = "\\begin_inset Argument 1"
3111 elif document.body[ertcontlastline].rstrip().endswith("}"):
3113 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3115 ertcontdivline = ertcontfirstline
3116 tok = document.body[ertcontdivline].find('>{')
3118 regexp = re.compile(r'.*>\{', re.IGNORECASE)
3119 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3120 tok = document.body[ertcontdivline].find('>{')
3122 if ertcontfirstline < ertcontlastline:
3123 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3124 document.body[ertcontlastline : ertcontlastline + 1] = [
3125 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3126 if ertcontdivline == ertcontfirstline:
3127 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3128 '\\end_layout', '', '\\end_inset', '',
3129 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3130 'status collapsed', '', '\\begin_layout Plain Layout',
3131 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3132 document.body[ertcontdivline][tok + 2:]]
3134 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3135 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3136 'status collapsed', '', '\\begin_layout Plain Layout',
3137 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3138 document.body[ertcontdivline][tok + 2:]]
3140 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3141 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3142 'status collapsed', '', '\\begin_layout Plain Layout',
3143 document.body[ertcontdivline][tok + 2:]]
3145 # check if have delimiters in two different ERTs
3146 tok = document.body[ertcontdivline].find('>')
3148 regexp = re.compile(r'.*>', re.IGNORECASE)
3149 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3150 tok = document.body[ertcontdivline].find('>')
3152 tokk = document.body[ertcontdivline].find('{')
3154 regexp = re.compile(r'.*\{', re.IGNORECASE)
3155 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, lastertend)
3156 tokk = document.body[ertcontdivlinetwo].find('{')
3158 if ertcontfirstline < ertcontlastline:
3159 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3160 document.body[ertcontlastline : ertcontlastline + 1] = [
3161 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3162 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3163 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3164 '\\end_inset', '', '', '\\begin_inset Argument 2',
3165 'status collapsed', '', '\\begin_layout Plain Layout',
3166 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3167 document.body[ertcontdivlinetwo][tokk + 1:]]
3169 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3170 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3171 'status collapsed', '', '\\begin_layout Plain Layout',
3172 document.body[ertcontdivlinetwo][tokk + 1:]]
3173 # Convert to ArgInset
3174 if ertcontfirstline < ertcontlastline:
3175 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3176 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 1',
3177 'status collapsed', '', '\\begin_layout Plain Layout',
3178 '\\begin_inset ERT', '']
3180 document.body[parbeg] = "\\begin_inset Argument 1"
3181 elif document.body[ertcontfirstline].lstrip().startswith("{"):
3182 # This is the block title
3183 if document.body[ertcontlastline].rstrip().endswith("}"):
3184 # strip off the braces
3185 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3186 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3187 if ertcontfirstline < ertcontlastline:
3188 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3189 document.body[parend : parend + 1] = [
3190 document.body[parend], '\\end_inset', '', '\\end_layout']
3191 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3192 'status collapsed', '', '\\begin_layout Plain Layout',
3193 '\\begin_inset ERT', '']
3195 # Convert to ArgInset
3196 document.body[parbeg] = "\\begin_inset Argument 2"
3197 # the overlay argument can also follow the title, so ...
3198 elif document.body[ertcontlastline].rstrip().endswith(">"):
3200 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3202 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3204 ertcontdivline = ertcontfirstline
3205 tok = document.body[ertcontdivline].find('}<')
3207 regexp = re.compile(r'.*\}<', re.IGNORECASE)
3208 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3209 tok = document.body[ertcontdivline].find('}<')
3211 if ertcontfirstline < ertcontlastline:
3212 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3213 document.body[ertcontlastline : ertcontlastline + 1] = [
3214 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3215 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3216 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3217 'status collapsed', '', '\\begin_layout Plain Layout',
3218 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3219 document.body[ertcontdivline][tok + 2:]]
3221 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3222 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3223 'status collapsed', '', '\\begin_layout Plain Layout',
3224 document.body[ertcontdivline][tok + 2:]]
3226 # check if have delimiters in two different ERTs
3227 tok = document.body[ertcontdivline].find('}')
3229 regexp = re.compile(r'.*\}', re.IGNORECASE)
3230 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3231 tok = document.body[ertcontdivline].find('}')
3233 tokk = document.body[ertcontdivline].find('<')
3235 regexp = re.compile(r'.*<', re.IGNORECASE)
3236 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, lastertend)
3237 tokk = document.body[ertcontdivlinetwo].find('<')
3239 if ertcontfirstline < ertcontlastline:
3240 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3241 document.body[ertcontlastline : ertcontlastline + 1] = [
3242 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3243 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3244 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3245 '\\end_inset', '', '', '\\begin_inset Argument 1',
3246 'status collapsed', '', '\\begin_layout Plain Layout',
3247 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3248 document.body[ertcontdivlinetwo][tokk + 1:]]
3250 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3251 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3252 'status collapsed', '', '\\begin_layout Plain Layout',
3253 document.body[ertcontdivlinetwo][tokk + 1:]]
3254 # Convert to ArgInset
3255 if ertcontfirstline < ertcontlastline:
3256 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3257 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3258 'status collapsed', '', '\\begin_layout Plain Layout',
3259 '\\begin_inset ERT', '']
3261 document.body[parbeg] = "\\begin_inset Argument 2"
3262 elif count_pars_in_inset(document.body, ertcontfirstline) > 1:
3263 # Multipar ERT. Skip this.
3266 # ERT has contents after the closing bracket. We cannot convert this.
3267 # convert_TeX_brace_to_Argument cannot either.
3268 #convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, False)
3272 j = find_end_of_layout(document.body, i)
3274 document.warning("end of layout not found!")
3275 k = find_token(document.body, "\\begin_inset Argument", i, j)
3277 document.warning("InsetArgument not found!")
3279 l = find_end_of_inset(document.body, k)
3280 m = find_token(document.body, "\\begin_inset ERT", l, j)
3283 ertcontfirstline = m + 5
3288 def convert_overprint(document):
3289 " Convert old beamer overprint layouts to ERT "
3291 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3292 if document.textclass not in beamer_classes:
3297 i = find_token(document.body, "\\begin_layout Overprint", i)
3300 # Find end of sequence
3301 j = find_end_of_sequence(document.body, i)
3303 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3307 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3309 if document.body[j] == "\\end_deeper":
3310 esubst = ["", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3312 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3313 endseq = endseq + len(esubst) - len(document.body[j : j])
3314 document.body[j : j] = esubst
3315 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3317 argend = find_end_of_layout(document.body, argbeg)
3319 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3322 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3323 endPlain = find_end_of_layout(document.body, beginPlain)
3324 content = document.body[beginPlain + 1 : endPlain]
3326 endseq = endseq - len(document.body[argbeg : argend + 1])
3328 del document.body[argbeg : argend + 1]
3329 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3331 endseq = endseq - len(document.body[i : i])
3332 document.body[i : i] = subst + ["\\end_layout"]
3333 endseq += len(subst)
3335 for p in range(i, endseq):
3336 if document.body[p] == "\\begin_layout Overprint":
3337 document.body[p] = "\\begin_layout Standard"
3342 def revert_overprint(document):
3343 " Revert old beamer overprint layouts to ERT "
3345 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3346 if document.textclass not in beamer_classes:
3351 i = find_token(document.body, "\\begin_layout Overprint", i)
3354 # Find end of sequence
3355 j = find_end_of_sequence(document.body, i)
3357 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3361 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3362 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}")
3363 endseq = endseq + len(esubst) - len(document.body[j : j])
3364 if document.body[j] == "\\end_deeper":
3365 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3367 document.body[j : j] = ["\\end_layout", ""] + esubst
3370 if document.body[r] == "\\begin_deeper":
3371 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3373 document.body[r] = ""
3374 document.body[s] = ""
3378 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3380 # Is this really our argument?
3381 nested = find_token(document.body, "\\begin_deeper", i, argbeg)
3383 argend = find_end_of_inset(document.body, argbeg)
3385 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3388 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3389 endPlain = find_end_of_layout(document.body, beginPlain)
3390 content = document.body[beginPlain + 1 : endPlain]
3392 endseq = endseq - len(document.body[argbeg : argend])
3394 del document.body[argbeg : argend + 1]
3395 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3397 endseq = endseq - len(document.body[i : i])
3398 document.body[i : i] = subst + ["\\end_layout"]
3399 endseq += len(subst)
3405 if document.body[p] == "\\begin_layout Overprint":
3406 q = find_end_of_layout(document.body, p)
3408 document.warning("Malformed LyX document. Cannot find end of Overprint layout!")
3411 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\onslide")
3412 argbeg = find_token(document.body, "\\begin_inset Argument item:1", p, q)
3414 argend = find_end_of_inset(document.body, argbeg)
3416 document.warning("Malformed LyX document. Cannot find end of Overprint item argument!")
3419 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3420 endPlain = find_end_of_layout(document.body, beginPlain)
3421 content = document.body[beginPlain + 1 : endPlain]
3423 endseq = endseq - len(document.body[argbeg : argend + 1])
3425 del document.body[argbeg : argend + 1]
3426 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3427 endseq = endseq - len(document.body[p : p + 1]) + len(subst)
3428 document.body[p : p + 1] = subst
3434 def revert_frametitle(document):
3435 " Reverts beamer frametitle layout to ERT "
3437 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3438 if document.textclass not in beamer_classes:
3441 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3444 i = find_token(document.body, "\\begin_layout FrameTitle", i)
3447 j = find_end_of_layout(document.body, i)
3449 document.warning("Malformed LyX document: Can't find end of FrameTitle layout")
3453 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
3454 endlay += len(put_cmd_in_ert("}"))
3455 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\frametitle")
3456 for p in range(i, j):
3459 m = rx.match(document.body[p])
3463 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3464 endPlain = find_end_of_layout(document.body, beginPlain)
3465 endInset = find_end_of_inset(document.body, p)
3466 content = document.body[beginPlain + 1 : endPlain]
3468 endlay = endlay - len(document.body[p : endInset + 1])
3470 del document.body[p : endInset + 1]
3471 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3473 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3474 endPlain = find_end_of_layout(document.body, beginPlain)
3475 endInset = find_end_of_inset(document.body, p)
3476 content = document.body[beginPlain + 1 : endPlain]
3478 endlay = endlay - len(document.body[p : endInset + 1])
3480 del document.body[p : endInset + 1]
3481 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3483 subst += put_cmd_in_ert("{")
3484 document.body[i : i + 1] = subst
3488 def convert_epigraph(document):
3489 " Converts memoir epigraph to new syntax "
3491 if document.textclass != "memoir":
3496 i = find_token(document.body, "\\begin_layout Epigraph", i)
3499 j = find_end_of_layout(document.body, i)
3501 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3506 ert = find_token(document.body, "\\begin_inset ERT", i, j)
3508 endInset = find_end_of_inset(document.body, ert)
3509 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", ert)
3510 endPlain = find_end_of_layout(document.body, beginPlain)
3511 ertcont = beginPlain + 2
3512 if document.body[ertcont] == "}{":
3514 # Convert to ArgInset
3515 endlay = endlay - 2 * len(document.body[j])
3516 begsubst = ['\\begin_inset Argument post:1', 'status collapsed', '',
3517 '\\begin_layout Plain Layout']
3518 endsubst = ['\\end_layout', '', '\\end_inset', '', document.body[j]]
3519 document.body[j : j + 1] = endsubst
3520 document.body[endInset + 1 : endInset + 1] = begsubst
3522 endlay += len(begsubst) + len(endsubst)
3523 endlay = endlay - len(document.body[ert : endInset + 1])
3524 del document.body[ert : endInset + 1]
3529 def revert_epigraph(document):
3530 " Reverts memoir epigraph argument to ERT "
3532 if document.textclass != "memoir":
3537 i = find_token(document.body, "\\begin_layout Epigraph", i)
3540 j = find_end_of_layout(document.body, i)
3542 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3547 p = find_token(document.body, "\\begin_layout Argument post:1", i, j)
3549 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3550 endPlain = find_end_of_layout(document.body, beginPlain)
3551 endInset = find_end_of_inset(document.body, p)
3552 content = document.body[beginPlain + 1 : endPlain]
3554 endlay = endlay - len(document.body[p : endInset + 1])
3556 del document.body[p : endInset + 1]
3557 subst += put_cmd_in_ert("}{") + content
3559 subst += put_cmd_in_ert("}{")
3561 document.body[j : j] = subst + document.body[j : j]
3565 def convert_captioninsets(document):
3566 " Converts caption insets to new syntax "
3570 i = find_token(document.body, "\\begin_inset Caption", i)
3573 document.body[i] = "\\begin_inset Caption Standard"
3577 def revert_captioninsets(document):
3578 " Reverts caption insets to old syntax "
3582 i = find_token(document.body, "\\begin_inset Caption Standard", i)
3585 document.body[i] = "\\begin_inset Caption"
3589 def convert_captionlayouts(document):
3590 " Convert caption layouts to caption insets. "
3593 "Captionabove": "Above",
3594 "Captionbelow": "Below",
3595 "FigCaption" : "FigCaption",
3596 "Table_Caption" : "Table",
3597 "CenteredCaption" : "Centered",
3598 "Bicaption" : "Bicaption",
3603 i = find_token(document.body, "\\begin_layout", i)
3606 val = get_value(document.body, "\\begin_layout", i)
3607 if val in caption_dict.keys():
3608 j = find_end_of_layout(document.body, i)
3610 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3613 document.body[j:j] = ["\\end_layout", "", "\\end_inset", "", ""]
3614 document.body[i:i+1] = ["\\begin_layout %s" % document.default_layout,
3615 "\\begin_inset Caption %s" % caption_dict[val], "",
3616 "\\begin_layout %s" % document.default_layout]
3620 def revert_captionlayouts(document):
3621 " Revert caption insets to caption layouts. "
3624 "Above" : "Captionabove",
3625 "Below" : "Captionbelow",
3626 "FigCaption" : "FigCaption",
3627 "Table" : "Table_Caption",
3628 "Centered" : "CenteredCaption",
3629 "Bicaption" : "Bicaption",
3633 rx = re.compile(r'^\\begin_inset Caption (\S+)$')
3635 i = find_token(document.body, "\\begin_inset Caption", i)
3639 m = rx.match(document.body[i])
3643 if val not in caption_dict.keys():
3647 # We either need to delete the previous \begin_layout line, or we
3648 # need to end the previous layout if this inset is not in the first
3649 # position of the paragraph.
3650 layout_before = find_token_backwards(document.body, "\\begin_layout", i)
3651 if layout_before == -1:
3652 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3654 layout_line = document.body[layout_before]
3655 del_layout_before = True
3656 l = layout_before + 1
3658 if document.body[l] != "":
3659 del_layout_before = False
3662 if del_layout_before:
3663 del document.body[layout_before:i]
3666 document.body[i:i] = ["\\end_layout", ""]
3669 # Find start of layout in the inset and end of inset
3670 j = find_token(document.body, "\\begin_layout", i)
3672 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3674 k = find_end_of_inset(document.body, i)
3676 document.warning("Malformed LyX document: Missing `\\end_inset'.")
3679 # We either need to delete the following \end_layout line, or we need
3680 # to restart the old layout if this inset is not at the paragraph end.
3681 layout_after = find_token(document.body, "\\end_layout", k)
3682 if layout_after == -1:
3683 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3685 del_layout_after = True
3687 while l < layout_after:
3688 if document.body[l] != "":
3689 del_layout_after = False
3692 if del_layout_after:
3693 del document.body[k+1:layout_after+1]
3695 document.body[k+1:k+1] = [layout_line, ""]
3697 # delete \begin_layout and \end_inset and replace \begin_inset with
3698 # "\begin_layout XXX". This works because we can only have one
3699 # paragraph in the caption inset: The old \end_layout will be recycled.
3700 del document.body[k]
3701 if document.body[k] == "":
3702 del document.body[k]
3703 del document.body[j]
3704 if document.body[j] == "":
3705 del document.body[j]
3706 document.body[i] = "\\begin_layout %s" % caption_dict[val]
3707 if document.body[i+1] == "":
3708 del document.body[i+1]
3712 def revert_fragileframe(document):
3713 " Reverts beamer FragileFrame layout to ERT "
3715 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3716 if document.textclass not in beamer_classes:
3721 i = find_token(document.body, "\\begin_layout FragileFrame", i)
3724 # Find end of sequence
3725 j = find_end_of_sequence(document.body, i)
3727 document.warning("Malformed LyX document. Cannot find end of FragileFrame sequence!")
3731 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{frame}")
3732 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{frame}")
3733 endseq = endseq + len(esubst) - len(document.body[j : j])
3734 if document.body[j] == "\\end_deeper":
3735 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3737 document.body[j : j] = esubst
3738 for q in range(i, j):
3739 if document.body[q] == "\\begin_layout FragileFrame":
3740 document.body[q] = "\\begin_layout %s" % document.default_layout
3743 if document.body[r] == "\\begin_deeper":
3744 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3746 document.body[r] = ""
3747 document.body[s] = ""
3751 for p in range(1, 5):
3752 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, j)
3755 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3756 endPlain = find_end_of_layout(document.body, beginPlain)
3757 endInset = find_end_of_inset(document.body, arg)
3758 content = document.body[beginPlain + 1 : endPlain]
3760 j = j - len(document.body[arg : endInset + 1])
3762 del document.body[arg : endInset + 1]
3763 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3765 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3766 endPlain = find_end_of_layout(document.body, beginPlain)
3767 endInset = find_end_of_inset(document.body, arg)
3768 content = document.body[beginPlain + 1 : endPlain]
3770 j = j - len(document.body[arg : endInset + 1])
3772 del document.body[arg : endInset + 1]
3773 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3775 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3776 endPlain = find_end_of_layout(document.body, beginPlain)
3777 endInset = find_end_of_inset(document.body, arg)
3778 content = document.body[beginPlain + 1 : endPlain]
3780 j = j - len(document.body[arg : endInset + 1])
3782 del document.body[arg : endInset + 1]
3783 subst += put_cmd_in_ert("[fragile,") + content + put_cmd_in_ert("]")
3785 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3786 endPlain = find_end_of_layout(document.body, beginPlain)
3787 endInset = find_end_of_inset(document.body, arg)
3788 content = document.body[beginPlain + 1 : endPlain]
3790 j = j - len(document.body[arg : endInset + 1])
3792 del document.body[arg : endInset + 1]
3793 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3795 subst += put_cmd_in_ert("[fragile]")
3797 document.body[i : i + 1] = subst
3801 def revert_newframes(document):
3802 " Reverts beamer Frame and PlainFrame layouts to old forms "
3804 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3805 if document.textclass not in beamer_classes:
3809 "Frame" : "BeginFrame",
3810 "PlainFrame" : "BeginPlainFrame",
3813 rx = re.compile(r'^\\begin_layout (\S+)$')
3816 i = find_token(document.body, "\\begin_layout", i)
3820 m = rx.match(document.body[i])
3824 if val not in frame_dict.keys():
3827 # Find end of sequence
3828 j = find_end_of_sequence(document.body, i)
3830 document.warning("Malformed LyX document. Cannot find end of Frame sequence!")
3834 subst = ["\\begin_layout %s" % frame_dict[val]]
3835 esubst = ["", "\\begin_layout EndFrame", "", "\\end_layout"]
3836 endseq = endseq + len(esubst) - len(document.body[j : j])
3837 if document.body[j] == "\\end_deeper":
3838 document.body[j : j] = esubst
3840 document.body[j+1 : j+1] = esubst
3841 for q in range(i, j):
3842 if document.body[q] == "\\begin_layout %s" % val:
3843 document.body[q] = "\\begin_layout %s" % document.default_layout
3846 if document.body[r] == "\\begin_deeper":
3847 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3849 document.body[r] = ""
3850 document.body[s] = ""
3854 l = find_end_of_layout(document.body, i)
3855 for p in range(1, 5):
3856 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, l)
3859 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3860 endPlain = find_end_of_layout(document.body, beginPlain)
3861 endInset = find_end_of_inset(document.body, arg)
3862 content = document.body[beginPlain + 1 : endPlain]
3864 l = l - len(document.body[arg : endInset + 1])
3866 del document.body[arg : endInset + 1]
3867 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3869 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3870 endPlain = find_end_of_layout(document.body, beginPlain)
3871 endInset = find_end_of_inset(document.body, arg)
3872 content = document.body[beginPlain + 1 : endPlain]
3874 l = l - len(document.body[arg : endInset + 1])
3876 del document.body[arg : endInset + 1]
3877 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3879 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3880 endPlain = find_end_of_layout(document.body, beginPlain)
3881 endInset = find_end_of_inset(document.body, arg)
3882 content = document.body[beginPlain + 1 : endPlain]
3884 l = l - len(document.body[arg : endInset + 1])
3886 del document.body[arg : endInset + 1]
3887 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3889 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3890 endPlain = find_end_of_layout(document.body, beginPlain)
3891 endInset = find_end_of_inset(document.body, arg)
3892 content = document.body[beginPlain + 1 : endPlain]
3894 l = l - len(document.body[arg : endInset + 1])
3896 del document.body[arg : endInset + 1]
3899 document.body[i : i + 1] = subst
3902 # known encodings that do not change their names (same LyX and LaTeX names)
3903 known_enc_tuple = ("auto", "default", "ansinew", "applemac", "armscii8", "ascii",
3904 "cp437", "cp437de", "cp850", "cp852", "cp855", "cp858", "cp862", "cp865", "cp866",
3905 "cp1250", "cp1251", "cp1252", "cp1255", "cp1256", "cp1257", "koi8-r", "koi8-u",
3906 "pt154", "pt254", "tis620-0", "utf8", "utf8x", "utf8-plain")
3908 def convert_encodings(document):
3909 "Use the LyX names of the encodings instead of the LaTeX names."
3910 LaTeX2LyX_enc_dict = {
3911 "8859-6": "iso8859-6",
3912 "8859-8": "iso8859-8",
3914 "euc": "euc-jp-platex",
3919 "iso88595": "iso8859-5",
3920 "iso-8859-7": "iso8859-7",
3922 "jis": "jis-platex",
3924 "l7xenc": "iso8859-13",
3925 "latin1": "iso8859-1",
3926 "latin2": "iso8859-2",
3927 "latin3": "iso8859-3",
3928 "latin4": "iso8859-4",
3929 "latin5": "iso8859-9",
3930 "latin9": "iso8859-15",
3931 "latin10": "iso8859-16",
3932 "SJIS": "shift-jis",
3933 "sjis": "shift-jis-platex",
3936 i = find_token(document.header, "\\inputencoding" , 0)
3939 val = get_value(document.header, "\\inputencoding", i)
3940 if val in LaTeX2LyX_enc_dict.keys():
3941 document.header[i] = "\\inputencoding %s" % LaTeX2LyX_enc_dict[val]
3942 elif val not in known_enc_tuple:
3943 document.warning("Ignoring unknown input encoding: `%s'" % val)
3946 def revert_encodings(document):
3947 """Revert to using the LaTeX names of the encodings instead of the LyX names.
3948 Also revert utf8-platex to sjis, the language default when using Japanese.
3950 LyX2LaTeX_enc_dict = {
3955 "euc-jp-platex": "euc",
3958 "iso8859-1": "latin1",
3959 "iso8859-2": "latin2",
3960 "iso8859-3": "latin3",
3961 "iso8859-4": "latin4",
3962 "iso8859-5": "iso88595",
3963 "iso8859-6": "8859-6",
3964 "iso8859-7": "iso-8859-7",
3965 "iso8859-8": "8859-8",
3966 "iso8859-9": "latin5",
3967 "iso8859-13": "l7xenc",
3968 "iso8859-15": "latin9",
3969 "iso8859-16": "latin10",
3971 "jis-platex": "jis",
3972 "shift-jis": "SJIS",
3973 "shift-jis-platex": "sjis",
3975 "utf8-platex": "sjis"
3977 i = find_token(document.header, "\\inputencoding" , 0)
3980 val = get_value(document.header, "\\inputencoding", i)
3981 if val in LyX2LaTeX_enc_dict.keys():
3982 document.header[i] = "\\inputencoding %s" % LyX2LaTeX_enc_dict[val]
3983 elif val not in known_enc_tuple:
3984 document.warning("Ignoring unknown input encoding: `%s'" % val)
3987 def revert_IEEEtran_3(document):
3989 Reverts Flex Insets to TeX-code
3991 if document.textclass == "IEEEtran":
3997 h = find_token(document.body, "\\begin_inset Flex Author Mark", h)
3999 endh = find_end_of_inset(document.body, h)
4000 document.body[endh - 2 : endh + 1] = put_cmd_in_ert("}")
4001 document.body[h : h + 4] = put_cmd_in_ert("\\IEEEauthorrefmark{")
4004 i = find_token(document.body, "\\begin_inset Flex Author Name", i)
4006 endi = find_end_of_inset(document.body, i)
4007 document.body[endi - 2 : endi + 1] = put_cmd_in_ert("}")
4008 document.body[i : i + 4] = put_cmd_in_ert("\\IEEEauthorblockN{")
4011 j = find_token(document.body, "\\begin_inset Flex Author Affiliation", j)
4013 endj = find_end_of_inset(document.body, j)
4014 document.body[endj - 2 : endj + 1] = put_cmd_in_ert("}")
4015 document.body[j : j + 4] = put_cmd_in_ert("\\IEEEauthorblockA{")
4017 if i == -1 and j == -1 and h == -1:
4021 def revert_kurier_fonts(document):
4022 " Revert kurier font definition to LaTeX "
4024 i = find_token(document.header, "\\font_math", 0)
4026 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4027 val = get_value(document.header, "\\font_math", i)
4028 if val == "kurier-math":
4029 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
4030 "\\usepackage[math]{kurier}\n" \
4031 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
4032 document.header[i] = "\\font_math auto"
4034 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4035 kurier_fonts = ["kurier", "kurierc", "kurierl", "kurierlc"]
4036 k = find_token(document.header, "\\font_sans kurier", 0)
4038 sf = get_value(document.header, "\\font_sans", k)
4039 if sf in kurier_fonts:
4040 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4041 document.header[k] = "\\font_sans default"
4043 def revert_iwona_fonts(document):
4044 " Revert iwona font definition to LaTeX "
4046 i = find_token(document.header, "\\font_math", 0)
4048 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4049 val = get_value(document.header, "\\font_math", i)
4050 if val == "iwona-math":
4051 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
4052 "\\usepackage[math]{iwona}\n" \
4053 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
4054 document.header[i] = "\\font_math auto"
4056 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4057 iwona_fonts = ["iwona", "iwonac", "iwonal", "iwonalc"]
4058 k = find_token(document.header, "\\font_sans iwona", 0)
4060 sf = get_value(document.header, "\\font_sans", k)
4061 if sf in iwona_fonts:
4062 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4063 document.header[k] = "\\font_sans default"
4066 def revert_new_libertines(document):
4067 " Revert new libertine font definition to LaTeX "
4069 if find_token(document.header, "\\use_non_tex_fonts true", 0) != -1:
4072 i = find_token(document.header, "\\font_typewriter libertine-mono", 0)
4074 preamble = "\\usepackage"
4075 sc = find_token(document.header, "\\font_tt_scale", 0)
4077 scval = get_value(document.header, "\\font_tt_scale", sc)
4079 preamble += "[scale=%f]" % (float(scval) / 100)
4080 document.header[sc] = "\\font_tt_scale 100"
4081 preamble += "{libertineMono-type1}"
4082 add_to_preamble(document, [preamble])
4083 document.header[i] = "\\font_typewriter default"
4085 k = find_token(document.header, "\\font_sans biolinum", 0)
4087 preamble = "\\usepackage"
4089 j = find_token(document.header, "\\font_osf true", 0)
4094 sc = find_token(document.header, "\\font_sf_scale", 0)
4096 scval = get_value(document.header, "\\font_sf_scale", sc)
4098 options += ",scale=%f" % (float(scval) / 100)
4099 document.header[sc] = "\\font_sf_scale 100"
4101 preamble += "[" + options +"]"
4102 preamble += "{biolinum-type1}"
4103 add_to_preamble(document, [preamble])
4104 document.header[k] = "\\font_sans default"
4107 def convert_lyxframes(document):
4108 " Converts old beamer frames to new style "
4110 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4111 if document.textclass not in beamer_classes:
4114 framebeg = ["BeginFrame", "BeginPlainFrame"]
4115 frameend = ["Frame", "PlainFrame", "EndFrame", "BeginFrame", "BeginPlainFrame", "AgainFrame",
4116 "Section", "Section*", "Subsection", "Subsection*", "Subsubsection", "Subsubsection*"]
4117 for lay in framebeg:
4120 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
4123 parent = get_containing_layout(document.body, i)
4124 if parent == False or parent[1] != i:
4125 document.warning("Wrong parent layout!")
4128 frametype = parent[0]
4132 # Step I: Convert ERT arguments
4133 # FIXME: See restrictions in convert_beamerframeargs method
4134 ertend = convert_beamerframeargs(document, i, parbeg)
4137 # Step II: Now rename the layout and convert the title to an argument
4138 j = find_end_of_layout(document.body, i)
4139 document.body[j : j + 1] = ['\\end_layout', '', '\\end_inset', '', '\\end_layout']
4140 if lay == "BeginFrame":
4141 document.body[i] = "\\begin_layout Frame"
4143 document.body[i] = "\\begin_layout PlainFrame"
4144 document.body[ertend + 1 : ertend + 1] = ['\\begin_inset Argument 4',
4145 'status open', '', '\\begin_layout Plain Layout']
4146 # Step III: find real frame end
4150 fend = find_token(document.body, "\\begin_layout", jj)
4152 document.warning("Malformed LyX document: No real frame end!")
4154 val = get_value(document.body, "\\begin_layout", fend)
4155 if val not in frameend:
4158 old = document.body[fend]
4159 if val == frametype:
4160 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4161 # consider explicit EndFrames between two identical frame types
4162 elif val == "EndFrame":
4163 nextlayout = find_token(document.body, "\\begin_layout", fend + 1)
4164 if nextlayout != -1 and get_value(document.body, "\\begin_layout", nextlayout) == frametype:
4165 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4167 document.body[fend : fend] = ['\\end_deeper']
4169 document.body[fend : fend] = ['\\end_deeper']
4170 document.body[j + 1 : j + 1] = ['', '\\begin_deeper']
4175 def remove_endframes(document):
4176 " Remove deprecated beamer endframes "
4178 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4179 if document.textclass not in beamer_classes:
4184 i = find_token_exact(document.body, "\\begin_layout EndFrame", i)
4187 j = find_end_of_layout(document.body, i)
4189 document.warning("Malformed LyX document: Missing \\end_layout to EndFrame")
4192 del document.body[i : j + 1]
4195 def revert_powerdot_flexes(document):
4196 " Reverts powerdot flex insets "
4198 if document.textclass != "powerdot":
4201 flexes = {"Onslide" : "\\onslide",
4202 "Onslide*" : "\\onslide*",
4203 "Onslide+" : "\\onslide+"}
4204 rx = re.compile(r'^\\begin_inset Flex (.+)$')
4208 i = find_token(document.body, "\\begin_inset Flex", i)
4211 m = rx.match(document.body[i])
4213 flextype = m.group(1)
4214 z = find_end_of_inset(document.body, i)
4216 document.warning("Can't find end of Flex " + flextype + " inset.")
4219 if flextype in flexes:
4220 pre = put_cmd_in_ert(flexes[flextype])
4221 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
4223 argend = find_end_of_inset(document.body, arg)
4225 document.warning("Can't find end of Argument!")
4228 # Find containing paragraph layout
4229 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
4230 endPlain = find_end_of_layout(document.body, beginPlain)
4231 argcontent = document.body[beginPlain + 1 : endPlain]
4233 z = z - len(document.body[arg : argend + 1])
4235 del document.body[arg : argend + 1]
4236 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
4237 pre += put_cmd_in_ert("{")
4238 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4239 endPlain = find_end_of_layout(document.body, beginPlain)
4241 z = z - len(document.body[i : beginPlain + 1])
4243 document.body[i : beginPlain + 1] = pre
4244 post = put_cmd_in_ert("}")
4245 document.body[z - 2 : z + 1] = post
4249 def revert_powerdot_pause(document):
4250 " Reverts powerdot pause layout to ERT "
4252 if document.textclass != "powerdot":
4257 i = find_token(document.body, "\\begin_layout Pause", i)
4260 j = find_end_of_layout(document.body, i)
4262 document.warning("Malformed LyX document: Can't find end of Pause layout")
4266 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\pause")
4267 for p in range(i, j):
4270 arg = find_token(document.body, "\\begin_inset Argument 1", i, j)
4272 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4273 endPlain = find_end_of_layout(document.body, beginPlain)
4274 endInset = find_end_of_inset(document.body, p)
4275 content = document.body[beginPlain + 1 : endPlain]
4277 endlay = endlay - len(document.body[p : endInset + 1])
4279 del document.body[p : endInset + 1]
4280 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4282 document.body[i : i + 1] = subst
4286 def revert_powerdot_itemargs(document):
4287 " Reverts powerdot item arguments to ERT "
4289 if document.textclass != "powerdot":
4293 list_layouts = ["Itemize", "ItemizeType1", "Enumerate", "EnumerateType1"]
4294 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4297 i = find_token(document.body, "\\begin_inset Argument", i)
4300 # Find containing paragraph layout
4301 parent = get_containing_layout(document.body, i)
4303 document.warning("Malformed LyX document: Can't find parent paragraph layout")
4308 realparbeg = parent[3]
4309 layoutname = parent[0]
4311 for p in range(parbeg, parend):
4315 if layoutname in list_layouts:
4316 m = rx.match(document.body[p])
4319 if argnr == "item:1":
4320 j = find_end_of_inset(document.body, i)
4321 # Find containing paragraph layout
4322 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4323 endPlain = find_end_of_layout(document.body, beginPlain)
4324 content = document.body[beginPlain + 1 : endPlain]
4325 del document.body[i:j+1]
4326 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4327 document.body[realparbeg : realparbeg] = subst
4328 elif argnr == "item:2":
4329 j = find_end_of_inset(document.body, i)
4330 # Find containing paragraph layout
4331 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4332 endPlain = find_end_of_layout(document.body, beginPlain)
4333 content = document.body[beginPlain + 1 : endPlain]
4334 del document.body[i:j+1]
4335 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
4336 document.body[realparbeg : realparbeg] = subst
4341 def revert_powerdot_columns(document):
4342 " Reverts powerdot twocolumn to TeX-code "
4343 if document.textclass != "powerdot":
4346 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4349 i = find_token(document.body, "\\begin_layout Twocolumn", i)
4352 j = find_end_of_layout(document.body, i)
4354 document.warning("Malformed LyX document: Can't find end of Twocolumn layout")
4358 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
4359 endlay += len(put_cmd_in_ert("}"))
4360 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\twocolumn")
4361 for p in range(i, j):
4364 m = rx.match(document.body[p])
4368 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4369 endPlain = find_end_of_layout(document.body, beginPlain)
4370 endInset = find_end_of_inset(document.body, p)
4371 content = document.body[beginPlain + 1 : endPlain]
4373 endlay = endlay - len(document.body[p : endInset + 1])
4375 del document.body[p : endInset + 1]
4376 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4378 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4379 endPlain = find_end_of_layout(document.body, beginPlain)
4380 endInset = find_end_of_inset(document.body, p)
4381 content = document.body[beginPlain + 1 : endPlain]
4383 endlay = endlay - len(document.body[p : endInset + 1])
4385 del document.body[p : endInset + 1]
4386 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
4388 subst += put_cmd_in_ert("{")
4389 document.body[i : i + 1] = subst
4393 def revert_mbox_fbox(document):
4394 'Convert revert mbox/fbox boxes to TeX-code'
4397 i = find_token(document.body, "\\begin_inset Box", i)
4400 j = find_token(document.body, "width", i)
4402 document.warning("Malformed LyX document: Can't find box width")
4404 width = get_value(document.body, "width", j)
4405 k = find_end_of_inset(document.body, j)
4407 document.warning("Malformed LyX document: Can't find end of box inset")
4410 BeginLayout = find_token(document.body, "\\begin_layout Plain Layout", j)
4411 EndLayout = find_end_of_layout(document.body, BeginLayout)
4412 # replace if width is ""
4414 document.body[EndLayout:k + 1] = put_cmd_in_ert("}")
4415 if document.body[i] == "\\begin_inset Box Frameless":
4416 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\mbox{")
4417 if document.body[i] == "\\begin_inset Box Boxed":
4418 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\fbox{")
4422 def revert_starred_caption(document):
4423 " Reverts unnumbered longtable caption insets "
4427 i = find_token(document.body, "\\begin_inset Caption LongTableNoNumber", i)
4430 # This is not equivalent, but since the caption inset is a full blown
4431 # text inset a true conversion to ERT is too difficult.
4432 document.body[i] = "\\begin_inset Caption Standard"
4436 def revert_forced_local_layout(document):
4439 i = find_token(document.header, "\\begin_forced_local_layout", i)
4442 j = find_end_of(document.header, i, "\\begin_forced_local_layout", "\\end_forced_local_layout")
4444 # this should not happen
4446 regexp = re.compile(r'\s*forcelocal', re.IGNORECASE)
4447 k = find_re(document.header, regexp, i, j)
4449 del document.header[k]
4451 k = find_re(document.header, regexp, i, j)
4452 k = find_token(document.header, "\\begin_local_layout", 0)
4454 document.header[i] = "\\begin_local_layout"
4455 document.header[j] = "\\end_local_layout"
4457 l = find_end_of(document.header, k, "\\begin_local_layout", "\\end_local_layout")
4459 # this should not happen
4461 lines = document.header[i+1 : j]
4463 document.header[k+1 : k+1] = lines
4464 document.header[i : j ] = []
4466 document.header[i : j ] = []
4467 document.header[k+1 : k+1] = lines
4470 def revert_aa1(document):
4471 " Reverts InsetArguments of aa to TeX-code "
4472 if document.textclass == "aa":
4476 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4478 revert_Argument_to_TeX_brace(document, i, 0, 1, 4, False, False)
4484 def revert_aa2(document):
4485 " Reverts InsetArguments of aa to TeX-code "
4486 if document.textclass == "aa":
4490 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4492 document.body[i] = "\\begin_layout Abstract"
4498 def revert_tibetan(document):
4499 "Set the document language for Tibetan to English"
4501 if document.language == "tibetan":
4502 document.language = "english"
4503 i = find_token(document.header, "\\language", 0)
4505 document.header[i] = "\\language english"
4507 while j < len(document.body):
4508 j = find_token(document.body, "\\lang tibetan", j)
4510 document.body[j] = document.body[j].replace("\\lang tibetan", "\\lang english")
4513 j = len(document.body)
4522 # The idea here is that we will have a sequence of chunk paragraphs.
4523 # We want to convert them to paragraphs in one or several chunk insets.
4524 # Individual chunks are terminated by the character @ on the last line.
4525 # This line will be discarded, and following lines are treated as new
4526 # chunks, which go into their own insets.
4527 # The first line of a chunk should look like: <<CONTENT>>=
4528 # We will discard the delimiters, and put the CONTENT into the
4529 # optional argument of the inset, if the CONTENT is non-empty.
4530 def convert_chunks(document):
4531 first_re = re.compile(r'<<(.*)>>=(.*)')
4534 # find start of a block of chunks
4535 i = find_token(document.body, "\\begin_layout Chunk", file_pos)
4541 chunk_started = False
4544 # process the one we just found
4545 j = find_end_of_layout(document.body, i)
4547 document.warning("Malformed LyX documents. Can't find end of Chunk layout!")
4548 # there is no point continuing, as we will run into the same error again.
4550 this_chunk = "".join(document.body[i + 1:j])
4552 # there may be empty lines between chunks
4553 # we just skip them.
4554 if not chunk_started:
4555 if this_chunk != "":
4557 chunk_started = True
4560 contents.append(document.body[i + 1:j])
4562 # look for potential chunk terminator
4563 # on the last line of the chunk paragraph
4564 if document.body[j - 1] == "@":
4567 # look for subsequent chunk paragraph
4568 i = find_token(document.body, "\\begin_layout", j)
4572 if get_value(document.body, "\\begin_layout", i) != "Chunk":
4575 file_pos = end = j + 1
4577 # The last chunk should simply have an "@" in it
4578 # or at least end with "@" (can happen if @ is
4579 # preceded by a newline)
4581 if len(contents) > 0:
4582 lastpar = ''.join(contents[-1])
4583 if not lastpar.endswith("@"):
4584 document.warning("Unexpected chunk content: chunk not terminated by '@'!")
4585 if len(contents) == 0:
4586 # convert empty chunk layouts to Standard
4587 document.body[start] = "\\begin_layout Standard"
4591 # chunk par only contains "@". Just drop it.
4594 # chunk par contains more. Only drop the "@".
4597 # The first line should look like: <<CONTENT>>=
4598 # We want the CONTENT
4599 optarg = ' '.join(contents[0])
4601 # We can already have real chunk content in
4602 # the first par (separated from the options by a newline).
4603 # We collect such stuff to re-insert it later.
4606 match = first_re.search(optarg)
4608 optarg = match.groups()[0]
4609 if match.groups()[1] != "":
4611 for c in contents[0]:
4612 if c.endswith(">>="):
4616 postoptstuff.append(c)
4617 # We have stripped everything. This can be deleted.
4620 newstuff = ['\\begin_layout Standard',
4621 '\\begin_inset Flex Chunk',
4623 '\\begin_layout Plain Layout', '']
4625 # If we have a non-empty optional argument, insert it.
4626 if match and optarg != "":
4628 ['\\begin_inset Argument 1',
4630 '\\begin_layout Plain Layout',
4635 # Since we already opened a Plain layout, the first paragraph
4636 # does not need to do that.
4639 # we need to replace newlines with new layouts
4641 started_text = False
4642 for lno in range(0,len(postoptstuff)):
4643 if postoptstuff[lno].startswith("\\begin_inset Newline newline"):
4645 elif start_newline != -1:
4646 if postoptstuff[lno].startswith("\\end_inset"):
4647 # replace that bit, but only if we already have some text
4648 # and we're not at the end except for a blank line
4649 if started_text and \
4650 (lno != len(postoptstuff) - 2 or postoptstuff[-1] != ""):
4651 newstuff.extend(['\\end_layout', '\n', '\\begin_layout Plain Layout', '\n'])
4655 newstuff.extend([postoptstuff[lno]])
4656 newstuff.append('\\end_layout')
4660 newstuff.extend(['', '\\begin_layout Plain Layout', ''])
4664 newstuff.append('\\end_layout')
4666 newstuff.extend(['', '\\end_inset', '', '\\end_layout', ''])
4668 document.body[start:end] = newstuff
4670 file_pos += len(newstuff) - (end - start)
4673 def revert_chunks(document):
4676 i = find_token(document.body, "\\begin_inset Flex Chunk", i)
4680 iend = find_end_of_inset(document.body, i)
4682 document.warning("Can't find end of Chunk!")
4686 # Look for optional argument
4688 ostart = find_token(document.body, "\\begin_inset Argument 1", i, iend)
4690 oend = find_end_of_inset(document.body, ostart)
4691 k = find_token(document.body, "\\begin_layout Plain Layout", ostart, oend)
4693 document.warning("Malformed LyX document: Can't find argument contents!")
4695 m = find_end_of_layout(document.body, k)
4696 optarg = "".join(document.body[k+1:m])
4699 # We now remove the optional argument, so we have something
4700 # uniform on which to work
4701 document.body[ostart : oend + 1] = []
4702 # iend is now invalid
4703 iend = find_end_of_inset(document.body, i)
4705 retval = get_containing_layout(document.body, i)
4707 document.warning("Can't find containing layout for Chunk!")
4710 (lname, lstart, lend, pstart) = retval
4711 # we now want to work through the various paragraphs, and collect their contents
4715 k = find_token(document.body, "\\begin_layout Plain Layout", k, lend)
4718 j = find_end_of_layout(document.body, k)
4720 document.warning("Can't find end of layout inside chunk!")
4722 parlist.append(document.body[k+1:j])
4724 # we now need to wrap all of these paragraphs in chunks
4727 newlines.extend(["\\begin_layout Chunk", "", "<<" + optarg + ">>=", "\\end_layout", ""])
4728 for stuff in parlist:
4729 newlines.extend(["\\begin_layout Chunk"] + stuff + ["\\end_layout", ""])
4730 newlines.extend(["\\begin_layout Chunk", "", "@", "\\end_layout", ""])
4731 # replace old content with new content
4732 document.body[lstart : lend + 1] = newlines
4733 i = lstart + len(newlines)
4740 supported_versions = ["2.1.0","2.1"]
4743 [415, [convert_undertilde]],
4745 [417, [convert_japanese_encodings]],
4746 [418, [convert_justification]],
4748 [420, [convert_biblio_style]],
4749 [421, [convert_longtable_captions]],
4750 [422, [convert_use_packages]],
4751 [423, [convert_use_mathtools]],
4752 [424, [convert_cite_engine_type]],
4753 # No convert_cancel, since cancel will be loaded automatically
4754 # in format 425 without any possibility to switch it off.
4755 # This has been fixed in format 464.
4759 [428, [convert_cell_rotation]],
4760 [429, [convert_table_rotation]],
4761 [430, [convert_listoflistings]],
4762 [431, [convert_use_amssymb]],
4764 [433, [convert_armenian]],
4772 [441, [convert_mdnomath]],
4777 [446, [convert_latexargs]],
4778 [447, [convert_IEEEtran, convert_AASTeX, convert_AGUTeX, convert_IJMP, convert_SIGPLAN, convert_SIGGRAPH, convert_EuropeCV, convert_Initials, convert_ModernCV]],
4779 [448, [convert_literate]],
4782 [451, [convert_beamerargs, convert_againframe_args, convert_corollary_args, convert_quote_args]],
4783 [452, [convert_beamerblocks]],
4784 [453, [convert_use_stmaryrd]],
4785 [454, [convert_overprint]],
4787 [456, [convert_epigraph]],
4788 [457, [convert_use_stackrel]],
4789 [458, [convert_captioninsets, convert_captionlayouts]],
4794 [463, [convert_encodings]],
4795 [464, [convert_use_cancel]],
4796 [465, [convert_lyxframes, remove_endframes]],
4802 [471, [convert_cite_engine_type_default]],
4805 [474, [convert_chunks, cleanup_beamerargs]],
4809 [473, [revert_chunks]],
4810 [472, [revert_tibetan]],
4811 [471, [revert_aa1,revert_aa2]],
4812 [470, [revert_cite_engine_type_default]],
4813 [469, [revert_forced_local_layout]],
4814 [468, [revert_starred_caption]],
4815 [467, [revert_mbox_fbox]],
4816 [466, [revert_iwona_fonts]],
4817 [465, [revert_powerdot_flexes, revert_powerdot_pause, revert_powerdot_itemargs, revert_powerdot_columns]],
4819 [463, [revert_use_cancel]],
4820 [462, [revert_encodings]],
4821 [461, [revert_new_libertines]],
4822 [460, [revert_kurier_fonts]],
4823 [459, [revert_IEEEtran_3]],
4824 [458, [revert_fragileframe, revert_newframes]],
4825 [457, [revert_captioninsets, revert_captionlayouts]],
4826 [456, [revert_use_stackrel]],
4827 [455, [revert_epigraph]],
4828 [454, [revert_frametitle]],
4829 [453, [revert_overprint]],
4830 [452, [revert_use_stmaryrd]],
4831 [451, [revert_beamerblocks]],
4832 [450, [revert_beamerargs, revert_beamerargs2, revert_beamerargs3, revert_beamerflex]],
4833 [449, [revert_garamondx, revert_garamondx_newtxmath]],
4834 [448, [revert_itemargs]],
4835 [447, [revert_literate]],
4836 [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]],
4837 [445, [revert_latexargs]],
4838 [444, [revert_uop]],
4839 [443, [revert_biolinum]],
4841 [441, [revert_newtxmath]],
4842 [440, [revert_mdnomath]],
4843 [439, [revert_mathfonts]],
4844 [438, [revert_minionpro]],
4845 [437, [revert_ipadeco, revert_ipachar]],
4846 [436, [revert_texgyre]],
4847 [435, [revert_mathdesign]],
4848 [434, [revert_txtt]],
4849 [433, [revert_libertine]],
4850 [432, [revert_armenian]],
4851 [431, [revert_languages, revert_ancientgreek]],
4852 [430, [revert_use_amssymb]],
4853 [429, [revert_listoflistings]],
4854 [428, [revert_table_rotation]],
4855 [427, [revert_cell_rotation]],
4856 [426, [revert_tipa]],
4857 [425, [revert_verbatim]],
4858 [424, [revert_cancel]],
4859 [423, [revert_cite_engine_type]],
4860 [422, [revert_use_mathtools]],
4861 [421, [revert_use_packages]],
4862 [420, [revert_longtable_captions]],
4863 [419, [revert_biblio_style]],
4864 [418, [revert_australian]],
4865 [417, [revert_justification]],
4866 [416, [revert_japanese_encodings]],
4867 [415, [revert_negative_space, revert_math_spaces]],
4868 [414, [revert_undertilde]],
4869 [413, [revert_visible_space]]
4873 if __name__ == "__main__":