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"]
171 # now check the case that we have "}" + "{" in two ERTs
172 else: # no brace pair found
174 endBrace = find_token(document.body, "]", lineERT, end_layout)
176 endBrace = find_token(document.body, "}", lineERT, end_layout)
177 if endBrace == lineERT + 5:
179 beginBrace = find_token(document.body, "[", endBrace, end_layout)
181 beginBrace = find_token(document.body, "{", endBrace, end_layout)
182 # assure that the ERTs are consecutive (11 or 12 depending if there is a space between the ERTs or not)
183 if beginBrace == endBrace + 11 or beginBrace == endBrace + 12:
184 end = find_token(document.body, "\\end_inset", beginBrace)
185 document.body[lineERT : end + 1] = ["\\end_layout", "", "\\end_inset"]
187 # in the case that n > 1 we have optional arguments before
188 # therefore detect them if any
190 # first check if there is an argument
191 lineArg = find_token(document.body, "\\begin_inset Argument", line)
192 if lineArg < lineERT and lineArg != -1:
193 # we have an argument, so now search backwards for its end
194 # we must now assure that we don't find other insets like e.g. a newline
195 endInsetArg = lineERT
196 endLayoutArg = endInsetArg
197 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
198 endInsetArg = endInsetArg - 1
199 endLayoutArg = endInsetArg
200 endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
201 endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
202 line = endInsetArg + 1
204 document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
206 document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
208 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
211 # set the line where the next argument will be inserted
212 if beginBrace == endBrace + 11:
220 if environment == True:
221 end_ERT = find_end_of_inset(document.body, lineERT)
223 document.warning("Can't find end of ERT!!")
225 # Note that this only checks for [ or { at the beginning of a line
227 opening = find_token(document.body, "[", lineERT, end_ERT)
229 opening = find_token(document.body, "{", lineERT, end_ERT)
231 document.body[lineERT : end_ERT + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
233 lineERT2 = find_token(document.body, "\\begin_inset ERT", end_ERT, end_layout)
235 end_ERT2 = find_end_of_inset(document.body, lineERT)
237 document.warning("Can't find end of second ERT!!")
240 closing = find_token(document.body, "]", lineERT2, end_ERT2)
242 closing = find_token(document.body, "}", lineERT2, end_ERT2)
243 if closing != -1: # assure that the "}" is in this ERT
244 end2 = find_token(document.body, "\\end_inset", closing)
245 document.body[lineERT2 : end2 + 1] = ["\\end_layout", "", "\\end_inset"]
248 ###############################################################################
250 ### Conversion and reversion routines
252 ###############################################################################
254 def revert_visible_space(document):
255 "Revert InsetSpace visible into its ERT counterpart"
258 i = find_token(document.body, "\\begin_inset space \\textvisiblespace{}", i)
261 end = find_end_of_inset(document.body, i)
262 subst = put_cmd_in_ert("\\textvisiblespace{}")
263 document.body[i:end + 1] = subst
266 undertilde_commands = ["utilde"]
267 def convert_undertilde(document):
268 " Load undertilde automatically "
269 i = find_token(document.header, "\\use_mathdots" , 0)
271 i = find_token(document.header, "\\use_mhchem" , 0)
273 i = find_token(document.header, "\\use_esint" , 0)
275 document.warning("Malformed LyX document: Can't find \\use_mathdots.")
277 j = find_token(document.preamble, "\\usepackage{undertilde}", 0)
279 # package was loaded in the preamble, convert this to header setting for round trip
280 document.header.insert(i + 1, "\\use_undertilde 2") # on
281 del document.preamble[j]
285 j = find_token(document.body, '\\begin_inset Formula', j)
288 k = find_end_of_inset(document.body, j)
290 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(j))
293 code = "\n".join(document.body[j:k])
294 for c in undertilde_commands:
295 if code.find("\\%s" % c) != -1:
296 # at least one of the commands was found - need to switch package off
297 document.header.insert(i + 1, "\\use_undertilde 0") # off
300 # no command was found - set to auto (bug 9069)
301 document.header.insert(i + 1, "\\use_undertilde 1") # auto
305 def revert_undertilde(document):
306 " Load undertilde if used in the document "
307 regexp = re.compile(r'(\\use_undertilde)')
308 i = find_re(document.header, regexp, 0)
309 value = "1" # default is auto
311 value = get_value(document.header, "\\use_undertilde" , i).split()[0]
312 del document.header[i]
313 if value == "2": # on
314 add_to_preamble(document, ["\\usepackage{undertilde}"])
315 elif value == "1": # auto
318 i = find_token(document.body, '\\begin_inset Formula', i)
321 j = find_end_of_inset(document.body, i)
323 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
326 code = "\n".join(document.body[i:j])
327 for c in undertilde_commands:
328 if code.find("\\%s" % c) != -1:
329 add_to_preamble(document, ["\\usepackage{undertilde}"])
334 def revert_negative_space(document):
335 "Revert InsetSpace negmedspace and negthickspace into its TeX-code counterpart"
340 i = find_token(document.body, "\\begin_inset space \\negmedspace{}", i)
342 j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
344 # load amsmath in the preamble if not already loaded if we are at the end of checking
346 i = find_token(document.header, "\\use_amsmath 2", 0)
348 add_to_preamble(document, ["\\@ifundefined{negthickspace}{\\usepackage{amsmath}}"])
352 end = find_end_of_inset(document.body, i)
353 subst = put_cmd_in_ert("\\negmedspace{}")
354 document.body[i:end + 1] = subst
355 j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
358 end = find_end_of_inset(document.body, j)
359 subst = put_cmd_in_ert("\\negthickspace{}")
360 document.body[j:end + 1] = subst
364 def revert_math_spaces(document):
365 "Revert formulas with protected custom space and protected hfills to TeX-code"
368 i = find_token(document.body, "\\begin_inset Formula", i)
371 j = document.body[i].find("\\hspace*")
373 end = find_end_of_inset(document.body, i)
374 subst = put_cmd_in_ert(document.body[i][21:])
375 document.body[i:end + 1] = subst
379 def convert_japanese_encodings(document):
380 " Rename the japanese encodings to names understood by platex "
382 "EUC-JP-pLaTeX": "euc",
384 "SJIS-pLaTeX": "sjis"
386 i = find_token(document.header, "\\inputencoding" , 0)
389 val = get_value(document.header, "\\inputencoding", i)
390 if val in jap_enc_dict.keys():
391 document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
394 def revert_japanese_encodings(document):
395 " Revert the japanese encodings name changes "
397 "euc": "EUC-JP-pLaTeX",
399 "sjis": "SJIS-pLaTeX"
401 i = find_token(document.header, "\\inputencoding" , 0)
404 val = get_value(document.header, "\\inputencoding", i)
405 if val in jap_enc_dict.keys():
406 document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
409 def convert_justification(document):
410 " Add the \\justification buffer param"
411 i = find_token(document.header, "\\use_indices" , 0)
413 document.warning("Malformed LyX document: Missing \\use_indices.")
415 document.header.insert(i + 1, "\\justification true")
418 def revert_justification(document):
419 " Revert the \\justification buffer param"
420 if not del_token(document.header, '\\justification', 0):
421 document.warning("Malformed LyX document: Missing \\justification.")
424 def revert_australian(document):
425 "Set English language variants Australian and Newzealand to English"
427 if document.language == "australian" or document.language == "newzealand":
428 document.language = "english"
429 i = find_token(document.header, "\\language", 0)
431 document.header[i] = "\\language english"
434 j = find_token(document.body, "\\lang australian", j)
436 j = find_token(document.body, "\\lang newzealand", 0)
440 document.body[j] = document.body[j].replace("\\lang newzealand", "\\lang english")
442 document.body[j] = document.body[j].replace("\\lang australian", "\\lang english")
446 def convert_biblio_style(document):
447 "Add a sensible default for \\biblio_style based on the citation engine."
448 i = find_token(document.header, "\\cite_engine", 0)
450 engine = get_value(document.header, "\\cite_engine", i).split("_")[0]
451 style = {"basic": "plain", "natbib": "plainnat", "jurabib": "jurabib"}
452 document.header.insert(i + 1, "\\biblio_style " + style[engine])
455 def revert_biblio_style(document):
456 "BibTeX insets with default option use the style defined by \\biblio_style."
457 i = find_token(document.header, "\\biblio_style" , 0)
459 document.warning("No \\biblio_style line. Nothing to do.")
462 default_style = get_value(document.header, "\\biblio_style", i)
463 del document.header[i]
465 # We are looking for bibtex insets having the default option
468 i = find_token(document.body, "\\begin_inset CommandInset bibtex", i)
471 j = find_end_of_inset(document.body, i)
473 document.warning("Malformed LyX document: Can't find end of bibtex inset at line " + str(i))
476 k = find_token(document.body, "options", i, j)
478 options = get_quoted_value(document.body, "options", k)
479 if "default" in options.split(","):
480 document.body[k] = 'options "%s"' \
481 % options.replace("default", default_style)
485 def handle_longtable_captions(document, forward):
488 begin_table = find_token(document.body, '<lyxtabular version=', begin_table)
489 if begin_table == -1:
491 end_table = find_end_of(document.body, begin_table, '<lyxtabular', '</lyxtabular>')
493 document.warning("Malformed LyX document: Could not find end of table.")
496 fline = find_token(document.body, "<features", begin_table, end_table)
498 document.warning("Can't find features for inset at line " + str(begin_table))
501 p = document.body[fline].find("islongtable")
506 numrows = get_option_value(document.body[begin_table], "rows")
508 numrows = int(numrows)
510 document.warning(document.body[begin_table])
511 document.warning("Unable to determine rows!")
512 begin_table = end_table
514 begin_row = begin_table
515 for row in range(numrows):
516 begin_row = find_token(document.body, '<row', begin_row, end_table)
518 document.warning("Can't find row " + str(row + 1))
520 end_row = find_end_of(document.body, begin_row, '<row', '</row>')
522 document.warning("Can't find end of row " + str(row + 1))
525 if (get_option_value(document.body[begin_row], 'caption') == 'true' and
526 get_option_value(document.body[begin_row], 'endfirsthead') != 'true' and
527 get_option_value(document.body[begin_row], 'endhead') != 'true' and
528 get_option_value(document.body[begin_row], 'endfoot') != 'true' and
529 get_option_value(document.body[begin_row], 'endlastfoot') != 'true'):
530 document.body[begin_row] = set_option_value(document.body[begin_row], 'caption', 'true", endfirsthead="true')
531 elif get_option_value(document.body[begin_row], 'caption') == 'true':
532 if get_option_value(document.body[begin_row], 'endfirsthead') == 'true':
533 document.body[begin_row] = set_option_value(document.body[begin_row], 'endfirsthead', 'false')
534 if get_option_value(document.body[begin_row], 'endhead') == 'true':
535 document.body[begin_row] = set_option_value(document.body[begin_row], 'endhead', 'false')
536 if get_option_value(document.body[begin_row], 'endfoot') == 'true':
537 document.body[begin_row] = set_option_value(document.body[begin_row], 'endfoot', 'false')
538 if get_option_value(document.body[begin_row], 'endlastfoot') == 'true':
539 document.body[begin_row] = set_option_value(document.body[begin_row], 'endlastfoot', 'false')
541 # since there could be a tabular inside this one, we
542 # cannot jump to end.
546 def convert_longtable_captions(document):
547 "Add a firsthead flag to caption rows"
548 handle_longtable_captions(document, True)
551 def revert_longtable_captions(document):
552 "remove head/foot flag from caption rows"
553 handle_longtable_captions(document, False)
556 def convert_use_packages(document):
557 "use_xxx yyy => use_package xxx yyy"
558 packages = ["amsmath", "esint", "mathdots", "mhchem", "undertilde"]
560 i = find_token(document.header, "\\use_%s" % p, 0)
562 value = get_value(document.header, "\\use_%s" % p, i)
563 document.header[i] = "\\use_package %s %s" % (p, value)
566 def revert_use_packages(document):
567 "use_package xxx yyy => use_xxx yyy"
568 packages = ["amsmath", "esint", "mhchem", "mathdots", "undertilde"]
569 # the order is arbitrary for the use_package version, and not all packages need to be given.
570 # Ensure a complete list and correct order (important for older LyX versions and especially lyx2lyx)
571 # first loop: find line with first package
574 regexp = re.compile(r'(\\use_package\s+%s)' % p)
575 i = find_re(document.header, regexp, 0)
576 if i != -1 and (j < 0 or i < j):
578 # second loop: replace or insert packages in front of all existing ones
580 regexp = re.compile(r'(\\use_package\s+%s)' % p)
581 i = find_re(document.header, regexp, 0)
583 value = get_value(document.header, "\\use_package %s" % p, i).split()[1]
584 del document.header[i]
585 document.header.insert(j, "\\use_%s %s" % (p, value))
587 document.header.insert(j, "\\use_%s 1" % p)
591 def convert_use_package(document, pkg, commands, oldauto):
592 # oldauto defines how the version we are converting from behaves:
593 # if it is true, the old version uses the package automatically.
594 # if it is false, the old version never uses the package.
595 i = find_token(document.header, "\\use_package", 0)
597 document.warning("Malformed LyX document: Can't find \\use_package.")
599 j = find_token(document.preamble, "\\usepackage{" + pkg + "}", 0)
601 # package was loaded in the preamble, convert this to header setting for round trip
602 document.header.insert(i + 1, "\\use_package " + pkg + " 2") # on
603 del document.preamble[j]
604 # If oldauto is true we have two options:
605 # We can either set the package to auto - this is correct for files in
606 # format 425 to 463, and may create a conflict for older files which use
607 # any command in commands with a different definition.
608 # Or we can look whether any command in commands is used, and set it to
609 # auto if not and to off if yes. This will not create a conflict, but will
610 # create uncompilable documents for files in format 425 to 463, which use
611 # any command in commands.
612 # We choose the first option since its error is less likely.
614 document.header.insert(i + 1, "\\use_package " + pkg + " 1") # auto
618 j = find_token(document.body, '\\begin_inset Formula', j)
621 k = find_end_of_inset(document.body, j)
623 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(j))
626 code = "\n".join(document.body[j:k])
628 if code.find("\\%s" % c) != -1:
629 # at least one of the commands was found - need to switch package off
630 document.header.insert(i + 1, "\\use_package " + pkg + " 0") # off
633 # no command was found - set to auto (bug 9069)
634 document.header.insert(i + 1, "\\use_package " + pkg + " 1") # auto
637 def revert_use_package(document, pkg, commands, oldauto):
638 # oldauto defines how the version we are reverting to behaves:
639 # if it is true, the old version uses the package automatically.
640 # if it is false, the old version never uses the package.
641 regexp = re.compile(r'(\\use_package\s+%s)' % pkg)
642 i = find_re(document.header, regexp, 0)
643 value = "1" # default is auto
645 value = get_value(document.header, "\\use_package" , i).split()[1]
646 del document.header[i]
647 if value == "2": # on
648 add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
649 elif value == "1" and not oldauto: # auto
652 i = find_token(document.body, '\\begin_inset Formula', i)
655 j = find_end_of_inset(document.body, i)
657 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
660 code = "\n".join(document.body[i:j])
662 if code.find("\\%s" % c) != -1:
663 add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
668 mathtools_commands = ["mathclap", "mathllap", "mathrlap", \
669 "lgathered", "rgathered", "vcentcolon", "dblcolon", \
670 "coloneqq", "Coloneqq", "coloneq", "Coloneq", "eqqcolon", \
671 "Eqqcolon", "eqcolon", "Eqcolon", "colonapprox", \
672 "Colonapprox", "colonsim", "Colonsim"]
673 def convert_use_mathtools(document):
674 "insert use_package mathtools"
675 convert_use_package(document, "mathtools", mathtools_commands, False)
678 def revert_use_mathtools(document):
679 "remove use_package mathtools"
680 revert_use_package(document, "mathtools", mathtools_commands, False)
683 # commands provided by stmaryrd.sty but LyX uses other packages:
684 # boxdot lightning, bigtriangledown, bigtriangleup
685 stmaryrd_commands = ["shortleftarrow", "shortrightarrow", "shortuparrow", \
686 "shortdownarrow", "Yup", "Ydown", "Yleft", "Yright", \
687 "varcurlyvee", "varcurlywedge", "minuso", "baro", \
688 "sslash", "bbslash", "moo", "varotimes", "varoast", \
689 "varobar", "varodot", "varoslash", "varobslash", \
690 "varocircle", "varoplus", "varominus", "boxast", \
691 "boxbar", "boxslash", "boxbslash", "boxcircle", \
692 "boxbox", "boxempty", "merge", "vartimes", \
693 "fatsemi", "sswarrow", "ssearrow", "curlywedgeuparrow", \
694 "curlywedgedownarrow", "fatslash", "fatbslash", "lbag", \
695 "rbag", "varbigcirc", "leftrightarroweq", \
696 "curlyveedownarrow", "curlyveeuparrow", "nnwarrow", \
697 "nnearrow", "leftslice", "rightslice", "varolessthan", \
698 "varogreaterthan", "varovee", "varowedge", "talloblong", \
699 "interleave", "obar", "obslash", "olessthan", \
700 "ogreaterthan", "ovee", "owedge", "oblong", "inplus", \
701 "niplus", "nplus", "subsetplus", "supsetplus", \
702 "subsetpluseq", "supsetpluseq", "Lbag", "Rbag", \
703 "llbracket", "rrbracket", "llparenthesis", \
704 "rrparenthesis", "binampersand", "bindnasrepma", \
705 "trianglelefteqslant", "trianglerighteqslant", \
706 "ntrianglelefteqslant", "ntrianglerighteqslant", \
707 "llfloor", "rrfloor", "llceil", "rrceil", "arrownot", \
708 "Arrownot", "Mapstochar", "mapsfromchar", "Mapsfromchar", \
709 "leftrightarrowtriangle", "leftarrowtriangle", \
710 "rightarrowtriangle", \
711 "bigcurlyvee", "bigcurlywedge", "bigsqcap", "bigbox", \
712 "bigparallel", "biginterleave", "bignplus", \
713 "varcopyright", "longarrownot", "Longarrownot", \
714 "Mapsto", "mapsfrom", "Mapsfrom" "Longmapsto", \
715 "longmapsfrom", "Longmapsfrom"]
716 def convert_use_stmaryrd(document):
717 "insert use_package stmaryrd"
718 convert_use_package(document, "stmaryrd", stmaryrd_commands, False)
721 def revert_use_stmaryrd(document):
722 "remove use_package stmaryrd"
723 revert_use_package(document, "stmaryrd", stmaryrd_commands, False)
726 stackrel_commands = ["stackrel"]
727 def convert_use_stackrel(document):
728 "insert use_package stackrel"
729 convert_use_package(document, "stackrel", stackrel_commands, False)
732 def revert_use_stackrel(document):
733 "remove use_package stackrel"
734 revert_use_package(document, "stackrel", stackrel_commands, False)
737 def convert_cite_engine_type(document):
738 "Determine the \\cite_engine_type from the citation engine."
739 i = find_token(document.header, "\\cite_engine", 0)
742 engine = get_value(document.header, "\\cite_engine", i)
744 engine, type = engine.split("_")
746 type = {"basic": "numerical", "jurabib": "authoryear"}[engine]
747 document.header[i] = "\\cite_engine " + engine
748 document.header.insert(i + 1, "\\cite_engine_type " + type)
751 def revert_cite_engine_type(document):
752 "Natbib had the type appended with an underscore."
753 engine_type = "numerical"
754 i = find_token(document.header, "\\cite_engine_type" , 0)
756 document.warning("No \\cite_engine_type line. Assuming numerical.")
758 engine_type = get_value(document.header, "\\cite_engine_type", i)
759 del document.header[i]
761 # We are looking for the natbib citation engine
762 i = find_token(document.header, "\\cite_engine natbib", 0)
765 document.header[i] = "\\cite_engine natbib_" + engine_type
768 def convert_cite_engine_type_default(document):
769 "Convert \\cite_engine_type to default for the basic citation engine."
770 i = find_token(document.header, "\\cite_engine basic", 0)
773 i = find_token(document.header, "\\cite_engine_type" , 0)
776 document.header[i] = "\\cite_engine_type default"
779 def revert_cite_engine_type_default(document):
780 """Revert \\cite_engine_type default.
782 Revert to numerical for the basic cite engine, otherwise to authoryear."""
783 engine_type = "authoryear"
784 i = find_token(document.header, "\\cite_engine_type default" , 0)
787 j = find_token(document.header, "\\cite_engine basic", 0)
789 engine_type = "numerical"
790 document.header[i] = "\\cite_engine_type " + engine_type
793 cancel_commands = ["cancel", "bcancel", "xcancel", "cancelto"]
794 # this is the same, as revert_use_cancel() except for the default
795 def revert_cancel(document):
796 "add cancel to the preamble if necessary"
797 revert_use_package(document, "cancel", cancel_commands, False)
800 def revert_verbatim(document):
801 " Revert verbatim einvironments completely to TeX-code. "
804 subst_end = ['\end_layout', '', '\\begin_layout Plain Layout',
806 '\\begin_layout Plain Layout', '', '',
809 '\\end_layout', '', '\\end_inset',
810 '', '', '\\end_layout']
811 subst_begin = ['\\begin_layout Standard', '\\noindent',
812 '\\begin_inset ERT', 'status open', '',
813 '\\begin_layout Plain Layout', '', '', '\\backslash',
815 '\\end_layout', '', '\\begin_layout Plain Layout', '']
818 i = find_token(document.body, "\\begin_layout Verbatim", i)
821 j = find_end_of_layout(document.body, i)
823 document.warning("Malformed LyX document: Can't find end of Verbatim layout")
826 # delete all line breaks insets (there are no other insets)
829 n = find_token(document.body, "\\begin_inset Newline newline", l, j)
831 n = find_token(document.body, "\\begin_inset Newline linebreak", l, j)
834 m = find_end_of_inset(document.body, n)
835 del(document.body[m:m+1])
836 document.body[n:n+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
838 # we deleted a line, so the end of the inset moved forward.
840 # consecutive verbatim environments need to be connected
841 k = find_token(document.body, "\\begin_layout Verbatim", j)
842 if k == j + 2 and consecutive == False:
844 document.body[j:j+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
845 document.body[i:i+1] = subst_begin
847 if k == j + 2 and consecutive == True:
848 document.body[j:j+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
849 del(document.body[i:i+1])
851 if k != j + 2 and consecutive == True:
852 document.body[j:j+1] = subst_end
853 # the next paragraph must not be indented
854 document.body[j+19:j+19] = ['\\noindent']
855 del(document.body[i:i+1])
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 document.body[i:i+1] = subst_begin
865 def revert_tipa(document):
866 " Revert native TIPA insets to mathed or ERT. "
869 i = find_token(document.body, "\\begin_inset IPA", i)
872 j = find_end_of_inset(document.body, i)
874 document.warning("Malformed LyX document: Can't find end of IPA inset")
878 n = find_token(document.body, "\\begin_layout", i, j)
880 document.warning("Malformed LyX document: IPA inset has no embedded layout")
883 m = find_end_of_layout(document.body, n)
885 document.warning("Malformed LyX document: Can't find end of embedded layout")
888 content = document.body[n+1:m]
889 p = find_token(document.body, "\\begin_layout", m, j)
890 if p != -1 or len(content) > 1:
892 content = document.body[i+1:j]
894 # IPA insets with multiple pars need to be wrapped by \begin{IPA}...\end{IPA}
895 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}")
896 add_to_preamble(document, ["\\usepackage{tipa,tipx}"])
898 # single-par IPA insets can be reverted to mathed
899 document.body[i:j+1] = ["\\begin_inset Formula $\\text{\\textipa{" + content[0] + "}}$", "\\end_inset"]
903 def revert_cell_rotation(document):
904 "Revert cell rotations to TeX-code"
906 load_rotating = False
910 # first, let's find out if we need to do anything
911 i = find_token(document.body, '<cell ', i)
914 j = document.body[i].find('rotate="')
916 k = document.body[i].find('"', j + 8)
917 value = document.body[i][j + 8 : k]
919 rgx = re.compile(r' rotate="[^"]+?"')
920 # remove rotate option
921 document.body[i] = rgx.sub('', document.body[i])
923 rgx = re.compile(r' rotate="[^"]+?"')
924 document.body[i] = rgx.sub(' rotate="true"', document.body[i])
926 rgx = re.compile(r' rotate="[^"]+?"')
928 # remove rotate option
929 document.body[i] = rgx.sub('', document.body[i])
931 document.body[i + 5 : i + 5] = \
932 put_cmd_in_ert("\\end{turn}")
933 document.body[i + 4 : i + 4] = \
934 put_cmd_in_ert("\\begin{turn}{" + value + "}")
940 add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"])
943 def convert_cell_rotation(document):
944 'Convert cell rotation statements from "true" to "90"'
948 # first, let's find out if we need to do anything
949 i = find_token(document.body, '<cell ', i)
952 j = document.body[i].find('rotate="true"')
954 rgx = re.compile(r'rotate="[^"]+?"')
955 # convert "true" to "90"
956 document.body[i] = rgx.sub('rotate="90"', document.body[i])
961 def revert_table_rotation(document):
962 "Revert table rotations to TeX-code"
964 load_rotating = False
968 # first, let's find out if we need to do anything
969 i = find_token(document.body, '<features ', i)
972 j = document.body[i].find('rotate="')
974 end_table = find_token(document.body, '</lyxtabular>', j)
975 k = document.body[i].find('"', j + 8)
976 value = document.body[i][j + 8 : k]
978 rgx = re.compile(r' rotate="[^"]+?"')
979 # remove rotate option
980 document.body[i] = rgx.sub('', document.body[i])
982 rgx = re.compile(r'rotate="[^"]+?"')
983 document.body[i] = rgx.sub('rotate="true"', document.body[i])
985 rgx = re.compile(r' rotate="[^"]+?"')
987 # remove rotate option
988 document.body[i] = rgx.sub('', document.body[i])
990 document.body[end_table + 3 : end_table + 3] = \
991 put_cmd_in_ert("\\end{turn}")
992 document.body[i - 2 : i - 2] = \
993 put_cmd_in_ert("\\begin{turn}{" + value + "}")
999 add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"])
1002 def convert_table_rotation(document):
1003 'Convert table rotation statements from "true" to "90"'
1007 # first, let's find out if we need to do anything
1008 i = find_token(document.body, '<features ', i)
1011 j = document.body[i].find('rotate="true"')
1013 rgx = re.compile(r'rotate="[^"]+?"')
1014 # convert "true" to "90"
1015 document.body[i] = rgx.sub('rotate="90"', document.body[i])
1020 def convert_listoflistings(document):
1021 'Convert ERT \lstlistoflistings to TOC lstlistoflistings inset'
1022 # We can support roundtrip because the command is so simple
1025 i = find_token(document.body, "\\begin_inset ERT", i)
1028 j = find_end_of_inset(document.body, i)
1030 document.warning("Malformed LyX document: Can't find end of ERT inset")
1033 ert = get_ert(document.body, i)
1034 if ert == "\\lstlistoflistings{}":
1035 document.body[i:j] = ["\\begin_inset CommandInset toc", "LatexCommand lstlistoflistings", ""]
1041 def revert_listoflistings(document):
1042 'Convert TOC lstlistoflistings inset to ERT lstlistoflistings'
1045 i = find_token(document.body, "\\begin_inset CommandInset toc", i)
1048 if document.body[i+1] == "LatexCommand lstlistoflistings":
1049 j = find_end_of_inset(document.body, i)
1051 document.warning("Malformed LyX document: Can't find end of TOC inset")
1054 subst = put_cmd_in_ert("\\lstlistoflistings{}")
1055 document.body[i:j+1] = subst
1056 add_to_preamble(document, ["\\usepackage{listings}"])
1060 def convert_use_amssymb(document):
1061 "insert use_package amssymb"
1062 regexp = re.compile(r'(\\use_package\s+amsmath)')
1063 i = find_re(document.header, regexp, 0)
1065 document.warning("Malformed LyX document: Can't find \\use_package amsmath.")
1067 value = get_value(document.header, "\\use_package" , i).split()[1]
1070 useamsmath = int(value)
1072 document.warning("Invalid \\use_package amsmath: " + value + ". Assuming auto.")
1074 j = find_token(document.preamble, "\\usepackage{amssymb}", 0)
1076 document.header.insert(i + 1, "\\use_package amssymb %d" % useamsmath)
1078 document.header.insert(i + 1, "\\use_package amssymb 2")
1079 del document.preamble[j]
1082 def revert_use_amssymb(document):
1083 "remove use_package amssymb"
1084 regexp1 = re.compile(r'(\\use_package\s+amsmath)')
1085 regexp2 = re.compile(r'(\\use_package\s+amssymb)')
1086 i = find_re(document.header, regexp1, 0)
1087 j = find_re(document.header, regexp2, 0)
1088 value1 = "1" # default is auto
1089 value2 = "1" # default is auto
1091 value1 = get_value(document.header, "\\use_package" , i).split()[1]
1093 value2 = get_value(document.header, "\\use_package" , j).split()[1]
1094 del document.header[j]
1095 if value1 != value2 and value2 == "2": # on
1096 add_to_preamble(document, ["\\usepackage{amssymb}"])
1099 def convert_use_cancel(document):
1100 "insert use_package cancel"
1101 convert_use_package(document, "cancel", cancel_commands, True)
1104 def revert_use_cancel(document):
1105 "remove use_package cancel"
1106 revert_use_package(document, "cancel", cancel_commands, True)
1109 def revert_ancientgreek(document):
1110 "Set the document language for ancientgreek to greek"
1112 if document.language == "ancientgreek":
1113 document.language = "greek"
1114 i = find_token(document.header, "\\language", 0)
1116 document.header[i] = "\\language greek"
1119 j = find_token(document.body, "\\lang ancientgreek", j)
1123 document.body[j] = document.body[j].replace("\\lang ancientgreek", "\\lang greek")
1127 def revert_languages(document):
1128 "Set the document language for new supported languages to English"
1131 "coptic", "divehi", "hindi", "kurmanji", "lao", "marathi", "occitan", "sanskrit",
1132 "syriac", "tamil", "telugu", "urdu"
1134 for n in range(len(languages)):
1135 if document.language == languages[n]:
1136 document.language = "english"
1137 i = find_token(document.header, "\\language", 0)
1139 document.header[i] = "\\language english"
1141 while j < len(document.body):
1142 j = find_token(document.body, "\\lang " + languages[n], j)
1144 document.body[j] = document.body[j].replace("\\lang " + languages[n], "\\lang english")
1147 j = len(document.body)
1150 def convert_armenian(document):
1151 "Use polyglossia and thus non-TeX fonts for Armenian"
1153 if document.language == "armenian":
1154 i = find_token(document.header, "\\use_non_tex_fonts", 0)
1156 document.header[i] = "\\use_non_tex_fonts true"
1159 def revert_armenian(document):
1160 "Use ArmTeX and thus TeX fonts for Armenian"
1162 if document.language == "armenian":
1163 i = find_token(document.header, "\\use_non_tex_fonts", 0)
1165 document.header[i] = "\\use_non_tex_fonts false"
1168 def revert_libertine(document):
1169 " Revert native libertine font definition to LaTeX "
1171 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1172 i = find_token(document.header, "\\font_roman libertine", 0)
1175 j = find_token(document.header, "\\font_osf true", 0)
1178 preamble = "\\usepackage"
1180 document.header[j] = "\\font_osf false"
1183 preamble += "[lining]"
1184 preamble += "{libertine-type1}"
1185 add_to_preamble(document, [preamble])
1186 document.header[i] = "\\font_roman default"
1189 def revert_txtt(document):
1190 " Revert native txtt font definition to LaTeX "
1192 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1193 i = find_token(document.header, "\\font_typewriter txtt", 0)
1195 preamble = "\\renewcommand{\\ttdefault}{txtt}"
1196 add_to_preamble(document, [preamble])
1197 document.header[i] = "\\font_typewriter default"
1200 def revert_mathdesign(document):
1201 " Revert native mathdesign font definition to LaTeX "
1203 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1209 i = find_token(document.header, "\\font_roman", 0)
1212 val = get_value(document.header, "\\font_roman", i)
1213 if val in mathdesign_dict.keys():
1214 preamble = "\\usepackage[%s" % mathdesign_dict[val]
1216 j = find_token(document.header, "\\font_osf true", 0)
1219 document.header[j] = "\\font_osf false"
1220 l = find_token(document.header, "\\font_sc true", 0)
1223 document.header[l] = "\\font_sc false"
1225 preamble += ",expert"
1226 preamble += "]{mathdesign}"
1227 add_to_preamble(document, [preamble])
1228 document.header[i] = "\\font_roman default"
1231 def revert_texgyre(document):
1232 " Revert native TeXGyre font definition to LaTeX "
1234 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1235 texgyre_fonts = ["tgadventor", "tgbonum", "tgchorus", "tgcursor", \
1236 "tgheros", "tgpagella", "tgschola", "tgtermes"]
1237 i = find_token(document.header, "\\font_roman", 0)
1239 val = get_value(document.header, "\\font_roman", i)
1240 if val in texgyre_fonts:
1241 preamble = "\\usepackage{%s}" % val
1242 add_to_preamble(document, [preamble])
1243 document.header[i] = "\\font_roman default"
1244 i = find_token(document.header, "\\font_sans", 0)
1246 val = get_value(document.header, "\\font_sans", i)
1247 if val in texgyre_fonts:
1248 preamble = "\\usepackage{%s}" % val
1249 add_to_preamble(document, [preamble])
1250 document.header[i] = "\\font_sans default"
1251 i = find_token(document.header, "\\font_typewriter", 0)
1253 val = get_value(document.header, "\\font_typewriter", i)
1254 if val in texgyre_fonts:
1255 preamble = "\\usepackage{%s}" % val
1256 add_to_preamble(document, [preamble])
1257 document.header[i] = "\\font_typewriter default"
1260 def revert_ipadeco(document):
1261 " Revert IPA decorations to ERT "
1264 i = find_token(document.body, "\\begin_inset IPADeco", i)
1267 end = find_end_of_inset(document.body, i)
1269 document.warning("Can't find end of inset at line " + str(i))
1272 line = document.body[i]
1273 rx = re.compile(r'\\begin_inset IPADeco (.*)$')
1275 decotype = m.group(1)
1276 if decotype != "toptiebar" and decotype != "bottomtiebar":
1277 document.warning("Invalid IPADeco type: " + decotype)
1280 blay = find_token(document.body, "\\begin_layout Plain Layout", i, end)
1282 document.warning("Can't find layout for inset at line " + str(i))
1285 bend = find_end_of_layout(document.body, blay)
1287 document.warning("Malformed LyX document: Could not find end of IPADeco inset's layout.")
1290 substi = ["\\begin_inset ERT", "status collapsed", "",
1291 "\\begin_layout Plain Layout", "", "", "\\backslash",
1292 decotype + "{", "\\end_layout", "", "\\end_inset"]
1293 substj = ["\\size default", "", "\\begin_inset ERT", "status collapsed", "",
1294 "\\begin_layout Plain Layout", "", "}", "\\end_layout", "", "\\end_inset"]
1295 # do the later one first so as not to mess up the numbering
1296 document.body[bend:end + 1] = substj
1297 document.body[i:blay + 1] = substi
1298 i = end + len(substi) + len(substj) - (end - bend) - (blay - i) - 2
1299 add_to_preamble(document, "\\usepackage{tipa}")
1302 def revert_ipachar(document):
1303 ' Revert \\IPAChar to ERT '
1306 while i < len(document.body):
1307 m = re.match(r'(.*)\\IPAChar \\(\w+\{\w+\})(.*)', document.body[i])
1311 ipachar = m.group(2)
1314 '\\begin_inset ERT',
1315 'status collapsed', '',
1316 '\\begin_layout Standard',
1317 '', '', '\\backslash',
1322 document.body[i: i+1] = subst
1327 add_to_preamble(document, "\\usepackage{tone}")
1330 def revert_minionpro(document):
1331 " Revert native MinionPro font definition to LaTeX "
1333 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1334 i = find_token(document.header, "\\font_roman minionpro", 0)
1337 j = find_token(document.header, "\\font_osf true", 0)
1340 preamble = "\\usepackage"
1342 document.header[j] = "\\font_osf false"
1345 preamble += "{MinionPro}"
1346 add_to_preamble(document, [preamble])
1347 document.header[i] = "\\font_roman default"
1350 def revert_mathfonts(document):
1351 " Revert native math font definitions to LaTeX "
1353 i = find_token(document.header, "\\font_math", 0)
1356 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1357 val = get_value(document.header, "\\font_math", i)
1358 if val == "eulervm":
1359 add_to_preamble(document, "\\usepackage{eulervm}")
1360 elif val == "default":
1362 "lmodern": "\\renewcommand{\\rmdefault}{lmr}",
1363 "minionpro": "\\usepackage[onlytext,lf]{MinionPro}",
1364 "minionpro-osf": "\\usepackage[onlytext]{MinionPro}",
1365 "palatino": "\\renewcommand{\\rmdefault}{ppl}",
1366 "palatino-osf": "\\renewcommand{\\rmdefault}{pplj}",
1367 "times": "\\renewcommand{\\rmdefault}{ptm}",
1368 "utopia": "\\renewcommand{\\rmdefault}{futs}",
1369 "utopia-osf": "\\renewcommand{\\rmdefault}{futj}",
1371 j = find_token(document.header, "\\font_roman", 0)
1373 rm = get_value(document.header, "\\font_roman", j)
1374 k = find_token(document.header, "\\font_osf true", 0)
1377 if rm in mathfont_dict.keys():
1378 add_to_preamble(document, mathfont_dict[rm])
1379 document.header[j] = "\\font_roman default"
1381 document.header[k] = "\\font_osf false"
1382 del document.header[i]
1385 def revert_mdnomath(document):
1386 " Revert mathdesign and fourier without math "
1388 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1390 "md-charter": "mdbch",
1391 "md-utopia": "mdput",
1392 "md-garamond": "mdugm"
1394 i = find_token(document.header, "\\font_roman", 0)
1397 val = get_value(document.header, "\\font_roman", i)
1398 if val in mathdesign_dict.keys():
1399 j = find_token(document.header, "\\font_math", 0)
1401 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1402 mval = get_value(document.header, "\\font_math", j)
1403 if mval == "default":
1404 document.header[i] = "\\font_roman default"
1405 add_to_preamble(document, "\\renewcommand{\\rmdefault}{%s}" % mathdesign_dict[val])
1407 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1410 def convert_mdnomath(document):
1411 " Change mathdesign font name "
1413 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1415 "mdbch": "md-charter",
1416 "mdput": "md-utopia",
1417 "mdugm": "md-garamond"
1419 i = find_token(document.header, "\\font_roman", 0)
1422 val = get_value(document.header, "\\font_roman", i)
1423 if val in mathdesign_dict.keys():
1424 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1427 def revert_newtxmath(document):
1428 " Revert native newtxmath definitions to LaTeX "
1430 i = find_token(document.header, "\\font_math", 0)
1433 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1434 val = get_value(document.header, "\\font_math", i)
1436 "libertine-ntxm": "\\usepackage[libertine]{newtxmath}",
1437 "minion-ntxm": "\\usepackage[minion]{newtxmath}",
1438 "newtxmath": "\\usepackage{newtxmath}",
1440 if val in mathfont_dict.keys():
1441 add_to_preamble(document, mathfont_dict[val])
1442 document.header[i] = "\\font_math auto"
1445 def revert_biolinum(document):
1446 " Revert native biolinum font definition to LaTeX "
1448 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1449 i = find_token(document.header, "\\font_sans biolinum", 0)
1452 j = find_token(document.header, "\\font_osf true", 0)
1455 preamble = "\\usepackage"
1458 preamble += "{biolinum-type1}"
1459 add_to_preamble(document, [preamble])
1460 document.header[i] = "\\font_sans default"
1463 def revert_uop(document):
1464 " Revert native URW Classico (Optima) font definition to LaTeX "
1466 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1467 i = find_token(document.header, "\\font_sans uop", 0)
1469 preamble = "\\renewcommand{\\sfdefault}{uop}"
1470 add_to_preamble(document, [preamble])
1471 document.header[i] = "\\font_sans default"
1474 def convert_latexargs(document):
1475 " Convert InsetArgument to new syntax "
1477 if find_token(document.body, "\\begin_inset Argument", 0) == -1:
1481 # A list of layouts (document classes) with only optional or no arguments.
1482 # These can be safely converted to the new syntax
1483 # (I took the liberty to add some of my personal layouts/modules here; JSP)
1484 safe_layouts = ["aa", "aapaper", "aastex", "achemso", "acmsiggraph", "AEA",
1485 "agu-dtd", "agums", "agutex", "amsart", "amsbook", "apa",
1486 "arab-article", "armenian-article", "article-beamer", "article",
1487 "beamer", "book", "broadway", "chess", "cl2emult", "ctex-article",
1488 "ctex-book", "ctex-report", "dinbrief", "docbook-book", "docbook-chapter",
1489 "docbook", "docbook-section", "doublecol-new", "dtk", "ectaart", "egs",
1490 "elsarticle", "elsart", "entcs", "europecv", "extarticle", "extbook",
1491 "extletter", "extreport", "foils", "frletter", "g-brief2", "g-brief",
1492 "heb-article", "heb-letter", "hollywood", "IEEEtran", "ijmpc", "ijmpd",
1493 "iopart", "isprs", "jarticle", "jasatex", "jbook", "jgrga", "jreport",
1494 "jsarticle", "jsbeamer", "jsbook", "jss", "kluwer", "latex8", "letter", "lettre",
1495 "literate-article", "literate-book", "literate-report", "llncs", "ltugboat",
1496 "memoir", "moderncv", "mwart", "mwbk", "mwrep", "paper", "powerdot",
1497 "recipebook", "report", "revtex4", "revtex", "scrartcl", "scrarticle-beamer",
1498 "scrbook", "scrlettr", "scrlttr2", "scrreprt", "seminar", "siamltex",
1499 "sigplanconf", "simplecv", "singlecol", "singlecol-new", "slides", "spie",
1500 "svglobal3", "svglobal", "svjog", "svmono", "svmult", "svprobth", "tarticle",
1501 "tbook", "treport", "tufte-book", "tufte-handout"]
1502 # A list of "safe" modules, same as above
1503 safe_modules = ["biblatex", "beameraddons", "beamersession", "braille", "customHeadersFooters",
1504 "endnotes", "enumitem", "eqs-within-sections", "figs-within-sections", "fix-cm",
1505 "fixltx2e", "foottoend", "hanging", "jscharstyles", "knitr", "lilypond",
1506 "linguistics", "linguisticx", "logicalmkup", "minimalistic", "nomindex", "noweb",
1507 "pdfcomment", "sweave", "tabs-within-sections", "theorems-ams-bytype",
1508 "theorems-ams-extended-bytype", "theorems-ams-extended", "theorems-ams", "theorems-bytype",
1509 "theorems-chap-bytype", "theorems-chap", "theorems-named", "theorems-sec-bytype",
1510 "theorems-sec", "theorems-starred", "theorems-std", "todonotes"]
1511 # Modules we need to take care of
1512 caveat_modules = ["initials"]
1513 # information about the relevant styles in caveat_modules (number of opt and req args)
1514 # use this if we get more caveat_modules. For now, use hard coding (see below).
1515 # initials = [{'Layout' : 'Initial', 'opt' : 1, 'req' : 1}]
1517 # Is this a known safe layout?
1518 safe_layout = document.textclass in safe_layouts
1520 document.warning("Lyx2lyx knows nothing about textclass '%s'. "
1521 "Please check if short title insets have been converted correctly."
1522 % document.textclass)
1523 # Do we use unsafe or unknown modules
1524 mods = document.get_module_list()
1525 unknown_modules = False
1526 used_caveat_modules = list()
1528 if mod in safe_modules:
1530 if mod in caveat_modules:
1531 used_caveat_modules.append(mod)
1533 unknown_modules = True
1534 document.warning("Lyx2lyx knows nothing about module '%s'. "
1535 "Please check if short title insets have been converted correctly."
1540 i = find_token(document.body, "\\begin_inset Argument", i)
1544 if not safe_layout or unknown_modules:
1545 # We cannot do more here since we have no access to this layout.
1546 # InsetArgument itself will do the real work
1547 # (see InsetArgument::updateBuffer())
1548 document.body[i] = "\\begin_inset Argument 999"
1552 # Find containing paragraph layout
1553 parent = get_containing_layout(document.body, i)
1555 document.warning("Malformed LyX document: Can't find parent paragraph layout")
1562 if len(used_caveat_modules) > 0:
1563 # We know for now that this must be the initials module with the Initial layout
1564 # If we get more such modules, we need some automating.
1565 if parent[0] == "Initial":
1566 # Layout has 1 opt and 1 req arg.
1567 # Count the actual arguments
1569 for p in range(parbeg, parend):
1570 if document.body[p] == "\\begin_inset Argument":
1575 # Collect all arguments in this paragraph
1577 for p in range(parbeg, parend):
1578 if document.body[p] == "\\begin_inset Argument":
1580 if allowed_opts != -1:
1581 # We have less arguments than opt + required.
1582 # required must take precedence.
1583 if argnr > allowed_opts and argnr < first_req:
1585 document.body[p] = "\\begin_inset Argument %d" % argnr
1589 def revert_latexargs(document):
1590 " Revert InsetArgument to old syntax "
1593 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
1596 # Search for Argument insets
1597 i = find_token(document.body, "\\begin_inset Argument", i)
1600 m = rx.match(document.body[i])
1602 # No ID: inset already reverted
1605 # Find containing paragraph layout
1606 parent = get_containing_layout(document.body, i)
1608 document.warning("Malformed LyX document: Can't find parent paragraph layout")
1613 # Do not set realparbeg to parent[3], since this does not work if we
1614 # have another inset (e.g. label or index) before the first argument
1615 # inset (this is the case in the user guide of LyX 2.0.8)
1617 # Collect all arguments in this paragraph
1619 for p in range(parbeg, parend):
1620 m = rx.match(document.body[p])
1623 # This is the first argument inset
1625 val = int(m.group(1))
1626 j = find_end_of_inset(document.body, p)
1627 # Revert to old syntax
1628 document.body[p] = "\\begin_inset Argument"
1630 document.warning("Malformed LyX document: Can't find end of Argument inset")
1633 args[val] = document.body[p : j + 1]
1635 realparend = realparend - len(document.body[p : j + 1])
1636 # Remove arg inset at this position
1637 del document.body[p : j + 1]
1641 # No argument inset found
1642 realparbeg = parent[3]
1643 # Now sort the arg insets
1645 for f in sorted(args):
1648 # Insert the sorted arg insets at paragraph begin
1649 document.body[realparbeg : realparbeg] = subst
1651 i = realparbeg + 1 + len(subst)
1654 def revert_IEEEtran(document):
1656 Reverts InsetArgument of
1659 Biography without photo
1662 if document.textclass == "IEEEtran":
1669 i = find_token(document.body, "\\begin_layout Page headings", i)
1671 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1674 i2 = find_token(document.body, "\\begin_inset Flex Paragraph Start", i2)
1676 revert_Argument_to_TeX_brace(document, i2, 0, 1, 1, False, False)
1679 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1681 revert_Argument_to_TeX_brace(document, j, 0, 1, 1, True, False)
1684 k = find_token(document.body, "\\begin_layout Biography", k)
1685 kA = find_token(document.body, "\\begin_layout Biography without photo", k)
1686 if k == kA and k != -1:
1690 # start with the second argument, therefore 2
1691 revert_Argument_to_TeX_brace(document, k, 0, 2, 2, True, False)
1693 if i == -1 and i2 == -1 and j == -1 and k == -1:
1697 def revert_IEEEtran_2(document):
1699 Reverts Flex Paragraph Start to TeX-code
1701 if document.textclass == "IEEEtran":
1704 begin = find_token(document.body, "\\begin_inset Flex Paragraph Start", begin)
1707 end1 = find_end_of_inset(document.body, begin)
1708 document.body[end1 - 2 : end1 + 1] = put_cmd_in_ert("}")
1709 document.body[begin : begin + 4] = put_cmd_in_ert("\\IEEEPARstart{")
1713 def convert_IEEEtran(document):
1718 Biography without photo
1721 if document.textclass == "IEEEtran":
1727 i = find_token(document.body, "\\begin_layout Page headings", i)
1729 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1732 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1734 convert_TeX_brace_to_Argument(document, j, 1, 1, False, True, False)
1737 # assure that we don't handle Biography Biography without photo
1738 k = find_token(document.body, "\\begin_layout Biography", k)
1739 kA = find_token(document.body, "\\begin_layout Biography without photo", k - 1)
1740 if k == kA and k != -1:
1744 # the argument we want to convert is the second one
1745 convert_TeX_brace_to_Argument(document, k, 2, 2, False, True, False)
1747 if i == -1 and j == -1 and k == -1:
1751 def revert_AASTeX(document):
1752 " Reverts InsetArgument of Altaffilation to TeX-code "
1753 if document.textclass == "aastex":
1756 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1759 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1763 def convert_AASTeX(document):
1764 " Converts ERT of Altaffilation to InsetArgument "
1765 if document.textclass == "aastex":
1768 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1771 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1775 def revert_AGUTeX(document):
1776 " Reverts InsetArgument of Author affiliation to TeX-code "
1777 if document.textclass == "agutex":
1780 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1783 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1787 def convert_AGUTeX(document):
1788 " Converts ERT of Author affiliation to InsetArgument "
1789 if document.textclass == "agutex":
1792 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1795 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1799 def revert_IJMP(document):
1800 " Reverts InsetArgument of MarkBoth to TeX-code "
1801 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1804 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1807 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1811 def convert_IJMP(document):
1812 " Converts ERT of MarkBoth to InsetArgument "
1813 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1816 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1819 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1823 def revert_SIGPLAN(document):
1824 " Reverts InsetArguments of SIGPLAN to TeX-code "
1825 if document.textclass == "sigplanconf":
1830 i = find_token(document.body, "\\begin_layout Conference", i)
1832 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1835 j = find_token(document.body, "\\begin_layout Author", j)
1837 revert_Argument_to_TeX_brace(document, j, 0, 1, 2, False, False)
1839 if i == -1 and j == -1:
1843 def convert_SIGPLAN(document):
1844 " Converts ERT of SIGPLAN to InsetArgument "
1845 if document.textclass == "sigplanconf":
1850 i = find_token(document.body, "\\begin_layout Conference", i)
1852 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1855 j = find_token(document.body, "\\begin_layout Author", j)
1857 convert_TeX_brace_to_Argument(document, j, 1, 2, False, False, False)
1859 if i == -1 and j == -1:
1863 def revert_SIGGRAPH(document):
1864 " Reverts InsetArgument of Flex CRcat to TeX-code "
1865 if document.textclass == "acmsiggraph":
1868 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1871 revert_Argument_to_TeX_brace(document, i, 0, 1, 3, False, False)
1875 def convert_SIGGRAPH(document):
1876 " Converts ERT of Flex CRcat to InsetArgument "
1877 if document.textclass == "acmsiggraph":
1880 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1883 convert_TeX_brace_to_Argument(document, i, 1, 3, True, False, False)
1887 def revert_EuropeCV(document):
1888 " Reverts InsetArguments of europeCV to TeX-code "
1889 if document.textclass == "europecv":
1896 i = find_token(document.body, "\\begin_layout Item", i)
1898 revert_Argument_to_TeX_brace(document, i, 0, 2, 2, False, False)
1901 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1903 revert_Argument_to_TeX_brace(document, j, 0, 2, 2, False, False)
1906 k = find_token(document.body, "\\begin_layout Language", k)
1908 revert_Argument_to_TeX_brace(document, k, 0, 2, 6, False, False)
1911 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1913 revert_Argument_to_TeX_brace(document, m, 0, 2, 6, False, False)
1915 if i == -1 and j == -1 and k == -1 and m == -1:
1919 def convert_EuropeCV(document):
1920 " Converts ERT of europeCV to InsetArgument "
1921 if document.textclass == "europecv":
1928 i = find_token(document.body, "\\begin_layout Item", i)
1930 convert_TeX_brace_to_Argument(document, i, 2, 2, False, False, False)
1933 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1935 convert_TeX_brace_to_Argument(document, j, 2, 2, False, False, False)
1938 k = find_token(document.body, "\\begin_layout Language", k)
1940 convert_TeX_brace_to_Argument(document, k, 2, 6, False, False, False)
1943 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1945 convert_TeX_brace_to_Argument(document, m, 2, 6, False, False, False)
1947 if i == -1 and j == -1 and k == -1 and m == -1:
1951 def revert_ModernCV(document):
1952 " Reverts InsetArguments of modernCV to TeX-code "
1953 if document.textclass == "moderncv":
1961 j = find_token(document.body, "\\begin_layout Entry", j)
1963 revert_Argument_to_TeX_brace(document, j, 0, 1, 5, False, False)
1966 k = find_token(document.body, "\\begin_layout Item", k)
1968 revert_Argument_to_TeX_brace(document, k, 0, 1, 1, False, False)
1971 m = find_token(document.body, "\\begin_layout ItemWithComment", m)
1973 revert_Argument_to_TeX_brace(document, m, 0, 1, 2, False, False)
1974 document.body[m] = document.body[m].replace("\\begin_layout ItemWithComment", "\\begin_layout Language")
1977 o = find_token(document.body, "\\begin_layout DoubleItem", o)
1979 revert_Argument_to_TeX_brace(document, o, 0, 1, 3, False, False)
1980 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout Computer")
1983 p = find_token(document.body, "\\begin_layout Social", p)
1985 revert_Argument_to_TeX_brace(document, p, 0, 1, 1, False, True)
1987 if j == -1 and k == -1 and m == -1 and o == -1 and p == -1:
1991 def revert_ModernCV_2(document):
1992 " Reverts the Flex:Column inset of modernCV to TeX-code "
1993 if document.textclass == "moderncv":
1997 flex = find_token(document.body, "\\begin_inset Flex Column", flex)
2000 flexEnd = find_end_of_inset(document.body, flex)
2001 wasOpt = revert_Argument_to_TeX_brace(document, flex, flexEnd, 1, 1, False, True)
2002 revert_Argument_to_TeX_brace(document, flex, 0, 2, 2, False, False)
2003 flexEnd = find_end_of_inset(document.body, flex)
2005 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn")
2007 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn{")
2008 document.body[flexEnd + 4 : flexEnd + 7] = put_cmd_in_ert("}")
2012 def revert_ModernCV_3(document):
2013 " Reverts the Column style of modernCV to TeX-code "
2014 if document.textclass == "moderncv":
2015 # revert the layouts
2016 revert_ModernCV(document)
2018 # get the position of the end of the last column inset
2019 LastFlexEnd = revert_ModernCV_2(document)
2021 p = find_token(document.body, "\\begin_layout Columns", p)
2024 pEnd = find_end_of_layout(document.body, p)
2025 document.body[p] = document.body[p].replace("\\begin_layout Columns", "\\begin_layout Standard")
2026 if LastFlexEnd != -1:
2027 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\begin{cvcolumns}")
2028 document.body[LastFlexEnd + 24 : LastFlexEnd + 24] = put_cmd_in_ert("\\end{cvcolumns}")
2032 def revert_ModernCV_4(document):
2033 " Reverts the style Social to TeX-code "
2034 if document.textclass == "moderncv":
2035 # revert the layouts
2036 revert_ModernCV(document)
2039 p = find_token(document.body, "\\begin_layout Social", p)
2042 pEnd = find_end_of_layout(document.body, p)
2043 document.body[p] = document.body[p].replace("\\begin_layout Social", "\\begin_layout Standard")
2044 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\social")
2045 hasOpt = find_token(document.body, "[", p + 9)
2047 document.body[p + 30 : p + 30] = put_cmd_in_ert("{")
2048 document.body[p + 41 : p + 41] = put_cmd_in_ert("}")
2050 document.body[p + 11 : p + 11] = put_cmd_in_ert("{")
2051 document.body[p + 21 : p + 21] = put_cmd_in_ert("}")
2055 def convert_ModernCV(document):
2056 " Converts ERT of modernCV to InsetArgument "
2057 if document.textclass == "moderncv":
2065 i = find_token(document.body, "\\begin_layout DoubleItem", i)
2067 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
2068 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout DoubleListItem")
2071 j = find_token(document.body, "\\begin_layout Entry", j)
2073 convert_TeX_brace_to_Argument(document, j, 1, 5, False, False, False)
2076 k = find_token(document.body, "\\begin_layout Item", k)
2078 convert_TeX_brace_to_Argument(document, k, 1, 1, False, False, False)
2081 m = find_token(document.body, "\\begin_layout Language", m)
2083 convert_TeX_brace_to_Argument(document, m, 1, 2, False, False, False)
2085 if i == -1 and j == -1 and k == -1 and m == -1:
2089 def revert_Initials(document):
2090 " Reverts InsetArgument of Initial to TeX-code "
2093 i = find_token(document.body, "\\begin_layout Initial", i)
2096 # first arg (optional) and second arg (first mandatory) are supported in LyX 2.0.x
2097 revert_Argument_to_TeX_brace(document, i, 0, 3, 3, False, False)
2101 def convert_Initials(document):
2102 " Converts ERT of Initial to InsetArgument "
2105 i = find_token(document.body, "\\begin_layout Initial", i)
2108 convert_TeX_brace_to_Argument(document, i, 3, 3, False, False, False)
2112 def revert_literate(document):
2113 " Revert Literate document to old format "
2114 if del_token(document.header, "noweb", 0):
2115 document.textclass = "literate-" + document.textclass
2118 i = find_token(document.body, "\\begin_layout Chunk", i)
2121 document.body[i] = "\\begin_layout Scrap"
2125 def convert_literate(document):
2126 " Convert Literate document to new format"
2127 i = find_token(document.header, "\\textclass", 0)
2128 if (i != -1) and "literate-" in document.header[i]:
2129 document.textclass = document.header[i].replace("\\textclass literate-", "")
2130 j = find_token(document.header, "\\begin_modules", 0)
2132 document.header.insert(j + 1, "noweb")
2134 document.header.insert(i + 1, "\\end_modules")
2135 document.header.insert(i + 1, "noweb")
2136 document.header.insert(i + 1, "\\begin_modules")
2139 i = find_token(document.body, "\\begin_layout Scrap", i)
2142 document.body[i] = "\\begin_layout Chunk"
2146 def revert_itemargs(document):
2147 " Reverts \\item arguments to TeX-code "
2150 i = find_token(document.body, "\\begin_inset Argument item:", i)
2153 j = find_end_of_inset(document.body, i)
2154 # Find containing paragraph layout
2155 parent = get_containing_layout(document.body, i)
2157 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2161 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2162 endPlain = find_end_of_layout(document.body, beginPlain)
2163 content = document.body[beginPlain + 1 : endPlain]
2164 del document.body[i:j+1]
2165 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2166 document.body[parbeg : parbeg] = subst
2170 def revert_garamondx_newtxmath(document):
2171 " Revert native garamond newtxmath definition to LaTeX "
2173 i = find_token(document.header, "\\font_math", 0)
2176 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2177 val = get_value(document.header, "\\font_math", i)
2178 if val == "garamondx-ntxm":
2179 add_to_preamble(document, "\\usepackage[garamondx]{newtxmath}")
2180 document.header[i] = "\\font_math auto"
2183 def revert_garamondx(document):
2184 " Revert native garamond font definition to LaTeX "
2186 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2187 i = find_token(document.header, "\\font_roman garamondx", 0)
2190 j = find_token(document.header, "\\font_osf true", 0)
2193 preamble = "\\usepackage"
2195 preamble += "[osfI]"
2196 preamble += "{garamondx}"
2197 add_to_preamble(document, [preamble])
2198 document.header[i] = "\\font_roman default"
2201 def convert_beamerargs(document):
2202 " Converts beamer arguments to new layout "
2204 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2205 if document.textclass not in beamer_classes:
2208 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2209 list_layouts = ["Itemize", "Enumerate", "Description"]
2210 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
2214 i = find_token(document.body, "\\begin_inset Argument", i)
2217 # Find containing paragraph layout
2218 parent = get_containing_layout(document.body, i)
2220 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2225 layoutname = parent[0]
2226 for p in range(parbeg, parend):
2227 if layoutname in shifted_layouts:
2228 m = rx.match(document.body[p])
2230 argnr = int(m.group(1))
2232 document.body[p] = "\\begin_inset Argument %d" % argnr
2233 if layoutname == "AgainFrame":
2234 m = rx.match(document.body[p])
2236 document.body[p] = "\\begin_inset Argument 3"
2237 if document.body[p + 4] == "\\begin_inset ERT":
2238 if document.body[p + 9].startswith("<"):
2239 # This is an overlay specification
2241 document.body[p + 9] = document.body[p + 9][1:]
2242 if document.body[p + 9].endswith(">"):
2244 document.body[p + 9] = document.body[p + 9][:-1]
2246 document.body[p] = "\\begin_inset Argument 2"
2247 if layoutname in list_layouts:
2248 m = rx.match(document.body[p])
2250 if m.group(1) == "1":
2251 if document.body[p + 4] == "\\begin_inset ERT":
2252 if document.body[p + 9].startswith("<"):
2253 # This is an overlay specification
2255 document.body[p + 9] = document.body[p + 9][1:]
2256 if document.body[p + 9].endswith(">"):
2258 document.body[p + 9] = document.body[p + 9][:-1]
2259 elif document.body[p + 4].startswith("<"):
2260 # This is an overlay specification (without ERT)
2262 document.body[p + 4] = document.body[p + 4][1:]
2263 if document.body[p + 4].endswith(">"):
2265 document.body[p + 4] = document.body[p + 4][:-1]
2266 elif layoutname != "Itemize":
2268 document.body[p] = "\\begin_inset Argument 2"
2273 # Helper function for the frame conversion routines
2275 # FIXME: This method currently requires the arguments to be either
2276 # * In one (whole) ERT each: <ERT>[<arg1>]</ERT><ERT><arg2></ERT><ERT>[arg3]</ERT>
2277 # * Altogether in one whole ERT: <ERT>[<arg1>]<arg2>[arg3]</ERT>
2278 # If individual arguments mix ERT and non-ERT or are splitted
2279 # over several ERTs, the parsing fails.
2280 def convert_beamerframeargs(document, i, parbeg):
2283 if document.body[parbeg] != "\\begin_inset ERT":
2285 ertend = find_end_of_inset(document.body, parbeg)
2287 document.warning("Malformed LyX document: missing ERT \\end_inset")
2289 ertcont = parbeg + 5
2290 if document.body[ertcont].startswith("[<"):
2291 # This is a default overlay specification
2293 document.body[ertcont] = document.body[ertcont][2:]
2294 if document.body[ertcont].endswith(">]"):
2296 document.body[ertcont] = document.body[ertcont][:-2]
2297 elif document.body[ertcont].endswith("]"):
2299 tok = document.body[ertcont].find('>][')
2301 subst = [document.body[ertcont][:tok],
2302 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2303 'status collapsed', '', '\\begin_layout Plain Layout',
2304 document.body[ertcont][tok + 3:-1]]
2305 document.body[ertcont : ertcont + 1] = subst
2307 # Convert to ArgInset
2308 document.body[parbeg] = "\\begin_inset Argument 2"
2309 elif document.body[ertcont].startswith("<"):
2310 # This is an overlay specification
2312 document.body[ertcont] = document.body[ertcont][1:]
2313 if document.body[ertcont].endswith(">"):
2315 document.body[ertcont] = document.body[ertcont][:-1]
2316 # Convert to ArgInset
2317 document.body[parbeg] = "\\begin_inset Argument 1"
2318 elif document.body[ertcont].endswith(">]"):
2320 tok = document.body[ertcont].find('>[<')
2322 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2323 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2324 'status collapsed', '', '\\begin_layout Plain Layout',
2325 document.body[ertcont][tok + 3:-2]]
2326 # Convert to ArgInset
2327 document.body[parbeg] = "\\begin_inset Argument 1"
2329 elif document.body[ertcont].endswith("]"):
2331 tok = document.body[ertcont].find('>[<')
2334 tokk = document.body[ertcont].find('>][')
2336 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2337 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2338 'status collapsed', '', '\\begin_layout Plain Layout',
2339 document.body[ertcont][tok + 3:tokk],
2340 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2341 'status collapsed', '', '\\begin_layout Plain Layout',
2342 document.body[ertcont][tokk + 3:-1]]
2345 tokk = document.body[ertcont].find('>[')
2347 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tokk],
2348 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2349 'status collapsed', '', '\\begin_layout Plain Layout',
2350 document.body[ertcont][tokk + 2:-1]]
2352 # Convert to ArgInset
2353 document.body[parbeg] = "\\begin_inset Argument 1"
2354 elif document.body[ertcont].startswith("["):
2355 # This is an ERT option
2357 document.body[ertcont] = document.body[ertcont][1:]
2358 if document.body[ertcont].endswith("]"):
2360 document.body[ertcont] = document.body[ertcont][:-1]
2361 # Convert to ArgInset
2362 document.body[parbeg] = "\\begin_inset Argument 3"
2368 def convert_againframe_args(document):
2369 " Converts beamer AgainFrame to new layout "
2371 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2372 if document.textclass not in beamer_classes:
2377 i = find_token(document.body, "\\begin_layout AgainFrame", i)
2380 parent = get_containing_layout(document.body, i)
2382 document.warning("Wrong parent layout!")
2386 # Convert ERT arguments
2387 # FIXME: See restrictions in convert_beamerframeargs method
2388 ertend = convert_beamerframeargs(document, i, parbeg)
2394 def convert_corollary_args(document):
2395 " Converts beamer corrolary-style ERT arguments native InsetArgs "
2397 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2398 if document.textclass not in beamer_classes:
2401 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2402 for lay in corollary_layouts:
2405 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2408 parent = get_containing_layout(document.body, i)
2410 document.warning("Wrong parent layout!")
2414 if document.body[parbeg] == "\\begin_inset ERT":
2415 ertcont = parbeg + 5
2416 if document.body[ertcont].startswith("<"):
2417 # This is an overlay specification
2419 document.body[ertcont] = document.body[ertcont][1:]
2420 if document.body[ertcont].endswith(">"):
2422 document.body[ertcont] = document.body[ertcont][:-1]
2423 elif document.body[ertcont].endswith("]"):
2425 tok = document.body[ertcont].find('>[')
2427 subst = [document.body[ertcont][:tok],
2428 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2429 'status collapsed', '', '\\begin_layout Plain Layout',
2430 document.body[ertcont][tok + 2:-1]]
2431 document.body[ertcont : ertcont + 1] = subst
2432 # Convert to ArgInset
2433 document.body[parbeg] = "\\begin_inset Argument 1"
2436 elif document.body[ertcont].startswith("["):
2437 if document.body[ertcont].endswith("]"):
2438 # This is an ERT option
2440 document.body[ertcont] = document.body[ertcont][1:]
2442 document.body[ertcont] = document.body[ertcont][:-1]
2443 # Convert to ArgInset
2444 document.body[parbeg] = "\\begin_inset Argument 2"
2446 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, True)
2453 def convert_quote_args(document):
2454 " Converts beamer quote style ERT args to native InsetArgs "
2456 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2457 if document.textclass not in beamer_classes:
2460 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2461 for lay in quote_layouts:
2464 i = find_token(document.body, "\\begin_layout " + lay, i)
2467 parent = get_containing_layout(document.body, i)
2469 document.warning("Wrong parent layout!")
2473 if document.body[parbeg] == "\\begin_inset ERT":
2474 if document.body[i + 6].startswith("<"):
2475 # This is an overlay specification
2477 document.body[i + 6] = document.body[i + 6][1:]
2478 if document.body[i + 6].endswith(">"):
2480 document.body[i + 6] = document.body[i + 6][:-1]
2481 # Convert to ArgInset
2482 document.body[i + 1] = "\\begin_inset Argument 1"
2486 def revert_beamerargs(document):
2487 " Reverts beamer arguments to old layout "
2489 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2490 if document.textclass not in beamer_classes:
2494 list_layouts = ["Itemize", "Enumerate", "Description"]
2495 headings = ["Part", "Section", "Section*", "Subsection", "Subsection*",
2496 "Subsubsection", "Subsubsection*", "FrameSubtitle", "NoteItem"]
2497 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2498 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2499 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2502 i = find_token(document.body, "\\begin_inset Argument", i)
2505 # Find containing paragraph layout
2506 parent = get_containing_layout(document.body, i)
2508 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2513 realparbeg = parent[3]
2514 layoutname = parent[0]
2516 for p in range(parbeg, parend):
2520 if layoutname in headings:
2521 m = rx.match(document.body[p])
2525 # Find containing paragraph layout
2526 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2527 endPlain = find_end_of_layout(document.body, beginPlain)
2528 endInset = find_end_of_inset(document.body, p)
2529 argcontent = document.body[beginPlain + 1 : endPlain]
2531 realparend = realparend - len(document.body[p : endInset + 1])
2533 del document.body[p : endInset + 1]
2534 if layoutname == "FrameSubtitle":
2535 pre = put_cmd_in_ert("\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2536 elif layoutname == "NoteItem":
2537 pre = put_cmd_in_ert("\\note<") + argcontent + put_cmd_in_ert(">[item]")
2538 elif layoutname.endswith('*'):
2539 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower()[:-1] + "<") + argcontent + put_cmd_in_ert(">*")
2541 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2542 secarg = find_token(document.body, "\\begin_inset Argument 2", parbeg, parend)
2544 # Find containing paragraph layout
2545 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", secarg)
2546 endPlain = find_end_of_layout(document.body, beginPlain)
2547 endInset = find_end_of_inset(document.body, secarg)
2548 argcontent = document.body[beginPlain + 1 : endPlain]
2550 realparend = realparend - len(document.body[secarg : endInset + 1])
2551 del document.body[secarg : endInset + 1]
2552 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2553 pre += put_cmd_in_ert("{")
2554 document.body[parbeg] = "\\begin_layout Standard"
2555 document.body[realparbeg : realparbeg] = pre
2556 pe = find_end_of_layout(document.body, parbeg)
2557 post = put_cmd_in_ert("}")
2558 document.body[pe : pe] = post
2559 realparend += len(pre) + len(post)
2560 if layoutname == "AgainFrame":
2561 m = rx.match(document.body[p])
2565 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2566 endPlain = find_end_of_layout(document.body, beginPlain)
2567 endInset = find_end_of_inset(document.body, p)
2568 content = document.body[beginPlain + 1 : endPlain]
2570 realparend = realparend - len(document.body[p : endInset + 1])
2572 del document.body[p : endInset + 1]
2573 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2574 document.body[realparbeg : realparbeg] = subst
2575 if layoutname == "Overprint":
2576 m = rx.match(document.body[p])
2580 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2581 endPlain = find_end_of_layout(document.body, beginPlain)
2582 endInset = find_end_of_inset(document.body, p)
2583 content = document.body[beginPlain + 1 : endPlain]
2585 realparend = realparend - len(document.body[p : endInset + 1])
2587 del document.body[p : endInset + 1]
2588 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2589 document.body[realparbeg : realparbeg] = subst
2590 if layoutname == "OverlayArea":
2591 m = rx.match(document.body[p])
2595 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2596 endPlain = find_end_of_layout(document.body, beginPlain)
2597 endInset = find_end_of_inset(document.body, p)
2598 content = document.body[beginPlain + 1 : endPlain]
2600 realparend = realparend - len(document.body[p : endInset + 1])
2602 del document.body[p : endInset + 1]
2603 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2604 document.body[realparbeg : realparbeg] = subst
2605 if layoutname in list_layouts:
2606 m = rx.match(document.body[p])
2610 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2611 endPlain = find_end_of_layout(document.body, beginPlain)
2612 endInset = find_end_of_inset(document.body, p)
2613 content = document.body[beginPlain + 1 : endPlain]
2614 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2615 realparend = realparend + len(subst) - len(content)
2616 document.body[beginPlain + 1 : endPlain] = subst
2617 elif argnr == "item:1":
2618 j = find_end_of_inset(document.body, i)
2619 # Find containing paragraph layout
2620 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2621 endPlain = find_end_of_layout(document.body, beginPlain)
2622 content = document.body[beginPlain + 1 : endPlain]
2623 del document.body[i:j+1]
2624 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2625 document.body[realparbeg : realparbeg] = subst
2626 elif argnr == "item:2":
2627 j = find_end_of_inset(document.body, i)
2628 # Find containing paragraph layout
2629 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2630 endPlain = find_end_of_layout(document.body, beginPlain)
2631 content = document.body[beginPlain + 1 : endPlain]
2632 del document.body[i:j+1]
2633 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2634 document.body[realparbeg : realparbeg] = subst
2635 if layoutname in quote_layouts:
2636 m = rx.match(document.body[p])
2640 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2641 endPlain = find_end_of_layout(document.body, beginPlain)
2642 endInset = find_end_of_inset(document.body, p)
2643 content = document.body[beginPlain + 1 : endPlain]
2645 realparend = realparend - len(document.body[p : endInset + 1])
2647 del document.body[p : endInset + 1]
2648 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2649 document.body[realparbeg : realparbeg] = subst
2650 if layoutname in corollary_layouts:
2651 m = rx.match(document.body[p])
2655 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2656 endPlain = find_end_of_layout(document.body, beginPlain)
2657 endInset = find_end_of_inset(document.body, p)
2658 content = document.body[beginPlain + 1 : endPlain]
2660 realparend = realparend - len(document.body[p : endInset + 1])
2662 del document.body[p : endInset + 1]
2663 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2664 document.body[realparbeg : realparbeg] = subst
2669 def revert_beamerargs2(document):
2670 " Reverts beamer arguments to old layout, step 2 "
2672 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2673 if document.textclass not in beamer_classes:
2677 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2678 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2679 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2682 i = find_token(document.body, "\\begin_inset Argument", i)
2685 # Find containing paragraph layout
2686 parent = get_containing_layout(document.body, i)
2688 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2693 realparbeg = parent[3]
2694 layoutname = parent[0]
2696 for p in range(parbeg, parend):
2700 if layoutname in shifted_layouts:
2701 m = rx.match(document.body[p])
2705 document.body[p] = "\\begin_inset Argument 1"
2706 if layoutname in corollary_layouts:
2707 m = rx.match(document.body[p])
2711 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2712 endPlain = find_end_of_layout(document.body, beginPlain)
2713 endInset = find_end_of_inset(document.body, p)
2714 content = document.body[beginPlain + 1 : endPlain]
2716 realparend = realparend - len(document.body[p : endInset + 1])
2718 del document.body[p : endInset + 1]
2719 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2720 document.body[realparbeg : realparbeg] = subst
2721 if layoutname == "OverlayArea":
2722 m = rx.match(document.body[p])
2726 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2727 endPlain = find_end_of_layout(document.body, beginPlain)
2728 endInset = find_end_of_inset(document.body, p)
2729 content = document.body[beginPlain + 1 : endPlain]
2731 realparend = realparend - len(document.body[p : endInset + 1])
2733 del document.body[p : endInset + 1]
2734 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2735 document.body[realparbeg : realparbeg] = subst
2736 if layoutname == "AgainFrame":
2737 m = rx.match(document.body[p])
2741 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2742 endPlain = find_end_of_layout(document.body, beginPlain)
2743 endInset = find_end_of_inset(document.body, p)
2744 content = document.body[beginPlain + 1 : endPlain]
2746 realparend = realparend - len(document.body[p : endInset + 1])
2748 del document.body[p : endInset + 1]
2749 subst = put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
2750 document.body[realparbeg : realparbeg] = subst
2754 def revert_beamerargs3(document):
2755 " Reverts beamer arguments to old layout, step 3 "
2757 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2758 if document.textclass not in beamer_classes:
2761 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2764 i = find_token(document.body, "\\begin_inset Argument", i)
2767 # Find containing paragraph layout
2768 parent = get_containing_layout(document.body, i)
2770 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2775 realparbeg = parent[3]
2776 layoutname = parent[0]
2778 for p in range(parbeg, parend):
2782 if layoutname == "AgainFrame":
2783 m = rx.match(document.body[p])
2787 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2788 endPlain = find_end_of_layout(document.body, beginPlain)
2789 endInset = find_end_of_inset(document.body, p)
2790 content = document.body[beginPlain + 1 : endPlain]
2792 realparend = realparend - len(document.body[p : endInset + 1])
2794 del document.body[p : endInset + 1]
2795 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2796 document.body[realparbeg : realparbeg] = subst
2800 def revert_beamerflex(document):
2801 " Reverts beamer Flex insets "
2803 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2804 if document.textclass not in beamer_classes:
2807 new_flexes = {"Bold" : "\\textbf", "Emphasize" : "\\emph", "Only" : "\\only",
2808 "Uncover" : "\\uncover", "Visible" : "\\visible",
2809 "Invisible" : "\\invisible", "Alternative" : "\\alt",
2810 "Beamer_Note" : "\\note"}
2811 old_flexes = {"Alert" : "\\alert", "Structure" : "\\structure"}
2812 rx = re.compile(r'^\\begin_inset Flex (.+)$')
2816 i = find_token(document.body, "\\begin_inset Flex", i)
2819 m = rx.match(document.body[i])
2821 flextype = m.group(1)
2822 z = find_end_of_inset(document.body, i)
2824 document.warning("Can't find end of Flex " + flextype + " inset.")
2827 if flextype in new_flexes:
2828 pre = put_cmd_in_ert(new_flexes[flextype])
2829 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2831 argend = find_end_of_inset(document.body, arg)
2833 document.warning("Can't find end of Argument!")
2836 # Find containing paragraph layout
2837 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2838 endPlain = find_end_of_layout(document.body, beginPlain)
2839 argcontent = document.body[beginPlain + 1 : endPlain]
2841 z = z - len(document.body[arg : argend + 1])
2843 del document.body[arg : argend + 1]
2844 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2845 arg = find_token(document.body, "\\begin_inset Argument 2", i, z)
2847 argend = find_end_of_inset(document.body, arg)
2849 document.warning("Can't find end of Argument!")
2852 # Find containing paragraph layout
2853 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2854 endPlain = find_end_of_layout(document.body, beginPlain)
2855 argcontent = document.body[beginPlain + 1 : endPlain]
2857 z = z - len(document.body[arg : argend + 1])
2859 del document.body[arg : argend + 1]
2860 if flextype == "Alternative":
2861 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
2863 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2864 pre += put_cmd_in_ert("{")
2865 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2866 endPlain = find_end_of_layout(document.body, beginPlain)
2868 z = z - len(document.body[i : beginPlain + 1])
2870 document.body[i : beginPlain + 1] = pre
2871 post = put_cmd_in_ert("}")
2872 document.body[z - 2 : z + 1] = post
2873 elif flextype in old_flexes:
2874 pre = put_cmd_in_ert(old_flexes[flextype])
2875 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2879 argend = find_end_of_inset(document.body, arg)
2881 document.warning("Can't find end of Argument!")
2884 # Find containing paragraph layout
2885 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2886 endPlain = find_end_of_layout(document.body, beginPlain)
2887 argcontent = document.body[beginPlain + 1 : endPlain]
2889 z = z - len(document.body[arg : argend + 1])
2891 del document.body[arg : argend + 1]
2892 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2893 pre += put_cmd_in_ert("{")
2894 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2895 endPlain = find_end_of_layout(document.body, beginPlain)
2897 z = z - len(document.body[i : beginPlain + 1])
2899 document.body[i : beginPlain + 1] = pre
2900 post = put_cmd_in_ert("}")
2901 document.body[z - 2 : z + 1] = post
2906 def revert_beamerblocks(document):
2907 " Reverts beamer block arguments to ERT "
2909 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2910 if document.textclass not in beamer_classes:
2913 blocks = ["Block", "ExampleBlock", "AlertBlock"]
2915 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2918 i = find_token(document.body, "\\begin_inset Argument", i)
2921 # Find containing paragraph layout
2922 parent = get_containing_layout(document.body, i)
2924 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2929 realparbeg = parent[3]
2930 layoutname = parent[0]
2932 for p in range(parbeg, parend):
2936 if layoutname in blocks:
2937 m = rx.match(document.body[p])
2941 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2942 endPlain = find_end_of_layout(document.body, beginPlain)
2943 endInset = find_end_of_inset(document.body, p)
2944 content = document.body[beginPlain + 1 : endPlain]
2946 realparend = realparend - len(document.body[p : endInset + 1])
2948 del document.body[p : endInset + 1]
2949 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2950 document.body[realparbeg : realparbeg] = subst
2952 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2953 endPlain = find_end_of_layout(document.body, beginPlain)
2954 endInset = find_end_of_inset(document.body, p)
2955 content = document.body[beginPlain + 1 : endPlain]
2957 realparend = realparend - len(document.body[p : endInset + 1])
2959 del document.body[p : endInset + 1]
2960 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2961 document.body[realparbeg : realparbeg] = subst
2966 def convert_beamerblocks(document):
2967 " Converts beamer block ERT args to native InsetArgs "
2969 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2970 if document.textclass not in beamer_classes:
2973 blocks = ["Block", "ExampleBlock", "AlertBlock"]
2977 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2980 parent = get_containing_layout(document.body, i)
2981 if parent == False or parent[1] != i:
2982 document.warning("Wrong parent layout!")
2989 if document.body[parbeg] == "\\begin_inset ERT":
2990 ertcontfirstline = parbeg + 5
2991 # Find the last ERT in this paragraph (which might also be the first)
2992 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
2993 if lastertbeg == -1:
2994 document.warning("Last ERT not found!")
2996 lastertend = find_end_of_inset(document.body, lastertbeg)
2997 if lastertend == -1:
2998 document.warning("End of last ERT not found!")
3000 ertcontlastline = lastertend - 3
3002 if document.body[ertcontfirstline].lstrip().startswith("<"):
3003 # This is an overlay specification
3005 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3006 if document.body[ertcontlastline].rstrip().endswith(">"):
3008 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3009 # Convert to ArgInset
3010 document.body[parbeg] = "\\begin_inset Argument 1"
3011 elif document.body[ertcontlastline].rstrip().endswith("}"):
3013 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3015 ertcontdivline = ertcontfirstline
3016 tok = document.body[ertcontdivline].find('>{')
3018 regexp = re.compile(r'.*>\{', re.IGNORECASE)
3019 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, ertcontlastline)
3020 tok = document.body[ertcontdivline].find('>{')
3022 if ertcontfirstline < ertcontlastline:
3023 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3024 document.body[ertcontlastline : ertcontlastline + 1] = [
3025 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3026 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3027 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3028 'status collapsed', '', '\\begin_layout Plain Layout',
3029 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3030 document.body[ertcontdivline][tok + 2:]]
3032 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3033 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3034 'status collapsed', '', '\\begin_layout Plain Layout',
3035 document.body[ertcontdivline][tok + 2:]]
3036 # Convert to ArgInset
3037 document.body[parbeg] = "\\begin_inset Argument 1"
3038 elif document.body[ertcontfirstline].lstrip().startswith("{"):
3039 # This is the block title
3040 if document.body[ertcontlastline].rstrip().endswith("}"):
3041 # strip off the braces
3042 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3043 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3044 if ertcontfirstline < ertcontlastline:
3045 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3046 document.body[parend : parend + 1] = [
3047 document.body[parend], '\\end_layout', '', '\\end_inset']
3048 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3049 'status collapsed', '', '\\begin_layout Plain Layout',
3050 '\\begin_inset ERT', '']
3052 # Convert to ArgInset
3053 document.body[parbeg] = "\\begin_inset Argument 2"
3054 elif count_pars_in_inset(document.body, ertcontfirstline) > 1:
3055 # Multipar ERT. Skip this.
3058 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, False)
3061 j = find_end_of_layout(document.body, i)
3063 document.warning("end of layout not found!")
3064 k = find_token(document.body, "\\begin_inset Argument", i, j)
3066 document.warning("InsetArgument not found!")
3068 l = find_end_of_inset(document.body, k)
3069 m = find_token(document.body, "\\begin_inset ERT", l, j)
3072 ertcontfirstline = m + 5
3077 def convert_overprint(document):
3078 " Convert old beamer overprint layouts to ERT "
3080 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3081 if document.textclass not in beamer_classes:
3086 i = find_token(document.body, "\\begin_layout Overprint", i)
3089 # Find end of sequence
3090 j = find_end_of_sequence(document.body, i)
3092 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3096 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3098 if document.body[j] == "\\end_deeper":
3099 esubst = ["", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3101 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3102 endseq = endseq + len(esubst) - len(document.body[j : j])
3103 document.body[j : j] = esubst
3104 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3106 argend = find_end_of_layout(document.body, argbeg)
3108 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3111 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3112 endPlain = find_end_of_layout(document.body, beginPlain)
3113 content = document.body[beginPlain + 1 : endPlain]
3115 endseq = endseq - len(document.body[argbeg : argend + 1])
3117 del document.body[argbeg : argend + 1]
3118 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3120 endseq = endseq - len(document.body[i : i])
3121 document.body[i : i] = subst + ["\\end_layout"]
3122 endseq += len(subst)
3124 for p in range(i, endseq):
3125 if document.body[p] == "\\begin_layout Overprint":
3126 document.body[p] = "\\begin_layout Standard"
3131 def revert_overprint(document):
3132 " Revert old beamer overprint layouts to ERT "
3134 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3135 if document.textclass not in beamer_classes:
3140 i = find_token(document.body, "\\begin_layout Overprint", i)
3143 # Find end of sequence
3144 j = find_end_of_sequence(document.body, i)
3146 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3150 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3151 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}")
3152 endseq = endseq + len(esubst) - len(document.body[j : j])
3153 if document.body[j] == "\\end_deeper":
3154 document.body[j : j] = ["\\end_deeper", ""] + esubst
3156 document.body[j : j] = esubst
3159 if document.body[r] == "\\begin_deeper":
3160 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3162 document.body[r] = ""
3163 document.body[s] = ""
3167 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3169 argend = find_end_of_inset(document.body, argbeg)
3171 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3174 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3175 endPlain = find_end_of_layout(document.body, beginPlain)
3176 content = document.body[beginPlain + 1 : endPlain]
3178 endseq = endseq - len(document.body[argbeg : argend])
3180 del document.body[argbeg : argend + 1]
3181 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3183 endseq = endseq - len(document.body[i : i])
3184 document.body[i : i] = subst + ["\\end_layout"]
3185 endseq += len(subst)
3191 if document.body[p] == "\\begin_layout Overprint":
3192 q = find_end_of_layout(document.body, p)
3194 document.warning("Malformed LyX document. Cannot find end of Overprint layout!")
3197 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\onslide")
3198 argbeg = find_token(document.body, "\\begin_inset Argument item:1", p, q)
3200 argend = find_end_of_inset(document.body, argbeg)
3202 document.warning("Malformed LyX document. Cannot find end of Overprint item argument!")
3205 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3206 endPlain = find_end_of_layout(document.body, beginPlain)
3207 content = document.body[beginPlain + 1 : endPlain]
3209 endseq = endseq - len(document.body[argbeg : argend + 1])
3211 del document.body[argbeg : argend + 1]
3212 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3213 endseq = endseq - len(document.body[p : p + 1]) + len(subst)
3214 document.body[p : p + 1] = subst
3220 def revert_frametitle(document):
3221 " Reverts beamer frametitle layout to ERT "
3223 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3224 if document.textclass not in beamer_classes:
3227 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3230 i = find_token(document.body, "\\begin_layout FrameTitle", i)
3233 j = find_end_of_layout(document.body, i)
3235 document.warning("Malformed LyX document: Can't find end of FrameTitle layout")
3239 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
3240 endlay += len(put_cmd_in_ert("}"))
3241 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\frametitle")
3242 for p in range(i, j):
3245 m = rx.match(document.body[p])
3249 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3250 endPlain = find_end_of_layout(document.body, beginPlain)
3251 endInset = find_end_of_inset(document.body, p)
3252 content = document.body[beginPlain + 1 : endPlain]
3254 endlay = endlay - len(document.body[p : endInset + 1])
3256 del document.body[p : endInset + 1]
3257 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3259 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3260 endPlain = find_end_of_layout(document.body, beginPlain)
3261 endInset = find_end_of_inset(document.body, p)
3262 content = document.body[beginPlain + 1 : endPlain]
3264 endlay = endlay - len(document.body[p : endInset + 1])
3266 del document.body[p : endInset + 1]
3267 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3269 subst += put_cmd_in_ert("{")
3270 document.body[i : i + 1] = subst
3274 def convert_epigraph(document):
3275 " Converts memoir epigraph to new syntax "
3277 if document.textclass != "memoir":
3282 i = find_token(document.body, "\\begin_layout Epigraph", i)
3285 j = find_end_of_layout(document.body, i)
3287 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3292 ert = find_token(document.body, "\\begin_inset ERT", i, j)
3294 endInset = find_end_of_inset(document.body, ert)
3295 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", ert)
3296 endPlain = find_end_of_layout(document.body, beginPlain)
3297 ertcont = beginPlain + 2
3298 if document.body[ertcont] == "}{":
3300 # Convert to ArgInset
3301 endlay = endlay - 2 * len(document.body[j])
3302 begsubst = ['\\begin_inset Argument post:1', 'status collapsed', '',
3303 '\\begin_layout Plain Layout']
3304 endsubst = ['\\end_layout', '', '\\end_inset', '', document.body[j]]
3305 document.body[j : j + 1] = endsubst
3306 document.body[endInset + 1 : endInset + 1] = begsubst
3308 endlay += len(begsubst) + len(endsubst)
3309 endlay = endlay - len(document.body[ert : endInset + 1])
3310 del document.body[ert : endInset + 1]
3315 def revert_epigraph(document):
3316 " Reverts memoir epigraph argument to ERT "
3318 if document.textclass != "memoir":
3323 i = find_token(document.body, "\\begin_layout Epigraph", i)
3326 j = find_end_of_layout(document.body, i)
3328 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3333 p = find_token(document.body, "\\begin_layout Argument post:1", i, j)
3335 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3336 endPlain = find_end_of_layout(document.body, beginPlain)
3337 endInset = find_end_of_inset(document.body, p)
3338 content = document.body[beginPlain + 1 : endPlain]
3340 endlay = endlay - len(document.body[p : endInset + 1])
3342 del document.body[p : endInset + 1]
3343 subst += put_cmd_in_ert("}{") + content
3345 subst += put_cmd_in_ert("}{")
3347 document.body[j : j] = subst + document.body[j : j]
3351 def convert_captioninsets(document):
3352 " Converts caption insets to new syntax "
3356 i = find_token(document.body, "\\begin_inset Caption", i)
3359 document.body[i] = "\\begin_inset Caption Standard"
3363 def revert_captioninsets(document):
3364 " Reverts caption insets to old syntax "
3368 i = find_token(document.body, "\\begin_inset Caption Standard", i)
3371 document.body[i] = "\\begin_inset Caption"
3375 def convert_captionlayouts(document):
3376 " Convert caption layouts to caption insets. "
3379 "Captionabove": "Above",
3380 "Captionbelow": "Below",
3381 "FigCaption" : "FigCaption",
3382 "Table_Caption" : "Table",
3383 "CenteredCaption" : "Centered",
3384 "Bicaption" : "Bicaption",
3389 i = find_token(document.body, "\\begin_layout", i)
3392 val = get_value(document.body, "\\begin_layout", i)
3393 if val in caption_dict.keys():
3394 j = find_end_of_layout(document.body, i)
3396 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3399 document.body[j:j] = ["\\end_layout", "", "\\end_inset", "", ""]
3400 document.body[i:i+1] = ["\\begin_layout %s" % document.default_layout,
3401 "\\begin_inset Caption %s" % caption_dict[val], "",
3402 "\\begin_layout %s" % document.default_layout]
3406 def revert_captionlayouts(document):
3407 " Revert caption insets to caption layouts. "
3410 "Above" : "Captionabove",
3411 "Below" : "Captionbelow",
3412 "FigCaption" : "FigCaption",
3413 "Table" : "Table_Caption",
3414 "Centered" : "CenteredCaption",
3415 "Bicaption" : "Bicaption",
3419 rx = re.compile(r'^\\begin_inset Caption (\S+)$')
3421 i = find_token(document.body, "\\begin_inset Caption", i)
3425 m = rx.match(document.body[i])
3429 if val not in caption_dict.keys():
3433 # We either need to delete the previous \begin_layout line, or we
3434 # need to end the previous layout if this inset is not in the first
3435 # position of the paragraph.
3436 layout_before = find_token_backwards(document.body, "\\begin_layout", i)
3437 if layout_before == -1:
3438 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3440 layout_line = document.body[layout_before]
3441 del_layout_before = True
3442 l = layout_before + 1
3444 if document.body[l] != "":
3445 del_layout_before = False
3448 if del_layout_before:
3449 del document.body[layout_before:i]
3452 document.body[i:i] = ["\\end_layout", ""]
3455 # Find start of layout in the inset and end of inset
3456 j = find_token(document.body, "\\begin_layout", i)
3458 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3460 k = find_end_of_inset(document.body, i)
3462 document.warning("Malformed LyX document: Missing `\\end_inset'.")
3465 # We either need to delete the following \end_layout line, or we need
3466 # to restart the old layout if this inset is not at the paragraph end.
3467 layout_after = find_token(document.body, "\\end_layout", k)
3468 if layout_after == -1:
3469 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3471 del_layout_after = True
3473 while l < layout_after:
3474 if document.body[l] != "":
3475 del_layout_after = False
3478 if del_layout_after:
3479 del document.body[k+1:layout_after+1]
3481 document.body[k+1:k+1] = [layout_line, ""]
3483 # delete \begin_layout and \end_inset and replace \begin_inset with
3484 # "\begin_layout XXX". This works because we can only have one
3485 # paragraph in the caption inset: The old \end_layout will be recycled.
3486 del document.body[k]
3487 if document.body[k] == "":
3488 del document.body[k]
3489 del document.body[j]
3490 if document.body[j] == "":
3491 del document.body[j]
3492 document.body[i] = "\\begin_layout %s" % caption_dict[val]
3493 if document.body[i+1] == "":
3494 del document.body[i+1]
3498 def revert_fragileframe(document):
3499 " Reverts beamer FragileFrame layout to ERT "
3501 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3502 if document.textclass not in beamer_classes:
3507 i = find_token(document.body, "\\begin_layout FragileFrame", i)
3510 # Find end of sequence
3511 j = find_end_of_sequence(document.body, i)
3513 document.warning("Malformed LyX document. Cannot find end of FragileFrame sequence!")
3517 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{frame}")
3518 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{frame}")
3519 endseq = endseq + len(esubst) - len(document.body[j : j])
3520 if document.body[j] == "\\end_deeper":
3521 document.body[j : j] = ["\\end_deeper", ""] + esubst
3523 document.body[j : j] = esubst
3524 for q in range(i, j):
3525 if document.body[q] == "\\begin_layout FragileFrame":
3526 document.body[q] = "\\begin_layout %s" % document.default_layout
3529 if document.body[r] == "\\begin_deeper":
3530 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3532 document.body[r] = ""
3533 document.body[s] = ""
3537 for p in range(1, 5):
3538 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, j)
3541 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3542 endPlain = find_end_of_layout(document.body, beginPlain)
3543 endInset = find_end_of_inset(document.body, arg)
3544 content = document.body[beginPlain + 1 : endPlain]
3546 j = j - len(document.body[arg : endInset + 1])
3548 del document.body[arg : endInset + 1]
3549 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3551 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3552 endPlain = find_end_of_layout(document.body, beginPlain)
3553 endInset = find_end_of_inset(document.body, arg)
3554 content = document.body[beginPlain + 1 : endPlain]
3556 j = j - len(document.body[arg : endInset + 1])
3558 del document.body[arg : endInset + 1]
3559 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3561 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3562 endPlain = find_end_of_layout(document.body, beginPlain)
3563 endInset = find_end_of_inset(document.body, arg)
3564 content = document.body[beginPlain + 1 : endPlain]
3566 j = j - len(document.body[arg : endInset + 1])
3568 del document.body[arg : endInset + 1]
3569 subst += put_cmd_in_ert("[fragile,") + content + put_cmd_in_ert("]")
3571 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3572 endPlain = find_end_of_layout(document.body, beginPlain)
3573 endInset = find_end_of_inset(document.body, arg)
3574 content = document.body[beginPlain + 1 : endPlain]
3576 j = j - len(document.body[arg : endInset + 1])
3578 del document.body[arg : endInset + 1]
3579 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3581 subst += put_cmd_in_ert("[fragile]")
3583 document.body[i : i + 1] = subst
3587 def revert_newframes(document):
3588 " Reverts beamer Frame and PlainFrame layouts to old forms "
3590 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3591 if document.textclass not in beamer_classes:
3595 "Frame" : "BeginFrame",
3596 "PlainFrame" : "BeginPlainFrame",
3599 rx = re.compile(r'^\\begin_layout (\S+)$')
3602 i = find_token(document.body, "\\begin_layout", i)
3606 m = rx.match(document.body[i])
3610 if val not in frame_dict.keys():
3613 # Find end of sequence
3614 j = find_end_of_sequence(document.body, i)
3616 document.warning("Malformed LyX document. Cannot find end of Frame sequence!")
3620 subst = ["\\begin_layout %s" % frame_dict[val]]
3621 esubst = ["\\end_layout", "", "\\begin_layout EndFrame", "", "\\end_layout"]
3622 endseq = endseq + len(esubst) - len(document.body[j : j])
3623 if document.body[j] == "\\end_deeper":
3624 document.body[j : j] = ["\\end_deeper", ""] + esubst
3626 document.body[j : j] = esubst
3627 for q in range(i, j):
3628 if document.body[q] == "\\begin_layout %s" % val:
3629 document.body[q] = "\\begin_layout %s" % document.default_layout
3632 if document.body[r] == "\\begin_deeper":
3633 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3635 document.body[r] = ""
3636 document.body[s] = ""
3640 l = find_end_of_layout(document.body, i)
3641 for p in range(1, 5):
3642 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, l)
3645 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3646 endPlain = find_end_of_layout(document.body, beginPlain)
3647 endInset = find_end_of_inset(document.body, arg)
3648 content = document.body[beginPlain + 1 : endPlain]
3650 l = l - len(document.body[arg : endInset + 1])
3652 del document.body[arg : endInset + 1]
3653 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3655 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3656 endPlain = find_end_of_layout(document.body, beginPlain)
3657 endInset = find_end_of_inset(document.body, arg)
3658 content = document.body[beginPlain + 1 : endPlain]
3660 l = l - len(document.body[arg : endInset + 1])
3662 del document.body[arg : endInset + 1]
3663 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3665 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3666 endPlain = find_end_of_layout(document.body, beginPlain)
3667 endInset = find_end_of_inset(document.body, arg)
3668 content = document.body[beginPlain + 1 : endPlain]
3670 l = l - len(document.body[arg : endInset + 1])
3672 del document.body[arg : endInset + 1]
3673 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3675 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3676 endPlain = find_end_of_layout(document.body, beginPlain)
3677 endInset = find_end_of_inset(document.body, arg)
3678 content = document.body[beginPlain + 1 : endPlain]
3680 l = l - len(document.body[arg : endInset + 1])
3682 del document.body[arg : endInset + 1]
3685 document.body[i : i + 1] = subst
3688 # known encodings that do not change their names (same LyX and LaTeX names)
3689 known_enc_tuple = ("auto", "default", "ansinew", "applemac", "armscii8", "ascii",
3690 "cp437", "cp437de", "cp850", "cp852", "cp855", "cp858", "cp862", "cp865", "cp866",
3691 "cp1250", "cp1251", "cp1252", "cp1255", "cp1256", "cp1257", "koi8-r", "koi8-u",
3692 "pt154", "pt254", "tis620-0", "utf8", "utf8x", "utf8-plain")
3694 def convert_encodings(document):
3695 "Use the LyX names of the encodings instead of the LaTeX names."
3696 LaTeX2LyX_enc_dict = {
3697 "8859-6": "iso8859-6",
3698 "8859-8": "iso8859-8",
3700 "euc": "euc-jp-platex",
3705 "iso88595": "iso8859-5",
3706 "iso-8859-7": "iso8859-7",
3708 "jis": "jis-platex",
3710 "l7xenc": "iso8859-13",
3711 "latin1": "iso8859-1",
3712 "latin2": "iso8859-2",
3713 "latin3": "iso8859-3",
3714 "latin4": "iso8859-4",
3715 "latin5": "iso8859-9",
3716 "latin9": "iso8859-15",
3717 "latin10": "iso8859-16",
3718 "SJIS": "shift-jis",
3719 "sjis": "shift-jis-platex",
3722 i = find_token(document.header, "\\inputencoding" , 0)
3725 val = get_value(document.header, "\\inputencoding", i)
3726 if val in LaTeX2LyX_enc_dict.keys():
3727 document.header[i] = "\\inputencoding %s" % LaTeX2LyX_enc_dict[val]
3728 elif val not in known_enc_tuple:
3729 document.warning("Ignoring unknown input encoding: `%s'" % val)
3732 def revert_encodings(document):
3733 """Revert to using the LaTeX names of the encodings instead of the LyX names.
3734 Also revert utf8-platex to sjis, the language default when using Japanese.
3736 LyX2LaTeX_enc_dict = {
3741 "euc-jp-platex": "euc",
3744 "iso8859-1": "latin1",
3745 "iso8859-2": "latin2",
3746 "iso8859-3": "latin3",
3747 "iso8859-4": "latin4",
3748 "iso8859-5": "iso88595",
3749 "iso8859-6": "8859-6",
3750 "iso8859-7": "iso-8859-7",
3751 "iso8859-8": "8859-8",
3752 "iso8859-9": "latin5",
3753 "iso8859-13": "l7xenc",
3754 "iso8859-15": "latin9",
3755 "iso8859-16": "latin10",
3757 "jis-platex": "jis",
3758 "shift-jis": "SJIS",
3759 "shift-jis-platex": "sjis",
3761 "utf8-platex": "sjis"
3763 i = find_token(document.header, "\\inputencoding" , 0)
3766 val = get_value(document.header, "\\inputencoding", i)
3767 if val in LyX2LaTeX_enc_dict.keys():
3768 document.header[i] = "\\inputencoding %s" % LyX2LaTeX_enc_dict[val]
3769 elif val not in known_enc_tuple:
3770 document.warning("Ignoring unknown input encoding: `%s'" % val)
3773 def revert_IEEEtran_3(document):
3775 Reverts Flex Insets to TeX-code
3777 if document.textclass == "IEEEtran":
3783 h = find_token(document.body, "\\begin_inset Flex Author Mark", h)
3785 endh = find_end_of_inset(document.body, h)
3786 document.body[endh - 2 : endh + 1] = put_cmd_in_ert("}")
3787 document.body[h : h + 4] = put_cmd_in_ert("\\IEEEauthorrefmark{")
3790 i = find_token(document.body, "\\begin_inset Flex Author Name", i)
3792 endi = find_end_of_inset(document.body, i)
3793 document.body[endi - 2 : endi + 1] = put_cmd_in_ert("}")
3794 document.body[i : i + 4] = put_cmd_in_ert("\\IEEEauthorblockN{")
3797 j = find_token(document.body, "\\begin_inset Flex Author Affiliation", j)
3799 endj = find_end_of_inset(document.body, j)
3800 document.body[endj - 2 : endj + 1] = put_cmd_in_ert("}")
3801 document.body[j : j + 4] = put_cmd_in_ert("\\IEEEauthorblockA{")
3803 if i == -1 and j == -1 and h == -1:
3807 def revert_kurier_fonts(document):
3808 " Revert kurier font definition to LaTeX "
3810 i = find_token(document.header, "\\font_math", 0)
3812 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
3813 val = get_value(document.header, "\\font_math", i)
3814 if val == "kurier-math":
3815 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
3816 "\\usepackage[math]{kurier}\n" \
3817 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
3818 document.header[i] = "\\font_math auto"
3820 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
3821 kurier_fonts = ["kurier", "kurierc", "kurierl", "kurierlc"]
3822 k = find_token(document.header, "\\font_sans kurier", 0)
3824 sf = get_value(document.header, "\\font_sans", k)
3825 if sf in kurier_fonts:
3826 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
3827 document.header[k] = "\\font_sans default"
3829 def revert_iwona_fonts(document):
3830 " Revert iwona font definition to LaTeX "
3832 i = find_token(document.header, "\\font_math", 0)
3834 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
3835 val = get_value(document.header, "\\font_math", i)
3836 if val == "iwona-math":
3837 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
3838 "\\usepackage[math]{iwona}\n" \
3839 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
3840 document.header[i] = "\\font_math auto"
3842 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
3843 iwona_fonts = ["iwona", "iwonac", "iwonal", "iwonalc"]
3844 k = find_token(document.header, "\\font_sans iwona", 0)
3846 sf = get_value(document.header, "\\font_sans", k)
3847 if sf in iwona_fonts:
3848 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
3849 document.header[k] = "\\font_sans default"
3852 def revert_new_libertines(document):
3853 " Revert new libertine font definition to LaTeX "
3855 if find_token(document.header, "\\use_non_tex_fonts true", 0) != -1:
3858 i = find_token(document.header, "\\font_typewriter libertine-mono", 0)
3860 preamble = "\\usepackage"
3861 sc = find_token(document.header, "\\font_tt_scale", 0)
3863 scval = get_value(document.header, "\\font_tt_scale", sc)
3865 preamble += "[scale=%f]" % (float(scval) / 100)
3866 document.header[sc] = "\\font_tt_scale 100"
3867 preamble += "{libertineMono-type1}"
3868 add_to_preamble(document, [preamble])
3869 document.header[i] = "\\font_typewriter default"
3871 k = find_token(document.header, "\\font_sans biolinum", 0)
3873 preamble = "\\usepackage"
3875 j = find_token(document.header, "\\font_osf true", 0)
3880 sc = find_token(document.header, "\\font_sf_scale", 0)
3882 scval = get_value(document.header, "\\font_sf_scale", sc)
3884 options += ",scale=%f" % (float(scval) / 100)
3885 document.header[sc] = "\\font_sf_scale 100"
3887 preamble += "[" + options +"]"
3888 preamble += "{biolinum-type1}"
3889 add_to_preamble(document, [preamble])
3890 document.header[k] = "\\font_sans default"
3893 def convert_lyxframes(document):
3894 " Converts old beamer frames to new style "
3896 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3897 if document.textclass not in beamer_classes:
3900 framebeg = ["BeginFrame", "BeginPlainFrame"]
3901 frameend = ["Frame", "PlainFrame", "EndFrame", "BeginFrame", "BeginPlainFrame", "AgainFrame",
3902 "Section", "Section*", "Subsection", "Subsection*", "Subsubsection", "Subsubsection*"]
3903 for lay in framebeg:
3906 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
3909 parent = get_containing_layout(document.body, i)
3910 if parent == False or parent[1] != i:
3911 document.warning("Wrong parent layout!")
3914 frametype = parent[0]
3918 # Step I: Convert ERT arguments
3919 # FIXME: See restrictions in convert_beamerframeargs method
3920 ertend = convert_beamerframeargs(document, i, parbeg)
3923 # Step II: Now rename the layout and convert the title to an argument
3924 j = find_end_of_layout(document.body, i)
3925 document.body[j : j + 1] = ['\\end_layout', '', '\\end_inset', '', '\\end_layout']
3926 if lay == "BeginFrame":
3927 document.body[i] = "\\begin_layout Frame"
3929 document.body[i] = "\\begin_layout PlainFrame"
3930 document.body[ertend + 1 : ertend + 1] = ['\\begin_inset Argument 4',
3931 'status open', '', '\\begin_layout Plain Layout']
3932 # Step III: find real frame end
3936 fend = find_token(document.body, "\\begin_layout", jj)
3938 document.warning("Malformed LyX document: No real frame end!")
3940 val = get_value(document.body, "\\begin_layout", fend)
3941 if val not in frameend:
3944 old = document.body[fend]
3945 if val == frametype:
3946 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
3947 # consider explicit EndFrames between two identical frame types
3948 elif val == "EndFrame":
3949 nextlayout = find_token(document.body, "\\begin_layout", fend + 1)
3950 if nextlayout != -1 and get_value(document.body, "\\begin_layout", nextlayout) == frametype:
3951 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
3953 document.body[fend : fend] = ['\\end_deeper']
3955 document.body[fend : fend] = ['\\end_deeper']
3956 document.body[j + 1 : j + 1] = ['', '\\begin_deeper']
3961 def remove_endframes(document):
3962 " Remove deprecated beamer endframes "
3964 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3965 if document.textclass not in beamer_classes:
3970 i = find_token_exact(document.body, "\\begin_layout EndFrame", i)
3973 j = find_end_of_layout(document.body, i)
3975 document.warning("Malformed LyX document: Missing \\end_layout to EndFrame")
3978 del document.body[i : j + 1]
3981 def revert_powerdot_flexes(document):
3982 " Reverts powerdot flex insets "
3984 if document.textclass != "powerdot":
3987 flexes = {"Onslide" : "\\onslide",
3988 "Onslide*" : "\\onslide*",
3989 "Onslide+" : "\\onslide+"}
3990 rx = re.compile(r'^\\begin_inset Flex (.+)$')
3994 i = find_token(document.body, "\\begin_inset Flex", i)
3997 m = rx.match(document.body[i])
3999 flextype = m.group(1)
4000 z = find_end_of_inset(document.body, i)
4002 document.warning("Can't find end of Flex " + flextype + " inset.")
4005 if flextype in flexes:
4006 pre = put_cmd_in_ert(flexes[flextype])
4007 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
4009 argend = find_end_of_inset(document.body, arg)
4011 document.warning("Can't find end of Argument!")
4014 # Find containing paragraph layout
4015 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
4016 endPlain = find_end_of_layout(document.body, beginPlain)
4017 argcontent = document.body[beginPlain + 1 : endPlain]
4019 z = z - len(document.body[arg : argend + 1])
4021 del document.body[arg : argend + 1]
4022 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
4023 pre += put_cmd_in_ert("{")
4024 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4025 endPlain = find_end_of_layout(document.body, beginPlain)
4027 z = z - len(document.body[i : beginPlain + 1])
4029 document.body[i : beginPlain + 1] = pre
4030 post = put_cmd_in_ert("}")
4031 document.body[z - 2 : z + 1] = post
4035 def revert_powerdot_pause(document):
4036 " Reverts powerdot pause layout to ERT "
4038 if document.textclass != "powerdot":
4043 i = find_token(document.body, "\\begin_layout Pause", i)
4046 j = find_end_of_layout(document.body, i)
4048 document.warning("Malformed LyX document: Can't find end of Pause layout")
4052 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\pause")
4053 for p in range(i, j):
4056 arg = find_token(document.body, "\\begin_inset Argument 1", i, j)
4058 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4059 endPlain = find_end_of_layout(document.body, beginPlain)
4060 endInset = find_end_of_inset(document.body, p)
4061 content = document.body[beginPlain + 1 : endPlain]
4063 endlay = endlay - len(document.body[p : endInset + 1])
4065 del document.body[p : endInset + 1]
4066 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4068 document.body[i : i + 1] = subst
4072 def revert_powerdot_itemargs(document):
4073 " Reverts powerdot item arguments to ERT "
4075 if document.textclass != "powerdot":
4079 list_layouts = ["Itemize", "ItemizeType1", "Enumerate", "EnumerateType1"]
4080 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4083 i = find_token(document.body, "\\begin_inset Argument", i)
4086 # Find containing paragraph layout
4087 parent = get_containing_layout(document.body, i)
4089 document.warning("Malformed LyX document: Can't find parent paragraph layout")
4094 realparbeg = parent[3]
4095 layoutname = parent[0]
4097 for p in range(parbeg, parend):
4101 if layoutname in list_layouts:
4102 m = rx.match(document.body[p])
4105 if argnr == "item:1":
4106 j = find_end_of_inset(document.body, i)
4107 # Find containing paragraph layout
4108 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4109 endPlain = find_end_of_layout(document.body, beginPlain)
4110 content = document.body[beginPlain + 1 : endPlain]
4111 del document.body[i:j+1]
4112 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4113 document.body[realparbeg : realparbeg] = subst
4114 elif argnr == "item:2":
4115 j = find_end_of_inset(document.body, i)
4116 # Find containing paragraph layout
4117 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4118 endPlain = find_end_of_layout(document.body, beginPlain)
4119 content = document.body[beginPlain + 1 : endPlain]
4120 del document.body[i:j+1]
4121 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
4122 document.body[realparbeg : realparbeg] = subst
4127 def revert_powerdot_columns(document):
4128 " Reverts powerdot twocolumn to TeX-code "
4129 if document.textclass != "powerdot":
4132 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4135 i = find_token(document.body, "\\begin_layout Twocolumn", i)
4138 j = find_end_of_layout(document.body, i)
4140 document.warning("Malformed LyX document: Can't find end of Twocolumn layout")
4144 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
4145 endlay += len(put_cmd_in_ert("}"))
4146 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\twocolumn")
4147 for p in range(i, j):
4150 m = rx.match(document.body[p])
4154 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4155 endPlain = find_end_of_layout(document.body, beginPlain)
4156 endInset = find_end_of_inset(document.body, p)
4157 content = document.body[beginPlain + 1 : endPlain]
4159 endlay = endlay - len(document.body[p : endInset + 1])
4161 del document.body[p : endInset + 1]
4162 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4164 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4165 endPlain = find_end_of_layout(document.body, beginPlain)
4166 endInset = find_end_of_inset(document.body, p)
4167 content = document.body[beginPlain + 1 : endPlain]
4169 endlay = endlay - len(document.body[p : endInset + 1])
4171 del document.body[p : endInset + 1]
4172 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
4174 subst += put_cmd_in_ert("{")
4175 document.body[i : i + 1] = subst
4179 def revert_mbox_fbox(document):
4180 'Convert revert mbox/fbox boxes to TeX-code'
4183 i = find_token(document.body, "\\begin_inset Box", i)
4186 j = find_token(document.body, "width", i)
4188 document.warning("Malformed LyX document: Can't find box width")
4190 width = get_value(document.body, "width", j)
4191 k = find_end_of_inset(document.body, j)
4193 document.warning("Malformed LyX document: Can't find end of box inset")
4196 BeginLayout = find_token(document.body, "\\begin_layout Plain Layout", j)
4197 EndLayout = find_token(document.body, "\\end_layout", BeginLayout)
4198 # replace if width is ""
4200 document.body[EndLayout:k + 1] = put_cmd_in_ert("}")
4201 if document.body[i] == "\\begin_inset Box Frameless":
4202 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\mbox{")
4203 if document.body[i] == "\\begin_inset Box Boxed":
4204 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\fbox{")
4208 def revert_starred_caption(document):
4209 " Reverts unnumbered longtable caption insets "
4213 i = find_token(document.body, "\\begin_inset Caption LongTableNoNumber", i)
4216 # This is not equivalent, but since the caption inset is a full blown
4217 # text inset a true conversion to ERT is too difficult.
4218 document.body[i] = "\\begin_inset Caption Standard"
4222 def revert_forced_local_layout(document):
4225 i = find_token(document.header, "\\begin_forced_local_layout", i)
4228 j = find_end_of(document.header, i, "\\begin_forced_local_layout", "\\end_forced_local_layout")
4230 # this should not happen
4232 regexp = re.compile(r'\s*forcelocal', re.IGNORECASE)
4233 k = find_re(document.header, regexp, i, j)
4235 del document.header[k]
4237 k = find_re(document.header, regexp, i, j)
4238 k = find_token(document.header, "\\begin_local_layout", 0)
4240 document.header[i] = "\\begin_local_layout"
4241 document.header[j] = "\\end_local_layout"
4243 l = find_end_of(document.header, k, "\\begin_local_layout", "\\end_local_layout")
4245 # this should not happen
4247 lines = document.header[i+1 : j]
4249 document.header[k+1 : k+1] = lines
4250 document.header[i : j ] = []
4252 document.header[i : j ] = []
4253 document.header[k+1 : k+1] = lines
4256 def revert_aa1(document):
4257 " Reverts InsetArguments of aa to TeX-code "
4258 if document.textclass == "aa":
4262 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4264 revert_Argument_to_TeX_brace(document, i, 0, 1, 4, False, False)
4270 def revert_aa2(document):
4271 " Reverts InsetArguments of aa to TeX-code "
4272 if document.textclass == "aa":
4276 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4278 document.body[i] = "\\begin_layout Abstract"
4284 def revert_tibetan(document):
4285 "Set the document language for Tibetan to English"
4287 if document.language == "tibetan":
4288 document.language = "english"
4289 i = find_token(document.header, "\\language", 0)
4291 document.header[i] = "\\language english"
4293 while j < len(document.body):
4294 j = find_token(document.body, "\\lang tibetan", j)
4296 document.body[j] = document.body[j].replace("\\lang tibetan", "\\lang english")
4299 j = len(document.body)
4308 # The idea here is that we will have a sequence of chunk paragraphs.
4309 # We want to convert them to paragraphs in one or several chunk insets.
4310 # Individual chunks are terminated by the character @ on the last line.
4311 # This line will be discarded, and following lines are treated as new
4312 # chunks, which go into their own insets.
4313 # The first line of a chunk should look like: <<CONTENT>>=
4314 # We will discard the delimiters, and put the CONTENT into the
4315 # optional argument of the inset, if the CONTENT is non-empty.
4316 def convert_chunks(document):
4317 first_re = re.compile(r'<<(.*)>>=(.*)')
4320 # find start of a block of chunks
4321 i = find_token(document.body, "\\begin_layout Chunk", file_pos)
4327 chunk_started = False
4330 # process the one we just found
4331 j = find_end_of_layout(document.body, i)
4333 document.warning("Malformed LyX documents. Can't find end of Chunk layout!")
4334 # there is no point continuing, as we will run into the same error again.
4336 this_chunk = "".join(document.body[i + 1:j])
4338 # there may be empty lines between chunks
4339 # we just skip them.
4340 if not chunk_started:
4341 if this_chunk != "":
4343 chunk_started = True
4346 contents.append(document.body[i + 1:j])
4348 # look for potential chunk terminator
4349 # on the last line of the chunk paragraph
4350 if document.body[j - 1] == "@":
4353 # look for subsequent chunk paragraph
4354 i = find_token(document.body, "\\begin_layout", j)
4358 if get_value(document.body, "\\begin_layout", i) != "Chunk":
4361 file_pos = end = j + 1
4363 # The last chunk should simply have an "@" in it
4364 # or at least end with "@" (can happen if @ is
4365 # preceded by a newline)
4366 lastpar = ''.join(contents[-1])
4367 if not lastpar.endswith("@"):
4368 document.warning("Unexpected chunk content: chunk not terminated by '@'!")
4372 # chunk par only contains "@". Just drop it.
4375 # chunk par contains more. Only drop the "@".
4378 # The first line should look like: <<CONTENT>>=
4379 # We want the CONTENT
4380 optarg = ' '.join(contents[0])
4382 # We can already have real chunk content in
4383 # the first par (separated from the options by a newline).
4384 # We collect such stuff to re-insert it later.
4387 match = first_re.search(optarg)
4389 optarg = match.groups()[0]
4390 if match.groups()[1] != "":
4392 for c in contents[0]:
4393 if c.endswith(">>="):
4397 postoptstuff.append(c)
4398 # We have stripped everything. This can be deleted.
4401 newstuff = ['\\begin_layout Standard',
4402 '\\begin_inset Flex Chunk',
4404 '\\begin_layout Plain Layout', '']
4406 # If we have a non-empty optional argument, insert it.
4407 if match and optarg != "":
4409 ['\\begin_inset Argument 1',
4411 '\\begin_layout Plain Layout',
4416 # Since we already opened a Plain layout, the first paragraph
4417 # does not need to do that.
4420 newstuff.extend(postoptstuff)
4421 newstuff.append('\\end_layout')
4425 newstuff.extend(['', '\\begin_layout Plain Layout', ''])
4429 newstuff.append('\\end_layout')
4431 newstuff.extend(['', '\\end_inset', '', '\\end_layout', ''])
4433 document.body[start:end] = newstuff
4435 file_pos += len(newstuff) - (end - start)
4438 def revert_chunks(document):
4441 i = find_token(document.body, "\\begin_inset Flex Chunk", i)
4445 iend = find_end_of_inset(document.body, i)
4447 document.warning("Can't find end of Chunk!")
4451 # Look for optional argument
4453 ostart = find_token(document.body, "\\begin_inset Argument 1", i, iend)
4455 oend = find_end_of_inset(document.body, ostart)
4456 k = find_token(document.body, "\\begin_layout Plain Layout", ostart, oend)
4458 document.warning("Malformed LyX document: Can't find argument contents!")
4460 m = find_end_of_layout(document.body, k)
4461 optarg = "".join(document.body[k+1:m])
4464 # We now remove the optional argument, so we have something
4465 # uniform on which to work
4466 document.body[ostart : oend + 1] = []
4467 # iend is now invalid
4468 iend = find_end_of_inset(document.body, i)
4470 retval = get_containing_layout(document.body, i)
4472 document.warning("Can't find containing layout for Chunk!")
4475 (lname, lstart, lend, pstart) = retval
4476 # we now want to work through the various paragraphs, and collect their contents
4480 k = find_token(document.body, "\\begin_layout Plain Layout", k, lend)
4483 j = find_end_of_layout(document.body, k)
4485 document.warning("Can't find end of layout inside chunk!")
4487 parlist.append(document.body[k+1:j])
4489 # we now need to wrap all of these paragraphs in chunks
4492 newlines.extend(["\\begin_layout Chunk", "", "<<" + optarg + ">>=", "\\end_layout", ""])
4493 for stuff in parlist:
4494 newlines.extend(["\\begin_layout Chunk"] + stuff + ["\\end_layout", ""])
4495 newlines.extend(["\\begin_layout Chunk", "", "@", "\\end_layout", ""])
4496 # replace old content with new content
4497 document.body[lstart : lend + 1] = newlines
4498 i = lstart + len(newlines)
4505 supported_versions = ["2.1.0","2.1"]
4508 [415, [convert_undertilde]],
4510 [417, [convert_japanese_encodings]],
4511 [418, [convert_justification]],
4513 [420, [convert_biblio_style]],
4514 [421, [convert_longtable_captions]],
4515 [422, [convert_use_packages]],
4516 [423, [convert_use_mathtools]],
4517 [424, [convert_cite_engine_type]],
4518 # No convert_cancel, since cancel will be loaded automatically
4519 # in format 425 without any possibility to switch it off.
4520 # This has been fixed in format 464.
4524 [428, [convert_cell_rotation]],
4525 [429, [convert_table_rotation]],
4526 [430, [convert_listoflistings]],
4527 [431, [convert_use_amssymb]],
4529 [433, [convert_armenian]],
4537 [441, [convert_mdnomath]],
4542 [446, [convert_latexargs]],
4543 [447, [convert_IEEEtran, convert_AASTeX, convert_AGUTeX, convert_IJMP, convert_SIGPLAN, convert_SIGGRAPH, convert_EuropeCV, convert_Initials, convert_ModernCV]],
4544 [448, [convert_literate]],
4547 [451, [convert_beamerargs, convert_againframe_args, convert_corollary_args, convert_quote_args]],
4548 [452, [convert_beamerblocks]],
4549 [453, [convert_use_stmaryrd]],
4550 [454, [convert_overprint]],
4552 [456, [convert_epigraph]],
4553 [457, [convert_use_stackrel]],
4554 [458, [convert_captioninsets, convert_captionlayouts]],
4559 [463, [convert_encodings]],
4560 [464, [convert_use_cancel]],
4561 [465, [convert_lyxframes, remove_endframes]],
4567 [471, [convert_cite_engine_type_default]],
4570 [474, [convert_chunks]],
4574 [473, [revert_chunks]],
4575 [472, [revert_tibetan]],
4576 [471, [revert_aa1,revert_aa2]],
4577 [470, [revert_cite_engine_type_default]],
4578 [469, [revert_forced_local_layout]],
4579 [468, [revert_starred_caption]],
4580 [467, [revert_mbox_fbox]],
4581 [466, [revert_iwona_fonts]],
4582 [465, [revert_powerdot_flexes, revert_powerdot_pause, revert_powerdot_itemargs, revert_powerdot_columns]],
4584 [463, [revert_use_cancel]],
4585 [462, [revert_encodings]],
4586 [461, [revert_new_libertines]],
4587 [460, [revert_kurier_fonts]],
4588 [459, [revert_IEEEtran_3]],
4589 [458, [revert_fragileframe, revert_newframes]],
4590 [457, [revert_captioninsets, revert_captionlayouts]],
4591 [456, [revert_use_stackrel]],
4592 [455, [revert_epigraph]],
4593 [454, [revert_frametitle]],
4594 [453, [revert_overprint]],
4595 [452, [revert_use_stmaryrd]],
4596 [451, [revert_beamerblocks]],
4597 [450, [revert_beamerargs, revert_beamerargs2, revert_beamerargs3, revert_beamerflex]],
4598 [449, [revert_garamondx, revert_garamondx_newtxmath]],
4599 [448, [revert_itemargs]],
4600 [447, [revert_literate]],
4601 [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]],
4602 [445, [revert_latexargs]],
4603 [444, [revert_uop]],
4604 [443, [revert_biolinum]],
4606 [441, [revert_newtxmath]],
4607 [440, [revert_mdnomath]],
4608 [439, [revert_mathfonts]],
4609 [438, [revert_minionpro]],
4610 [437, [revert_ipadeco, revert_ipachar]],
4611 [436, [revert_texgyre]],
4612 [435, [revert_mathdesign]],
4613 [434, [revert_txtt]],
4614 [433, [revert_libertine]],
4615 [432, [revert_armenian]],
4616 [431, [revert_languages, revert_ancientgreek]],
4617 [430, [revert_use_amssymb]],
4618 [429, [revert_listoflistings]],
4619 [428, [revert_table_rotation]],
4620 [427, [revert_cell_rotation]],
4621 [426, [revert_tipa]],
4622 [425, [revert_verbatim]],
4623 [424, [revert_cancel]],
4624 [423, [revert_cite_engine_type]],
4625 [422, [revert_use_mathtools]],
4626 [421, [revert_use_packages]],
4627 [420, [revert_longtable_captions]],
4628 [419, [revert_biblio_style]],
4629 [418, [revert_australian]],
4630 [417, [revert_justification]],
4631 [416, [revert_japanese_encodings]],
4632 [415, [revert_negative_space, revert_math_spaces]],
4633 [414, [revert_undertilde]],
4634 [413, [revert_visible_space]]
4638 if __name__ == "__main__":