1 # -*- coding: utf-8 -*-
2 # This file is part of lyx2lyx
3 # -*- coding: utf-8 -*-
4 # Copyright (C) 2011 The LyX team
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 """ Convert files to the file format generated by LyX 2.1"""
26 # Uncomment only what you need to import, please.
28 from parser_tools import count_pars_in_inset, del_token, find_token, find_token_exact, \
29 find_token_backwards, find_end_of, find_end_of_inset, find_end_of_layout, \
30 find_end_of_sequence, find_re, get_option_value, get_containing_layout, \
31 get_value, get_quoted_value, set_option_value
33 #from parser_tools import find_token, find_end_of, find_tokens, \
34 #find_end_of_inset, find_end_of_layout, \
35 #is_in_inset, del_token, check_token
37 from lyx2lyx_tools import add_to_preamble, put_cmd_in_ert, get_ert
39 #from lyx2lyx_tools import insert_to_preamble, \
40 # lyx2latex, latex_length, revert_flex_inset, \
41 # revert_font_attrs, hex2ratio, str2bool
43 ####################################################################
44 # Private helper functions
46 #def remove_option(lines, m, option):
47 #''' removes option from line m. returns whether we did anything '''
48 #l = lines[m].find(option)
51 #val = lines[m][l:].split('"')[1]
52 #lines[m] = lines[m][:l - 1] + lines[m][l+len(option + '="' + val + '"'):]
56 def revert_Argument_to_TeX_brace(document, line, endline, n, nmax, environment, opt):
58 Reverts an InsetArgument to TeX-code
60 revert_Argument_to_TeX_brace(document, LineOfBegin, LineOfEnd, StartArgument, EndArgument, isEnvironment, isOpt)
61 LineOfBegin is the line of the \begin_layout or \begin_inset statement
62 LineOfEnd is the line of the \end_layout or \end_inset statement, if "0" is given, the end of the file is used instead
63 StartArgument is the number of the first argument that needs to be converted
64 EndArgument is the number of the last argument that needs to be converted or the last defined one
65 isEnvironment must be true, if the layout is for a LaTeX environment
66 isOpt must be true, if the argument is an optional one
70 while lineArg != -1 and n < nmax + 1:
71 lineArg = find_token(document.body, "\\begin_inset Argument " + str(n), line)
72 if lineArg > endline and endline != 0:
75 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", lineArg)
76 # we have to assure that no other inset is in the Argument
77 beginInset = find_token(document.body, "\\begin_inset", beginPlain)
78 endInset = find_token(document.body, "\\end_inset", beginPlain)
81 while beginInset < endInset and beginInset != -1:
82 beginInset = find_token(document.body, "\\begin_inset", k)
83 endInset = find_token(document.body, "\\end_inset", l)
86 if environment == False:
88 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}{")
89 del(document.body[lineArg : beginPlain + 1])
92 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("]")
93 document.body[lineArg : beginPlain + 1] = put_cmd_in_ert("[")
96 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}")
97 document.body[lineArg : beginPlain + 1] = put_cmd_in_ert("{")
103 def convert_TeX_brace_to_Argument(document, line, n, nmax, inset, environment, opt):
105 Converts TeX code for mandatory arguments to an InsetArgument
106 The conversion of TeX code for optional arguments must be done with another routine
107 !!! Be careful if the braces are different in your case as expected here:
108 - "}{" separates mandatory arguments of commands
109 - "}" + "{" separates mandatory arguments of commands
110 - "}" + " " + "{" separates mandatory arguments of commands
111 - { and } surround a mandatory argument of an environment
113 convert_TeX_brace_to_Argument(document, LineOfBeginLayout/Inset, StartArgument, EndArgument, isInset, isEnvironment, isOpt)
114 LineOfBeginLayout/Inset is the line of the \begin_layout or \begin_inset statement
115 StartArgument is the number of the first ERT that needs to be converted
116 EndArgument is the number of the last ERT that needs to be converted
117 isInset must be true, if braces inside an InsetLayout needs to be converted
118 isEnvironment must be true, if the layout is for a LaTeX environment
119 isOpt must be true, if the argument is an optional one
121 Todo: this routine can currently handle only one mandatory argument of environments
124 end_layout = find_end_of_layout(document.body, line)
129 lineERT = find_token(document.body, "\\begin_inset ERT", lineERT, end_layout)
132 if environment == False:
133 end_ERT = find_end_of_inset(document.body, lineERT)
135 document.warning("Can't find end of ERT!!")
137 # Note that this only checks for ][ or }{ at the beginning of a line
139 bracePair = find_token(document.body, "][", lineERT, end_ERT)
141 bracePair = find_token(document.body, "}{", lineERT, end_ERT)
143 end = find_token(document.body, "\\end_inset", bracePair)
144 document.body[lineERT : end_ERT + 1] = ["\\end_layout", "", "\\end_inset"]
146 # in the case that n > 1 we have optional arguments before
147 # therefore detect them if any
149 # first check if there is an argument
150 lineArg = find_token(document.body, "\\begin_inset Argument", line)
151 if lineArg < lineERT and lineArg != -1:
152 # we have an argument, so now search backwards for its end
153 # we must now assure that we don't find other insets like e.g. a newline
154 endInsetArg = lineERT
155 endLayoutArg = endInsetArg
156 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
157 endInsetArg = endInsetArg - 1
158 endLayoutArg = endInsetArg
159 endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
160 endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
161 line = endInsetArg + 1
163 document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
165 document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
167 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
172 # no brace pair found
173 # now check the case that we have "}" + "{" in two ERTs
175 endBrace = find_token(document.body, "]", lineERT, end_layout)
177 endBrace = find_token(document.body, "}", lineERT, end_layout)
178 if endBrace == lineERT + 5:
180 beginBrace = find_token(document.body, "[", endBrace, end_layout)
182 beginBrace = find_token(document.body, "{", endBrace, end_layout)
183 # assure that the ERTs are consecutive (11 or 12 depending if there is a space between the ERTs or not)
184 if beginBrace == endBrace + 11 or beginBrace == endBrace + 12:
185 end = find_token(document.body, "\\end_inset", beginBrace)
186 document.body[lineERT : end + 1] = ["\\end_layout", "", "\\end_inset"]
188 # in the case that n > 1 we have optional arguments before
189 # therefore detect them if any
191 # first check if there is an argument
192 lineArg = find_token(document.body, "\\begin_inset Argument", line)
193 if lineArg < lineERT and lineArg != -1:
194 # we have an argument, so now search backwards for its end
195 # we must now assure that we don't find other insets like e.g. a newline
196 endInsetArg = lineERT
197 endLayoutArg = endInsetArg
198 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
199 endInsetArg = endInsetArg - 1
200 endLayoutArg = endInsetArg
201 endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
202 endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
203 line = endInsetArg + 1
205 document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
207 document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
209 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
212 # set the line where the next argument will be inserted
213 if beginBrace == endBrace + 11:
221 if environment == True:
222 end_ERT = find_end_of_inset(document.body, lineERT)
224 document.warning("Can't find end of ERT!!")
226 # Note that this only checks for [ or { at the beginning of a line
228 opening = find_token(document.body, "[", lineERT, end_ERT)
230 opening = find_token(document.body, "{", lineERT, end_ERT)
232 document.body[lineERT : end_ERT + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
234 lineERT2 = find_token(document.body, "\\begin_inset ERT", end_ERT, end_layout)
236 end_ERT2 = find_end_of_inset(document.body, lineERT2)
238 document.warning("Can't find end of second ERT!!")
241 closing = find_token(document.body, "]", lineERT2, end_ERT2)
243 closing = find_token(document.body, "}", lineERT2, end_ERT2)
244 if closing != -1: # assure that the "}" is in this ERT
245 end2 = find_token(document.body, "\\end_inset", closing)
246 document.body[lineERT2 : end2 + 1] = ["\\end_layout", "", "\\end_inset"]
249 ###############################################################################
251 ### Conversion and reversion routines
253 ###############################################################################
255 def revert_visible_space(document):
256 "Revert InsetSpace visible into its ERT counterpart"
259 i = find_token(document.body, "\\begin_inset space \\textvisiblespace{}", i)
262 end = find_end_of_inset(document.body, i)
263 subst = put_cmd_in_ert("\\textvisiblespace{}")
264 document.body[i:end + 1] = subst
267 undertilde_commands = ["utilde"]
268 def convert_undertilde(document):
269 " Load undertilde automatically "
270 i = find_token(document.header, "\\use_mathdots" , 0)
272 i = find_token(document.header, "\\use_mhchem" , 0)
274 i = find_token(document.header, "\\use_esint" , 0)
276 document.warning("Malformed LyX document: Can't find \\use_mathdots.")
278 j = find_token(document.preamble, "\\usepackage{undertilde}", 0)
280 # package was loaded in the preamble, convert this to header setting for round trip
281 document.header.insert(i + 1, "\\use_undertilde 2") # on
282 del document.preamble[j]
286 j = find_token(document.body, '\\begin_inset Formula', j)
289 k = find_end_of_inset(document.body, j)
291 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(j))
294 code = "\n".join(document.body[j:k])
295 for c in undertilde_commands:
296 if code.find("\\%s" % c) != -1:
297 # at least one of the commands was found - need to switch package off
298 document.header.insert(i + 1, "\\use_undertilde 0") # off
301 # no command was found - set to auto (bug 9069)
302 document.header.insert(i + 1, "\\use_undertilde 1") # auto
306 def revert_undertilde(document):
307 " Load undertilde if used in the document "
308 regexp = re.compile(r'(\\use_undertilde)')
309 i = find_re(document.header, regexp, 0)
310 value = "1" # default is auto
312 value = get_value(document.header, "\\use_undertilde" , i).split()[0]
313 del document.header[i]
314 if value == "2": # on
315 add_to_preamble(document, ["\\usepackage{undertilde}"])
316 elif value == "1": # auto
319 i = find_token(document.body, '\\begin_inset Formula', i)
322 j = find_end_of_inset(document.body, i)
324 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
327 code = "\n".join(document.body[i:j])
328 for c in undertilde_commands:
329 if code.find("\\%s" % c) != -1:
330 add_to_preamble(document, ["\\usepackage{undertilde}"])
335 def revert_negative_space(document):
336 "Revert InsetSpace negmedspace and negthickspace into its TeX-code counterpart"
341 i = find_token(document.body, "\\begin_inset space \\negmedspace{}", i)
343 j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
345 # load amsmath in the preamble if not already loaded if we are at the end of checking
347 i = find_token(document.header, "\\use_amsmath 2", 0)
349 add_to_preamble(document, ["\\@ifundefined{negthickspace}{\\usepackage{amsmath}}"])
353 end = find_end_of_inset(document.body, i)
354 subst = put_cmd_in_ert("\\negmedspace{}")
355 document.body[i:end + 1] = subst
356 j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
359 end = find_end_of_inset(document.body, j)
360 subst = put_cmd_in_ert("\\negthickspace{}")
361 document.body[j:end + 1] = subst
365 def revert_math_spaces(document):
366 "Revert formulas with protected custom space and protected hfills to TeX-code"
369 i = find_token(document.body, "\\begin_inset Formula", i)
372 j = document.body[i].find("\\hspace*")
374 end = find_end_of_inset(document.body, i)
375 subst = put_cmd_in_ert(document.body[i][21:])
376 document.body[i:end + 1] = subst
380 def convert_japanese_encodings(document):
381 " Rename the japanese encodings to names understood by platex "
383 "EUC-JP-pLaTeX": "euc",
385 "SJIS-pLaTeX": "sjis"
387 i = find_token(document.header, "\\inputencoding" , 0)
390 val = get_value(document.header, "\\inputencoding", i)
391 if val in jap_enc_dict.keys():
392 document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
395 def revert_japanese_encodings(document):
396 " Revert the japanese encodings name changes "
398 "euc": "EUC-JP-pLaTeX",
400 "sjis": "SJIS-pLaTeX"
402 i = find_token(document.header, "\\inputencoding" , 0)
405 val = get_value(document.header, "\\inputencoding", i)
406 if val in jap_enc_dict.keys():
407 document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
410 def convert_justification(document):
411 " Add the \\justification buffer param"
412 i = find_token(document.header, "\\suppress_date" , 0)
414 i = find_token(document.header, "\\paperorientation" , 0)
416 i = find_token(document.header, "\\use_indices" , 0)
418 i = find_token(document.header, "\\use_bibtopic" , 0)
420 document.warning("Malformed LyX document: Missing \\suppress_date.")
422 document.header.insert(i + 1, "\\justification true")
425 def revert_justification(document):
426 " Revert the \\justification buffer param"
427 if not del_token(document.header, '\\justification', 0):
428 document.warning("Malformed LyX document: Missing \\justification.")
431 def revert_australian(document):
432 "Set English language variants Australian and Newzealand to English"
434 if document.language == "australian" or document.language == "newzealand":
435 document.language = "english"
436 i = find_token(document.header, "\\language", 0)
438 document.header[i] = "\\language english"
441 j = find_token(document.body, "\\lang australian", j)
443 j = find_token(document.body, "\\lang newzealand", 0)
447 document.body[j] = document.body[j].replace("\\lang newzealand", "\\lang english")
449 document.body[j] = document.body[j].replace("\\lang australian", "\\lang english")
453 def convert_biblio_style(document):
454 "Add a sensible default for \\biblio_style based on the citation engine."
455 i = find_token(document.header, "\\cite_engine", 0)
457 engine = get_value(document.header, "\\cite_engine", i).split("_")[0]
458 style = {"basic": "plain", "natbib": "plainnat", "jurabib": "jurabib"}
459 document.header.insert(i + 1, "\\biblio_style " + style[engine])
462 def revert_biblio_style(document):
463 "BibTeX insets with default option use the style defined by \\biblio_style."
464 i = find_token(document.header, "\\biblio_style" , 0)
466 document.warning("No \\biblio_style line. Nothing to do.")
469 default_style = get_value(document.header, "\\biblio_style", i)
470 del document.header[i]
472 # We are looking for bibtex insets having the default option
475 i = find_token(document.body, "\\begin_inset CommandInset bibtex", i)
478 j = find_end_of_inset(document.body, i)
480 document.warning("Malformed LyX document: Can't find end of bibtex inset at line " + str(i))
483 k = find_token(document.body, "options", i, j)
485 options = get_quoted_value(document.body, "options", k)
486 if "default" in options.split(","):
487 document.body[k] = 'options "%s"' \
488 % options.replace("default", default_style)
492 def handle_longtable_captions(document, forward):
495 begin_table = find_token(document.body, '<lyxtabular version=', begin_table)
496 if begin_table == -1:
498 end_table = find_end_of(document.body, begin_table, '<lyxtabular', '</lyxtabular>')
500 document.warning("Malformed LyX document: Could not find end of table.")
503 fline = find_token(document.body, "<features", begin_table, end_table)
505 document.warning("Can't find features for inset at line " + str(begin_table))
508 p = document.body[fline].find("islongtable")
513 numrows = get_option_value(document.body[begin_table], "rows")
515 numrows = int(numrows)
517 document.warning(document.body[begin_table])
518 document.warning("Unable to determine rows!")
519 begin_table = end_table
521 begin_row = begin_table
522 for row in range(numrows):
523 begin_row = find_token(document.body, '<row', begin_row, end_table)
525 document.warning("Can't find row " + str(row + 1))
527 end_row = find_end_of(document.body, begin_row, '<row', '</row>')
529 document.warning("Can't find end of row " + str(row + 1))
532 if (get_option_value(document.body[begin_row], 'caption') == 'true' and
533 get_option_value(document.body[begin_row], 'endfirsthead') != 'true' and
534 get_option_value(document.body[begin_row], 'endhead') != 'true' and
535 get_option_value(document.body[begin_row], 'endfoot') != 'true' and
536 get_option_value(document.body[begin_row], 'endlastfoot') != 'true'):
537 document.body[begin_row] = set_option_value(document.body[begin_row], 'caption', 'true", endfirsthead="true')
538 elif get_option_value(document.body[begin_row], 'caption') == 'true':
539 if get_option_value(document.body[begin_row], 'endfirsthead') == 'true':
540 document.body[begin_row] = set_option_value(document.body[begin_row], 'endfirsthead', 'false')
541 if get_option_value(document.body[begin_row], 'endhead') == 'true':
542 document.body[begin_row] = set_option_value(document.body[begin_row], 'endhead', 'false')
543 if get_option_value(document.body[begin_row], 'endfoot') == 'true':
544 document.body[begin_row] = set_option_value(document.body[begin_row], 'endfoot', 'false')
545 if get_option_value(document.body[begin_row], 'endlastfoot') == 'true':
546 document.body[begin_row] = set_option_value(document.body[begin_row], 'endlastfoot', 'false')
548 # since there could be a tabular inside this one, we
549 # cannot jump to end.
553 def convert_longtable_captions(document):
554 "Add a firsthead flag to caption rows"
555 handle_longtable_captions(document, True)
558 def revert_longtable_captions(document):
559 "remove head/foot flag from caption rows"
560 handle_longtable_captions(document, False)
563 def convert_use_packages(document):
564 "use_xxx yyy => use_package xxx yyy"
565 packages = ["amsmath", "esint", "mathdots", "mhchem", "undertilde"]
567 i = find_token(document.header, "\\use_%s" % p, 0)
569 value = get_value(document.header, "\\use_%s" % p, i)
570 document.header[i] = "\\use_package %s %s" % (p, value)
573 def revert_use_packages(document):
574 "use_package xxx yyy => use_xxx yyy"
575 packages = ["amsmath", "esint", "mhchem", "mathdots", "undertilde"]
576 # the order is arbitrary for the use_package version, and not all packages need to be given.
577 # Ensure a complete list and correct order (important for older LyX versions and especially lyx2lyx)
578 # first loop: find line with first package
581 regexp = re.compile(r'(\\use_package\s+%s)' % p)
582 i = find_re(document.header, regexp, 0)
583 if i != -1 and (j < 0 or i < j):
585 # second loop: replace or insert packages in front of all existing ones
587 regexp = re.compile(r'(\\use_package\s+%s)' % p)
588 i = find_re(document.header, regexp, 0)
590 value = get_value(document.header, "\\use_package %s" % p, i).split()[1]
591 del document.header[i]
592 document.header.insert(j, "\\use_%s %s" % (p, value))
594 document.header.insert(j, "\\use_%s 1" % p)
598 def convert_use_package(document, pkg, commands, oldauto):
599 # oldauto defines how the version we are converting from behaves:
600 # if it is true, the old version uses the package automatically.
601 # if it is false, the old version never uses the package.
602 i = find_token(document.header, "\\use_package", 0)
604 document.warning("Malformed LyX document: Can't find \\use_package.")
606 j = find_token(document.preamble, "\\usepackage{" + pkg + "}", 0)
608 # package was loaded in the preamble, convert this to header setting for round trip
609 document.header.insert(i + 1, "\\use_package " + pkg + " 2") # on
610 del document.preamble[j]
611 # If oldauto is true we have two options:
612 # We can either set the package to auto - this is correct for files in
613 # format 425 to 463, and may create a conflict for older files which use
614 # any command in commands with a different definition.
615 # Or we can look whether any command in commands is used, and set it to
616 # auto if not and to off if yes. This will not create a conflict, but will
617 # create uncompilable documents for files in format 425 to 463, which use
618 # any command in commands.
619 # We choose the first option since its error is less likely.
621 document.header.insert(i + 1, "\\use_package " + pkg + " 1") # auto
625 j = find_token(document.body, '\\begin_inset Formula', j)
628 k = find_end_of_inset(document.body, j)
630 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(j))
633 code = "\n".join(document.body[j:k])
635 if code.find("\\%s" % c) != -1:
636 # at least one of the commands was found - need to switch package off
637 document.header.insert(i + 1, "\\use_package " + pkg + " 0") # off
640 # no command was found - set to auto (bug 9069)
641 document.header.insert(i + 1, "\\use_package " + pkg + " 1") # auto
644 def revert_use_package(document, pkg, commands, oldauto):
645 # oldauto defines how the version we are reverting to behaves:
646 # if it is true, the old version uses the package automatically.
647 # if it is false, the old version never uses the package.
648 regexp = re.compile(r'(\\use_package\s+%s)' % pkg)
649 i = find_re(document.header, regexp, 0)
650 value = "1" # default is auto
652 value = get_value(document.header, "\\use_package" , i).split()[1]
653 del document.header[i]
654 if value == "2": # on
655 add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
656 elif value == "1" and not oldauto: # auto
659 i = find_token(document.body, '\\begin_inset Formula', i)
662 j = find_end_of_inset(document.body, i)
664 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
667 code = "\n".join(document.body[i:j])
669 if code.find("\\%s" % c) != -1:
670 add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
675 mathtools_commands = ["mathclap", "mathllap", "mathrlap", \
676 "lgathered", "rgathered", "vcentcolon", "dblcolon", \
677 "coloneqq", "Coloneqq", "coloneq", "Coloneq", "eqqcolon", \
678 "Eqqcolon", "eqcolon", "Eqcolon", "colonapprox", \
679 "Colonapprox", "colonsim", "Colonsim"]
680 def convert_use_mathtools(document):
681 "insert use_package mathtools"
682 convert_use_package(document, "mathtools", mathtools_commands, False)
685 def revert_use_mathtools(document):
686 "remove use_package mathtools"
687 revert_use_package(document, "mathtools", mathtools_commands, False)
690 # commands provided by stmaryrd.sty but LyX uses other packages:
691 # boxdot lightning, bigtriangledown, bigtriangleup
692 stmaryrd_commands = ["shortleftarrow", "shortrightarrow", "shortuparrow", \
693 "shortdownarrow", "Yup", "Ydown", "Yleft", "Yright", \
694 "varcurlyvee", "varcurlywedge", "minuso", "baro", \
695 "sslash", "bbslash", "moo", "varotimes", "varoast", \
696 "varobar", "varodot", "varoslash", "varobslash", \
697 "varocircle", "varoplus", "varominus", "boxast", \
698 "boxbar", "boxslash", "boxbslash", "boxcircle", \
699 "boxbox", "boxempty", "merge", "vartimes", \
700 "fatsemi", "sswarrow", "ssearrow", "curlywedgeuparrow", \
701 "curlywedgedownarrow", "fatslash", "fatbslash", "lbag", \
702 "rbag", "varbigcirc", "leftrightarroweq", \
703 "curlyveedownarrow", "curlyveeuparrow", "nnwarrow", \
704 "nnearrow", "leftslice", "rightslice", "varolessthan", \
705 "varogreaterthan", "varovee", "varowedge", "talloblong", \
706 "interleave", "obar", "obslash", "olessthan", \
707 "ogreaterthan", "ovee", "owedge", "oblong", "inplus", \
708 "niplus", "nplus", "subsetplus", "supsetplus", \
709 "subsetpluseq", "supsetpluseq", "Lbag", "Rbag", \
710 "llbracket", "rrbracket", "llparenthesis", \
711 "rrparenthesis", "binampersand", "bindnasrepma", \
712 "trianglelefteqslant", "trianglerighteqslant", \
713 "ntrianglelefteqslant", "ntrianglerighteqslant", \
714 "llfloor", "rrfloor", "llceil", "rrceil", "arrownot", \
715 "Arrownot", "Mapstochar", "mapsfromchar", "Mapsfromchar", \
716 "leftrightarrowtriangle", "leftarrowtriangle", \
717 "rightarrowtriangle", \
718 "bigcurlyvee", "bigcurlywedge", "bigsqcap", "bigbox", \
719 "bigparallel", "biginterleave", "bignplus", \
720 "varcopyright", "longarrownot", "Longarrownot", \
721 "Mapsto", "mapsfrom", "Mapsfrom" "Longmapsto", \
722 "longmapsfrom", "Longmapsfrom"]
723 def convert_use_stmaryrd(document):
724 "insert use_package stmaryrd"
725 convert_use_package(document, "stmaryrd", stmaryrd_commands, False)
728 def revert_use_stmaryrd(document):
729 "remove use_package stmaryrd"
730 revert_use_package(document, "stmaryrd", stmaryrd_commands, False)
733 stackrel_commands = ["stackrel"]
734 def convert_use_stackrel(document):
735 "insert use_package stackrel"
736 convert_use_package(document, "stackrel", stackrel_commands, False)
739 def revert_use_stackrel(document):
740 "remove use_package stackrel"
741 revert_use_package(document, "stackrel", stackrel_commands, False)
744 def convert_cite_engine_type(document):
745 "Determine the \\cite_engine_type from the citation engine."
746 i = find_token(document.header, "\\cite_engine", 0)
749 engine = get_value(document.header, "\\cite_engine", i)
751 engine, type = engine.split("_")
753 type = {"basic": "numerical", "jurabib": "authoryear"}[engine]
754 document.header[i] = "\\cite_engine " + engine
755 document.header.insert(i + 1, "\\cite_engine_type " + type)
758 def revert_cite_engine_type(document):
759 "Natbib had the type appended with an underscore."
760 engine_type = "numerical"
761 i = find_token(document.header, "\\cite_engine_type" , 0)
763 document.warning("No \\cite_engine_type line. Assuming numerical.")
765 engine_type = get_value(document.header, "\\cite_engine_type", i)
766 del document.header[i]
768 # We are looking for the natbib citation engine
769 i = find_token(document.header, "\\cite_engine natbib", 0)
772 document.header[i] = "\\cite_engine natbib_" + engine_type
775 def convert_cite_engine_type_default(document):
776 "Convert \\cite_engine_type to default for the basic citation engine."
777 i = find_token(document.header, "\\cite_engine basic", 0)
780 i = find_token(document.header, "\\cite_engine_type" , 0)
783 document.header[i] = "\\cite_engine_type default"
786 def revert_cite_engine_type_default(document):
787 """Revert \\cite_engine_type default.
789 Revert to numerical for the basic cite engine, otherwise to authoryear."""
790 engine_type = "authoryear"
791 i = find_token(document.header, "\\cite_engine_type default" , 0)
794 j = find_token(document.header, "\\cite_engine basic", 0)
796 engine_type = "numerical"
797 document.header[i] = "\\cite_engine_type " + engine_type
800 cancel_commands = ["cancel", "bcancel", "xcancel", "cancelto"]
801 # this is the same, as revert_use_cancel() except for the default
802 def revert_cancel(document):
803 "add cancel to the preamble if necessary"
804 revert_use_package(document, "cancel", cancel_commands, False)
807 def revert_verbatim(document):
808 " Revert verbatim einvironments completely to TeX-code. "
811 subst_end = ['\end_layout', '', '\\begin_layout Plain Layout',
813 '\\begin_layout Plain Layout', '', '',
816 '\\end_layout', '', '\\end_inset',
817 '', '', '\\end_layout']
818 subst_begin = ['\\begin_layout Standard', '\\noindent',
819 '\\begin_inset ERT', 'status open', '',
820 '\\begin_layout Plain Layout', '', '', '\\backslash',
822 '\\end_layout', '', '\\begin_layout Plain Layout', '']
825 i = find_token(document.body, "\\begin_layout Verbatim", i)
828 j = find_end_of_layout(document.body, i)
830 document.warning("Malformed LyX document: Can't find end of Verbatim layout")
833 # delete all line breaks insets (there are no other insets)
836 n = find_token(document.body, "\\begin_inset Newline newline", l, j)
838 n = find_token(document.body, "\\begin_inset Newline linebreak", l, j)
841 m = find_end_of_inset(document.body, n)
842 del(document.body[m:m+1])
843 document.body[n:n+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
845 # we deleted a line, so the end of the inset moved forward.
847 # consecutive verbatim environments need to be connected
848 k = find_token(document.body, "\\begin_layout Verbatim", j)
849 if k == j + 2 and consecutive == False:
851 document.body[j:j+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
852 document.body[i:i+1] = subst_begin
854 if k == j + 2 and consecutive == True:
855 document.body[j:j+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
856 del(document.body[i:i+1])
858 if k != j + 2 and consecutive == True:
859 document.body[j:j+1] = subst_end
860 # the next paragraph must not be indented
861 document.body[j+19:j+19] = ['\\noindent']
862 del(document.body[i:i+1])
866 document.body[j:j+1] = subst_end
867 # the next paragraph must not be indented
868 document.body[j+19:j+19] = ['\\noindent']
869 document.body[i:i+1] = subst_begin
872 def revert_tipa(document):
873 " Revert native TIPA insets to mathed or ERT. "
876 i = find_token(document.body, "\\begin_inset IPA", i)
879 j = find_end_of_inset(document.body, i)
881 document.warning("Malformed LyX document: Can't find end of IPA inset")
885 n = find_token(document.body, "\\begin_layout", i, j)
887 document.warning("Malformed LyX document: IPA inset has no embedded layout")
890 m = find_end_of_layout(document.body, n)
892 document.warning("Malformed LyX document: Can't find end of embedded layout")
895 content = document.body[n+1:m]
896 p = find_token(document.body, "\\begin_layout", m, j)
897 if p != -1 or len(content) > 1:
899 content = document.body[i+1:j]
901 # IPA insets with multiple pars need to be wrapped by \begin{IPA}...\end{IPA}
902 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}")
903 add_to_preamble(document, ["\\usepackage{tipa,tipx}"])
905 # single-par IPA insets can be reverted to mathed
906 document.body[i:j+1] = ["\\begin_inset Formula $\\text{\\textipa{" + content[0] + "}}$", "\\end_inset"]
910 def revert_cell_rotation(document):
911 "Revert cell rotations to TeX-code"
913 load_rotating = False
917 # first, let's find out if we need to do anything
918 i = find_token(document.body, '<cell ', i)
921 j = document.body[i].find('rotate="')
923 k = document.body[i].find('"', j + 8)
924 value = document.body[i][j + 8 : k]
926 rgx = re.compile(r' rotate="[^"]+?"')
927 # remove rotate option
928 document.body[i] = rgx.sub('', document.body[i])
930 rgx = re.compile(r' rotate="[^"]+?"')
931 document.body[i] = rgx.sub(' rotate="true"', document.body[i])
933 rgx = re.compile(r' rotate="[^"]+?"')
935 # remove rotate option
936 document.body[i] = rgx.sub('', document.body[i])
938 document.body[i + 5 : i + 5] = \
939 put_cmd_in_ert("\\end{turn}")
940 document.body[i + 4 : i + 4] = \
941 put_cmd_in_ert("\\begin{turn}{" + value + "}")
947 add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"])
950 def convert_cell_rotation(document):
951 'Convert cell rotation statements from "true" to "90"'
955 # first, let's find out if we need to do anything
956 i = find_token(document.body, '<cell ', i)
959 j = document.body[i].find('rotate="true"')
961 rgx = re.compile(r'rotate="[^"]+?"')
962 # convert "true" to "90"
963 document.body[i] = rgx.sub('rotate="90"', document.body[i])
968 def revert_table_rotation(document):
969 "Revert table rotations to TeX-code"
971 load_rotating = False
975 # first, let's find out if we need to do anything
976 i = find_token(document.body, '<features ', i)
979 j = document.body[i].find('rotate="')
981 end_table = find_token(document.body, '</lyxtabular>', j)
982 k = document.body[i].find('"', j + 8)
983 value = document.body[i][j + 8 : k]
985 rgx = re.compile(r' rotate="[^"]+?"')
986 # remove rotate option
987 document.body[i] = rgx.sub('', document.body[i])
989 rgx = re.compile(r'rotate="[^"]+?"')
990 document.body[i] = rgx.sub('rotate="true"', document.body[i])
992 rgx = re.compile(r' rotate="[^"]+?"')
994 # remove rotate option
995 document.body[i] = rgx.sub('', document.body[i])
997 document.body[end_table + 3 : end_table + 3] = \
998 put_cmd_in_ert("\\end{turn}")
999 document.body[i - 2 : i - 2] = \
1000 put_cmd_in_ert("\\begin{turn}{" + value + "}")
1006 add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"])
1009 def convert_table_rotation(document):
1010 'Convert table rotation statements from "true" to "90"'
1014 # first, let's find out if we need to do anything
1015 i = find_token(document.body, '<features ', i)
1018 j = document.body[i].find('rotate="true"')
1020 rgx = re.compile(r'rotate="[^"]+?"')
1021 # convert "true" to "90"
1022 document.body[i] = rgx.sub('rotate="90"', document.body[i])
1027 def convert_listoflistings(document):
1028 'Convert ERT \lstlistoflistings to TOC lstlistoflistings inset'
1029 # We can support roundtrip because the command is so simple
1032 i = find_token(document.body, "\\begin_inset ERT", i)
1035 j = find_end_of_inset(document.body, i)
1037 document.warning("Malformed LyX document: Can't find end of ERT inset")
1040 ert = get_ert(document.body, i)
1041 if ert == "\\lstlistoflistings{}":
1042 document.body[i:j] = ["\\begin_inset CommandInset toc", "LatexCommand lstlistoflistings", ""]
1048 def revert_listoflistings(document):
1049 'Convert TOC lstlistoflistings inset to ERT lstlistoflistings'
1052 i = find_token(document.body, "\\begin_inset CommandInset toc", i)
1055 if document.body[i+1] == "LatexCommand lstlistoflistings":
1056 j = find_end_of_inset(document.body, i)
1058 document.warning("Malformed LyX document: Can't find end of TOC inset")
1061 subst = put_cmd_in_ert("\\lstlistoflistings{}")
1062 document.body[i:j+1] = subst
1063 add_to_preamble(document, ["\\usepackage{listings}"])
1067 def convert_use_amssymb(document):
1068 "insert use_package amssymb"
1069 regexp = re.compile(r'(\\use_package\s+amsmath)')
1070 i = find_re(document.header, regexp, 0)
1072 document.warning("Malformed LyX document: Can't find \\use_package amsmath.")
1074 value = get_value(document.header, "\\use_package" , i).split()[1]
1077 useamsmath = int(value)
1079 document.warning("Invalid \\use_package amsmath: " + value + ". Assuming auto.")
1081 j = find_token(document.preamble, "\\usepackage{amssymb}", 0)
1083 document.header.insert(i + 1, "\\use_package amssymb %d" % useamsmath)
1085 document.header.insert(i + 1, "\\use_package amssymb 2")
1086 del document.preamble[j]
1089 def revert_use_amssymb(document):
1090 "remove use_package amssymb"
1091 regexp1 = re.compile(r'(\\use_package\s+amsmath)')
1092 regexp2 = re.compile(r'(\\use_package\s+amssymb)')
1093 i = find_re(document.header, regexp1, 0)
1094 j = find_re(document.header, regexp2, 0)
1095 value1 = "1" # default is auto
1096 value2 = "1" # default is auto
1098 value1 = get_value(document.header, "\\use_package" , i).split()[1]
1100 value2 = get_value(document.header, "\\use_package" , j).split()[1]
1101 del document.header[j]
1102 if value1 != value2 and value2 == "2": # on
1103 add_to_preamble(document, ["\\usepackage{amssymb}"])
1106 def convert_use_cancel(document):
1107 "insert use_package cancel"
1108 convert_use_package(document, "cancel", cancel_commands, True)
1111 def revert_use_cancel(document):
1112 "remove use_package cancel"
1113 revert_use_package(document, "cancel", cancel_commands, True)
1116 def revert_ancientgreek(document):
1117 "Set the document language for ancientgreek to greek"
1119 if document.language == "ancientgreek":
1120 document.language = "greek"
1121 i = find_token(document.header, "\\language", 0)
1123 document.header[i] = "\\language greek"
1126 j = find_token(document.body, "\\lang ancientgreek", j)
1130 document.body[j] = document.body[j].replace("\\lang ancientgreek", "\\lang greek")
1134 def revert_languages(document):
1135 "Set the document language for new supported languages to English"
1138 "coptic", "divehi", "hindi", "kurmanji", "lao", "marathi", "occitan", "sanskrit",
1139 "syriac", "tamil", "telugu", "urdu"
1141 for n in range(len(languages)):
1142 if document.language == languages[n]:
1143 document.language = "english"
1144 i = find_token(document.header, "\\language", 0)
1146 document.header[i] = "\\language english"
1148 while j < len(document.body):
1149 j = find_token(document.body, "\\lang " + languages[n], j)
1151 document.body[j] = document.body[j].replace("\\lang " + languages[n], "\\lang english")
1154 j = len(document.body)
1157 def convert_armenian(document):
1158 "Use polyglossia and thus non-TeX fonts for Armenian"
1160 if document.language == "armenian":
1161 i = find_token(document.header, "\\use_non_tex_fonts", 0)
1163 document.header[i] = "\\use_non_tex_fonts true"
1166 def revert_armenian(document):
1167 "Use ArmTeX and thus TeX fonts for Armenian"
1169 if document.language == "armenian":
1170 i = find_token(document.header, "\\use_non_tex_fonts", 0)
1172 document.header[i] = "\\use_non_tex_fonts false"
1175 def revert_libertine(document):
1176 " Revert native libertine font definition to LaTeX "
1178 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1179 i = find_token(document.header, "\\font_roman libertine", 0)
1182 j = find_token(document.header, "\\font_osf true", 0)
1185 preamble = "\\usepackage"
1187 document.header[j] = "\\font_osf false"
1190 preamble += "[lining]"
1191 preamble += "{libertine-type1}"
1192 add_to_preamble(document, [preamble])
1193 document.header[i] = "\\font_roman default"
1196 def revert_txtt(document):
1197 " Revert native txtt font definition to LaTeX "
1199 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1200 i = find_token(document.header, "\\font_typewriter txtt", 0)
1202 preamble = "\\renewcommand{\\ttdefault}{txtt}"
1203 add_to_preamble(document, [preamble])
1204 document.header[i] = "\\font_typewriter default"
1207 def revert_mathdesign(document):
1208 " Revert native mathdesign font definition to LaTeX "
1210 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1216 i = find_token(document.header, "\\font_roman", 0)
1219 val = get_value(document.header, "\\font_roman", i)
1220 if val in mathdesign_dict.keys():
1221 preamble = "\\usepackage[%s" % mathdesign_dict[val]
1223 j = find_token(document.header, "\\font_osf true", 0)
1226 document.header[j] = "\\font_osf false"
1227 l = find_token(document.header, "\\font_sc true", 0)
1230 document.header[l] = "\\font_sc false"
1232 preamble += ",expert"
1233 preamble += "]{mathdesign}"
1234 add_to_preamble(document, [preamble])
1235 document.header[i] = "\\font_roman default"
1238 def revert_texgyre(document):
1239 " Revert native TeXGyre font definition to LaTeX "
1241 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1242 texgyre_fonts = ["tgadventor", "tgbonum", "tgchorus", "tgcursor", \
1243 "tgheros", "tgpagella", "tgschola", "tgtermes"]
1244 i = find_token(document.header, "\\font_roman", 0)
1246 val = get_value(document.header, "\\font_roman", i)
1247 if val in texgyre_fonts:
1248 preamble = "\\usepackage{%s}" % val
1249 add_to_preamble(document, [preamble])
1250 document.header[i] = "\\font_roman default"
1251 i = find_token(document.header, "\\font_sans", 0)
1253 val = get_value(document.header, "\\font_sans", i)
1254 if val in texgyre_fonts:
1255 preamble = "\\usepackage{%s}" % val
1256 add_to_preamble(document, [preamble])
1257 document.header[i] = "\\font_sans default"
1258 i = find_token(document.header, "\\font_typewriter", 0)
1260 val = get_value(document.header, "\\font_typewriter", i)
1261 if val in texgyre_fonts:
1262 preamble = "\\usepackage{%s}" % val
1263 add_to_preamble(document, [preamble])
1264 document.header[i] = "\\font_typewriter default"
1267 def revert_ipadeco(document):
1268 " Revert IPA decorations to ERT "
1271 i = find_token(document.body, "\\begin_inset IPADeco", i)
1274 end = find_end_of_inset(document.body, i)
1276 document.warning("Can't find end of inset at line " + str(i))
1279 line = document.body[i]
1280 rx = re.compile(r'\\begin_inset IPADeco (.*)$')
1282 decotype = m.group(1)
1283 if decotype != "toptiebar" and decotype != "bottomtiebar":
1284 document.warning("Invalid IPADeco type: " + decotype)
1287 blay = find_token(document.body, "\\begin_layout Plain Layout", i, end)
1289 document.warning("Can't find layout for inset at line " + str(i))
1292 bend = find_end_of_layout(document.body, blay)
1294 document.warning("Malformed LyX document: Could not find end of IPADeco inset's layout.")
1297 substi = ["\\begin_inset ERT", "status collapsed", "",
1298 "\\begin_layout Plain Layout", "", "", "\\backslash",
1299 decotype + "{", "\\end_layout", "", "\\end_inset"]
1300 substj = ["\\size default", "", "\\begin_inset ERT", "status collapsed", "",
1301 "\\begin_layout Plain Layout", "", "}", "\\end_layout", "", "\\end_inset"]
1302 # do the later one first so as not to mess up the numbering
1303 document.body[bend:end + 1] = substj
1304 document.body[i:blay + 1] = substi
1305 i = end + len(substi) + len(substj) - (end - bend) - (blay - i) - 2
1306 add_to_preamble(document, "\\usepackage{tipa}")
1309 def revert_ipachar(document):
1310 ' Revert \\IPAChar to ERT '
1313 while i < len(document.body):
1314 m = re.match(r'(.*)\\IPAChar \\(\w+\{\w+\})(.*)', document.body[i])
1318 ipachar = m.group(2)
1321 '\\begin_inset ERT',
1322 'status collapsed', '',
1323 '\\begin_layout Standard',
1324 '', '', '\\backslash',
1329 document.body[i: i+1] = subst
1334 add_to_preamble(document, "\\usepackage{tone}")
1337 def revert_minionpro(document):
1338 " Revert native MinionPro font definition to LaTeX "
1340 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1341 i = find_token(document.header, "\\font_roman minionpro", 0)
1344 j = find_token(document.header, "\\font_osf true", 0)
1347 preamble = "\\usepackage"
1349 document.header[j] = "\\font_osf false"
1352 preamble += "{MinionPro}"
1353 add_to_preamble(document, [preamble])
1354 document.header[i] = "\\font_roman default"
1357 def revert_mathfonts(document):
1358 " Revert native math font definitions to LaTeX "
1360 i = find_token(document.header, "\\font_math", 0)
1363 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1364 val = get_value(document.header, "\\font_math", i)
1365 if val == "eulervm":
1366 add_to_preamble(document, "\\usepackage{eulervm}")
1367 elif val == "default":
1369 "lmodern": "\\renewcommand{\\rmdefault}{lmr}",
1370 "minionpro": "\\usepackage[onlytext,lf]{MinionPro}",
1371 "minionpro-osf": "\\usepackage[onlytext]{MinionPro}",
1372 "palatino": "\\renewcommand{\\rmdefault}{ppl}",
1373 "palatino-osf": "\\renewcommand{\\rmdefault}{pplj}",
1374 "times": "\\renewcommand{\\rmdefault}{ptm}",
1375 "utopia": "\\renewcommand{\\rmdefault}{futs}",
1376 "utopia-osf": "\\renewcommand{\\rmdefault}{futj}",
1378 j = find_token(document.header, "\\font_roman", 0)
1380 rm = get_value(document.header, "\\font_roman", j)
1381 k = find_token(document.header, "\\font_osf true", 0)
1384 if rm in mathfont_dict.keys():
1385 add_to_preamble(document, mathfont_dict[rm])
1386 document.header[j] = "\\font_roman default"
1388 document.header[k] = "\\font_osf false"
1389 del document.header[i]
1392 def revert_mdnomath(document):
1393 " Revert mathdesign and fourier without math "
1395 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1397 "md-charter": "mdbch",
1398 "md-utopia": "mdput",
1399 "md-garamond": "mdugm"
1401 i = find_token(document.header, "\\font_roman", 0)
1404 val = get_value(document.header, "\\font_roman", i)
1405 if val in mathdesign_dict.keys():
1406 j = find_token(document.header, "\\font_math", 0)
1408 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1409 mval = get_value(document.header, "\\font_math", j)
1410 if mval == "default":
1411 document.header[i] = "\\font_roman default"
1412 add_to_preamble(document, "\\renewcommand{\\rmdefault}{%s}" % mathdesign_dict[val])
1414 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1417 def convert_mdnomath(document):
1418 " Change mathdesign font name "
1420 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1422 "mdbch": "md-charter",
1423 "mdput": "md-utopia",
1424 "mdugm": "md-garamond"
1426 i = find_token(document.header, "\\font_roman", 0)
1429 val = get_value(document.header, "\\font_roman", i)
1430 if val in mathdesign_dict.keys():
1431 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1434 def revert_newtxmath(document):
1435 " Revert native newtxmath definitions to LaTeX "
1437 i = find_token(document.header, "\\font_math", 0)
1440 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1441 val = get_value(document.header, "\\font_math", i)
1443 "libertine-ntxm": "\\usepackage[libertine]{newtxmath}",
1444 "minion-ntxm": "\\usepackage[minion]{newtxmath}",
1445 "newtxmath": "\\usepackage{newtxmath}",
1447 if val in mathfont_dict.keys():
1448 add_to_preamble(document, mathfont_dict[val])
1449 document.header[i] = "\\font_math auto"
1452 def revert_biolinum(document):
1453 " Revert native biolinum font definition to LaTeX "
1455 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1456 i = find_token(document.header, "\\font_sans biolinum", 0)
1459 j = find_token(document.header, "\\font_osf true", 0)
1462 preamble = "\\usepackage"
1465 preamble += "{biolinum-type1}"
1466 add_to_preamble(document, [preamble])
1467 document.header[i] = "\\font_sans default"
1470 def revert_uop(document):
1471 " Revert native URW Classico (Optima) font definition to LaTeX "
1473 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1474 i = find_token(document.header, "\\font_sans uop", 0)
1476 preamble = "\\renewcommand{\\sfdefault}{uop}"
1477 add_to_preamble(document, [preamble])
1478 document.header[i] = "\\font_sans default"
1481 def convert_latexargs(document):
1482 " Convert InsetArgument to new syntax "
1484 if find_token(document.body, "\\begin_inset Argument", 0) == -1:
1488 # A list of layouts (document classes) with only optional or no arguments.
1489 # These can be safely converted to the new syntax
1490 # (I took the liberty to add some of my personal layouts/modules here; JSP)
1491 safe_layouts = ["aa", "aapaper", "aastex", "achemso", "acmsiggraph", "AEA",
1492 "agu-dtd", "agums", "agutex", "amsart", "amsbook", "apa",
1493 "arab-article", "armenian-article", "article-beamer", "article",
1494 "beamer", "book", "broadway", "chess", "cl2emult", "ctex-article",
1495 "ctex-book", "ctex-report", "dinbrief", "docbook-book", "docbook-chapter",
1496 "docbook", "docbook-section", "doublecol-new", "dtk", "ectaart", "egs",
1497 "elsarticle", "elsart", "entcs", "europecv", "extarticle", "extbook",
1498 "extletter", "extreport", "foils", "frletter", "g-brief2", "g-brief",
1499 "heb-article", "heb-letter", "hollywood", "IEEEtran", "ijmpc", "ijmpd",
1500 "iopart", "isprs", "jarticle", "jasatex", "jbook", "jgrga", "jreport",
1501 "jsarticle", "jsbeamer", "jsbook", "jss", "kluwer", "latex8", "letter", "lettre",
1502 "literate-article", "literate-book", "literate-report", "llncs", "ltugboat",
1503 "memoir", "moderncv", "mwart", "mwbk", "mwrep", "paper", "powerdot",
1504 "recipebook", "report", "revtex4", "revtex", "scrartcl", "scrarticle-beamer",
1505 "scrbook", "scrlettr", "scrlttr2", "scrreprt", "seminar", "siamltex",
1506 "sigplanconf", "simplecv", "singlecol", "singlecol-new", "slides", "spie",
1507 "svglobal3", "svglobal", "svjog", "svmono", "svmult", "svprobth", "tarticle",
1508 "tbook", "treport", "tufte-book", "tufte-handout"]
1509 # A list of "safe" modules, same as above
1510 safe_modules = ["biblatex", "beameraddons", "beamer-resenumerate", "beamersession", "braille",
1511 "customHeadersFooters", "endnotes", "enumitem", "eqs-within-sections", "figs-within-sections",
1512 "fix-cm", "fixltx2e", "foottoend", "hanging", "jscharstyles", "knitr", "lilypond",
1513 "linguistics", "linguisticx", "logicalmkup", "minimalistic", "nomindex", "noweb",
1514 "pdfcomment", "sweave", "tabs-within-sections", "theorems-ams-bytype",
1515 "theorems-ams-extended-bytype", "theorems-ams-extended", "theorems-ams", "theorems-bytype",
1516 "theorems-chap-bytype", "theorems-chap", "theorems-named", "theorems-sec-bytype",
1517 "theorems-sec", "theorems-starred", "theorems-std", "todonotes"]
1518 # Modules we need to take care of
1519 caveat_modules = ["initials"]
1520 # information about the relevant styles in caveat_modules (number of opt and req args)
1521 # use this if we get more caveat_modules. For now, use hard coding (see below).
1522 # initials = [{'Layout' : 'Initial', 'opt' : 1, 'req' : 1}]
1524 # Is this a known safe layout?
1525 safe_layout = document.textclass in safe_layouts
1527 document.warning("Lyx2lyx knows nothing about textclass '%s'. "
1528 "Please check if short title insets have been converted correctly."
1529 % document.textclass)
1530 # Do we use unsafe or unknown modules
1531 mods = document.get_module_list()
1532 unknown_modules = False
1533 used_caveat_modules = list()
1535 if mod in safe_modules:
1537 if mod in caveat_modules:
1538 used_caveat_modules.append(mod)
1540 unknown_modules = True
1541 document.warning("Lyx2lyx knows nothing about module '%s'. "
1542 "Please check if short title insets have been converted correctly."
1547 i = find_token(document.body, "\\begin_inset Argument", i)
1551 if not safe_layout or unknown_modules:
1552 # We cannot do more here since we have no access to this layout.
1553 # InsetArgument itself will do the real work
1554 # (see InsetArgument::updateBuffer())
1555 document.body[i] = "\\begin_inset Argument 999"
1559 # Find containing paragraph layout
1560 parent = get_containing_layout(document.body, i)
1562 document.warning("Malformed LyX document: Can't find parent paragraph layout")
1569 if len(used_caveat_modules) > 0:
1570 # We know for now that this must be the initials module with the Initial layout
1571 # If we get more such modules, we need some automating.
1572 if parent[0] == "Initial":
1573 # Layout has 1 opt and 1 req arg.
1574 # Count the actual arguments
1576 for p in range(parbeg, parend):
1577 if document.body[p] == "\\begin_inset Argument":
1582 # Collect all arguments in this paragraph
1584 for p in range(parbeg, parend):
1585 if document.body[p] == "\\begin_inset Argument":
1587 if allowed_opts != -1:
1588 # We have less arguments than opt + required.
1589 # required must take precedence.
1590 if argnr > allowed_opts and argnr < first_req:
1592 document.body[p] = "\\begin_inset Argument %d" % argnr
1596 def revert_latexargs(document):
1597 " Revert InsetArgument to old syntax "
1600 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
1603 # Search for Argument insets
1604 i = find_token(document.body, "\\begin_inset Argument", i)
1607 m = rx.match(document.body[i])
1609 # No ID: inset already reverted
1612 # Find containing paragraph layout
1613 parent = get_containing_layout(document.body, i)
1615 document.warning("Malformed LyX document: Can't find parent paragraph layout")
1620 # Do not set realparbeg to parent[3], since this does not work if we
1621 # have another inset (e.g. label or index) before the first argument
1622 # inset (this is the case in the user guide of LyX 2.0.8)
1624 # Collect all arguments in this paragraph
1626 for p in range(parbeg, parend):
1627 m = rx.match(document.body[p])
1630 # This is the first argument inset
1632 val = int(m.group(1))
1633 j = find_end_of_inset(document.body, p)
1634 # Revert to old syntax
1635 document.body[p] = "\\begin_inset Argument"
1637 document.warning("Malformed LyX document: Can't find end of Argument inset")
1640 args[val] = document.body[p : j + 1]
1642 realparend = realparend - len(document.body[p : j + 1])
1643 # Remove arg inset at this position
1644 del document.body[p : j + 1]
1648 # No argument inset found
1649 realparbeg = parent[3]
1650 # Now sort the arg insets
1652 for f in sorted(args):
1655 # Insert the sorted arg insets at paragraph begin
1656 document.body[realparbeg : realparbeg] = subst
1658 i = realparbeg + 1 + len(subst)
1661 def revert_IEEEtran(document):
1663 Reverts InsetArgument of
1666 Biography without photo
1669 if document.textclass == "IEEEtran":
1676 i = find_token(document.body, "\\begin_layout Page headings", i)
1678 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1681 i2 = find_token(document.body, "\\begin_inset Flex Paragraph Start", i2)
1683 revert_Argument_to_TeX_brace(document, i2, 0, 1, 1, False, False)
1686 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1688 revert_Argument_to_TeX_brace(document, j, 0, 1, 1, True, False)
1691 k = find_token(document.body, "\\begin_layout Biography", k)
1692 kA = find_token(document.body, "\\begin_layout Biography without photo", k)
1693 if k == kA and k != -1:
1697 # start with the second argument, therefore 2
1698 revert_Argument_to_TeX_brace(document, k, 0, 2, 2, True, False)
1700 if i == -1 and i2 == -1 and j == -1 and k == -1:
1704 def revert_IEEEtran_2(document):
1706 Reverts Flex Paragraph Start to TeX-code
1708 if document.textclass == "IEEEtran":
1711 begin = find_token(document.body, "\\begin_inset Flex Paragraph Start", begin)
1714 end1 = find_end_of_inset(document.body, begin)
1715 document.body[end1 - 2 : end1 + 1] = put_cmd_in_ert("}")
1716 document.body[begin : begin + 4] = put_cmd_in_ert("\\IEEEPARstart{")
1720 def convert_IEEEtran(document):
1725 Biography without photo
1728 if document.textclass == "IEEEtran":
1734 i = find_token(document.body, "\\begin_layout Page headings", i)
1736 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1739 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1741 convert_TeX_brace_to_Argument(document, j, 1, 1, False, True, False)
1744 # assure that we don't handle Biography Biography without photo
1745 k = find_token(document.body, "\\begin_layout Biography", k)
1746 kA = find_token(document.body, "\\begin_layout Biography without photo", k - 1)
1747 if k == kA and k != -1:
1751 # the argument we want to convert is the second one
1752 convert_TeX_brace_to_Argument(document, k, 2, 2, False, True, False)
1754 if i == -1 and j == -1 and k == -1:
1758 def revert_AASTeX(document):
1759 " Reverts InsetArgument of Altaffilation to TeX-code "
1760 if document.textclass == "aastex":
1763 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1766 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1770 def convert_AASTeX(document):
1771 " Converts ERT of Altaffilation to InsetArgument "
1772 if document.textclass == "aastex":
1775 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1778 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1782 def revert_AGUTeX(document):
1783 " Reverts InsetArgument of Author affiliation to TeX-code "
1784 if document.textclass == "agutex":
1787 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1790 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1794 def convert_AGUTeX(document):
1795 " Converts ERT of Author affiliation to InsetArgument "
1796 if document.textclass == "agutex":
1799 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1802 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1806 def revert_IJMP(document):
1807 " Reverts InsetArgument of MarkBoth to TeX-code "
1808 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1811 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1814 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1818 def convert_IJMP(document):
1819 " Converts ERT of MarkBoth to InsetArgument "
1820 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1823 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1826 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1830 def revert_SIGPLAN(document):
1831 " Reverts InsetArguments of SIGPLAN to TeX-code "
1832 if document.textclass == "sigplanconf":
1837 i = find_token(document.body, "\\begin_layout Conference", i)
1839 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1842 j = find_token(document.body, "\\begin_layout Author", j)
1844 revert_Argument_to_TeX_brace(document, j, 0, 1, 2, False, False)
1846 if i == -1 and j == -1:
1850 def convert_SIGPLAN(document):
1851 " Converts ERT of SIGPLAN to InsetArgument "
1852 if document.textclass == "sigplanconf":
1857 i = find_token(document.body, "\\begin_layout Conference", i)
1859 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1862 j = find_token(document.body, "\\begin_layout Author", j)
1864 convert_TeX_brace_to_Argument(document, j, 1, 2, False, False, False)
1866 if i == -1 and j == -1:
1870 def revert_SIGGRAPH(document):
1871 " Reverts InsetArgument of Flex CRcat to TeX-code "
1872 if document.textclass == "acmsiggraph":
1875 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1878 revert_Argument_to_TeX_brace(document, i, 0, 1, 3, False, False)
1882 def convert_SIGGRAPH(document):
1883 " Converts ERT of Flex CRcat to InsetArgument "
1884 if document.textclass == "acmsiggraph":
1887 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1890 convert_TeX_brace_to_Argument(document, i, 1, 3, True, False, False)
1894 def revert_EuropeCV(document):
1895 " Reverts InsetArguments of europeCV to TeX-code "
1896 if document.textclass == "europecv":
1903 i = find_token(document.body, "\\begin_layout Item", i)
1905 revert_Argument_to_TeX_brace(document, i, 0, 2, 2, False, False)
1908 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1910 revert_Argument_to_TeX_brace(document, j, 0, 2, 2, False, False)
1913 k = find_token(document.body, "\\begin_layout Language", k)
1915 revert_Argument_to_TeX_brace(document, k, 0, 2, 6, False, False)
1918 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1920 revert_Argument_to_TeX_brace(document, m, 0, 2, 6, False, False)
1922 if i == -1 and j == -1 and k == -1 and m == -1:
1926 def convert_EuropeCV(document):
1927 " Converts ERT of europeCV to InsetArgument "
1928 if document.textclass == "europecv":
1935 i = find_token(document.body, "\\begin_layout Item", i)
1937 convert_TeX_brace_to_Argument(document, i, 2, 2, False, False, False)
1940 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1942 convert_TeX_brace_to_Argument(document, j, 2, 2, False, False, False)
1945 k = find_token(document.body, "\\begin_layout Language", k)
1947 convert_TeX_brace_to_Argument(document, k, 2, 6, False, False, False)
1950 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1952 convert_TeX_brace_to_Argument(document, m, 2, 6, False, False, False)
1954 if i == -1 and j == -1 and k == -1 and m == -1:
1958 def revert_ModernCV(document):
1959 " Reverts InsetArguments of modernCV to TeX-code "
1960 if document.textclass == "moderncv":
1968 j = find_token(document.body, "\\begin_layout Entry", j)
1970 revert_Argument_to_TeX_brace(document, j, 0, 1, 5, False, False)
1973 k = find_token(document.body, "\\begin_layout Item", k)
1975 revert_Argument_to_TeX_brace(document, k, 0, 1, 1, False, False)
1978 m = find_token(document.body, "\\begin_layout ItemWithComment", m)
1980 revert_Argument_to_TeX_brace(document, m, 0, 1, 2, False, False)
1981 document.body[m] = document.body[m].replace("\\begin_layout ItemWithComment", "\\begin_layout Language")
1984 o = find_token(document.body, "\\begin_layout DoubleItem", o)
1986 revert_Argument_to_TeX_brace(document, o, 0, 1, 3, False, False)
1987 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout Computer")
1990 p = find_token(document.body, "\\begin_layout Social", p)
1992 revert_Argument_to_TeX_brace(document, p, 0, 1, 1, False, True)
1994 if j == -1 and k == -1 and m == -1 and o == -1 and p == -1:
1998 def revert_ModernCV_2(document):
1999 " Reverts the Flex:Column inset of modernCV to TeX-code "
2000 if document.textclass == "moderncv":
2004 flex = find_token(document.body, "\\begin_inset Flex Column", flex)
2007 flexEnd = find_end_of_inset(document.body, flex)
2008 wasOpt = revert_Argument_to_TeX_brace(document, flex, flexEnd, 1, 1, False, True)
2009 revert_Argument_to_TeX_brace(document, flex, 0, 2, 2, False, False)
2010 flexEnd = find_end_of_inset(document.body, flex)
2012 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn")
2014 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn{")
2015 document.body[flexEnd + 4 : flexEnd + 7] = put_cmd_in_ert("}")
2019 def revert_ModernCV_3(document):
2020 " Reverts the Column style of modernCV to TeX-code "
2021 if document.textclass == "moderncv":
2022 # revert the layouts
2023 revert_ModernCV(document)
2025 # get the position of the end of the last column inset
2026 LastFlexEnd = revert_ModernCV_2(document)
2028 p = find_token(document.body, "\\begin_layout Columns", p)
2031 pEnd = find_end_of_layout(document.body, p)
2032 document.body[p] = document.body[p].replace("\\begin_layout Columns", "\\begin_layout Standard")
2033 if LastFlexEnd != -1:
2034 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\begin{cvcolumns}")
2035 document.body[LastFlexEnd + 24 : LastFlexEnd + 24] = put_cmd_in_ert("\\end{cvcolumns}")
2039 def revert_ModernCV_4(document):
2040 " Reverts the style Social to TeX-code "
2041 if document.textclass == "moderncv":
2042 # revert the layouts
2043 revert_ModernCV(document)
2046 p = find_token(document.body, "\\begin_layout Social", p)
2049 pEnd = find_end_of_layout(document.body, p)
2050 document.body[p] = document.body[p].replace("\\begin_layout Social", "\\begin_layout Standard")
2051 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\social")
2052 hasOpt = find_token(document.body, "[", p + 9)
2054 document.body[p + 30 : p + 30] = put_cmd_in_ert("{")
2055 document.body[p + 41 : p + 41] = put_cmd_in_ert("}")
2057 document.body[p + 11 : p + 11] = put_cmd_in_ert("{")
2058 document.body[p + 21 : p + 21] = put_cmd_in_ert("}")
2062 def convert_ModernCV(document):
2063 " Converts ERT of modernCV to InsetArgument "
2064 if document.textclass == "moderncv":
2072 i = find_token(document.body, "\\begin_layout DoubleItem", i)
2074 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
2075 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout DoubleListItem")
2078 j = find_token(document.body, "\\begin_layout Entry", j)
2080 convert_TeX_brace_to_Argument(document, j, 1, 5, False, False, False)
2083 k = find_token(document.body, "\\begin_layout Item", k)
2085 convert_TeX_brace_to_Argument(document, k, 1, 1, False, False, False)
2088 m = find_token(document.body, "\\begin_layout Language", m)
2090 convert_TeX_brace_to_Argument(document, m, 1, 2, False, False, False)
2092 if i == -1 and j == -1 and k == -1 and m == -1:
2096 def revert_Initials(document):
2097 " Reverts InsetArgument of Initial to TeX-code "
2100 i = find_token(document.body, "\\begin_layout Initial", i)
2103 # first arg (optional) and second arg (first mandatory) are supported in LyX 2.0.x
2104 revert_Argument_to_TeX_brace(document, i, 0, 3, 3, False, False)
2108 def convert_Initials(document):
2109 " Converts ERT of Initial to InsetArgument "
2112 i = find_token(document.body, "\\begin_layout Initial", i)
2115 convert_TeX_brace_to_Argument(document, i, 3, 3, False, False, False)
2119 def revert_literate(document):
2120 " Revert Literate document to old format "
2121 if del_token(document.header, "noweb", 0):
2122 document.textclass = "literate-" + document.textclass
2125 i = find_token(document.body, "\\begin_layout Chunk", i)
2128 document.body[i] = "\\begin_layout Scrap"
2132 def convert_literate(document):
2133 " Convert Literate document to new format"
2134 i = find_token(document.header, "\\textclass", 0)
2135 if (i != -1) and "literate-" in document.header[i]:
2136 document.textclass = document.header[i].replace("\\textclass literate-", "")
2137 j = find_token(document.header, "\\begin_modules", 0)
2139 document.header.insert(j + 1, "noweb")
2141 document.header.insert(i + 1, "\\end_modules")
2142 document.header.insert(i + 1, "noweb")
2143 document.header.insert(i + 1, "\\begin_modules")
2146 i = find_token(document.body, "\\begin_layout Scrap", i)
2149 document.body[i] = "\\begin_layout Chunk"
2153 def revert_itemargs(document):
2154 " Reverts \\item arguments to TeX-code "
2157 i = find_token(document.body, "\\begin_inset Argument item:", i)
2160 j = find_end_of_inset(document.body, i)
2161 # Find containing paragraph layout
2162 parent = get_containing_layout(document.body, i)
2164 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2168 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2169 endPlain = find_end_of_layout(document.body, beginPlain)
2170 content = document.body[beginPlain + 1 : endPlain]
2171 del document.body[i:j+1]
2172 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2173 document.body[parbeg : parbeg] = subst
2177 def revert_garamondx_newtxmath(document):
2178 " Revert native garamond newtxmath definition to LaTeX "
2180 i = find_token(document.header, "\\font_math", 0)
2183 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2184 val = get_value(document.header, "\\font_math", i)
2185 if val == "garamondx-ntxm":
2186 add_to_preamble(document, "\\usepackage[garamondx]{newtxmath}")
2187 document.header[i] = "\\font_math auto"
2190 def revert_garamondx(document):
2191 " Revert native garamond font definition to LaTeX "
2193 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2194 i = find_token(document.header, "\\font_roman garamondx", 0)
2197 j = find_token(document.header, "\\font_osf true", 0)
2200 preamble = "\\usepackage"
2202 preamble += "[osfI]"
2203 preamble += "{garamondx}"
2204 add_to_preamble(document, [preamble])
2205 document.header[i] = "\\font_roman default"
2208 def convert_beamerargs(document):
2209 " Converts beamer arguments to new layout "
2211 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2212 if document.textclass not in beamer_classes:
2215 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2216 list_layouts = ["Itemize", "Enumerate", "Description"]
2217 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
2221 i = find_token(document.body, "\\begin_inset Argument", i)
2224 # Find containing paragraph layout
2225 parent = get_containing_layout(document.body, i)
2227 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2232 layoutname = parent[0]
2233 for p in range(parbeg, parend):
2234 if layoutname in shifted_layouts:
2235 m = rx.match(document.body[p])
2237 argnr = int(m.group(1))
2239 document.body[p] = "\\begin_inset Argument %d" % argnr
2240 if layoutname == "AgainFrame":
2241 m = rx.match(document.body[p])
2243 document.body[p] = "\\begin_inset Argument 3"
2244 if document.body[p + 4] == "\\begin_inset ERT":
2245 if document.body[p + 9].startswith("<"):
2246 # This is an overlay specification
2248 document.body[p + 9] = document.body[p + 9][1:]
2249 if document.body[p + 9].endswith(">"):
2251 document.body[p + 9] = document.body[p + 9][:-1]
2253 document.body[p] = "\\begin_inset Argument 2"
2254 if layoutname in list_layouts:
2255 m = rx.match(document.body[p])
2257 if m.group(1) == "1":
2258 if document.body[p + 4] == "\\begin_inset ERT":
2259 if document.body[p + 9].startswith("<"):
2260 # This is an overlay specification
2262 document.body[p + 9] = document.body[p + 9][1:]
2263 if document.body[p + 9].endswith(">"):
2265 document.body[p + 9] = document.body[p + 9][:-1]
2266 elif document.body[p + 4].startswith("<"):
2267 # This is an overlay specification (without ERT)
2269 document.body[p + 4] = document.body[p + 4][1:]
2270 if document.body[p + 4].endswith(">"):
2272 document.body[p + 4] = document.body[p + 4][:-1]
2273 elif layoutname != "Itemize":
2275 document.body[p] = "\\begin_inset Argument 2"
2280 # Helper function for the frame conversion routines
2282 # FIXME: This method currently requires the arguments to be either
2283 # * In one (whole) ERT each: <ERT>[<arg1>]</ERT><ERT><arg2></ERT><ERT>[arg3]</ERT>
2284 # * Altogether in one whole ERT: <ERT>[<arg1>]<arg2>[arg3]</ERT>
2285 # If individual arguments mix ERT and non-ERT or are splitted
2286 # over several ERTs, the parsing fails.
2287 def convert_beamerframeargs(document, i, parbeg):
2290 if document.body[parbeg] != "\\begin_inset ERT":
2292 ertend = find_end_of_inset(document.body, parbeg)
2294 document.warning("Malformed LyX document: missing ERT \\end_inset")
2296 ertcont = parbeg + 5
2297 if document.body[ertcont].startswith("[<"):
2298 # This is a default overlay specification
2300 document.body[ertcont] = document.body[ertcont][2:]
2301 if document.body[ertcont].endswith(">]"):
2303 document.body[ertcont] = document.body[ertcont][:-2]
2304 elif document.body[ertcont].endswith("]"):
2306 tok = document.body[ertcont].find('>][')
2308 subst = [document.body[ertcont][:tok],
2309 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2310 'status collapsed', '', '\\begin_layout Plain Layout',
2311 document.body[ertcont][tok + 3:-1]]
2312 document.body[ertcont : ertcont + 1] = subst
2314 # Convert to ArgInset
2315 document.body[parbeg] = "\\begin_inset Argument 2"
2316 elif document.body[ertcont].startswith("<"):
2317 # This is an overlay specification
2319 document.body[ertcont] = document.body[ertcont][1:]
2320 if document.body[ertcont].endswith(">"):
2322 document.body[ertcont] = document.body[ertcont][:-1]
2323 # Convert to ArgInset
2324 document.body[parbeg] = "\\begin_inset Argument 1"
2325 elif document.body[ertcont].endswith(">]"):
2327 tok = document.body[ertcont].find('>[<')
2329 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2330 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2331 'status collapsed', '', '\\begin_layout Plain Layout',
2332 document.body[ertcont][tok + 3:-2]]
2333 # Convert to ArgInset
2334 document.body[parbeg] = "\\begin_inset Argument 1"
2336 elif document.body[ertcont].endswith("]"):
2338 tok = document.body[ertcont].find('>[<')
2341 tokk = document.body[ertcont].find('>][')
2343 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2344 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2345 'status collapsed', '', '\\begin_layout Plain Layout',
2346 document.body[ertcont][tok + 3:tokk],
2347 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2348 'status collapsed', '', '\\begin_layout Plain Layout',
2349 document.body[ertcont][tokk + 3:-1]]
2352 tokk = document.body[ertcont].find('>[')
2354 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tokk],
2355 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2356 'status collapsed', '', '\\begin_layout Plain Layout',
2357 document.body[ertcont][tokk + 2:-1]]
2359 # Convert to ArgInset
2360 document.body[parbeg] = "\\begin_inset Argument 1"
2361 elif document.body[ertcont].startswith("["):
2362 # This is an ERT option
2364 document.body[ertcont] = document.body[ertcont][1:]
2365 if document.body[ertcont].endswith("]"):
2367 document.body[ertcont] = document.body[ertcont][:-1]
2368 # Convert to ArgInset
2369 document.body[parbeg] = "\\begin_inset Argument 3"
2375 def convert_againframe_args(document):
2376 " Converts beamer AgainFrame to new layout "
2378 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2379 if document.textclass not in beamer_classes:
2384 i = find_token(document.body, "\\begin_layout AgainFrame", i)
2387 parent = get_containing_layout(document.body, i)
2389 document.warning("Wrong parent layout!")
2393 # Convert ERT arguments
2394 # FIXME: See restrictions in convert_beamerframeargs method
2395 ertend = convert_beamerframeargs(document, i, parbeg)
2401 def convert_corollary_args(document):
2402 " Converts beamer corrolary-style ERT arguments native InsetArgs "
2404 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2405 if document.textclass not in beamer_classes:
2408 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2409 for lay in corollary_layouts:
2412 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2415 parent = get_containing_layout(document.body, i)
2417 document.warning("Wrong parent layout!")
2421 if document.body[parbeg] == "\\begin_inset ERT":
2422 ertcontfirstline = parbeg + 5
2423 # Find the last ERT in this paragraph (which might also be the first)
2424 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
2425 if lastertbeg == -1:
2426 document.warning("Last ERT not found!")
2428 lastertend = find_end_of_inset(document.body, lastertbeg)
2429 if lastertend == -1:
2430 document.warning("End of last ERT not found!")
2432 ertcontlastline = lastertend - 3
2433 if document.body[ertcontfirstline].startswith("<"):
2434 # This is an overlay specification
2436 document.body[ertcontfirstline] = document.body[ertcontfirstline][1:]
2437 if document.body[ertcontlastline].endswith(">"):
2439 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
2440 if ertcontfirstline < ertcontlastline:
2441 # Multiline ERT. Might contain TeX code. Embrace in ERT.
2442 document.body[ertcontlastline : ertcontlastline + 1] = [
2443 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
2444 document.body[ertcontfirstline : ertcontfirstline + 1] = [
2445 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
2446 'status collapsed', '', '\\begin_layout Plain Layout',
2447 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
2448 document.body[ertcontfirstline]]
2450 # Convert to ArgInset
2451 document.body[parbeg] = "\\begin_inset Argument 1"
2452 elif document.body[ertcontlastline].endswith("]"):
2454 ertcontdivline = document.body[ertcontfirstline].find('>[')
2455 if ertcontdivline != -1:
2456 if ertcontfirstline < ertcontlastline:
2457 # Multiline ERT. Might contain TeX code. Embrace in ERT.
2458 document.body[ertcontlastline : ertcontlastline + 1] = [
2459 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
2460 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
2461 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2462 'status collapsed', '', '\\begin_layout Plain Layout',
2463 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
2464 document.body[ertcontdivline][tok + 2:]]
2466 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
2467 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2468 'status collapsed', '', '\\begin_layout Plain Layout',
2469 document.body[ertcontdivline][tok + 2:]]
2470 # Convert to ArgInset
2471 document.body[parbeg] = "\\begin_inset Argument 1"
2474 elif document.body[ertcontlastline].startswith("["):
2475 if document.body[ertcontlastline].endswith("]"):
2476 # This is an ERT option
2478 document.body[ertcontlastline] = document.body[ertcontlastline][1:]
2480 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
2481 # Convert to ArgInset
2482 document.body[parbeg] = "\\begin_inset Argument 2"
2484 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, True)
2491 def convert_quote_args(document):
2492 " Converts beamer quote style ERT args to native InsetArgs "
2494 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2495 if document.textclass not in beamer_classes:
2498 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2499 for lay in quote_layouts:
2502 i = find_token(document.body, "\\begin_layout " + lay, i)
2505 parent = get_containing_layout(document.body, i)
2507 document.warning("Wrong parent layout!")
2511 if document.body[parbeg] == "\\begin_inset ERT":
2512 if document.body[i + 6].startswith("<"):
2513 # This is an overlay specification
2515 document.body[i + 6] = document.body[i + 6][1:]
2516 if document.body[i + 6].endswith(">"):
2518 document.body[i + 6] = document.body[i + 6][:-1]
2519 # Convert to ArgInset
2520 document.body[i + 1] = "\\begin_inset Argument 1"
2524 def cleanup_beamerargs(document):
2525 " Clean up empty ERTs (conversion artefacts) "
2527 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2528 if document.textclass not in beamer_classes:
2533 i = find_token(document.body, "\\begin_inset Argument", i)
2536 j = find_end_of_inset(document.body, i)
2538 document.warning("Malformed LyX document: Can't find end of Argument inset")
2542 ertbeg = find_token(document.body, "\\begin_inset ERT", i, j)
2545 ertend = find_end_of_inset(document.body, ertbeg)
2547 document.warning("Malformed LyX document: Can't find end of ERT inset")
2549 stripped = [line for line in document.body[ertbeg : ertend + 1] if line.strip()]
2550 if len(stripped) == 5:
2551 # This is an empty ERT
2552 offset = len(document.body[ertbeg : ertend + 1])
2553 del document.body[ertbeg : ertend + 1]
2560 def revert_beamerargs(document):
2561 " Reverts beamer arguments to old layout "
2563 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2564 if document.textclass not in beamer_classes:
2568 list_layouts = ["Itemize", "Enumerate", "Description"]
2569 headings = ["Part", "Section", "Section*", "Subsection", "Subsection*",
2570 "Subsubsection", "Subsubsection*", "FrameSubtitle", "NoteItem"]
2571 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2572 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2573 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2576 i = find_token(document.body, "\\begin_inset Argument", i)
2579 # Find containing paragraph layout
2580 parent = get_containing_layout(document.body, i)
2582 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2587 realparbeg = parent[3]
2588 layoutname = parent[0]
2590 for p in range(parbeg, parend):
2594 if layoutname in headings:
2595 m = rx.match(document.body[p])
2599 # Find containing paragraph layout
2600 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2601 endPlain = find_end_of_layout(document.body, beginPlain)
2602 endInset = find_end_of_inset(document.body, p)
2603 argcontent = document.body[beginPlain + 1 : endPlain]
2605 realparend = realparend - len(document.body[p : endInset + 1])
2607 del document.body[p : endInset + 1]
2608 if layoutname == "FrameSubtitle":
2609 pre = put_cmd_in_ert("\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2610 elif layoutname == "NoteItem":
2611 pre = put_cmd_in_ert("\\note<") + argcontent + put_cmd_in_ert(">[item]")
2612 elif layoutname.endswith('*'):
2613 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower()[:-1] + "<") + argcontent + put_cmd_in_ert(">*")
2615 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2616 secarg = find_token(document.body, "\\begin_inset Argument 2", parbeg, parend)
2618 # Find containing paragraph layout
2619 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", secarg)
2620 endPlain = find_end_of_layout(document.body, beginPlain)
2621 endInset = find_end_of_inset(document.body, secarg)
2622 argcontent = document.body[beginPlain + 1 : endPlain]
2624 realparend = realparend - len(document.body[secarg : endInset + 1])
2625 del document.body[secarg : endInset + 1]
2626 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2627 pre += put_cmd_in_ert("{")
2628 document.body[parbeg] = "\\begin_layout Standard"
2629 document.body[realparbeg : realparbeg] = pre
2630 pe = find_end_of_layout(document.body, parbeg)
2631 post = put_cmd_in_ert("}")
2632 document.body[pe : pe] = post
2633 realparend += len(pre) + len(post)
2634 if layoutname == "AgainFrame":
2635 m = rx.match(document.body[p])
2639 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2640 endPlain = find_end_of_layout(document.body, beginPlain)
2641 endInset = find_end_of_inset(document.body, p)
2642 content = document.body[beginPlain + 1 : endPlain]
2644 realparend = realparend - len(document.body[p : endInset + 1])
2646 del document.body[p : endInset + 1]
2647 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2648 document.body[realparbeg : realparbeg] = subst
2649 if layoutname == "Overprint":
2650 m = rx.match(document.body[p])
2654 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2655 endPlain = find_end_of_layout(document.body, beginPlain)
2656 endInset = find_end_of_inset(document.body, p)
2657 content = document.body[beginPlain + 1 : endPlain]
2659 realparend = realparend - len(document.body[p : endInset + 1])
2661 del document.body[p : endInset + 1]
2662 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2663 document.body[realparbeg : realparbeg] = subst
2664 if layoutname == "OverlayArea":
2665 m = rx.match(document.body[p])
2669 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2670 endPlain = find_end_of_layout(document.body, beginPlain)
2671 endInset = find_end_of_inset(document.body, p)
2672 content = document.body[beginPlain + 1 : endPlain]
2674 realparend = realparend - len(document.body[p : endInset + 1])
2676 del document.body[p : endInset + 1]
2677 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2678 document.body[realparbeg : realparbeg] = subst
2679 if layoutname in list_layouts:
2680 m = rx.match(document.body[p])
2684 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2685 endPlain = find_end_of_layout(document.body, beginPlain)
2686 endInset = find_end_of_inset(document.body, p)
2687 content = document.body[beginPlain + 1 : endPlain]
2688 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2689 realparend = realparend + len(subst) - len(content)
2690 document.body[beginPlain + 1 : endPlain] = subst
2691 elif argnr == "item:1":
2692 j = find_end_of_inset(document.body, i)
2693 # Find containing paragraph layout
2694 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2695 endPlain = find_end_of_layout(document.body, beginPlain)
2696 content = document.body[beginPlain + 1 : endPlain]
2697 del document.body[i:j+1]
2698 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2699 document.body[realparbeg : realparbeg] = subst
2700 elif argnr == "item:2":
2701 j = find_end_of_inset(document.body, i)
2702 # Find containing paragraph layout
2703 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2704 endPlain = find_end_of_layout(document.body, beginPlain)
2705 content = document.body[beginPlain + 1 : endPlain]
2706 del document.body[i:j+1]
2707 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2708 document.body[realparbeg : realparbeg] = subst
2709 if layoutname in quote_layouts:
2710 m = rx.match(document.body[p])
2714 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2715 endPlain = find_end_of_layout(document.body, beginPlain)
2716 endInset = find_end_of_inset(document.body, p)
2717 content = document.body[beginPlain + 1 : endPlain]
2719 realparend = realparend - len(document.body[p : endInset + 1])
2721 del document.body[p : endInset + 1]
2722 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2723 document.body[realparbeg : realparbeg] = subst
2724 if layoutname in corollary_layouts:
2725 m = rx.match(document.body[p])
2729 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2730 endPlain = find_end_of_layout(document.body, beginPlain)
2731 endInset = find_end_of_inset(document.body, p)
2732 content = document.body[beginPlain + 1 : endPlain]
2734 realparend = realparend - len(document.body[p : endInset + 1])
2736 del document.body[p : endInset + 1]
2737 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2738 document.body[realparbeg : realparbeg] = subst
2743 def revert_beamerargs2(document):
2744 " Reverts beamer arguments to old layout, step 2 "
2746 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2747 if document.textclass not in beamer_classes:
2751 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2752 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2753 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2756 i = find_token(document.body, "\\begin_inset Argument", i)
2759 # Find containing paragraph layout
2760 parent = get_containing_layout(document.body, i)
2762 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2767 realparbeg = parent[3]
2768 layoutname = parent[0]
2770 for p in range(parbeg, parend):
2774 if layoutname in shifted_layouts:
2775 m = rx.match(document.body[p])
2779 document.body[p] = "\\begin_inset Argument 1"
2780 if layoutname in corollary_layouts:
2781 m = rx.match(document.body[p])
2785 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2786 endPlain = find_end_of_layout(document.body, beginPlain)
2787 endInset = find_end_of_inset(document.body, p)
2788 content = document.body[beginPlain + 1 : endPlain]
2790 realparend = realparend - len(document.body[p : endInset + 1])
2792 del document.body[p : endInset + 1]
2793 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2794 document.body[realparbeg : realparbeg] = subst
2795 if layoutname == "OverlayArea":
2796 m = rx.match(document.body[p])
2800 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2801 endPlain = find_end_of_layout(document.body, beginPlain)
2802 endInset = find_end_of_inset(document.body, p)
2803 content = document.body[beginPlain + 1 : endPlain]
2805 realparend = realparend - len(document.body[p : endInset + 1])
2807 del document.body[p : endInset + 1]
2808 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2809 document.body[realparbeg : realparbeg] = subst
2810 if layoutname == "AgainFrame":
2811 m = rx.match(document.body[p])
2815 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2816 endPlain = find_end_of_layout(document.body, beginPlain)
2817 endInset = find_end_of_inset(document.body, p)
2818 content = document.body[beginPlain + 1 : endPlain]
2820 realparend = realparend - len(document.body[p : endInset + 1])
2822 del document.body[p : endInset + 1]
2823 subst = put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
2824 document.body[realparbeg : realparbeg] = subst
2828 def revert_beamerargs3(document):
2829 " Reverts beamer arguments to old layout, step 3 "
2831 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2832 if document.textclass not in beamer_classes:
2835 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2838 i = find_token(document.body, "\\begin_inset Argument", i)
2841 # Find containing paragraph layout
2842 parent = get_containing_layout(document.body, i)
2844 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2849 realparbeg = parent[3]
2850 layoutname = parent[0]
2852 for p in range(parbeg, parend):
2856 if layoutname == "AgainFrame":
2857 m = rx.match(document.body[p])
2861 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2862 endPlain = find_end_of_layout(document.body, beginPlain)
2863 endInset = find_end_of_inset(document.body, p)
2864 content = document.body[beginPlain + 1 : endPlain]
2866 realparend = realparend - len(document.body[p : endInset + 1])
2868 del document.body[p : endInset + 1]
2869 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2870 document.body[realparbeg : realparbeg] = subst
2874 def revert_beamerflex(document):
2875 " Reverts beamer Flex insets "
2877 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2878 if document.textclass not in beamer_classes:
2881 new_flexes = {"Bold" : "\\textbf", "Emphasize" : "\\emph", "Only" : "\\only",
2882 "Uncover" : "\\uncover", "Visible" : "\\visible",
2883 "Invisible" : "\\invisible", "Alternative" : "\\alt",
2884 "Beamer_Note" : "\\note"}
2885 old_flexes = {"Alert" : "\\alert", "Structure" : "\\structure"}
2886 rx = re.compile(r'^\\begin_inset Flex (.+)$')
2890 i = find_token(document.body, "\\begin_inset Flex", i)
2893 m = rx.match(document.body[i])
2895 flextype = m.group(1)
2896 z = find_end_of_inset(document.body, i)
2898 document.warning("Can't find end of Flex " + flextype + " inset.")
2901 if flextype in new_flexes:
2902 pre = put_cmd_in_ert(new_flexes[flextype])
2903 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2905 argend = find_end_of_inset(document.body, arg)
2907 document.warning("Can't find end of Argument!")
2910 # Find containing paragraph layout
2911 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2912 endPlain = find_end_of_layout(document.body, beginPlain)
2913 argcontent = document.body[beginPlain + 1 : endPlain]
2915 z = z - len(document.body[arg : argend + 1])
2917 del document.body[arg : argend + 1]
2918 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2919 arg = find_token(document.body, "\\begin_inset Argument 2", i, z)
2921 argend = find_end_of_inset(document.body, arg)
2923 document.warning("Can't find end of Argument!")
2926 # Find containing paragraph layout
2927 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2928 endPlain = find_end_of_layout(document.body, beginPlain)
2929 argcontent = document.body[beginPlain + 1 : endPlain]
2931 z = z - len(document.body[arg : argend + 1])
2933 del document.body[arg : argend + 1]
2934 if flextype == "Alternative":
2935 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
2937 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2938 pre += put_cmd_in_ert("{")
2939 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2940 endPlain = find_end_of_layout(document.body, beginPlain)
2942 z = z - len(document.body[i : beginPlain + 1])
2944 document.body[i : beginPlain + 1] = pre
2945 post = put_cmd_in_ert("}")
2946 document.body[z - 2 : z + 1] = post
2947 elif flextype in old_flexes:
2948 pre = put_cmd_in_ert(old_flexes[flextype])
2949 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2953 argend = find_end_of_inset(document.body, arg)
2955 document.warning("Can't find end of Argument!")
2958 # Find containing paragraph layout
2959 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2960 endPlain = find_end_of_layout(document.body, beginPlain)
2961 argcontent = document.body[beginPlain + 1 : endPlain]
2963 z = z - len(document.body[arg : argend + 1])
2965 del document.body[arg : argend + 1]
2966 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2967 pre += put_cmd_in_ert("{")
2968 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2969 endPlain = find_end_of_layout(document.body, beginPlain)
2971 z = z - len(document.body[i : beginPlain + 1])
2973 document.body[i : beginPlain + 1] = pre
2974 post = put_cmd_in_ert("}")
2975 document.body[z - 2 : z + 1] = post
2980 def revert_beamerblocks(document):
2981 " Reverts beamer block arguments to ERT "
2983 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2984 if document.textclass not in beamer_classes:
2987 blocks = ["Block", "ExampleBlock", "AlertBlock"]
2989 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2992 i = find_token(document.body, "\\begin_inset Argument", i)
2995 # Find containing paragraph layout
2996 parent = get_containing_layout(document.body, i)
2998 document.warning("Malformed LyX document: Can't find parent paragraph layout")
3003 realparbeg = parent[3]
3004 layoutname = parent[0]
3006 for p in range(parbeg, parend):
3010 if layoutname in blocks:
3011 m = rx.match(document.body[p])
3015 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3016 endPlain = find_end_of_layout(document.body, beginPlain)
3017 endInset = find_end_of_inset(document.body, p)
3018 content = document.body[beginPlain + 1 : endPlain]
3020 realparend = realparend - len(document.body[p : endInset + 1])
3022 del document.body[p : endInset + 1]
3023 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3024 document.body[realparbeg : realparbeg] = subst
3026 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3027 endPlain = find_end_of_layout(document.body, beginPlain)
3028 endInset = find_end_of_inset(document.body, p)
3029 content = document.body[beginPlain + 1 : endPlain]
3031 realparend = realparend - len(document.body[p : endInset + 1])
3033 del document.body[p : endInset + 1]
3034 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3035 document.body[realparbeg : realparbeg] = subst
3040 def convert_beamerblocks(document):
3041 " Converts beamer block ERT args to native InsetArgs "
3043 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3044 if document.textclass not in beamer_classes:
3047 blocks = ["Block", "ExampleBlock", "AlertBlock"]
3051 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
3054 parent = get_containing_layout(document.body, i)
3055 if parent == False or parent[1] != i:
3056 document.warning("Wrong parent layout!")
3063 if document.body[parbeg] == "\\begin_inset ERT":
3064 ertcontfirstline = parbeg + 5
3068 # Find the last ERT in this paragraph used for arguments
3069 # (which might also be the first)
3070 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
3071 if lastertbeg == -1:
3072 document.warning("Last ERT not found!")
3074 lastertend = find_end_of_inset(document.body, lastertbeg)
3075 if lastertend == -1:
3076 document.warning("End of last ERT not found!")
3078 # Is this ERT really used for an argument?
3079 # Note: This will fail when non-argument ERTs actually use brackets
3081 regexp = re.compile(r'.*[>\]\}]', re.IGNORECASE)
3082 cbracket = find_re(document.body, regexp, lastertbeg, lastertend)
3085 if lastertbeg == parbeg:
3088 if lastertbeg == -1 or lastertend == -1:
3090 ertcontlastline = lastertend - 3
3092 if document.body[ertcontfirstline].lstrip().startswith("<"):
3093 # This is an overlay specification
3095 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3096 if document.body[ertcontlastline].rstrip().endswith(">"):
3098 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3099 # Convert to ArgInset
3100 document.body[parbeg] = "\\begin_inset Argument 1"
3101 elif document.body[ertcontlastline].rstrip().endswith("}"):
3103 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3105 ertcontdivline = ertcontfirstline
3106 tok = document.body[ertcontdivline].find('>{')
3108 regexp = re.compile(r'.*>\{', re.IGNORECASE)
3109 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3110 tok = document.body[ertcontdivline].find('>{')
3112 if ertcontfirstline < ertcontlastline:
3113 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3114 document.body[ertcontlastline : ertcontlastline + 1] = [
3115 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3116 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3117 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3118 'status collapsed', '', '\\begin_layout Plain Layout',
3119 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3120 document.body[ertcontdivline][tok + 2:]]
3122 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3123 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3124 'status collapsed', '', '\\begin_layout Plain Layout',
3125 document.body[ertcontdivline][tok + 2:]]
3127 # check if have delimiters in two different ERTs
3128 tok = document.body[ertcontdivline].find('>')
3130 regexp = re.compile(r'.*>', re.IGNORECASE)
3131 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3132 tok = document.body[ertcontdivline].find('>')
3134 tokk = document.body[ertcontdivline].find('{')
3136 regexp = re.compile(r'.*\{', re.IGNORECASE)
3137 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, lastertend)
3138 tokk = document.body[ertcontdivlinetwo].find('{')
3140 if ertcontfirstline < ertcontlastline:
3141 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3142 document.body[ertcontlastline : ertcontlastline + 1] = [
3143 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3144 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3145 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3146 '\\end_inset', '', '', '\\begin_inset Argument 2',
3147 'status collapsed', '', '\\begin_layout Plain Layout',
3148 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3149 document.body[ertcontdivlinetwo][tokk + 1:]]
3151 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3152 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3153 'status collapsed', '', '\\begin_layout Plain Layout',
3154 document.body[ertcontdivlinetwo][tokk + 1:]]
3155 # Convert to ArgInset
3156 if ertcontfirstline < ertcontlastline:
3157 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3158 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 1',
3159 'status collapsed', '', '\\begin_layout Plain Layout',
3160 '\\begin_inset ERT', '']
3162 document.body[parbeg] = "\\begin_inset Argument 1"
3163 elif document.body[ertcontfirstline].lstrip().startswith("{"):
3164 # This is the block title
3165 if document.body[ertcontlastline].rstrip().endswith("}"):
3166 # strip off the braces
3167 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3168 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3169 if ertcontfirstline < ertcontlastline:
3170 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3171 document.body[parend : parend + 1] = [
3172 document.body[parend], '\\end_inset', '', '\\end_layout']
3173 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3174 'status collapsed', '', '\\begin_layout Plain Layout',
3175 '\\begin_inset ERT', '']
3177 # Convert to ArgInset
3178 document.body[parbeg] = "\\begin_inset Argument 2"
3179 # the overlay argument can also follow the title, so ...
3180 elif document.body[ertcontlastline].rstrip().endswith(">"):
3182 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3184 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3186 ertcontdivline = ertcontfirstline
3187 tok = document.body[ertcontdivline].find('}<')
3189 regexp = re.compile(r'.*\}<', re.IGNORECASE)
3190 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3191 tok = document.body[ertcontdivline].find('}<')
3193 if ertcontfirstline < ertcontlastline:
3194 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3195 document.body[ertcontlastline : ertcontlastline + 1] = [
3196 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3197 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3198 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3199 'status collapsed', '', '\\begin_layout Plain Layout',
3200 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3201 document.body[ertcontdivline][tok + 2:]]
3203 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3204 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3205 'status collapsed', '', '\\begin_layout Plain Layout',
3206 document.body[ertcontdivline][tok + 2:]]
3208 # check if have delimiters in two different ERTs
3209 tok = document.body[ertcontdivline].find('}')
3211 regexp = re.compile(r'.*\}', re.IGNORECASE)
3212 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3213 tok = document.body[ertcontdivline].find('}')
3215 tokk = document.body[ertcontdivline].find('<')
3217 regexp = re.compile(r'.*<', re.IGNORECASE)
3218 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, lastertend)
3219 tokk = document.body[ertcontdivlinetwo].find('<')
3221 if ertcontfirstline < ertcontlastline:
3222 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3223 document.body[ertcontlastline : ertcontlastline + 1] = [
3224 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3225 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3226 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3227 '\\end_inset', '', '', '\\begin_inset Argument 1',
3228 'status collapsed', '', '\\begin_layout Plain Layout',
3229 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3230 document.body[ertcontdivlinetwo][tokk + 1:]]
3232 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3233 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3234 'status collapsed', '', '\\begin_layout Plain Layout',
3235 document.body[ertcontdivlinetwo][tokk + 1:]]
3236 # Convert to ArgInset
3237 if ertcontfirstline < ertcontlastline:
3238 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3239 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3240 'status collapsed', '', '\\begin_layout Plain Layout',
3241 '\\begin_inset ERT', '']
3243 document.body[parbeg] = "\\begin_inset Argument 2"
3244 elif count_pars_in_inset(document.body, ertcontfirstline) > 1:
3245 # Multipar ERT. Skip this.
3248 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, False)
3251 j = find_end_of_layout(document.body, i)
3253 document.warning("end of layout not found!")
3254 k = find_token(document.body, "\\begin_inset Argument", i, j)
3256 document.warning("InsetArgument not found!")
3258 l = find_end_of_inset(document.body, k)
3259 m = find_token(document.body, "\\begin_inset ERT", l, j)
3262 ertcontfirstline = m + 5
3267 def convert_overprint(document):
3268 " Convert old beamer overprint layouts to ERT "
3270 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3271 if document.textclass not in beamer_classes:
3276 i = find_token(document.body, "\\begin_layout Overprint", i)
3279 # Find end of sequence
3280 j = find_end_of_sequence(document.body, i)
3282 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3286 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3288 if document.body[j] == "\\end_deeper":
3289 esubst = ["", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3291 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3292 endseq = endseq + len(esubst) - len(document.body[j : j])
3293 document.body[j : j] = esubst
3294 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3296 argend = find_end_of_layout(document.body, argbeg)
3298 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3301 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3302 endPlain = find_end_of_layout(document.body, beginPlain)
3303 content = document.body[beginPlain + 1 : endPlain]
3305 endseq = endseq - len(document.body[argbeg : argend + 1])
3307 del document.body[argbeg : argend + 1]
3308 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3310 endseq = endseq - len(document.body[i : i])
3311 document.body[i : i] = subst + ["\\end_layout"]
3312 endseq += len(subst)
3314 for p in range(i, endseq):
3315 if document.body[p] == "\\begin_layout Overprint":
3316 document.body[p] = "\\begin_layout Standard"
3321 def revert_overprint(document):
3322 " Revert old beamer overprint layouts to ERT "
3324 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3325 if document.textclass not in beamer_classes:
3330 i = find_token(document.body, "\\begin_layout Overprint", i)
3333 # Find end of sequence
3334 j = find_end_of_sequence(document.body, i)
3336 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3340 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3341 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}")
3342 endseq = endseq + len(esubst) - len(document.body[j : j])
3343 if document.body[j] == "\\end_deeper":
3344 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3346 document.body[j : j] = ["\\end_layout", ""] + esubst
3349 if document.body[r] == "\\begin_deeper":
3350 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3352 document.body[r] = ""
3353 document.body[s] = ""
3357 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3359 # Is this really our argument?
3360 nested = find_token(document.body, "\\begin_deeper", i, argbeg)
3362 argend = find_end_of_inset(document.body, argbeg)
3364 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3367 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3368 endPlain = find_end_of_layout(document.body, beginPlain)
3369 content = document.body[beginPlain + 1 : endPlain]
3371 endseq = endseq - len(document.body[argbeg : argend])
3373 del document.body[argbeg : argend + 1]
3374 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3376 endseq = endseq - len(document.body[i : i])
3377 document.body[i : i] = subst + ["\\end_layout"]
3378 endseq += len(subst)
3384 if document.body[p] == "\\begin_layout Overprint":
3385 q = find_end_of_layout(document.body, p)
3387 document.warning("Malformed LyX document. Cannot find end of Overprint layout!")
3390 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\onslide")
3391 argbeg = find_token(document.body, "\\begin_inset Argument item:1", p, q)
3393 argend = find_end_of_inset(document.body, argbeg)
3395 document.warning("Malformed LyX document. Cannot find end of Overprint item argument!")
3398 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3399 endPlain = find_end_of_layout(document.body, beginPlain)
3400 content = document.body[beginPlain + 1 : endPlain]
3402 endseq = endseq - len(document.body[argbeg : argend + 1])
3404 del document.body[argbeg : argend + 1]
3405 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3406 endseq = endseq - len(document.body[p : p + 1]) + len(subst)
3407 document.body[p : p + 1] = subst
3413 def revert_frametitle(document):
3414 " Reverts beamer frametitle layout to ERT "
3416 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3417 if document.textclass not in beamer_classes:
3420 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3423 i = find_token(document.body, "\\begin_layout FrameTitle", i)
3426 j = find_end_of_layout(document.body, i)
3428 document.warning("Malformed LyX document: Can't find end of FrameTitle layout")
3432 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
3433 endlay += len(put_cmd_in_ert("}"))
3434 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\frametitle")
3435 for p in range(i, j):
3438 m = rx.match(document.body[p])
3442 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3443 endPlain = find_end_of_layout(document.body, beginPlain)
3444 endInset = find_end_of_inset(document.body, p)
3445 content = document.body[beginPlain + 1 : endPlain]
3447 endlay = endlay - len(document.body[p : endInset + 1])
3449 del document.body[p : endInset + 1]
3450 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3452 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3453 endPlain = find_end_of_layout(document.body, beginPlain)
3454 endInset = find_end_of_inset(document.body, p)
3455 content = document.body[beginPlain + 1 : endPlain]
3457 endlay = endlay - len(document.body[p : endInset + 1])
3459 del document.body[p : endInset + 1]
3460 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3462 subst += put_cmd_in_ert("{")
3463 document.body[i : i + 1] = subst
3467 def convert_epigraph(document):
3468 " Converts memoir epigraph to new syntax "
3470 if document.textclass != "memoir":
3475 i = find_token(document.body, "\\begin_layout Epigraph", i)
3478 j = find_end_of_layout(document.body, i)
3480 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3485 ert = find_token(document.body, "\\begin_inset ERT", i, j)
3487 endInset = find_end_of_inset(document.body, ert)
3488 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", ert)
3489 endPlain = find_end_of_layout(document.body, beginPlain)
3490 ertcont = beginPlain + 2
3491 if document.body[ertcont] == "}{":
3493 # Convert to ArgInset
3494 endlay = endlay - 2 * len(document.body[j])
3495 begsubst = ['\\begin_inset Argument post:1', 'status collapsed', '',
3496 '\\begin_layout Plain Layout']
3497 endsubst = ['\\end_layout', '', '\\end_inset', '', document.body[j]]
3498 document.body[j : j + 1] = endsubst
3499 document.body[endInset + 1 : endInset + 1] = begsubst
3501 endlay += len(begsubst) + len(endsubst)
3502 endlay = endlay - len(document.body[ert : endInset + 1])
3503 del document.body[ert : endInset + 1]
3508 def revert_epigraph(document):
3509 " Reverts memoir epigraph argument to ERT "
3511 if document.textclass != "memoir":
3516 i = find_token(document.body, "\\begin_layout Epigraph", i)
3519 j = find_end_of_layout(document.body, i)
3521 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3526 p = find_token(document.body, "\\begin_layout Argument post:1", i, j)
3528 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3529 endPlain = find_end_of_layout(document.body, beginPlain)
3530 endInset = find_end_of_inset(document.body, p)
3531 content = document.body[beginPlain + 1 : endPlain]
3533 endlay = endlay - len(document.body[p : endInset + 1])
3535 del document.body[p : endInset + 1]
3536 subst += put_cmd_in_ert("}{") + content
3538 subst += put_cmd_in_ert("}{")
3540 document.body[j : j] = subst + document.body[j : j]
3544 def convert_captioninsets(document):
3545 " Converts caption insets to new syntax "
3549 i = find_token(document.body, "\\begin_inset Caption", i)
3552 document.body[i] = "\\begin_inset Caption Standard"
3556 def revert_captioninsets(document):
3557 " Reverts caption insets to old syntax "
3561 i = find_token(document.body, "\\begin_inset Caption Standard", i)
3564 document.body[i] = "\\begin_inset Caption"
3568 def convert_captionlayouts(document):
3569 " Convert caption layouts to caption insets. "
3572 "Captionabove": "Above",
3573 "Captionbelow": "Below",
3574 "FigCaption" : "FigCaption",
3575 "Table_Caption" : "Table",
3576 "CenteredCaption" : "Centered",
3577 "Bicaption" : "Bicaption",
3582 i = find_token(document.body, "\\begin_layout", i)
3585 val = get_value(document.body, "\\begin_layout", i)
3586 if val in caption_dict.keys():
3587 j = find_end_of_layout(document.body, i)
3589 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3592 document.body[j:j] = ["\\end_layout", "", "\\end_inset", "", ""]
3593 document.body[i:i+1] = ["\\begin_layout %s" % document.default_layout,
3594 "\\begin_inset Caption %s" % caption_dict[val], "",
3595 "\\begin_layout %s" % document.default_layout]
3599 def revert_captionlayouts(document):
3600 " Revert caption insets to caption layouts. "
3603 "Above" : "Captionabove",
3604 "Below" : "Captionbelow",
3605 "FigCaption" : "FigCaption",
3606 "Table" : "Table_Caption",
3607 "Centered" : "CenteredCaption",
3608 "Bicaption" : "Bicaption",
3612 rx = re.compile(r'^\\begin_inset Caption (\S+)$')
3614 i = find_token(document.body, "\\begin_inset Caption", i)
3618 m = rx.match(document.body[i])
3622 if val not in caption_dict.keys():
3626 # We either need to delete the previous \begin_layout line, or we
3627 # need to end the previous layout if this inset is not in the first
3628 # position of the paragraph.
3629 layout_before = find_token_backwards(document.body, "\\begin_layout", i)
3630 if layout_before == -1:
3631 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3633 layout_line = document.body[layout_before]
3634 del_layout_before = True
3635 l = layout_before + 1
3637 if document.body[l] != "":
3638 del_layout_before = False
3641 if del_layout_before:
3642 del document.body[layout_before:i]
3645 document.body[i:i] = ["\\end_layout", ""]
3648 # Find start of layout in the inset and end of inset
3649 j = find_token(document.body, "\\begin_layout", i)
3651 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3653 k = find_end_of_inset(document.body, i)
3655 document.warning("Malformed LyX document: Missing `\\end_inset'.")
3658 # We either need to delete the following \end_layout line, or we need
3659 # to restart the old layout if this inset is not at the paragraph end.
3660 layout_after = find_token(document.body, "\\end_layout", k)
3661 if layout_after == -1:
3662 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3664 del_layout_after = True
3666 while l < layout_after:
3667 if document.body[l] != "":
3668 del_layout_after = False
3671 if del_layout_after:
3672 del document.body[k+1:layout_after+1]
3674 document.body[k+1:k+1] = [layout_line, ""]
3676 # delete \begin_layout and \end_inset and replace \begin_inset with
3677 # "\begin_layout XXX". This works because we can only have one
3678 # paragraph in the caption inset: The old \end_layout will be recycled.
3679 del document.body[k]
3680 if document.body[k] == "":
3681 del document.body[k]
3682 del document.body[j]
3683 if document.body[j] == "":
3684 del document.body[j]
3685 document.body[i] = "\\begin_layout %s" % caption_dict[val]
3686 if document.body[i+1] == "":
3687 del document.body[i+1]
3691 def revert_fragileframe(document):
3692 " Reverts beamer FragileFrame layout to ERT "
3694 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3695 if document.textclass not in beamer_classes:
3700 i = find_token(document.body, "\\begin_layout FragileFrame", i)
3703 # Find end of sequence
3704 j = find_end_of_sequence(document.body, i)
3706 document.warning("Malformed LyX document. Cannot find end of FragileFrame sequence!")
3710 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{frame}")
3711 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{frame}")
3712 endseq = endseq + len(esubst) - len(document.body[j : j])
3713 if document.body[j] == "\\end_deeper":
3714 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3716 document.body[j : j] = esubst
3717 for q in range(i, j):
3718 if document.body[q] == "\\begin_layout FragileFrame":
3719 document.body[q] = "\\begin_layout %s" % document.default_layout
3722 if document.body[r] == "\\begin_deeper":
3723 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3725 document.body[r] = ""
3726 document.body[s] = ""
3730 for p in range(1, 5):
3731 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, j)
3734 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3735 endPlain = find_end_of_layout(document.body, beginPlain)
3736 endInset = find_end_of_inset(document.body, arg)
3737 content = document.body[beginPlain + 1 : endPlain]
3739 j = j - len(document.body[arg : endInset + 1])
3741 del document.body[arg : endInset + 1]
3742 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3744 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3745 endPlain = find_end_of_layout(document.body, beginPlain)
3746 endInset = find_end_of_inset(document.body, arg)
3747 content = document.body[beginPlain + 1 : endPlain]
3749 j = j - len(document.body[arg : endInset + 1])
3751 del document.body[arg : endInset + 1]
3752 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3754 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3755 endPlain = find_end_of_layout(document.body, beginPlain)
3756 endInset = find_end_of_inset(document.body, arg)
3757 content = document.body[beginPlain + 1 : endPlain]
3759 j = j - len(document.body[arg : endInset + 1])
3761 del document.body[arg : endInset + 1]
3762 subst += put_cmd_in_ert("[fragile,") + content + put_cmd_in_ert("]")
3764 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3765 endPlain = find_end_of_layout(document.body, beginPlain)
3766 endInset = find_end_of_inset(document.body, arg)
3767 content = document.body[beginPlain + 1 : endPlain]
3769 j = j - len(document.body[arg : endInset + 1])
3771 del document.body[arg : endInset + 1]
3772 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3774 subst += put_cmd_in_ert("[fragile]")
3776 document.body[i : i + 1] = subst
3780 def revert_newframes(document):
3781 " Reverts beamer Frame and PlainFrame layouts to old forms "
3783 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3784 if document.textclass not in beamer_classes:
3788 "Frame" : "BeginFrame",
3789 "PlainFrame" : "BeginPlainFrame",
3792 rx = re.compile(r'^\\begin_layout (\S+)$')
3795 i = find_token(document.body, "\\begin_layout", i)
3799 m = rx.match(document.body[i])
3803 if val not in frame_dict.keys():
3806 # Find end of sequence
3807 j = find_end_of_sequence(document.body, i)
3809 document.warning("Malformed LyX document. Cannot find end of Frame sequence!")
3813 subst = ["\\begin_layout %s" % frame_dict[val]]
3814 esubst = ["", "\\begin_layout EndFrame", "", "\\end_layout"]
3815 endseq = endseq + len(esubst) - len(document.body[j : j])
3816 if document.body[j] == "\\end_deeper":
3817 document.body[j : j] = esubst
3819 document.body[j+1 : j+1] = esubst
3820 for q in range(i, j):
3821 if document.body[q] == "\\begin_layout %s" % val:
3822 document.body[q] = "\\begin_layout %s" % document.default_layout
3825 if document.body[r] == "\\begin_deeper":
3826 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3828 document.body[r] = ""
3829 document.body[s] = ""
3833 l = find_end_of_layout(document.body, i)
3834 for p in range(1, 5):
3835 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, l)
3838 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3839 endPlain = find_end_of_layout(document.body, beginPlain)
3840 endInset = find_end_of_inset(document.body, arg)
3841 content = document.body[beginPlain + 1 : endPlain]
3843 l = l - len(document.body[arg : endInset + 1])
3845 del document.body[arg : endInset + 1]
3846 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3848 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3849 endPlain = find_end_of_layout(document.body, beginPlain)
3850 endInset = find_end_of_inset(document.body, arg)
3851 content = document.body[beginPlain + 1 : endPlain]
3853 l = l - len(document.body[arg : endInset + 1])
3855 del document.body[arg : endInset + 1]
3856 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3858 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3859 endPlain = find_end_of_layout(document.body, beginPlain)
3860 endInset = find_end_of_inset(document.body, arg)
3861 content = document.body[beginPlain + 1 : endPlain]
3863 l = l - len(document.body[arg : endInset + 1])
3865 del document.body[arg : endInset + 1]
3866 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3868 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3869 endPlain = find_end_of_layout(document.body, beginPlain)
3870 endInset = find_end_of_inset(document.body, arg)
3871 content = document.body[beginPlain + 1 : endPlain]
3873 l = l - len(document.body[arg : endInset + 1])
3875 del document.body[arg : endInset + 1]
3878 document.body[i : i + 1] = subst
3881 # known encodings that do not change their names (same LyX and LaTeX names)
3882 known_enc_tuple = ("auto", "default", "ansinew", "applemac", "armscii8", "ascii",
3883 "cp437", "cp437de", "cp850", "cp852", "cp855", "cp858", "cp862", "cp865", "cp866",
3884 "cp1250", "cp1251", "cp1252", "cp1255", "cp1256", "cp1257", "koi8-r", "koi8-u",
3885 "pt154", "pt254", "tis620-0", "utf8", "utf8x", "utf8-plain")
3887 def convert_encodings(document):
3888 "Use the LyX names of the encodings instead of the LaTeX names."
3889 LaTeX2LyX_enc_dict = {
3890 "8859-6": "iso8859-6",
3891 "8859-8": "iso8859-8",
3893 "euc": "euc-jp-platex",
3898 "iso88595": "iso8859-5",
3899 "iso-8859-7": "iso8859-7",
3901 "jis": "jis-platex",
3903 "l7xenc": "iso8859-13",
3904 "latin1": "iso8859-1",
3905 "latin2": "iso8859-2",
3906 "latin3": "iso8859-3",
3907 "latin4": "iso8859-4",
3908 "latin5": "iso8859-9",
3909 "latin9": "iso8859-15",
3910 "latin10": "iso8859-16",
3911 "SJIS": "shift-jis",
3912 "sjis": "shift-jis-platex",
3915 i = find_token(document.header, "\\inputencoding" , 0)
3918 val = get_value(document.header, "\\inputencoding", i)
3919 if val in LaTeX2LyX_enc_dict.keys():
3920 document.header[i] = "\\inputencoding %s" % LaTeX2LyX_enc_dict[val]
3921 elif val not in known_enc_tuple:
3922 document.warning("Ignoring unknown input encoding: `%s'" % val)
3925 def revert_encodings(document):
3926 """Revert to using the LaTeX names of the encodings instead of the LyX names.
3927 Also revert utf8-platex to sjis, the language default when using Japanese.
3929 LyX2LaTeX_enc_dict = {
3934 "euc-jp-platex": "euc",
3937 "iso8859-1": "latin1",
3938 "iso8859-2": "latin2",
3939 "iso8859-3": "latin3",
3940 "iso8859-4": "latin4",
3941 "iso8859-5": "iso88595",
3942 "iso8859-6": "8859-6",
3943 "iso8859-7": "iso-8859-7",
3944 "iso8859-8": "8859-8",
3945 "iso8859-9": "latin5",
3946 "iso8859-13": "l7xenc",
3947 "iso8859-15": "latin9",
3948 "iso8859-16": "latin10",
3950 "jis-platex": "jis",
3951 "shift-jis": "SJIS",
3952 "shift-jis-platex": "sjis",
3954 "utf8-platex": "sjis"
3956 i = find_token(document.header, "\\inputencoding" , 0)
3959 val = get_value(document.header, "\\inputencoding", i)
3960 if val in LyX2LaTeX_enc_dict.keys():
3961 document.header[i] = "\\inputencoding %s" % LyX2LaTeX_enc_dict[val]
3962 elif val not in known_enc_tuple:
3963 document.warning("Ignoring unknown input encoding: `%s'" % val)
3966 def revert_IEEEtran_3(document):
3968 Reverts Flex Insets to TeX-code
3970 if document.textclass == "IEEEtran":
3976 h = find_token(document.body, "\\begin_inset Flex Author Mark", h)
3978 endh = find_end_of_inset(document.body, h)
3979 document.body[endh - 2 : endh + 1] = put_cmd_in_ert("}")
3980 document.body[h : h + 4] = put_cmd_in_ert("\\IEEEauthorrefmark{")
3983 i = find_token(document.body, "\\begin_inset Flex Author Name", i)
3985 endi = find_end_of_inset(document.body, i)
3986 document.body[endi - 2 : endi + 1] = put_cmd_in_ert("}")
3987 document.body[i : i + 4] = put_cmd_in_ert("\\IEEEauthorblockN{")
3990 j = find_token(document.body, "\\begin_inset Flex Author Affiliation", j)
3992 endj = find_end_of_inset(document.body, j)
3993 document.body[endj - 2 : endj + 1] = put_cmd_in_ert("}")
3994 document.body[j : j + 4] = put_cmd_in_ert("\\IEEEauthorblockA{")
3996 if i == -1 and j == -1 and h == -1:
4000 def revert_kurier_fonts(document):
4001 " Revert kurier font definition to LaTeX "
4003 i = find_token(document.header, "\\font_math", 0)
4005 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4006 val = get_value(document.header, "\\font_math", i)
4007 if val == "kurier-math":
4008 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
4009 "\\usepackage[math]{kurier}\n" \
4010 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
4011 document.header[i] = "\\font_math auto"
4013 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4014 kurier_fonts = ["kurier", "kurierc", "kurierl", "kurierlc"]
4015 k = find_token(document.header, "\\font_sans kurier", 0)
4017 sf = get_value(document.header, "\\font_sans", k)
4018 if sf in kurier_fonts:
4019 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4020 document.header[k] = "\\font_sans default"
4022 def revert_iwona_fonts(document):
4023 " Revert iwona font definition to LaTeX "
4025 i = find_token(document.header, "\\font_math", 0)
4027 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4028 val = get_value(document.header, "\\font_math", i)
4029 if val == "iwona-math":
4030 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
4031 "\\usepackage[math]{iwona}\n" \
4032 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
4033 document.header[i] = "\\font_math auto"
4035 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4036 iwona_fonts = ["iwona", "iwonac", "iwonal", "iwonalc"]
4037 k = find_token(document.header, "\\font_sans iwona", 0)
4039 sf = get_value(document.header, "\\font_sans", k)
4040 if sf in iwona_fonts:
4041 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4042 document.header[k] = "\\font_sans default"
4045 def revert_new_libertines(document):
4046 " Revert new libertine font definition to LaTeX "
4048 if find_token(document.header, "\\use_non_tex_fonts true", 0) != -1:
4051 i = find_token(document.header, "\\font_typewriter libertine-mono", 0)
4053 preamble = "\\usepackage"
4054 sc = find_token(document.header, "\\font_tt_scale", 0)
4056 scval = get_value(document.header, "\\font_tt_scale", sc)
4058 preamble += "[scale=%f]" % (float(scval) / 100)
4059 document.header[sc] = "\\font_tt_scale 100"
4060 preamble += "{libertineMono-type1}"
4061 add_to_preamble(document, [preamble])
4062 document.header[i] = "\\font_typewriter default"
4064 k = find_token(document.header, "\\font_sans biolinum", 0)
4066 preamble = "\\usepackage"
4068 j = find_token(document.header, "\\font_osf true", 0)
4073 sc = find_token(document.header, "\\font_sf_scale", 0)
4075 scval = get_value(document.header, "\\font_sf_scale", sc)
4077 options += ",scale=%f" % (float(scval) / 100)
4078 document.header[sc] = "\\font_sf_scale 100"
4080 preamble += "[" + options +"]"
4081 preamble += "{biolinum-type1}"
4082 add_to_preamble(document, [preamble])
4083 document.header[k] = "\\font_sans default"
4086 def convert_lyxframes(document):
4087 " Converts old beamer frames to new style "
4089 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4090 if document.textclass not in beamer_classes:
4093 framebeg = ["BeginFrame", "BeginPlainFrame"]
4094 frameend = ["Frame", "PlainFrame", "EndFrame", "BeginFrame", "BeginPlainFrame", "AgainFrame",
4095 "Section", "Section*", "Subsection", "Subsection*", "Subsubsection", "Subsubsection*"]
4096 for lay in framebeg:
4099 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
4102 parent = get_containing_layout(document.body, i)
4103 if parent == False or parent[1] != i:
4104 document.warning("Wrong parent layout!")
4107 frametype = parent[0]
4111 # Step I: Convert ERT arguments
4112 # FIXME: See restrictions in convert_beamerframeargs method
4113 ertend = convert_beamerframeargs(document, i, parbeg)
4116 # Step II: Now rename the layout and convert the title to an argument
4117 j = find_end_of_layout(document.body, i)
4118 document.body[j : j + 1] = ['\\end_layout', '', '\\end_inset', '', '\\end_layout']
4119 if lay == "BeginFrame":
4120 document.body[i] = "\\begin_layout Frame"
4122 document.body[i] = "\\begin_layout PlainFrame"
4123 document.body[ertend + 1 : ertend + 1] = ['\\begin_inset Argument 4',
4124 'status open', '', '\\begin_layout Plain Layout']
4125 # Step III: find real frame end
4129 fend = find_token(document.body, "\\begin_layout", jj)
4131 document.warning("Malformed LyX document: No real frame end!")
4133 val = get_value(document.body, "\\begin_layout", fend)
4134 if val not in frameend:
4137 old = document.body[fend]
4138 if val == frametype:
4139 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4140 # consider explicit EndFrames between two identical frame types
4141 elif val == "EndFrame":
4142 nextlayout = find_token(document.body, "\\begin_layout", fend + 1)
4143 if nextlayout != -1 and get_value(document.body, "\\begin_layout", nextlayout) == frametype:
4144 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4146 document.body[fend : fend] = ['\\end_deeper']
4148 document.body[fend : fend] = ['\\end_deeper']
4149 document.body[j + 1 : j + 1] = ['', '\\begin_deeper']
4154 def remove_endframes(document):
4155 " Remove deprecated beamer endframes "
4157 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4158 if document.textclass not in beamer_classes:
4163 i = find_token_exact(document.body, "\\begin_layout EndFrame", i)
4166 j = find_end_of_layout(document.body, i)
4168 document.warning("Malformed LyX document: Missing \\end_layout to EndFrame")
4171 del document.body[i : j + 1]
4174 def revert_powerdot_flexes(document):
4175 " Reverts powerdot flex insets "
4177 if document.textclass != "powerdot":
4180 flexes = {"Onslide" : "\\onslide",
4181 "Onslide*" : "\\onslide*",
4182 "Onslide+" : "\\onslide+"}
4183 rx = re.compile(r'^\\begin_inset Flex (.+)$')
4187 i = find_token(document.body, "\\begin_inset Flex", i)
4190 m = rx.match(document.body[i])
4192 flextype = m.group(1)
4193 z = find_end_of_inset(document.body, i)
4195 document.warning("Can't find end of Flex " + flextype + " inset.")
4198 if flextype in flexes:
4199 pre = put_cmd_in_ert(flexes[flextype])
4200 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
4202 argend = find_end_of_inset(document.body, arg)
4204 document.warning("Can't find end of Argument!")
4207 # Find containing paragraph layout
4208 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
4209 endPlain = find_end_of_layout(document.body, beginPlain)
4210 argcontent = document.body[beginPlain + 1 : endPlain]
4212 z = z - len(document.body[arg : argend + 1])
4214 del document.body[arg : argend + 1]
4215 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
4216 pre += put_cmd_in_ert("{")
4217 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4218 endPlain = find_end_of_layout(document.body, beginPlain)
4220 z = z - len(document.body[i : beginPlain + 1])
4222 document.body[i : beginPlain + 1] = pre
4223 post = put_cmd_in_ert("}")
4224 document.body[z - 2 : z + 1] = post
4228 def revert_powerdot_pause(document):
4229 " Reverts powerdot pause layout to ERT "
4231 if document.textclass != "powerdot":
4236 i = find_token(document.body, "\\begin_layout Pause", i)
4239 j = find_end_of_layout(document.body, i)
4241 document.warning("Malformed LyX document: Can't find end of Pause layout")
4245 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\pause")
4246 for p in range(i, j):
4249 arg = find_token(document.body, "\\begin_inset Argument 1", i, j)
4251 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4252 endPlain = find_end_of_layout(document.body, beginPlain)
4253 endInset = find_end_of_inset(document.body, p)
4254 content = document.body[beginPlain + 1 : endPlain]
4256 endlay = endlay - len(document.body[p : endInset + 1])
4258 del document.body[p : endInset + 1]
4259 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4261 document.body[i : i + 1] = subst
4265 def revert_powerdot_itemargs(document):
4266 " Reverts powerdot item arguments to ERT "
4268 if document.textclass != "powerdot":
4272 list_layouts = ["Itemize", "ItemizeType1", "Enumerate", "EnumerateType1"]
4273 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4276 i = find_token(document.body, "\\begin_inset Argument", i)
4279 # Find containing paragraph layout
4280 parent = get_containing_layout(document.body, i)
4282 document.warning("Malformed LyX document: Can't find parent paragraph layout")
4287 realparbeg = parent[3]
4288 layoutname = parent[0]
4290 for p in range(parbeg, parend):
4294 if layoutname in list_layouts:
4295 m = rx.match(document.body[p])
4298 if argnr == "item:1":
4299 j = find_end_of_inset(document.body, i)
4300 # Find containing paragraph layout
4301 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4302 endPlain = find_end_of_layout(document.body, beginPlain)
4303 content = document.body[beginPlain + 1 : endPlain]
4304 del document.body[i:j+1]
4305 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4306 document.body[realparbeg : realparbeg] = subst
4307 elif argnr == "item:2":
4308 j = find_end_of_inset(document.body, i)
4309 # Find containing paragraph layout
4310 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4311 endPlain = find_end_of_layout(document.body, beginPlain)
4312 content = document.body[beginPlain + 1 : endPlain]
4313 del document.body[i:j+1]
4314 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
4315 document.body[realparbeg : realparbeg] = subst
4320 def revert_powerdot_columns(document):
4321 " Reverts powerdot twocolumn to TeX-code "
4322 if document.textclass != "powerdot":
4325 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4328 i = find_token(document.body, "\\begin_layout Twocolumn", i)
4331 j = find_end_of_layout(document.body, i)
4333 document.warning("Malformed LyX document: Can't find end of Twocolumn layout")
4337 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
4338 endlay += len(put_cmd_in_ert("}"))
4339 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\twocolumn")
4340 for p in range(i, j):
4343 m = rx.match(document.body[p])
4347 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4348 endPlain = find_end_of_layout(document.body, beginPlain)
4349 endInset = find_end_of_inset(document.body, p)
4350 content = document.body[beginPlain + 1 : endPlain]
4352 endlay = endlay - len(document.body[p : endInset + 1])
4354 del document.body[p : endInset + 1]
4355 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4357 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4358 endPlain = find_end_of_layout(document.body, beginPlain)
4359 endInset = find_end_of_inset(document.body, p)
4360 content = document.body[beginPlain + 1 : endPlain]
4362 endlay = endlay - len(document.body[p : endInset + 1])
4364 del document.body[p : endInset + 1]
4365 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
4367 subst += put_cmd_in_ert("{")
4368 document.body[i : i + 1] = subst
4372 def revert_mbox_fbox(document):
4373 'Convert revert mbox/fbox boxes to TeX-code'
4376 i = find_token(document.body, "\\begin_inset Box", i)
4379 j = find_token(document.body, "width", i)
4381 document.warning("Malformed LyX document: Can't find box width")
4383 width = get_value(document.body, "width", j)
4384 k = find_end_of_inset(document.body, j)
4386 document.warning("Malformed LyX document: Can't find end of box inset")
4389 BeginLayout = find_token(document.body, "\\begin_layout Plain Layout", j)
4390 EndLayout = find_end_of_layout(document.body, BeginLayout)
4391 # replace if width is ""
4393 document.body[EndLayout:k + 1] = put_cmd_in_ert("}")
4394 if document.body[i] == "\\begin_inset Box Frameless":
4395 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\mbox{")
4396 if document.body[i] == "\\begin_inset Box Boxed":
4397 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\fbox{")
4401 def revert_starred_caption(document):
4402 " Reverts unnumbered longtable caption insets "
4406 i = find_token(document.body, "\\begin_inset Caption LongTableNoNumber", i)
4409 # This is not equivalent, but since the caption inset is a full blown
4410 # text inset a true conversion to ERT is too difficult.
4411 document.body[i] = "\\begin_inset Caption Standard"
4415 def revert_forced_local_layout(document):
4418 i = find_token(document.header, "\\begin_forced_local_layout", i)
4421 j = find_end_of(document.header, i, "\\begin_forced_local_layout", "\\end_forced_local_layout")
4423 # this should not happen
4425 regexp = re.compile(r'\s*forcelocal', re.IGNORECASE)
4426 k = find_re(document.header, regexp, i, j)
4428 del document.header[k]
4430 k = find_re(document.header, regexp, i, j)
4431 k = find_token(document.header, "\\begin_local_layout", 0)
4433 document.header[i] = "\\begin_local_layout"
4434 document.header[j] = "\\end_local_layout"
4436 l = find_end_of(document.header, k, "\\begin_local_layout", "\\end_local_layout")
4438 # this should not happen
4440 lines = document.header[i+1 : j]
4442 document.header[k+1 : k+1] = lines
4443 document.header[i : j ] = []
4445 document.header[i : j ] = []
4446 document.header[k+1 : k+1] = lines
4449 def revert_aa1(document):
4450 " Reverts InsetArguments of aa to TeX-code "
4451 if document.textclass == "aa":
4455 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4457 revert_Argument_to_TeX_brace(document, i, 0, 1, 4, False, False)
4463 def revert_aa2(document):
4464 " Reverts InsetArguments of aa to TeX-code "
4465 if document.textclass == "aa":
4469 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4471 document.body[i] = "\\begin_layout Abstract"
4477 def revert_tibetan(document):
4478 "Set the document language for Tibetan to English"
4480 if document.language == "tibetan":
4481 document.language = "english"
4482 i = find_token(document.header, "\\language", 0)
4484 document.header[i] = "\\language english"
4486 while j < len(document.body):
4487 j = find_token(document.body, "\\lang tibetan", j)
4489 document.body[j] = document.body[j].replace("\\lang tibetan", "\\lang english")
4492 j = len(document.body)
4501 # The idea here is that we will have a sequence of chunk paragraphs.
4502 # We want to convert them to paragraphs in one or several chunk insets.
4503 # Individual chunks are terminated by the character @ on the last line.
4504 # This line will be discarded, and following lines are treated as new
4505 # chunks, which go into their own insets.
4506 # The first line of a chunk should look like: <<CONTENT>>=
4507 # We will discard the delimiters, and put the CONTENT into the
4508 # optional argument of the inset, if the CONTENT is non-empty.
4509 def convert_chunks(document):
4510 first_re = re.compile(r'<<(.*)>>=(.*)')
4513 # find start of a block of chunks
4514 i = find_token(document.body, "\\begin_layout Chunk", file_pos)
4520 chunk_started = False
4523 # process the one we just found
4524 j = find_end_of_layout(document.body, i)
4526 document.warning("Malformed LyX documents. Can't find end of Chunk layout!")
4527 # there is no point continuing, as we will run into the same error again.
4529 this_chunk = "".join(document.body[i + 1:j])
4531 # there may be empty lines between chunks
4532 # we just skip them.
4533 if not chunk_started:
4534 if this_chunk != "":
4536 chunk_started = True
4539 contents.append(document.body[i + 1:j])
4541 # look for potential chunk terminator
4542 # on the last line of the chunk paragraph
4543 if document.body[j - 1] == "@":
4546 # look for subsequent chunk paragraph
4547 i = find_token(document.body, "\\begin_layout", j)
4551 if get_value(document.body, "\\begin_layout", i) != "Chunk":
4554 file_pos = end = j + 1
4556 # The last chunk should simply have an "@" in it
4557 # or at least end with "@" (can happen if @ is
4558 # preceded by a newline)
4559 lastpar = ''.join(contents[-1])
4560 if not lastpar.endswith("@"):
4561 document.warning("Unexpected chunk content: chunk not terminated by '@'!")
4565 # chunk par only contains "@". Just drop it.
4568 # chunk par contains more. Only drop the "@".
4571 # The first line should look like: <<CONTENT>>=
4572 # We want the CONTENT
4573 optarg = ' '.join(contents[0])
4575 # We can already have real chunk content in
4576 # the first par (separated from the options by a newline).
4577 # We collect such stuff to re-insert it later.
4580 match = first_re.search(optarg)
4582 optarg = match.groups()[0]
4583 if match.groups()[1] != "":
4585 for c in contents[0]:
4586 if c.endswith(">>="):
4590 postoptstuff.append(c)
4591 # We have stripped everything. This can be deleted.
4594 newstuff = ['\\begin_layout Standard',
4595 '\\begin_inset Flex Chunk',
4597 '\\begin_layout Plain Layout', '']
4599 # If we have a non-empty optional argument, insert it.
4600 if match and optarg != "":
4602 ['\\begin_inset Argument 1',
4604 '\\begin_layout Plain Layout',
4609 # Since we already opened a Plain layout, the first paragraph
4610 # does not need to do that.
4613 newstuff.extend(postoptstuff)
4614 newstuff.append('\\end_layout')
4618 newstuff.extend(['', '\\begin_layout Plain Layout', ''])
4622 newstuff.append('\\end_layout')
4624 newstuff.extend(['', '\\end_inset', '', '\\end_layout', ''])
4626 document.body[start:end] = newstuff
4628 file_pos += len(newstuff) - (end - start)
4631 def revert_chunks(document):
4634 i = find_token(document.body, "\\begin_inset Flex Chunk", i)
4638 iend = find_end_of_inset(document.body, i)
4640 document.warning("Can't find end of Chunk!")
4644 # Look for optional argument
4646 ostart = find_token(document.body, "\\begin_inset Argument 1", i, iend)
4648 oend = find_end_of_inset(document.body, ostart)
4649 k = find_token(document.body, "\\begin_layout Plain Layout", ostart, oend)
4651 document.warning("Malformed LyX document: Can't find argument contents!")
4653 m = find_end_of_layout(document.body, k)
4654 optarg = "".join(document.body[k+1:m])
4657 # We now remove the optional argument, so we have something
4658 # uniform on which to work
4659 document.body[ostart : oend + 1] = []
4660 # iend is now invalid
4661 iend = find_end_of_inset(document.body, i)
4663 retval = get_containing_layout(document.body, i)
4665 document.warning("Can't find containing layout for Chunk!")
4668 (lname, lstart, lend, pstart) = retval
4669 # we now want to work through the various paragraphs, and collect their contents
4673 k = find_token(document.body, "\\begin_layout Plain Layout", k, lend)
4676 j = find_end_of_layout(document.body, k)
4678 document.warning("Can't find end of layout inside chunk!")
4680 parlist.append(document.body[k+1:j])
4682 # we now need to wrap all of these paragraphs in chunks
4685 newlines.extend(["\\begin_layout Chunk", "", "<<" + optarg + ">>=", "\\end_layout", ""])
4686 for stuff in parlist:
4687 newlines.extend(["\\begin_layout Chunk"] + stuff + ["\\end_layout", ""])
4688 newlines.extend(["\\begin_layout Chunk", "", "@", "\\end_layout", ""])
4689 # replace old content with new content
4690 document.body[lstart : lend + 1] = newlines
4691 i = lstart + len(newlines)
4698 supported_versions = ["2.1.0","2.1"]
4701 [415, [convert_undertilde]],
4703 [417, [convert_japanese_encodings]],
4704 [418, [convert_justification]],
4706 [420, [convert_biblio_style]],
4707 [421, [convert_longtable_captions]],
4708 [422, [convert_use_packages]],
4709 [423, [convert_use_mathtools]],
4710 [424, [convert_cite_engine_type]],
4711 # No convert_cancel, since cancel will be loaded automatically
4712 # in format 425 without any possibility to switch it off.
4713 # This has been fixed in format 464.
4717 [428, [convert_cell_rotation]],
4718 [429, [convert_table_rotation]],
4719 [430, [convert_listoflistings]],
4720 [431, [convert_use_amssymb]],
4722 [433, [convert_armenian]],
4730 [441, [convert_mdnomath]],
4735 [446, [convert_latexargs]],
4736 [447, [convert_IEEEtran, convert_AASTeX, convert_AGUTeX, convert_IJMP, convert_SIGPLAN, convert_SIGGRAPH, convert_EuropeCV, convert_Initials, convert_ModernCV]],
4737 [448, [convert_literate]],
4740 [451, [convert_beamerargs, convert_againframe_args, convert_corollary_args, convert_quote_args]],
4741 [452, [convert_beamerblocks]],
4742 [453, [convert_use_stmaryrd]],
4743 [454, [convert_overprint]],
4745 [456, [convert_epigraph]],
4746 [457, [convert_use_stackrel]],
4747 [458, [convert_captioninsets, convert_captionlayouts]],
4752 [463, [convert_encodings]],
4753 [464, [convert_use_cancel]],
4754 [465, [convert_lyxframes, remove_endframes]],
4760 [471, [convert_cite_engine_type_default]],
4763 [474, [convert_chunks, cleanup_beamerargs]],
4767 [473, [revert_chunks]],
4768 [472, [revert_tibetan]],
4769 [471, [revert_aa1,revert_aa2]],
4770 [470, [revert_cite_engine_type_default]],
4771 [469, [revert_forced_local_layout]],
4772 [468, [revert_starred_caption]],
4773 [467, [revert_mbox_fbox]],
4774 [466, [revert_iwona_fonts]],
4775 [465, [revert_powerdot_flexes, revert_powerdot_pause, revert_powerdot_itemargs, revert_powerdot_columns]],
4777 [463, [revert_use_cancel]],
4778 [462, [revert_encodings]],
4779 [461, [revert_new_libertines]],
4780 [460, [revert_kurier_fonts]],
4781 [459, [revert_IEEEtran_3]],
4782 [458, [revert_fragileframe, revert_newframes]],
4783 [457, [revert_captioninsets, revert_captionlayouts]],
4784 [456, [revert_use_stackrel]],
4785 [455, [revert_epigraph]],
4786 [454, [revert_frametitle]],
4787 [453, [revert_overprint]],
4788 [452, [revert_use_stmaryrd]],
4789 [451, [revert_beamerblocks]],
4790 [450, [revert_beamerargs, revert_beamerargs2, revert_beamerargs3, revert_beamerflex]],
4791 [449, [revert_garamondx, revert_garamondx_newtxmath]],
4792 [448, [revert_itemargs]],
4793 [447, [revert_literate]],
4794 [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]],
4795 [445, [revert_latexargs]],
4796 [444, [revert_uop]],
4797 [443, [revert_biolinum]],
4799 [441, [revert_newtxmath]],
4800 [440, [revert_mdnomath]],
4801 [439, [revert_mathfonts]],
4802 [438, [revert_minionpro]],
4803 [437, [revert_ipadeco, revert_ipachar]],
4804 [436, [revert_texgyre]],
4805 [435, [revert_mathdesign]],
4806 [434, [revert_txtt]],
4807 [433, [revert_libertine]],
4808 [432, [revert_armenian]],
4809 [431, [revert_languages, revert_ancientgreek]],
4810 [430, [revert_use_amssymb]],
4811 [429, [revert_listoflistings]],
4812 [428, [revert_table_rotation]],
4813 [427, [revert_cell_rotation]],
4814 [426, [revert_tipa]],
4815 [425, [revert_verbatim]],
4816 [424, [revert_cancel]],
4817 [423, [revert_cite_engine_type]],
4818 [422, [revert_use_mathtools]],
4819 [421, [revert_use_packages]],
4820 [420, [revert_longtable_captions]],
4821 [419, [revert_biblio_style]],
4822 [418, [revert_australian]],
4823 [417, [revert_justification]],
4824 [416, [revert_japanese_encodings]],
4825 [415, [revert_negative_space, revert_math_spaces]],
4826 [414, [revert_undertilde]],
4827 [413, [revert_visible_space]]
4831 if __name__ == "__main__":