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
3065 # Find the last ERT in this paragraph (which might also be the first)
3066 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
3067 if lastertbeg == -1:
3068 document.warning("Last ERT not found!")
3070 lastertend = find_end_of_inset(document.body, lastertbeg)
3071 if lastertend == -1:
3072 document.warning("End of last ERT not found!")
3074 ertcontlastline = lastertend - 3
3076 if document.body[ertcontfirstline].lstrip().startswith("<"):
3077 # This is an overlay specification
3079 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3080 if document.body[ertcontlastline].rstrip().endswith(">"):
3082 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3083 # Convert to ArgInset
3084 document.body[parbeg] = "\\begin_inset Argument 1"
3085 elif document.body[ertcontlastline].rstrip().endswith("}"):
3087 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3089 ertcontdivline = ertcontfirstline
3090 tok = document.body[ertcontdivline].find('>{')
3092 regexp = re.compile(r'.*>\{', re.IGNORECASE)
3093 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3094 tok = document.body[ertcontdivline].find('>{')
3096 if ertcontfirstline < ertcontlastline:
3097 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3098 document.body[ertcontlastline : ertcontlastline + 1] = [
3099 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3100 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3101 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3102 'status collapsed', '', '\\begin_layout Plain Layout',
3103 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3104 document.body[ertcontdivline][tok + 2:]]
3106 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3107 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3108 'status collapsed', '', '\\begin_layout Plain Layout',
3109 document.body[ertcontdivline][tok + 2:]]
3111 # check if have delimiters in two different ERTs
3112 tok = document.body[ertcontdivline].find('>')
3114 regexp = re.compile(r'.*>', re.IGNORECASE)
3115 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3116 tok = document.body[ertcontdivline].find('>')
3118 tokk = document.body[ertcontdivline].find('{')
3120 regexp = re.compile(r'.*\{', re.IGNORECASE)
3121 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, lastertend)
3122 tokk = document.body[ertcontdivlinetwo].find('{')
3124 if ertcontfirstline < ertcontlastline:
3125 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3126 document.body[ertcontlastline : ertcontlastline + 1] = [
3127 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3128 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3129 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3130 '\\end_inset', '', '', '\\begin_inset Argument 2',
3131 'status collapsed', '', '\\begin_layout Plain Layout',
3132 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3133 document.body[ertcontdivlinetwo][tokk + 1:]]
3135 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3136 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3137 'status collapsed', '', '\\begin_layout Plain Layout',
3138 document.body[ertcontdivlinetwo][tokk + 1:]]
3139 # Convert to ArgInset
3140 if ertcontfirstline < ertcontlastline:
3141 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3142 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 1',
3143 'status collapsed', '', '\\begin_layout Plain Layout',
3144 '\\begin_inset ERT', '']
3146 document.body[parbeg] = "\\begin_inset Argument 1"
3147 elif document.body[ertcontfirstline].lstrip().startswith("{"):
3148 # This is the block title
3149 if document.body[ertcontlastline].rstrip().endswith("}"):
3150 # strip off the braces
3151 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3152 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3153 if ertcontfirstline < ertcontlastline:
3154 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3155 document.body[parend : parend + 1] = [
3156 document.body[parend], '\\end_inset', '', '\\end_layout']
3157 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3158 'status collapsed', '', '\\begin_layout Plain Layout',
3159 '\\begin_inset ERT', '']
3161 # Convert to ArgInset
3162 document.body[parbeg] = "\\begin_inset Argument 2"
3163 # the overlay argument can also follow the title, so ...
3164 elif document.body[ertcontlastline].rstrip().endswith(">"):
3166 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3168 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3170 ertcontdivline = ertcontfirstline
3171 tok = document.body[ertcontdivline].find('}<')
3173 regexp = re.compile(r'.*\}<', re.IGNORECASE)
3174 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3175 tok = document.body[ertcontdivline].find('}<')
3177 if ertcontfirstline < ertcontlastline:
3178 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3179 document.body[ertcontlastline : ertcontlastline + 1] = [
3180 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3181 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3182 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3183 'status collapsed', '', '\\begin_layout Plain Layout',
3184 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3185 document.body[ertcontdivline][tok + 2:]]
3187 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3188 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3189 'status collapsed', '', '\\begin_layout Plain Layout',
3190 document.body[ertcontdivline][tok + 2:]]
3192 # check if have delimiters in two different ERTs
3193 tok = document.body[ertcontdivline].find('}')
3195 regexp = re.compile(r'.*\}', re.IGNORECASE)
3196 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3197 tok = document.body[ertcontdivline].find('}')
3199 tokk = document.body[ertcontdivline].find('<')
3201 regexp = re.compile(r'.*<', re.IGNORECASE)
3202 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, lastertend)
3203 tokk = document.body[ertcontdivlinetwo].find('<')
3205 if ertcontfirstline < ertcontlastline:
3206 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3207 document.body[ertcontlastline : ertcontlastline + 1] = [
3208 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3209 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3210 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3211 '\\end_inset', '', '', '\\begin_inset Argument 1',
3212 'status collapsed', '', '\\begin_layout Plain Layout',
3213 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3214 document.body[ertcontdivlinetwo][tokk + 1:]]
3216 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3217 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3218 'status collapsed', '', '\\begin_layout Plain Layout',
3219 document.body[ertcontdivlinetwo][tokk + 1:]]
3220 # Convert to ArgInset
3221 if ertcontfirstline < ertcontlastline:
3222 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3223 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3224 'status collapsed', '', '\\begin_layout Plain Layout',
3225 '\\begin_inset ERT', '']
3227 document.body[parbeg] = "\\begin_inset Argument 2"
3228 elif count_pars_in_inset(document.body, ertcontfirstline) > 1:
3229 # Multipar ERT. Skip this.
3232 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, False)
3235 j = find_end_of_layout(document.body, i)
3237 document.warning("end of layout not found!")
3238 k = find_token(document.body, "\\begin_inset Argument", i, j)
3240 document.warning("InsetArgument not found!")
3242 l = find_end_of_inset(document.body, k)
3243 m = find_token(document.body, "\\begin_inset ERT", l, j)
3246 ertcontfirstline = m + 5
3251 def convert_overprint(document):
3252 " Convert old beamer overprint layouts to ERT "
3254 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3255 if document.textclass not in beamer_classes:
3260 i = find_token(document.body, "\\begin_layout Overprint", i)
3263 # Find end of sequence
3264 j = find_end_of_sequence(document.body, i)
3266 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3270 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3272 if document.body[j] == "\\end_deeper":
3273 esubst = ["", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3275 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3276 endseq = endseq + len(esubst) - len(document.body[j : j])
3277 document.body[j : j] = esubst
3278 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3280 argend = find_end_of_layout(document.body, argbeg)
3282 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3285 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3286 endPlain = find_end_of_layout(document.body, beginPlain)
3287 content = document.body[beginPlain + 1 : endPlain]
3289 endseq = endseq - len(document.body[argbeg : argend + 1])
3291 del document.body[argbeg : argend + 1]
3292 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3294 endseq = endseq - len(document.body[i : i])
3295 document.body[i : i] = subst + ["\\end_layout"]
3296 endseq += len(subst)
3298 for p in range(i, endseq):
3299 if document.body[p] == "\\begin_layout Overprint":
3300 document.body[p] = "\\begin_layout Standard"
3305 def revert_overprint(document):
3306 " Revert old beamer overprint layouts to ERT "
3308 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3309 if document.textclass not in beamer_classes:
3314 i = find_token(document.body, "\\begin_layout Overprint", i)
3317 # Find end of sequence
3318 j = find_end_of_sequence(document.body, i)
3320 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3324 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3325 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}")
3326 endseq = endseq + len(esubst) - len(document.body[j : j])
3327 if document.body[j] == "\\end_deeper":
3328 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3330 document.body[j : j] = ["\\end_layout", ""] + esubst
3333 if document.body[r] == "\\begin_deeper":
3334 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3336 document.body[r] = ""
3337 document.body[s] = ""
3341 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3343 # Is this really our argument?
3344 nested = find_token(document.body, "\\begin_deeper", i, argbeg)
3346 argend = find_end_of_inset(document.body, argbeg)
3348 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3351 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3352 endPlain = find_end_of_layout(document.body, beginPlain)
3353 content = document.body[beginPlain + 1 : endPlain]
3355 endseq = endseq - len(document.body[argbeg : argend])
3357 del document.body[argbeg : argend + 1]
3358 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3360 endseq = endseq - len(document.body[i : i])
3361 document.body[i : i] = subst + ["\\end_layout"]
3362 endseq += len(subst)
3368 if document.body[p] == "\\begin_layout Overprint":
3369 q = find_end_of_layout(document.body, p)
3371 document.warning("Malformed LyX document. Cannot find end of Overprint layout!")
3374 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\onslide")
3375 argbeg = find_token(document.body, "\\begin_inset Argument item:1", p, q)
3377 argend = find_end_of_inset(document.body, argbeg)
3379 document.warning("Malformed LyX document. Cannot find end of Overprint item argument!")
3382 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3383 endPlain = find_end_of_layout(document.body, beginPlain)
3384 content = document.body[beginPlain + 1 : endPlain]
3386 endseq = endseq - len(document.body[argbeg : argend + 1])
3388 del document.body[argbeg : argend + 1]
3389 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3390 endseq = endseq - len(document.body[p : p + 1]) + len(subst)
3391 document.body[p : p + 1] = subst
3397 def revert_frametitle(document):
3398 " Reverts beamer frametitle layout to ERT "
3400 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3401 if document.textclass not in beamer_classes:
3404 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3407 i = find_token(document.body, "\\begin_layout FrameTitle", i)
3410 j = find_end_of_layout(document.body, i)
3412 document.warning("Malformed LyX document: Can't find end of FrameTitle layout")
3416 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
3417 endlay += len(put_cmd_in_ert("}"))
3418 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\frametitle")
3419 for p in range(i, j):
3422 m = rx.match(document.body[p])
3426 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3427 endPlain = find_end_of_layout(document.body, beginPlain)
3428 endInset = find_end_of_inset(document.body, p)
3429 content = document.body[beginPlain + 1 : endPlain]
3431 endlay = endlay - len(document.body[p : endInset + 1])
3433 del document.body[p : endInset + 1]
3434 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3436 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3437 endPlain = find_end_of_layout(document.body, beginPlain)
3438 endInset = find_end_of_inset(document.body, p)
3439 content = document.body[beginPlain + 1 : endPlain]
3441 endlay = endlay - len(document.body[p : endInset + 1])
3443 del document.body[p : endInset + 1]
3444 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3446 subst += put_cmd_in_ert("{")
3447 document.body[i : i + 1] = subst
3451 def convert_epigraph(document):
3452 " Converts memoir epigraph to new syntax "
3454 if document.textclass != "memoir":
3459 i = find_token(document.body, "\\begin_layout Epigraph", i)
3462 j = find_end_of_layout(document.body, i)
3464 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3469 ert = find_token(document.body, "\\begin_inset ERT", i, j)
3471 endInset = find_end_of_inset(document.body, ert)
3472 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", ert)
3473 endPlain = find_end_of_layout(document.body, beginPlain)
3474 ertcont = beginPlain + 2
3475 if document.body[ertcont] == "}{":
3477 # Convert to ArgInset
3478 endlay = endlay - 2 * len(document.body[j])
3479 begsubst = ['\\begin_inset Argument post:1', 'status collapsed', '',
3480 '\\begin_layout Plain Layout']
3481 endsubst = ['\\end_layout', '', '\\end_inset', '', document.body[j]]
3482 document.body[j : j + 1] = endsubst
3483 document.body[endInset + 1 : endInset + 1] = begsubst
3485 endlay += len(begsubst) + len(endsubst)
3486 endlay = endlay - len(document.body[ert : endInset + 1])
3487 del document.body[ert : endInset + 1]
3492 def revert_epigraph(document):
3493 " Reverts memoir epigraph argument to ERT "
3495 if document.textclass != "memoir":
3500 i = find_token(document.body, "\\begin_layout Epigraph", i)
3503 j = find_end_of_layout(document.body, i)
3505 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3510 p = find_token(document.body, "\\begin_layout Argument post:1", i, j)
3512 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3513 endPlain = find_end_of_layout(document.body, beginPlain)
3514 endInset = find_end_of_inset(document.body, p)
3515 content = document.body[beginPlain + 1 : endPlain]
3517 endlay = endlay - len(document.body[p : endInset + 1])
3519 del document.body[p : endInset + 1]
3520 subst += put_cmd_in_ert("}{") + content
3522 subst += put_cmd_in_ert("}{")
3524 document.body[j : j] = subst + document.body[j : j]
3528 def convert_captioninsets(document):
3529 " Converts caption insets to new syntax "
3533 i = find_token(document.body, "\\begin_inset Caption", i)
3536 document.body[i] = "\\begin_inset Caption Standard"
3540 def revert_captioninsets(document):
3541 " Reverts caption insets to old syntax "
3545 i = find_token(document.body, "\\begin_inset Caption Standard", i)
3548 document.body[i] = "\\begin_inset Caption"
3552 def convert_captionlayouts(document):
3553 " Convert caption layouts to caption insets. "
3556 "Captionabove": "Above",
3557 "Captionbelow": "Below",
3558 "FigCaption" : "FigCaption",
3559 "Table_Caption" : "Table",
3560 "CenteredCaption" : "Centered",
3561 "Bicaption" : "Bicaption",
3566 i = find_token(document.body, "\\begin_layout", i)
3569 val = get_value(document.body, "\\begin_layout", i)
3570 if val in caption_dict.keys():
3571 j = find_end_of_layout(document.body, i)
3573 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3576 document.body[j:j] = ["\\end_layout", "", "\\end_inset", "", ""]
3577 document.body[i:i+1] = ["\\begin_layout %s" % document.default_layout,
3578 "\\begin_inset Caption %s" % caption_dict[val], "",
3579 "\\begin_layout %s" % document.default_layout]
3583 def revert_captionlayouts(document):
3584 " Revert caption insets to caption layouts. "
3587 "Above" : "Captionabove",
3588 "Below" : "Captionbelow",
3589 "FigCaption" : "FigCaption",
3590 "Table" : "Table_Caption",
3591 "Centered" : "CenteredCaption",
3592 "Bicaption" : "Bicaption",
3596 rx = re.compile(r'^\\begin_inset Caption (\S+)$')
3598 i = find_token(document.body, "\\begin_inset Caption", i)
3602 m = rx.match(document.body[i])
3606 if val not in caption_dict.keys():
3610 # We either need to delete the previous \begin_layout line, or we
3611 # need to end the previous layout if this inset is not in the first
3612 # position of the paragraph.
3613 layout_before = find_token_backwards(document.body, "\\begin_layout", i)
3614 if layout_before == -1:
3615 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3617 layout_line = document.body[layout_before]
3618 del_layout_before = True
3619 l = layout_before + 1
3621 if document.body[l] != "":
3622 del_layout_before = False
3625 if del_layout_before:
3626 del document.body[layout_before:i]
3629 document.body[i:i] = ["\\end_layout", ""]
3632 # Find start of layout in the inset and end of inset
3633 j = find_token(document.body, "\\begin_layout", i)
3635 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3637 k = find_end_of_inset(document.body, i)
3639 document.warning("Malformed LyX document: Missing `\\end_inset'.")
3642 # We either need to delete the following \end_layout line, or we need
3643 # to restart the old layout if this inset is not at the paragraph end.
3644 layout_after = find_token(document.body, "\\end_layout", k)
3645 if layout_after == -1:
3646 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3648 del_layout_after = True
3650 while l < layout_after:
3651 if document.body[l] != "":
3652 del_layout_after = False
3655 if del_layout_after:
3656 del document.body[k+1:layout_after+1]
3658 document.body[k+1:k+1] = [layout_line, ""]
3660 # delete \begin_layout and \end_inset and replace \begin_inset with
3661 # "\begin_layout XXX". This works because we can only have one
3662 # paragraph in the caption inset: The old \end_layout will be recycled.
3663 del document.body[k]
3664 if document.body[k] == "":
3665 del document.body[k]
3666 del document.body[j]
3667 if document.body[j] == "":
3668 del document.body[j]
3669 document.body[i] = "\\begin_layout %s" % caption_dict[val]
3670 if document.body[i+1] == "":
3671 del document.body[i+1]
3675 def revert_fragileframe(document):
3676 " Reverts beamer FragileFrame layout to ERT "
3678 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3679 if document.textclass not in beamer_classes:
3684 i = find_token(document.body, "\\begin_layout FragileFrame", i)
3687 # Find end of sequence
3688 j = find_end_of_sequence(document.body, i)
3690 document.warning("Malformed LyX document. Cannot find end of FragileFrame sequence!")
3694 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{frame}")
3695 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{frame}")
3696 endseq = endseq + len(esubst) - len(document.body[j : j])
3697 if document.body[j] == "\\end_deeper":
3698 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3700 document.body[j : j] = esubst
3701 for q in range(i, j):
3702 if document.body[q] == "\\begin_layout FragileFrame":
3703 document.body[q] = "\\begin_layout %s" % document.default_layout
3706 if document.body[r] == "\\begin_deeper":
3707 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3709 document.body[r] = ""
3710 document.body[s] = ""
3714 for p in range(1, 5):
3715 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, j)
3718 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3719 endPlain = find_end_of_layout(document.body, beginPlain)
3720 endInset = find_end_of_inset(document.body, arg)
3721 content = document.body[beginPlain + 1 : endPlain]
3723 j = j - len(document.body[arg : endInset + 1])
3725 del document.body[arg : endInset + 1]
3726 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3728 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3729 endPlain = find_end_of_layout(document.body, beginPlain)
3730 endInset = find_end_of_inset(document.body, arg)
3731 content = document.body[beginPlain + 1 : endPlain]
3733 j = j - len(document.body[arg : endInset + 1])
3735 del document.body[arg : endInset + 1]
3736 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3738 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3739 endPlain = find_end_of_layout(document.body, beginPlain)
3740 endInset = find_end_of_inset(document.body, arg)
3741 content = document.body[beginPlain + 1 : endPlain]
3743 j = j - len(document.body[arg : endInset + 1])
3745 del document.body[arg : endInset + 1]
3746 subst += put_cmd_in_ert("[fragile,") + content + put_cmd_in_ert("]")
3748 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3749 endPlain = find_end_of_layout(document.body, beginPlain)
3750 endInset = find_end_of_inset(document.body, arg)
3751 content = document.body[beginPlain + 1 : endPlain]
3753 j = j - len(document.body[arg : endInset + 1])
3755 del document.body[arg : endInset + 1]
3756 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3758 subst += put_cmd_in_ert("[fragile]")
3760 document.body[i : i + 1] = subst
3764 def revert_newframes(document):
3765 " Reverts beamer Frame and PlainFrame layouts to old forms "
3767 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3768 if document.textclass not in beamer_classes:
3772 "Frame" : "BeginFrame",
3773 "PlainFrame" : "BeginPlainFrame",
3776 rx = re.compile(r'^\\begin_layout (\S+)$')
3779 i = find_token(document.body, "\\begin_layout", i)
3783 m = rx.match(document.body[i])
3787 if val not in frame_dict.keys():
3790 # Find end of sequence
3791 j = find_end_of_sequence(document.body, i)
3793 document.warning("Malformed LyX document. Cannot find end of Frame sequence!")
3797 subst = ["\\begin_layout %s" % frame_dict[val]]
3798 esubst = ["", "\\begin_layout EndFrame", "", "\\end_layout"]
3799 endseq = endseq + len(esubst) - len(document.body[j : j])
3800 if document.body[j] == "\\end_deeper":
3801 document.body[j : j] = esubst
3803 document.body[j+1 : j+1] = esubst
3804 for q in range(i, j):
3805 if document.body[q] == "\\begin_layout %s" % val:
3806 document.body[q] = "\\begin_layout %s" % document.default_layout
3809 if document.body[r] == "\\begin_deeper":
3810 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3812 document.body[r] = ""
3813 document.body[s] = ""
3817 l = find_end_of_layout(document.body, i)
3818 for p in range(1, 5):
3819 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, l)
3822 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3823 endPlain = find_end_of_layout(document.body, beginPlain)
3824 endInset = find_end_of_inset(document.body, arg)
3825 content = document.body[beginPlain + 1 : endPlain]
3827 l = l - len(document.body[arg : endInset + 1])
3829 del document.body[arg : endInset + 1]
3830 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3832 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3833 endPlain = find_end_of_layout(document.body, beginPlain)
3834 endInset = find_end_of_inset(document.body, arg)
3835 content = document.body[beginPlain + 1 : endPlain]
3837 l = l - len(document.body[arg : endInset + 1])
3839 del document.body[arg : endInset + 1]
3840 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3842 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3843 endPlain = find_end_of_layout(document.body, beginPlain)
3844 endInset = find_end_of_inset(document.body, arg)
3845 content = document.body[beginPlain + 1 : endPlain]
3847 l = l - len(document.body[arg : endInset + 1])
3849 del document.body[arg : endInset + 1]
3850 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3852 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3853 endPlain = find_end_of_layout(document.body, beginPlain)
3854 endInset = find_end_of_inset(document.body, arg)
3855 content = document.body[beginPlain + 1 : endPlain]
3857 l = l - len(document.body[arg : endInset + 1])
3859 del document.body[arg : endInset + 1]
3862 document.body[i : i + 1] = subst
3865 # known encodings that do not change their names (same LyX and LaTeX names)
3866 known_enc_tuple = ("auto", "default", "ansinew", "applemac", "armscii8", "ascii",
3867 "cp437", "cp437de", "cp850", "cp852", "cp855", "cp858", "cp862", "cp865", "cp866",
3868 "cp1250", "cp1251", "cp1252", "cp1255", "cp1256", "cp1257", "koi8-r", "koi8-u",
3869 "pt154", "pt254", "tis620-0", "utf8", "utf8x", "utf8-plain")
3871 def convert_encodings(document):
3872 "Use the LyX names of the encodings instead of the LaTeX names."
3873 LaTeX2LyX_enc_dict = {
3874 "8859-6": "iso8859-6",
3875 "8859-8": "iso8859-8",
3877 "euc": "euc-jp-platex",
3882 "iso88595": "iso8859-5",
3883 "iso-8859-7": "iso8859-7",
3885 "jis": "jis-platex",
3887 "l7xenc": "iso8859-13",
3888 "latin1": "iso8859-1",
3889 "latin2": "iso8859-2",
3890 "latin3": "iso8859-3",
3891 "latin4": "iso8859-4",
3892 "latin5": "iso8859-9",
3893 "latin9": "iso8859-15",
3894 "latin10": "iso8859-16",
3895 "SJIS": "shift-jis",
3896 "sjis": "shift-jis-platex",
3899 i = find_token(document.header, "\\inputencoding" , 0)
3902 val = get_value(document.header, "\\inputencoding", i)
3903 if val in LaTeX2LyX_enc_dict.keys():
3904 document.header[i] = "\\inputencoding %s" % LaTeX2LyX_enc_dict[val]
3905 elif val not in known_enc_tuple:
3906 document.warning("Ignoring unknown input encoding: `%s'" % val)
3909 def revert_encodings(document):
3910 """Revert to using the LaTeX names of the encodings instead of the LyX names.
3911 Also revert utf8-platex to sjis, the language default when using Japanese.
3913 LyX2LaTeX_enc_dict = {
3918 "euc-jp-platex": "euc",
3921 "iso8859-1": "latin1",
3922 "iso8859-2": "latin2",
3923 "iso8859-3": "latin3",
3924 "iso8859-4": "latin4",
3925 "iso8859-5": "iso88595",
3926 "iso8859-6": "8859-6",
3927 "iso8859-7": "iso-8859-7",
3928 "iso8859-8": "8859-8",
3929 "iso8859-9": "latin5",
3930 "iso8859-13": "l7xenc",
3931 "iso8859-15": "latin9",
3932 "iso8859-16": "latin10",
3934 "jis-platex": "jis",
3935 "shift-jis": "SJIS",
3936 "shift-jis-platex": "sjis",
3938 "utf8-platex": "sjis"
3940 i = find_token(document.header, "\\inputencoding" , 0)
3943 val = get_value(document.header, "\\inputencoding", i)
3944 if val in LyX2LaTeX_enc_dict.keys():
3945 document.header[i] = "\\inputencoding %s" % LyX2LaTeX_enc_dict[val]
3946 elif val not in known_enc_tuple:
3947 document.warning("Ignoring unknown input encoding: `%s'" % val)
3950 def revert_IEEEtran_3(document):
3952 Reverts Flex Insets to TeX-code
3954 if document.textclass == "IEEEtran":
3960 h = find_token(document.body, "\\begin_inset Flex Author Mark", h)
3962 endh = find_end_of_inset(document.body, h)
3963 document.body[endh - 2 : endh + 1] = put_cmd_in_ert("}")
3964 document.body[h : h + 4] = put_cmd_in_ert("\\IEEEauthorrefmark{")
3967 i = find_token(document.body, "\\begin_inset Flex Author Name", i)
3969 endi = find_end_of_inset(document.body, i)
3970 document.body[endi - 2 : endi + 1] = put_cmd_in_ert("}")
3971 document.body[i : i + 4] = put_cmd_in_ert("\\IEEEauthorblockN{")
3974 j = find_token(document.body, "\\begin_inset Flex Author Affiliation", j)
3976 endj = find_end_of_inset(document.body, j)
3977 document.body[endj - 2 : endj + 1] = put_cmd_in_ert("}")
3978 document.body[j : j + 4] = put_cmd_in_ert("\\IEEEauthorblockA{")
3980 if i == -1 and j == -1 and h == -1:
3984 def revert_kurier_fonts(document):
3985 " Revert kurier font definition to LaTeX "
3987 i = find_token(document.header, "\\font_math", 0)
3989 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
3990 val = get_value(document.header, "\\font_math", i)
3991 if val == "kurier-math":
3992 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
3993 "\\usepackage[math]{kurier}\n" \
3994 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
3995 document.header[i] = "\\font_math auto"
3997 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
3998 kurier_fonts = ["kurier", "kurierc", "kurierl", "kurierlc"]
3999 k = find_token(document.header, "\\font_sans kurier", 0)
4001 sf = get_value(document.header, "\\font_sans", k)
4002 if sf in kurier_fonts:
4003 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4004 document.header[k] = "\\font_sans default"
4006 def revert_iwona_fonts(document):
4007 " Revert iwona font definition to LaTeX "
4009 i = find_token(document.header, "\\font_math", 0)
4011 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4012 val = get_value(document.header, "\\font_math", i)
4013 if val == "iwona-math":
4014 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
4015 "\\usepackage[math]{iwona}\n" \
4016 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
4017 document.header[i] = "\\font_math auto"
4019 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4020 iwona_fonts = ["iwona", "iwonac", "iwonal", "iwonalc"]
4021 k = find_token(document.header, "\\font_sans iwona", 0)
4023 sf = get_value(document.header, "\\font_sans", k)
4024 if sf in iwona_fonts:
4025 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4026 document.header[k] = "\\font_sans default"
4029 def revert_new_libertines(document):
4030 " Revert new libertine font definition to LaTeX "
4032 if find_token(document.header, "\\use_non_tex_fonts true", 0) != -1:
4035 i = find_token(document.header, "\\font_typewriter libertine-mono", 0)
4037 preamble = "\\usepackage"
4038 sc = find_token(document.header, "\\font_tt_scale", 0)
4040 scval = get_value(document.header, "\\font_tt_scale", sc)
4042 preamble += "[scale=%f]" % (float(scval) / 100)
4043 document.header[sc] = "\\font_tt_scale 100"
4044 preamble += "{libertineMono-type1}"
4045 add_to_preamble(document, [preamble])
4046 document.header[i] = "\\font_typewriter default"
4048 k = find_token(document.header, "\\font_sans biolinum", 0)
4050 preamble = "\\usepackage"
4052 j = find_token(document.header, "\\font_osf true", 0)
4057 sc = find_token(document.header, "\\font_sf_scale", 0)
4059 scval = get_value(document.header, "\\font_sf_scale", sc)
4061 options += ",scale=%f" % (float(scval) / 100)
4062 document.header[sc] = "\\font_sf_scale 100"
4064 preamble += "[" + options +"]"
4065 preamble += "{biolinum-type1}"
4066 add_to_preamble(document, [preamble])
4067 document.header[k] = "\\font_sans default"
4070 def convert_lyxframes(document):
4071 " Converts old beamer frames to new style "
4073 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4074 if document.textclass not in beamer_classes:
4077 framebeg = ["BeginFrame", "BeginPlainFrame"]
4078 frameend = ["Frame", "PlainFrame", "EndFrame", "BeginFrame", "BeginPlainFrame", "AgainFrame",
4079 "Section", "Section*", "Subsection", "Subsection*", "Subsubsection", "Subsubsection*"]
4080 for lay in framebeg:
4083 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
4086 parent = get_containing_layout(document.body, i)
4087 if parent == False or parent[1] != i:
4088 document.warning("Wrong parent layout!")
4091 frametype = parent[0]
4095 # Step I: Convert ERT arguments
4096 # FIXME: See restrictions in convert_beamerframeargs method
4097 ertend = convert_beamerframeargs(document, i, parbeg)
4100 # Step II: Now rename the layout and convert the title to an argument
4101 j = find_end_of_layout(document.body, i)
4102 document.body[j : j + 1] = ['\\end_layout', '', '\\end_inset', '', '\\end_layout']
4103 if lay == "BeginFrame":
4104 document.body[i] = "\\begin_layout Frame"
4106 document.body[i] = "\\begin_layout PlainFrame"
4107 document.body[ertend + 1 : ertend + 1] = ['\\begin_inset Argument 4',
4108 'status open', '', '\\begin_layout Plain Layout']
4109 # Step III: find real frame end
4113 fend = find_token(document.body, "\\begin_layout", jj)
4115 document.warning("Malformed LyX document: No real frame end!")
4117 val = get_value(document.body, "\\begin_layout", fend)
4118 if val not in frameend:
4121 old = document.body[fend]
4122 if val == frametype:
4123 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4124 # consider explicit EndFrames between two identical frame types
4125 elif val == "EndFrame":
4126 nextlayout = find_token(document.body, "\\begin_layout", fend + 1)
4127 if nextlayout != -1 and get_value(document.body, "\\begin_layout", nextlayout) == frametype:
4128 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4130 document.body[fend : fend] = ['\\end_deeper']
4132 document.body[fend : fend] = ['\\end_deeper']
4133 document.body[j + 1 : j + 1] = ['', '\\begin_deeper']
4138 def remove_endframes(document):
4139 " Remove deprecated beamer endframes "
4141 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4142 if document.textclass not in beamer_classes:
4147 i = find_token_exact(document.body, "\\begin_layout EndFrame", i)
4150 j = find_end_of_layout(document.body, i)
4152 document.warning("Malformed LyX document: Missing \\end_layout to EndFrame")
4155 del document.body[i : j + 1]
4158 def revert_powerdot_flexes(document):
4159 " Reverts powerdot flex insets "
4161 if document.textclass != "powerdot":
4164 flexes = {"Onslide" : "\\onslide",
4165 "Onslide*" : "\\onslide*",
4166 "Onslide+" : "\\onslide+"}
4167 rx = re.compile(r'^\\begin_inset Flex (.+)$')
4171 i = find_token(document.body, "\\begin_inset Flex", i)
4174 m = rx.match(document.body[i])
4176 flextype = m.group(1)
4177 z = find_end_of_inset(document.body, i)
4179 document.warning("Can't find end of Flex " + flextype + " inset.")
4182 if flextype in flexes:
4183 pre = put_cmd_in_ert(flexes[flextype])
4184 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
4186 argend = find_end_of_inset(document.body, arg)
4188 document.warning("Can't find end of Argument!")
4191 # Find containing paragraph layout
4192 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
4193 endPlain = find_end_of_layout(document.body, beginPlain)
4194 argcontent = document.body[beginPlain + 1 : endPlain]
4196 z = z - len(document.body[arg : argend + 1])
4198 del document.body[arg : argend + 1]
4199 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
4200 pre += put_cmd_in_ert("{")
4201 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4202 endPlain = find_end_of_layout(document.body, beginPlain)
4204 z = z - len(document.body[i : beginPlain + 1])
4206 document.body[i : beginPlain + 1] = pre
4207 post = put_cmd_in_ert("}")
4208 document.body[z - 2 : z + 1] = post
4212 def revert_powerdot_pause(document):
4213 " Reverts powerdot pause layout to ERT "
4215 if document.textclass != "powerdot":
4220 i = find_token(document.body, "\\begin_layout Pause", i)
4223 j = find_end_of_layout(document.body, i)
4225 document.warning("Malformed LyX document: Can't find end of Pause layout")
4229 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\pause")
4230 for p in range(i, j):
4233 arg = find_token(document.body, "\\begin_inset Argument 1", i, j)
4235 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4236 endPlain = find_end_of_layout(document.body, beginPlain)
4237 endInset = find_end_of_inset(document.body, p)
4238 content = document.body[beginPlain + 1 : endPlain]
4240 endlay = endlay - len(document.body[p : endInset + 1])
4242 del document.body[p : endInset + 1]
4243 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4245 document.body[i : i + 1] = subst
4249 def revert_powerdot_itemargs(document):
4250 " Reverts powerdot item arguments to ERT "
4252 if document.textclass != "powerdot":
4256 list_layouts = ["Itemize", "ItemizeType1", "Enumerate", "EnumerateType1"]
4257 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4260 i = find_token(document.body, "\\begin_inset Argument", i)
4263 # Find containing paragraph layout
4264 parent = get_containing_layout(document.body, i)
4266 document.warning("Malformed LyX document: Can't find parent paragraph layout")
4271 realparbeg = parent[3]
4272 layoutname = parent[0]
4274 for p in range(parbeg, parend):
4278 if layoutname in list_layouts:
4279 m = rx.match(document.body[p])
4282 if argnr == "item:1":
4283 j = find_end_of_inset(document.body, i)
4284 # Find containing paragraph layout
4285 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4286 endPlain = find_end_of_layout(document.body, beginPlain)
4287 content = document.body[beginPlain + 1 : endPlain]
4288 del document.body[i:j+1]
4289 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4290 document.body[realparbeg : realparbeg] = subst
4291 elif argnr == "item:2":
4292 j = find_end_of_inset(document.body, i)
4293 # Find containing paragraph layout
4294 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4295 endPlain = find_end_of_layout(document.body, beginPlain)
4296 content = document.body[beginPlain + 1 : endPlain]
4297 del document.body[i:j+1]
4298 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
4299 document.body[realparbeg : realparbeg] = subst
4304 def revert_powerdot_columns(document):
4305 " Reverts powerdot twocolumn to TeX-code "
4306 if document.textclass != "powerdot":
4309 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4312 i = find_token(document.body, "\\begin_layout Twocolumn", i)
4315 j = find_end_of_layout(document.body, i)
4317 document.warning("Malformed LyX document: Can't find end of Twocolumn layout")
4321 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
4322 endlay += len(put_cmd_in_ert("}"))
4323 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\twocolumn")
4324 for p in range(i, j):
4327 m = rx.match(document.body[p])
4331 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4332 endPlain = find_end_of_layout(document.body, beginPlain)
4333 endInset = find_end_of_inset(document.body, p)
4334 content = document.body[beginPlain + 1 : endPlain]
4336 endlay = endlay - len(document.body[p : endInset + 1])
4338 del document.body[p : endInset + 1]
4339 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4341 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4342 endPlain = find_end_of_layout(document.body, beginPlain)
4343 endInset = find_end_of_inset(document.body, p)
4344 content = document.body[beginPlain + 1 : endPlain]
4346 endlay = endlay - len(document.body[p : endInset + 1])
4348 del document.body[p : endInset + 1]
4349 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
4351 subst += put_cmd_in_ert("{")
4352 document.body[i : i + 1] = subst
4356 def revert_mbox_fbox(document):
4357 'Convert revert mbox/fbox boxes to TeX-code'
4360 i = find_token(document.body, "\\begin_inset Box", i)
4363 j = find_token(document.body, "width", i)
4365 document.warning("Malformed LyX document: Can't find box width")
4367 width = get_value(document.body, "width", j)
4368 k = find_end_of_inset(document.body, j)
4370 document.warning("Malformed LyX document: Can't find end of box inset")
4373 BeginLayout = find_token(document.body, "\\begin_layout Plain Layout", j)
4374 EndLayout = find_end_of_layout(document.body, BeginLayout)
4375 # replace if width is ""
4377 document.body[EndLayout:k + 1] = put_cmd_in_ert("}")
4378 if document.body[i] == "\\begin_inset Box Frameless":
4379 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\mbox{")
4380 if document.body[i] == "\\begin_inset Box Boxed":
4381 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\fbox{")
4385 def revert_starred_caption(document):
4386 " Reverts unnumbered longtable caption insets "
4390 i = find_token(document.body, "\\begin_inset Caption LongTableNoNumber", i)
4393 # This is not equivalent, but since the caption inset is a full blown
4394 # text inset a true conversion to ERT is too difficult.
4395 document.body[i] = "\\begin_inset Caption Standard"
4399 def revert_forced_local_layout(document):
4402 i = find_token(document.header, "\\begin_forced_local_layout", i)
4405 j = find_end_of(document.header, i, "\\begin_forced_local_layout", "\\end_forced_local_layout")
4407 # this should not happen
4409 regexp = re.compile(r'\s*forcelocal', re.IGNORECASE)
4410 k = find_re(document.header, regexp, i, j)
4412 del document.header[k]
4414 k = find_re(document.header, regexp, i, j)
4415 k = find_token(document.header, "\\begin_local_layout", 0)
4417 document.header[i] = "\\begin_local_layout"
4418 document.header[j] = "\\end_local_layout"
4420 l = find_end_of(document.header, k, "\\begin_local_layout", "\\end_local_layout")
4422 # this should not happen
4424 lines = document.header[i+1 : j]
4426 document.header[k+1 : k+1] = lines
4427 document.header[i : j ] = []
4429 document.header[i : j ] = []
4430 document.header[k+1 : k+1] = lines
4433 def revert_aa1(document):
4434 " Reverts InsetArguments of aa to TeX-code "
4435 if document.textclass == "aa":
4439 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4441 revert_Argument_to_TeX_brace(document, i, 0, 1, 4, False, False)
4447 def revert_aa2(document):
4448 " Reverts InsetArguments of aa to TeX-code "
4449 if document.textclass == "aa":
4453 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4455 document.body[i] = "\\begin_layout Abstract"
4461 def revert_tibetan(document):
4462 "Set the document language for Tibetan to English"
4464 if document.language == "tibetan":
4465 document.language = "english"
4466 i = find_token(document.header, "\\language", 0)
4468 document.header[i] = "\\language english"
4470 while j < len(document.body):
4471 j = find_token(document.body, "\\lang tibetan", j)
4473 document.body[j] = document.body[j].replace("\\lang tibetan", "\\lang english")
4476 j = len(document.body)
4485 # The idea here is that we will have a sequence of chunk paragraphs.
4486 # We want to convert them to paragraphs in one or several chunk insets.
4487 # Individual chunks are terminated by the character @ on the last line.
4488 # This line will be discarded, and following lines are treated as new
4489 # chunks, which go into their own insets.
4490 # The first line of a chunk should look like: <<CONTENT>>=
4491 # We will discard the delimiters, and put the CONTENT into the
4492 # optional argument of the inset, if the CONTENT is non-empty.
4493 def convert_chunks(document):
4494 first_re = re.compile(r'<<(.*)>>=(.*)')
4497 # find start of a block of chunks
4498 i = find_token(document.body, "\\begin_layout Chunk", file_pos)
4504 chunk_started = False
4507 # process the one we just found
4508 j = find_end_of_layout(document.body, i)
4510 document.warning("Malformed LyX documents. Can't find end of Chunk layout!")
4511 # there is no point continuing, as we will run into the same error again.
4513 this_chunk = "".join(document.body[i + 1:j])
4515 # there may be empty lines between chunks
4516 # we just skip them.
4517 if not chunk_started:
4518 if this_chunk != "":
4520 chunk_started = True
4523 contents.append(document.body[i + 1:j])
4525 # look for potential chunk terminator
4526 # on the last line of the chunk paragraph
4527 if document.body[j - 1] == "@":
4530 # look for subsequent chunk paragraph
4531 i = find_token(document.body, "\\begin_layout", j)
4535 if get_value(document.body, "\\begin_layout", i) != "Chunk":
4538 file_pos = end = j + 1
4540 # The last chunk should simply have an "@" in it
4541 # or at least end with "@" (can happen if @ is
4542 # preceded by a newline)
4543 lastpar = ''.join(contents[-1])
4544 if not lastpar.endswith("@"):
4545 document.warning("Unexpected chunk content: chunk not terminated by '@'!")
4549 # chunk par only contains "@". Just drop it.
4552 # chunk par contains more. Only drop the "@".
4555 # The first line should look like: <<CONTENT>>=
4556 # We want the CONTENT
4557 optarg = ' '.join(contents[0])
4559 # We can already have real chunk content in
4560 # the first par (separated from the options by a newline).
4561 # We collect such stuff to re-insert it later.
4564 match = first_re.search(optarg)
4566 optarg = match.groups()[0]
4567 if match.groups()[1] != "":
4569 for c in contents[0]:
4570 if c.endswith(">>="):
4574 postoptstuff.append(c)
4575 # We have stripped everything. This can be deleted.
4578 newstuff = ['\\begin_layout Standard',
4579 '\\begin_inset Flex Chunk',
4581 '\\begin_layout Plain Layout', '']
4583 # If we have a non-empty optional argument, insert it.
4584 if match and optarg != "":
4586 ['\\begin_inset Argument 1',
4588 '\\begin_layout Plain Layout',
4593 # Since we already opened a Plain layout, the first paragraph
4594 # does not need to do that.
4597 newstuff.extend(postoptstuff)
4598 newstuff.append('\\end_layout')
4602 newstuff.extend(['', '\\begin_layout Plain Layout', ''])
4606 newstuff.append('\\end_layout')
4608 newstuff.extend(['', '\\end_inset', '', '\\end_layout', ''])
4610 document.body[start:end] = newstuff
4612 file_pos += len(newstuff) - (end - start)
4615 def revert_chunks(document):
4618 i = find_token(document.body, "\\begin_inset Flex Chunk", i)
4622 iend = find_end_of_inset(document.body, i)
4624 document.warning("Can't find end of Chunk!")
4628 # Look for optional argument
4630 ostart = find_token(document.body, "\\begin_inset Argument 1", i, iend)
4632 oend = find_end_of_inset(document.body, ostart)
4633 k = find_token(document.body, "\\begin_layout Plain Layout", ostart, oend)
4635 document.warning("Malformed LyX document: Can't find argument contents!")
4637 m = find_end_of_layout(document.body, k)
4638 optarg = "".join(document.body[k+1:m])
4641 # We now remove the optional argument, so we have something
4642 # uniform on which to work
4643 document.body[ostart : oend + 1] = []
4644 # iend is now invalid
4645 iend = find_end_of_inset(document.body, i)
4647 retval = get_containing_layout(document.body, i)
4649 document.warning("Can't find containing layout for Chunk!")
4652 (lname, lstart, lend, pstart) = retval
4653 # we now want to work through the various paragraphs, and collect their contents
4657 k = find_token(document.body, "\\begin_layout Plain Layout", k, lend)
4660 j = find_end_of_layout(document.body, k)
4662 document.warning("Can't find end of layout inside chunk!")
4664 parlist.append(document.body[k+1:j])
4666 # we now need to wrap all of these paragraphs in chunks
4669 newlines.extend(["\\begin_layout Chunk", "", "<<" + optarg + ">>=", "\\end_layout", ""])
4670 for stuff in parlist:
4671 newlines.extend(["\\begin_layout Chunk"] + stuff + ["\\end_layout", ""])
4672 newlines.extend(["\\begin_layout Chunk", "", "@", "\\end_layout", ""])
4673 # replace old content with new content
4674 document.body[lstart : lend + 1] = newlines
4675 i = lstart + len(newlines)
4682 supported_versions = ["2.1.0","2.1"]
4685 [415, [convert_undertilde]],
4687 [417, [convert_japanese_encodings]],
4688 [418, [convert_justification]],
4690 [420, [convert_biblio_style]],
4691 [421, [convert_longtable_captions]],
4692 [422, [convert_use_packages]],
4693 [423, [convert_use_mathtools]],
4694 [424, [convert_cite_engine_type]],
4695 # No convert_cancel, since cancel will be loaded automatically
4696 # in format 425 without any possibility to switch it off.
4697 # This has been fixed in format 464.
4701 [428, [convert_cell_rotation]],
4702 [429, [convert_table_rotation]],
4703 [430, [convert_listoflistings]],
4704 [431, [convert_use_amssymb]],
4706 [433, [convert_armenian]],
4714 [441, [convert_mdnomath]],
4719 [446, [convert_latexargs]],
4720 [447, [convert_IEEEtran, convert_AASTeX, convert_AGUTeX, convert_IJMP, convert_SIGPLAN, convert_SIGGRAPH, convert_EuropeCV, convert_Initials, convert_ModernCV]],
4721 [448, [convert_literate]],
4724 [451, [convert_beamerargs, convert_againframe_args, convert_corollary_args, convert_quote_args]],
4725 [452, [convert_beamerblocks]],
4726 [453, [convert_use_stmaryrd]],
4727 [454, [convert_overprint]],
4729 [456, [convert_epigraph]],
4730 [457, [convert_use_stackrel]],
4731 [458, [convert_captioninsets, convert_captionlayouts]],
4736 [463, [convert_encodings]],
4737 [464, [convert_use_cancel]],
4738 [465, [convert_lyxframes, remove_endframes]],
4744 [471, [convert_cite_engine_type_default]],
4747 [474, [convert_chunks, cleanup_beamerargs]],
4751 [473, [revert_chunks]],
4752 [472, [revert_tibetan]],
4753 [471, [revert_aa1,revert_aa2]],
4754 [470, [revert_cite_engine_type_default]],
4755 [469, [revert_forced_local_layout]],
4756 [468, [revert_starred_caption]],
4757 [467, [revert_mbox_fbox]],
4758 [466, [revert_iwona_fonts]],
4759 [465, [revert_powerdot_flexes, revert_powerdot_pause, revert_powerdot_itemargs, revert_powerdot_columns]],
4761 [463, [revert_use_cancel]],
4762 [462, [revert_encodings]],
4763 [461, [revert_new_libertines]],
4764 [460, [revert_kurier_fonts]],
4765 [459, [revert_IEEEtran_3]],
4766 [458, [revert_fragileframe, revert_newframes]],
4767 [457, [revert_captioninsets, revert_captionlayouts]],
4768 [456, [revert_use_stackrel]],
4769 [455, [revert_epigraph]],
4770 [454, [revert_frametitle]],
4771 [453, [revert_overprint]],
4772 [452, [revert_use_stmaryrd]],
4773 [451, [revert_beamerblocks]],
4774 [450, [revert_beamerargs, revert_beamerargs2, revert_beamerargs3, revert_beamerflex]],
4775 [449, [revert_garamondx, revert_garamondx_newtxmath]],
4776 [448, [revert_itemargs]],
4777 [447, [revert_literate]],
4778 [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]],
4779 [445, [revert_latexargs]],
4780 [444, [revert_uop]],
4781 [443, [revert_biolinum]],
4783 [441, [revert_newtxmath]],
4784 [440, [revert_mdnomath]],
4785 [439, [revert_mathfonts]],
4786 [438, [revert_minionpro]],
4787 [437, [revert_ipadeco, revert_ipachar]],
4788 [436, [revert_texgyre]],
4789 [435, [revert_mathdesign]],
4790 [434, [revert_txtt]],
4791 [433, [revert_libertine]],
4792 [432, [revert_armenian]],
4793 [431, [revert_languages, revert_ancientgreek]],
4794 [430, [revert_use_amssymb]],
4795 [429, [revert_listoflistings]],
4796 [428, [revert_table_rotation]],
4797 [427, [revert_cell_rotation]],
4798 [426, [revert_tipa]],
4799 [425, [revert_verbatim]],
4800 [424, [revert_cancel]],
4801 [423, [revert_cite_engine_type]],
4802 [422, [revert_use_mathtools]],
4803 [421, [revert_use_packages]],
4804 [420, [revert_longtable_captions]],
4805 [419, [revert_biblio_style]],
4806 [418, [revert_australian]],
4807 [417, [revert_justification]],
4808 [416, [revert_japanese_encodings]],
4809 [415, [revert_negative_space, revert_math_spaces]],
4810 [414, [revert_undertilde]],
4811 [413, [revert_visible_space]]
4815 if __name__ == "__main__":