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