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 if ertcontdivline == ertcontfirstline:
3117 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3118 '\\end_layout', '', '\\end_inset', '',
3119 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3120 'status collapsed', '', '\\begin_layout Plain Layout',
3121 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3122 document.body[ertcontdivline][tok + 2:]]
3124 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3125 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3126 'status collapsed', '', '\\begin_layout Plain Layout',
3127 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3128 document.body[ertcontdivline][tok + 2:]]
3130 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3131 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3132 'status collapsed', '', '\\begin_layout Plain Layout',
3133 document.body[ertcontdivline][tok + 2:]]
3135 # check if have delimiters in two different ERTs
3136 tok = document.body[ertcontdivline].find('>')
3138 regexp = re.compile(r'.*>', re.IGNORECASE)
3139 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3140 tok = document.body[ertcontdivline].find('>')
3142 tokk = document.body[ertcontdivline].find('{')
3144 regexp = re.compile(r'.*\{', re.IGNORECASE)
3145 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, lastertend)
3146 tokk = document.body[ertcontdivlinetwo].find('{')
3148 if ertcontfirstline < ertcontlastline:
3149 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3150 document.body[ertcontlastline : ertcontlastline + 1] = [
3151 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3152 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3153 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3154 '\\end_inset', '', '', '\\begin_inset Argument 2',
3155 'status collapsed', '', '\\begin_layout Plain Layout',
3156 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3157 document.body[ertcontdivlinetwo][tokk + 1:]]
3159 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3160 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3161 'status collapsed', '', '\\begin_layout Plain Layout',
3162 document.body[ertcontdivlinetwo][tokk + 1:]]
3163 # Convert to ArgInset
3164 if ertcontfirstline < ertcontlastline:
3165 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3166 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 1',
3167 'status collapsed', '', '\\begin_layout Plain Layout',
3168 '\\begin_inset ERT', '']
3170 document.body[parbeg] = "\\begin_inset Argument 1"
3171 elif document.body[ertcontfirstline].lstrip().startswith("{"):
3172 # This is the block title
3173 if document.body[ertcontlastline].rstrip().endswith("}"):
3174 # strip off the braces
3175 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3176 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3177 if ertcontfirstline < ertcontlastline:
3178 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3179 document.body[parend : parend + 1] = [
3180 document.body[parend], '\\end_inset', '', '\\end_layout']
3181 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3182 'status collapsed', '', '\\begin_layout Plain Layout',
3183 '\\begin_inset ERT', '']
3185 # Convert to ArgInset
3186 document.body[parbeg] = "\\begin_inset Argument 2"
3187 # the overlay argument can also follow the title, so ...
3188 elif document.body[ertcontlastline].rstrip().endswith(">"):
3190 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3192 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3194 ertcontdivline = ertcontfirstline
3195 tok = document.body[ertcontdivline].find('}<')
3197 regexp = re.compile(r'.*\}<', re.IGNORECASE)
3198 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3199 tok = document.body[ertcontdivline].find('}<')
3201 if ertcontfirstline < ertcontlastline:
3202 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3203 document.body[ertcontlastline : ertcontlastline + 1] = [
3204 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3205 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3206 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3207 'status collapsed', '', '\\begin_layout Plain Layout',
3208 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3209 document.body[ertcontdivline][tok + 2:]]
3211 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3212 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3213 'status collapsed', '', '\\begin_layout Plain Layout',
3214 document.body[ertcontdivline][tok + 2:]]
3216 # check if have delimiters in two different ERTs
3217 tok = document.body[ertcontdivline].find('}')
3219 regexp = re.compile(r'.*\}', re.IGNORECASE)
3220 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3221 tok = document.body[ertcontdivline].find('}')
3223 tokk = document.body[ertcontdivline].find('<')
3225 regexp = re.compile(r'.*<', re.IGNORECASE)
3226 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, lastertend)
3227 tokk = document.body[ertcontdivlinetwo].find('<')
3229 if ertcontfirstline < ertcontlastline:
3230 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3231 document.body[ertcontlastline : ertcontlastline + 1] = [
3232 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3233 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3234 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3235 '\\end_inset', '', '', '\\begin_inset Argument 1',
3236 'status collapsed', '', '\\begin_layout Plain Layout',
3237 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3238 document.body[ertcontdivlinetwo][tokk + 1:]]
3240 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3241 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3242 'status collapsed', '', '\\begin_layout Plain Layout',
3243 document.body[ertcontdivlinetwo][tokk + 1:]]
3244 # Convert to ArgInset
3245 if ertcontfirstline < ertcontlastline:
3246 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3247 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3248 'status collapsed', '', '\\begin_layout Plain Layout',
3249 '\\begin_inset ERT', '']
3251 document.body[parbeg] = "\\begin_inset Argument 2"
3252 elif count_pars_in_inset(document.body, ertcontfirstline) > 1:
3253 # Multipar ERT. Skip this.
3256 # ERT has contents after the closing bracket. We cannot convert this.
3257 # convert_TeX_brace_to_Argument cannot either.
3258 #convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, False)
3262 j = find_end_of_layout(document.body, i)
3264 document.warning("end of layout not found!")
3265 k = find_token(document.body, "\\begin_inset Argument", i, j)
3267 document.warning("InsetArgument not found!")
3269 l = find_end_of_inset(document.body, k)
3270 m = find_token(document.body, "\\begin_inset ERT", l, j)
3273 ertcontfirstline = m + 5
3278 def convert_overprint(document):
3279 " Convert old beamer overprint layouts to ERT "
3281 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3282 if document.textclass not in beamer_classes:
3287 i = find_token(document.body, "\\begin_layout Overprint", i)
3290 # Find end of sequence
3291 j = find_end_of_sequence(document.body, i)
3293 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3297 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3299 if document.body[j] == "\\end_deeper":
3300 esubst = ["", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3302 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3303 endseq = endseq + len(esubst) - len(document.body[j : j])
3304 document.body[j : j] = esubst
3305 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3307 argend = find_end_of_layout(document.body, argbeg)
3309 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3312 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3313 endPlain = find_end_of_layout(document.body, beginPlain)
3314 content = document.body[beginPlain + 1 : endPlain]
3316 endseq = endseq - len(document.body[argbeg : argend + 1])
3318 del document.body[argbeg : argend + 1]
3319 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3321 endseq = endseq - len(document.body[i : i])
3322 document.body[i : i] = subst + ["\\end_layout"]
3323 endseq += len(subst)
3325 for p in range(i, endseq):
3326 if document.body[p] == "\\begin_layout Overprint":
3327 document.body[p] = "\\begin_layout Standard"
3332 def revert_overprint(document):
3333 " Revert old beamer overprint layouts to ERT "
3335 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3336 if document.textclass not in beamer_classes:
3341 i = find_token(document.body, "\\begin_layout Overprint", i)
3344 # Find end of sequence
3345 j = find_end_of_sequence(document.body, i)
3347 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3351 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3352 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}")
3353 endseq = endseq + len(esubst) - len(document.body[j : j])
3354 if document.body[j] == "\\end_deeper":
3355 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3357 document.body[j : j] = ["\\end_layout", ""] + esubst
3360 if document.body[r] == "\\begin_deeper":
3361 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3363 document.body[r] = ""
3364 document.body[s] = ""
3368 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3370 # Is this really our argument?
3371 nested = find_token(document.body, "\\begin_deeper", i, argbeg)
3373 argend = find_end_of_inset(document.body, argbeg)
3375 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3378 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3379 endPlain = find_end_of_layout(document.body, beginPlain)
3380 content = document.body[beginPlain + 1 : endPlain]
3382 endseq = endseq - len(document.body[argbeg : argend])
3384 del document.body[argbeg : argend + 1]
3385 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3387 endseq = endseq - len(document.body[i : i])
3388 document.body[i : i] = subst + ["\\end_layout"]
3389 endseq += len(subst)
3395 if document.body[p] == "\\begin_layout Overprint":
3396 q = find_end_of_layout(document.body, p)
3398 document.warning("Malformed LyX document. Cannot find end of Overprint layout!")
3401 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\onslide")
3402 argbeg = find_token(document.body, "\\begin_inset Argument item:1", p, q)
3404 argend = find_end_of_inset(document.body, argbeg)
3406 document.warning("Malformed LyX document. Cannot find end of Overprint item argument!")
3409 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3410 endPlain = find_end_of_layout(document.body, beginPlain)
3411 content = document.body[beginPlain + 1 : endPlain]
3413 endseq = endseq - len(document.body[argbeg : argend + 1])
3415 del document.body[argbeg : argend + 1]
3416 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3417 endseq = endseq - len(document.body[p : p + 1]) + len(subst)
3418 document.body[p : p + 1] = subst
3424 def revert_frametitle(document):
3425 " Reverts beamer frametitle layout to ERT "
3427 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3428 if document.textclass not in beamer_classes:
3431 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3434 i = find_token(document.body, "\\begin_layout FrameTitle", i)
3437 j = find_end_of_layout(document.body, i)
3439 document.warning("Malformed LyX document: Can't find end of FrameTitle layout")
3443 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
3444 endlay += len(put_cmd_in_ert("}"))
3445 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\frametitle")
3446 for p in range(i, j):
3449 m = rx.match(document.body[p])
3453 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3454 endPlain = find_end_of_layout(document.body, beginPlain)
3455 endInset = find_end_of_inset(document.body, p)
3456 content = document.body[beginPlain + 1 : endPlain]
3458 endlay = endlay - len(document.body[p : endInset + 1])
3460 del document.body[p : endInset + 1]
3461 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3463 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3464 endPlain = find_end_of_layout(document.body, beginPlain)
3465 endInset = find_end_of_inset(document.body, p)
3466 content = document.body[beginPlain + 1 : endPlain]
3468 endlay = endlay - len(document.body[p : endInset + 1])
3470 del document.body[p : endInset + 1]
3471 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3473 subst += put_cmd_in_ert("{")
3474 document.body[i : i + 1] = subst
3478 def convert_epigraph(document):
3479 " Converts memoir epigraph to new syntax "
3481 if document.textclass != "memoir":
3486 i = find_token(document.body, "\\begin_layout Epigraph", i)
3489 j = find_end_of_layout(document.body, i)
3491 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3496 ert = find_token(document.body, "\\begin_inset ERT", i, j)
3498 endInset = find_end_of_inset(document.body, ert)
3499 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", ert)
3500 endPlain = find_end_of_layout(document.body, beginPlain)
3501 ertcont = beginPlain + 2
3502 if document.body[ertcont] == "}{":
3504 # Convert to ArgInset
3505 endlay = endlay - 2 * len(document.body[j])
3506 begsubst = ['\\begin_inset Argument post:1', 'status collapsed', '',
3507 '\\begin_layout Plain Layout']
3508 endsubst = ['\\end_layout', '', '\\end_inset', '', document.body[j]]
3509 document.body[j : j + 1] = endsubst
3510 document.body[endInset + 1 : endInset + 1] = begsubst
3512 endlay += len(begsubst) + len(endsubst)
3513 endlay = endlay - len(document.body[ert : endInset + 1])
3514 del document.body[ert : endInset + 1]
3519 def revert_epigraph(document):
3520 " Reverts memoir epigraph argument to ERT "
3522 if document.textclass != "memoir":
3527 i = find_token(document.body, "\\begin_layout Epigraph", i)
3530 j = find_end_of_layout(document.body, i)
3532 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3537 p = find_token(document.body, "\\begin_layout Argument post:1", i, j)
3539 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3540 endPlain = find_end_of_layout(document.body, beginPlain)
3541 endInset = find_end_of_inset(document.body, p)
3542 content = document.body[beginPlain + 1 : endPlain]
3544 endlay = endlay - len(document.body[p : endInset + 1])
3546 del document.body[p : endInset + 1]
3547 subst += put_cmd_in_ert("}{") + content
3549 subst += put_cmd_in_ert("}{")
3551 document.body[j : j] = subst + document.body[j : j]
3555 def convert_captioninsets(document):
3556 " Converts caption insets to new syntax "
3560 i = find_token(document.body, "\\begin_inset Caption", i)
3563 document.body[i] = "\\begin_inset Caption Standard"
3567 def revert_captioninsets(document):
3568 " Reverts caption insets to old syntax "
3572 i = find_token(document.body, "\\begin_inset Caption Standard", i)
3575 document.body[i] = "\\begin_inset Caption"
3579 def convert_captionlayouts(document):
3580 " Convert caption layouts to caption insets. "
3583 "Captionabove": "Above",
3584 "Captionbelow": "Below",
3585 "FigCaption" : "FigCaption",
3586 "Table_Caption" : "Table",
3587 "CenteredCaption" : "Centered",
3588 "Bicaption" : "Bicaption",
3593 i = find_token(document.body, "\\begin_layout", i)
3596 val = get_value(document.body, "\\begin_layout", i)
3597 if val in caption_dict.keys():
3598 j = find_end_of_layout(document.body, i)
3600 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3603 document.body[j:j] = ["\\end_layout", "", "\\end_inset", "", ""]
3604 document.body[i:i+1] = ["\\begin_layout %s" % document.default_layout,
3605 "\\begin_inset Caption %s" % caption_dict[val], "",
3606 "\\begin_layout %s" % document.default_layout]
3610 def revert_captionlayouts(document):
3611 " Revert caption insets to caption layouts. "
3614 "Above" : "Captionabove",
3615 "Below" : "Captionbelow",
3616 "FigCaption" : "FigCaption",
3617 "Table" : "Table_Caption",
3618 "Centered" : "CenteredCaption",
3619 "Bicaption" : "Bicaption",
3623 rx = re.compile(r'^\\begin_inset Caption (\S+)$')
3625 i = find_token(document.body, "\\begin_inset Caption", i)
3629 m = rx.match(document.body[i])
3633 if val not in caption_dict.keys():
3637 # We either need to delete the previous \begin_layout line, or we
3638 # need to end the previous layout if this inset is not in the first
3639 # position of the paragraph.
3640 layout_before = find_token_backwards(document.body, "\\begin_layout", i)
3641 if layout_before == -1:
3642 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3644 layout_line = document.body[layout_before]
3645 del_layout_before = True
3646 l = layout_before + 1
3648 if document.body[l] != "":
3649 del_layout_before = False
3652 if del_layout_before:
3653 del document.body[layout_before:i]
3656 document.body[i:i] = ["\\end_layout", ""]
3659 # Find start of layout in the inset and end of inset
3660 j = find_token(document.body, "\\begin_layout", i)
3662 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3664 k = find_end_of_inset(document.body, i)
3666 document.warning("Malformed LyX document: Missing `\\end_inset'.")
3669 # We either need to delete the following \end_layout line, or we need
3670 # to restart the old layout if this inset is not at the paragraph end.
3671 layout_after = find_token(document.body, "\\end_layout", k)
3672 if layout_after == -1:
3673 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3675 del_layout_after = True
3677 while l < layout_after:
3678 if document.body[l] != "":
3679 del_layout_after = False
3682 if del_layout_after:
3683 del document.body[k+1:layout_after+1]
3685 document.body[k+1:k+1] = [layout_line, ""]
3687 # delete \begin_layout and \end_inset and replace \begin_inset with
3688 # "\begin_layout XXX". This works because we can only have one
3689 # paragraph in the caption inset: The old \end_layout will be recycled.
3690 del document.body[k]
3691 if document.body[k] == "":
3692 del document.body[k]
3693 del document.body[j]
3694 if document.body[j] == "":
3695 del document.body[j]
3696 document.body[i] = "\\begin_layout %s" % caption_dict[val]
3697 if document.body[i+1] == "":
3698 del document.body[i+1]
3702 def revert_fragileframe(document):
3703 " Reverts beamer FragileFrame layout to ERT "
3705 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3706 if document.textclass not in beamer_classes:
3711 i = find_token(document.body, "\\begin_layout FragileFrame", i)
3714 # Find end of sequence
3715 j = find_end_of_sequence(document.body, i)
3717 document.warning("Malformed LyX document. Cannot find end of FragileFrame sequence!")
3721 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{frame}")
3722 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{frame}")
3723 endseq = endseq + len(esubst) - len(document.body[j : j])
3724 if document.body[j] == "\\end_deeper":
3725 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3727 document.body[j : j] = esubst
3728 for q in range(i, j):
3729 if document.body[q] == "\\begin_layout FragileFrame":
3730 document.body[q] = "\\begin_layout %s" % document.default_layout
3733 if document.body[r] == "\\begin_deeper":
3734 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3736 document.body[r] = ""
3737 document.body[s] = ""
3741 for p in range(1, 5):
3742 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, j)
3745 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3746 endPlain = find_end_of_layout(document.body, beginPlain)
3747 endInset = find_end_of_inset(document.body, arg)
3748 content = document.body[beginPlain + 1 : endPlain]
3750 j = j - len(document.body[arg : endInset + 1])
3752 del document.body[arg : endInset + 1]
3753 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3755 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3756 endPlain = find_end_of_layout(document.body, beginPlain)
3757 endInset = find_end_of_inset(document.body, arg)
3758 content = document.body[beginPlain + 1 : endPlain]
3760 j = j - len(document.body[arg : endInset + 1])
3762 del document.body[arg : endInset + 1]
3763 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3765 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3766 endPlain = find_end_of_layout(document.body, beginPlain)
3767 endInset = find_end_of_inset(document.body, arg)
3768 content = document.body[beginPlain + 1 : endPlain]
3770 j = j - len(document.body[arg : endInset + 1])
3772 del document.body[arg : endInset + 1]
3773 subst += put_cmd_in_ert("[fragile,") + content + put_cmd_in_ert("]")
3775 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3776 endPlain = find_end_of_layout(document.body, beginPlain)
3777 endInset = find_end_of_inset(document.body, arg)
3778 content = document.body[beginPlain + 1 : endPlain]
3780 j = j - len(document.body[arg : endInset + 1])
3782 del document.body[arg : endInset + 1]
3783 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3785 subst += put_cmd_in_ert("[fragile]")
3787 document.body[i : i + 1] = subst
3791 def revert_newframes(document):
3792 " Reverts beamer Frame and PlainFrame layouts to old forms "
3794 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3795 if document.textclass not in beamer_classes:
3799 "Frame" : "BeginFrame",
3800 "PlainFrame" : "BeginPlainFrame",
3803 rx = re.compile(r'^\\begin_layout (\S+)$')
3806 i = find_token(document.body, "\\begin_layout", i)
3810 m = rx.match(document.body[i])
3814 if val not in frame_dict.keys():
3817 # Find end of sequence
3818 j = find_end_of_sequence(document.body, i)
3820 document.warning("Malformed LyX document. Cannot find end of Frame sequence!")
3824 subst = ["\\begin_layout %s" % frame_dict[val]]
3825 esubst = ["", "\\begin_layout EndFrame", "", "\\end_layout"]
3826 endseq = endseq + len(esubst) - len(document.body[j : j])
3827 if document.body[j] == "\\end_deeper":
3828 document.body[j : j] = esubst
3830 document.body[j+1 : j+1] = esubst
3831 for q in range(i, j):
3832 if document.body[q] == "\\begin_layout %s" % val:
3833 document.body[q] = "\\begin_layout %s" % document.default_layout
3836 if document.body[r] == "\\begin_deeper":
3837 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3839 document.body[r] = ""
3840 document.body[s] = ""
3844 l = find_end_of_layout(document.body, i)
3845 for p in range(1, 5):
3846 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, l)
3849 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3850 endPlain = find_end_of_layout(document.body, beginPlain)
3851 endInset = find_end_of_inset(document.body, arg)
3852 content = document.body[beginPlain + 1 : endPlain]
3854 l = l - len(document.body[arg : endInset + 1])
3856 del document.body[arg : endInset + 1]
3857 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3859 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3860 endPlain = find_end_of_layout(document.body, beginPlain)
3861 endInset = find_end_of_inset(document.body, arg)
3862 content = document.body[beginPlain + 1 : endPlain]
3864 l = l - len(document.body[arg : endInset + 1])
3866 del document.body[arg : endInset + 1]
3867 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3869 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3870 endPlain = find_end_of_layout(document.body, beginPlain)
3871 endInset = find_end_of_inset(document.body, arg)
3872 content = document.body[beginPlain + 1 : endPlain]
3874 l = l - len(document.body[arg : endInset + 1])
3876 del document.body[arg : endInset + 1]
3877 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3879 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3880 endPlain = find_end_of_layout(document.body, beginPlain)
3881 endInset = find_end_of_inset(document.body, arg)
3882 content = document.body[beginPlain + 1 : endPlain]
3884 l = l - len(document.body[arg : endInset + 1])
3886 del document.body[arg : endInset + 1]
3889 document.body[i : i + 1] = subst
3892 # known encodings that do not change their names (same LyX and LaTeX names)
3893 known_enc_tuple = ("auto", "default", "ansinew", "applemac", "armscii8", "ascii",
3894 "cp437", "cp437de", "cp850", "cp852", "cp855", "cp858", "cp862", "cp865", "cp866",
3895 "cp1250", "cp1251", "cp1252", "cp1255", "cp1256", "cp1257", "koi8-r", "koi8-u",
3896 "pt154", "pt254", "tis620-0", "utf8", "utf8x", "utf8-plain")
3898 def convert_encodings(document):
3899 "Use the LyX names of the encodings instead of the LaTeX names."
3900 LaTeX2LyX_enc_dict = {
3901 "8859-6": "iso8859-6",
3902 "8859-8": "iso8859-8",
3904 "euc": "euc-jp-platex",
3909 "iso88595": "iso8859-5",
3910 "iso-8859-7": "iso8859-7",
3912 "jis": "jis-platex",
3914 "l7xenc": "iso8859-13",
3915 "latin1": "iso8859-1",
3916 "latin2": "iso8859-2",
3917 "latin3": "iso8859-3",
3918 "latin4": "iso8859-4",
3919 "latin5": "iso8859-9",
3920 "latin9": "iso8859-15",
3921 "latin10": "iso8859-16",
3922 "SJIS": "shift-jis",
3923 "sjis": "shift-jis-platex",
3926 i = find_token(document.header, "\\inputencoding" , 0)
3929 val = get_value(document.header, "\\inputencoding", i)
3930 if val in LaTeX2LyX_enc_dict.keys():
3931 document.header[i] = "\\inputencoding %s" % LaTeX2LyX_enc_dict[val]
3932 elif val not in known_enc_tuple:
3933 document.warning("Ignoring unknown input encoding: `%s'" % val)
3936 def revert_encodings(document):
3937 """Revert to using the LaTeX names of the encodings instead of the LyX names.
3938 Also revert utf8-platex to sjis, the language default when using Japanese.
3940 LyX2LaTeX_enc_dict = {
3945 "euc-jp-platex": "euc",
3948 "iso8859-1": "latin1",
3949 "iso8859-2": "latin2",
3950 "iso8859-3": "latin3",
3951 "iso8859-4": "latin4",
3952 "iso8859-5": "iso88595",
3953 "iso8859-6": "8859-6",
3954 "iso8859-7": "iso-8859-7",
3955 "iso8859-8": "8859-8",
3956 "iso8859-9": "latin5",
3957 "iso8859-13": "l7xenc",
3958 "iso8859-15": "latin9",
3959 "iso8859-16": "latin10",
3961 "jis-platex": "jis",
3962 "shift-jis": "SJIS",
3963 "shift-jis-platex": "sjis",
3965 "utf8-platex": "sjis"
3967 i = find_token(document.header, "\\inputencoding" , 0)
3970 val = get_value(document.header, "\\inputencoding", i)
3971 if val in LyX2LaTeX_enc_dict.keys():
3972 document.header[i] = "\\inputencoding %s" % LyX2LaTeX_enc_dict[val]
3973 elif val not in known_enc_tuple:
3974 document.warning("Ignoring unknown input encoding: `%s'" % val)
3977 def revert_IEEEtran_3(document):
3979 Reverts Flex Insets to TeX-code
3981 if document.textclass == "IEEEtran":
3987 h = find_token(document.body, "\\begin_inset Flex Author Mark", h)
3989 endh = find_end_of_inset(document.body, h)
3990 document.body[endh - 2 : endh + 1] = put_cmd_in_ert("}")
3991 document.body[h : h + 4] = put_cmd_in_ert("\\IEEEauthorrefmark{")
3994 i = find_token(document.body, "\\begin_inset Flex Author Name", i)
3996 endi = find_end_of_inset(document.body, i)
3997 document.body[endi - 2 : endi + 1] = put_cmd_in_ert("}")
3998 document.body[i : i + 4] = put_cmd_in_ert("\\IEEEauthorblockN{")
4001 j = find_token(document.body, "\\begin_inset Flex Author Affiliation", j)
4003 endj = find_end_of_inset(document.body, j)
4004 document.body[endj - 2 : endj + 1] = put_cmd_in_ert("}")
4005 document.body[j : j + 4] = put_cmd_in_ert("\\IEEEauthorblockA{")
4007 if i == -1 and j == -1 and h == -1:
4011 def revert_kurier_fonts(document):
4012 " Revert kurier font definition to LaTeX "
4014 i = find_token(document.header, "\\font_math", 0)
4016 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4017 val = get_value(document.header, "\\font_math", i)
4018 if val == "kurier-math":
4019 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
4020 "\\usepackage[math]{kurier}\n" \
4021 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
4022 document.header[i] = "\\font_math auto"
4024 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4025 kurier_fonts = ["kurier", "kurierc", "kurierl", "kurierlc"]
4026 k = find_token(document.header, "\\font_sans kurier", 0)
4028 sf = get_value(document.header, "\\font_sans", k)
4029 if sf in kurier_fonts:
4030 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4031 document.header[k] = "\\font_sans default"
4033 def revert_iwona_fonts(document):
4034 " Revert iwona font definition to LaTeX "
4036 i = find_token(document.header, "\\font_math", 0)
4038 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4039 val = get_value(document.header, "\\font_math", i)
4040 if val == "iwona-math":
4041 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
4042 "\\usepackage[math]{iwona}\n" \
4043 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
4044 document.header[i] = "\\font_math auto"
4046 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4047 iwona_fonts = ["iwona", "iwonac", "iwonal", "iwonalc"]
4048 k = find_token(document.header, "\\font_sans iwona", 0)
4050 sf = get_value(document.header, "\\font_sans", k)
4051 if sf in iwona_fonts:
4052 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4053 document.header[k] = "\\font_sans default"
4056 def revert_new_libertines(document):
4057 " Revert new libertine font definition to LaTeX "
4059 if find_token(document.header, "\\use_non_tex_fonts true", 0) != -1:
4062 i = find_token(document.header, "\\font_typewriter libertine-mono", 0)
4064 preamble = "\\usepackage"
4065 sc = find_token(document.header, "\\font_tt_scale", 0)
4067 scval = get_value(document.header, "\\font_tt_scale", sc)
4069 preamble += "[scale=%f]" % (float(scval) / 100)
4070 document.header[sc] = "\\font_tt_scale 100"
4071 preamble += "{libertineMono-type1}"
4072 add_to_preamble(document, [preamble])
4073 document.header[i] = "\\font_typewriter default"
4075 k = find_token(document.header, "\\font_sans biolinum", 0)
4077 preamble = "\\usepackage"
4079 j = find_token(document.header, "\\font_osf true", 0)
4084 sc = find_token(document.header, "\\font_sf_scale", 0)
4086 scval = get_value(document.header, "\\font_sf_scale", sc)
4088 options += ",scale=%f" % (float(scval) / 100)
4089 document.header[sc] = "\\font_sf_scale 100"
4091 preamble += "[" + options +"]"
4092 preamble += "{biolinum-type1}"
4093 add_to_preamble(document, [preamble])
4094 document.header[k] = "\\font_sans default"
4097 def convert_lyxframes(document):
4098 " Converts old beamer frames to new style "
4100 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4101 if document.textclass not in beamer_classes:
4104 framebeg = ["BeginFrame", "BeginPlainFrame"]
4105 frameend = ["Frame", "PlainFrame", "EndFrame", "BeginFrame", "BeginPlainFrame", "AgainFrame",
4106 "Section", "Section*", "Subsection", "Subsection*", "Subsubsection", "Subsubsection*"]
4107 for lay in framebeg:
4110 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
4113 parent = get_containing_layout(document.body, i)
4114 if parent == False or parent[1] != i:
4115 document.warning("Wrong parent layout!")
4118 frametype = parent[0]
4122 # Step I: Convert ERT arguments
4123 # FIXME: See restrictions in convert_beamerframeargs method
4124 ertend = convert_beamerframeargs(document, i, parbeg)
4127 # Step II: Now rename the layout and convert the title to an argument
4128 j = find_end_of_layout(document.body, i)
4129 document.body[j : j + 1] = ['\\end_layout', '', '\\end_inset', '', '\\end_layout']
4130 if lay == "BeginFrame":
4131 document.body[i] = "\\begin_layout Frame"
4133 document.body[i] = "\\begin_layout PlainFrame"
4134 document.body[ertend + 1 : ertend + 1] = ['\\begin_inset Argument 4',
4135 'status open', '', '\\begin_layout Plain Layout']
4136 # Step III: find real frame end
4140 fend = find_token(document.body, "\\begin_layout", jj)
4142 document.warning("Malformed LyX document: No real frame end!")
4144 val = get_value(document.body, "\\begin_layout", fend)
4145 if val not in frameend:
4148 old = document.body[fend]
4149 if val == frametype:
4150 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4151 # consider explicit EndFrames between two identical frame types
4152 elif val == "EndFrame":
4153 nextlayout = find_token(document.body, "\\begin_layout", fend + 1)
4154 if nextlayout != -1 and get_value(document.body, "\\begin_layout", nextlayout) == frametype:
4155 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4157 document.body[fend : fend] = ['\\end_deeper']
4159 document.body[fend : fend] = ['\\end_deeper']
4160 document.body[j + 1 : j + 1] = ['', '\\begin_deeper']
4165 def remove_endframes(document):
4166 " Remove deprecated beamer endframes "
4168 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4169 if document.textclass not in beamer_classes:
4174 i = find_token_exact(document.body, "\\begin_layout EndFrame", i)
4177 j = find_end_of_layout(document.body, i)
4179 document.warning("Malformed LyX document: Missing \\end_layout to EndFrame")
4182 del document.body[i : j + 1]
4185 def revert_powerdot_flexes(document):
4186 " Reverts powerdot flex insets "
4188 if document.textclass != "powerdot":
4191 flexes = {"Onslide" : "\\onslide",
4192 "Onslide*" : "\\onslide*",
4193 "Onslide+" : "\\onslide+"}
4194 rx = re.compile(r'^\\begin_inset Flex (.+)$')
4198 i = find_token(document.body, "\\begin_inset Flex", i)
4201 m = rx.match(document.body[i])
4203 flextype = m.group(1)
4204 z = find_end_of_inset(document.body, i)
4206 document.warning("Can't find end of Flex " + flextype + " inset.")
4209 if flextype in flexes:
4210 pre = put_cmd_in_ert(flexes[flextype])
4211 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
4213 argend = find_end_of_inset(document.body, arg)
4215 document.warning("Can't find end of Argument!")
4218 # Find containing paragraph layout
4219 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
4220 endPlain = find_end_of_layout(document.body, beginPlain)
4221 argcontent = document.body[beginPlain + 1 : endPlain]
4223 z = z - len(document.body[arg : argend + 1])
4225 del document.body[arg : argend + 1]
4226 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
4227 pre += put_cmd_in_ert("{")
4228 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4229 endPlain = find_end_of_layout(document.body, beginPlain)
4231 z = z - len(document.body[i : beginPlain + 1])
4233 document.body[i : beginPlain + 1] = pre
4234 post = put_cmd_in_ert("}")
4235 document.body[z - 2 : z + 1] = post
4239 def revert_powerdot_pause(document):
4240 " Reverts powerdot pause layout to ERT "
4242 if document.textclass != "powerdot":
4247 i = find_token(document.body, "\\begin_layout Pause", i)
4250 j = find_end_of_layout(document.body, i)
4252 document.warning("Malformed LyX document: Can't find end of Pause layout")
4256 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\pause")
4257 for p in range(i, j):
4260 arg = find_token(document.body, "\\begin_inset Argument 1", i, j)
4262 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4263 endPlain = find_end_of_layout(document.body, beginPlain)
4264 endInset = find_end_of_inset(document.body, p)
4265 content = document.body[beginPlain + 1 : endPlain]
4267 endlay = endlay - len(document.body[p : endInset + 1])
4269 del document.body[p : endInset + 1]
4270 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4272 document.body[i : i + 1] = subst
4276 def revert_powerdot_itemargs(document):
4277 " Reverts powerdot item arguments to ERT "
4279 if document.textclass != "powerdot":
4283 list_layouts = ["Itemize", "ItemizeType1", "Enumerate", "EnumerateType1"]
4284 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4287 i = find_token(document.body, "\\begin_inset Argument", i)
4290 # Find containing paragraph layout
4291 parent = get_containing_layout(document.body, i)
4293 document.warning("Malformed LyX document: Can't find parent paragraph layout")
4298 realparbeg = parent[3]
4299 layoutname = parent[0]
4301 for p in range(parbeg, parend):
4305 if layoutname in list_layouts:
4306 m = rx.match(document.body[p])
4309 if argnr == "item:1":
4310 j = find_end_of_inset(document.body, i)
4311 # Find containing paragraph layout
4312 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4313 endPlain = find_end_of_layout(document.body, beginPlain)
4314 content = document.body[beginPlain + 1 : endPlain]
4315 del document.body[i:j+1]
4316 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4317 document.body[realparbeg : realparbeg] = subst
4318 elif argnr == "item:2":
4319 j = find_end_of_inset(document.body, i)
4320 # Find containing paragraph layout
4321 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4322 endPlain = find_end_of_layout(document.body, beginPlain)
4323 content = document.body[beginPlain + 1 : endPlain]
4324 del document.body[i:j+1]
4325 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
4326 document.body[realparbeg : realparbeg] = subst
4331 def revert_powerdot_columns(document):
4332 " Reverts powerdot twocolumn to TeX-code "
4333 if document.textclass != "powerdot":
4336 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4339 i = find_token(document.body, "\\begin_layout Twocolumn", i)
4342 j = find_end_of_layout(document.body, i)
4344 document.warning("Malformed LyX document: Can't find end of Twocolumn layout")
4348 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
4349 endlay += len(put_cmd_in_ert("}"))
4350 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\twocolumn")
4351 for p in range(i, j):
4354 m = rx.match(document.body[p])
4358 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4359 endPlain = find_end_of_layout(document.body, beginPlain)
4360 endInset = find_end_of_inset(document.body, p)
4361 content = document.body[beginPlain + 1 : endPlain]
4363 endlay = endlay - len(document.body[p : endInset + 1])
4365 del document.body[p : endInset + 1]
4366 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4368 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4369 endPlain = find_end_of_layout(document.body, beginPlain)
4370 endInset = find_end_of_inset(document.body, p)
4371 content = document.body[beginPlain + 1 : endPlain]
4373 endlay = endlay - len(document.body[p : endInset + 1])
4375 del document.body[p : endInset + 1]
4376 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
4378 subst += put_cmd_in_ert("{")
4379 document.body[i : i + 1] = subst
4383 def revert_mbox_fbox(document):
4384 'Convert revert mbox/fbox boxes to TeX-code'
4387 i = find_token(document.body, "\\begin_inset Box", i)
4390 j = find_token(document.body, "width", i)
4392 document.warning("Malformed LyX document: Can't find box width")
4394 width = get_value(document.body, "width", j)
4395 k = find_end_of_inset(document.body, j)
4397 document.warning("Malformed LyX document: Can't find end of box inset")
4400 BeginLayout = find_token(document.body, "\\begin_layout Plain Layout", j)
4401 EndLayout = find_end_of_layout(document.body, BeginLayout)
4402 # replace if width is ""
4404 document.body[EndLayout:k + 1] = put_cmd_in_ert("}")
4405 if document.body[i] == "\\begin_inset Box Frameless":
4406 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\mbox{")
4407 if document.body[i] == "\\begin_inset Box Boxed":
4408 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\fbox{")
4412 def revert_starred_caption(document):
4413 " Reverts unnumbered longtable caption insets "
4417 i = find_token(document.body, "\\begin_inset Caption LongTableNoNumber", i)
4420 # This is not equivalent, but since the caption inset is a full blown
4421 # text inset a true conversion to ERT is too difficult.
4422 document.body[i] = "\\begin_inset Caption Standard"
4426 def revert_forced_local_layout(document):
4429 i = find_token(document.header, "\\begin_forced_local_layout", i)
4432 j = find_end_of(document.header, i, "\\begin_forced_local_layout", "\\end_forced_local_layout")
4434 # this should not happen
4436 regexp = re.compile(r'\s*forcelocal', re.IGNORECASE)
4437 k = find_re(document.header, regexp, i, j)
4439 del document.header[k]
4441 k = find_re(document.header, regexp, i, j)
4442 k = find_token(document.header, "\\begin_local_layout", 0)
4444 document.header[i] = "\\begin_local_layout"
4445 document.header[j] = "\\end_local_layout"
4447 l = find_end_of(document.header, k, "\\begin_local_layout", "\\end_local_layout")
4449 # this should not happen
4451 lines = document.header[i+1 : j]
4453 document.header[k+1 : k+1] = lines
4454 document.header[i : j ] = []
4456 document.header[i : j ] = []
4457 document.header[k+1 : k+1] = lines
4460 def revert_aa1(document):
4461 " Reverts InsetArguments of aa to TeX-code "
4462 if document.textclass == "aa":
4466 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4468 revert_Argument_to_TeX_brace(document, i, 0, 1, 4, False, False)
4474 def revert_aa2(document):
4475 " Reverts InsetArguments of aa to TeX-code "
4476 if document.textclass == "aa":
4480 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4482 document.body[i] = "\\begin_layout Abstract"
4488 def revert_tibetan(document):
4489 "Set the document language for Tibetan to English"
4491 if document.language == "tibetan":
4492 document.language = "english"
4493 i = find_token(document.header, "\\language", 0)
4495 document.header[i] = "\\language english"
4497 while j < len(document.body):
4498 j = find_token(document.body, "\\lang tibetan", j)
4500 document.body[j] = document.body[j].replace("\\lang tibetan", "\\lang english")
4503 j = len(document.body)
4512 # The idea here is that we will have a sequence of chunk paragraphs.
4513 # We want to convert them to paragraphs in one or several chunk insets.
4514 # Individual chunks are terminated by the character @ on the last line.
4515 # This line will be discarded, and following lines are treated as new
4516 # chunks, which go into their own insets.
4517 # The first line of a chunk should look like: <<CONTENT>>=
4518 # We will discard the delimiters, and put the CONTENT into the
4519 # optional argument of the inset, if the CONTENT is non-empty.
4520 def convert_chunks(document):
4521 first_re = re.compile(r'<<(.*)>>=(.*)')
4524 # find start of a block of chunks
4525 i = find_token(document.body, "\\begin_layout Chunk", file_pos)
4531 chunk_started = False
4534 # process the one we just found
4535 j = find_end_of_layout(document.body, i)
4537 document.warning("Malformed LyX documents. Can't find end of Chunk layout!")
4538 # there is no point continuing, as we will run into the same error again.
4540 this_chunk = "".join(document.body[i + 1:j])
4542 # there may be empty lines between chunks
4543 # we just skip them.
4544 if not chunk_started:
4545 if this_chunk != "":
4547 chunk_started = True
4550 contents.append(document.body[i + 1:j])
4552 # look for potential chunk terminator
4553 # on the last line of the chunk paragraph
4554 if document.body[j - 1] == "@":
4557 # look for subsequent chunk paragraph
4558 i = find_token(document.body, "\\begin_layout", j)
4562 if get_value(document.body, "\\begin_layout", i) != "Chunk":
4565 file_pos = end = j + 1
4567 # The last chunk should simply have an "@" in it
4568 # or at least end with "@" (can happen if @ is
4569 # preceded by a newline)
4570 lastpar = ''.join(contents[-1])
4571 if not lastpar.endswith("@"):
4572 document.warning("Unexpected chunk content: chunk not terminated by '@'!")
4576 # chunk par only contains "@". Just drop it.
4579 # chunk par contains more. Only drop the "@".
4582 # The first line should look like: <<CONTENT>>=
4583 # We want the CONTENT
4584 optarg = ' '.join(contents[0])
4586 # We can already have real chunk content in
4587 # the first par (separated from the options by a newline).
4588 # We collect such stuff to re-insert it later.
4591 match = first_re.search(optarg)
4593 optarg = match.groups()[0]
4594 if match.groups()[1] != "":
4596 for c in contents[0]:
4597 if c.endswith(">>="):
4601 postoptstuff.append(c)
4602 # We have stripped everything. This can be deleted.
4605 newstuff = ['\\begin_layout Standard',
4606 '\\begin_inset Flex Chunk',
4608 '\\begin_layout Plain Layout', '']
4610 # If we have a non-empty optional argument, insert it.
4611 if match and optarg != "":
4613 ['\\begin_inset Argument 1',
4615 '\\begin_layout Plain Layout',
4620 # Since we already opened a Plain layout, the first paragraph
4621 # does not need to do that.
4624 newstuff.extend(postoptstuff)
4625 newstuff.append('\\end_layout')
4629 newstuff.extend(['', '\\begin_layout Plain Layout', ''])
4633 newstuff.append('\\end_layout')
4635 newstuff.extend(['', '\\end_inset', '', '\\end_layout', ''])
4637 document.body[start:end] = newstuff
4639 file_pos += len(newstuff) - (end - start)
4642 def revert_chunks(document):
4645 i = find_token(document.body, "\\begin_inset Flex Chunk", i)
4649 iend = find_end_of_inset(document.body, i)
4651 document.warning("Can't find end of Chunk!")
4655 # Look for optional argument
4657 ostart = find_token(document.body, "\\begin_inset Argument 1", i, iend)
4659 oend = find_end_of_inset(document.body, ostart)
4660 k = find_token(document.body, "\\begin_layout Plain Layout", ostart, oend)
4662 document.warning("Malformed LyX document: Can't find argument contents!")
4664 m = find_end_of_layout(document.body, k)
4665 optarg = "".join(document.body[k+1:m])
4668 # We now remove the optional argument, so we have something
4669 # uniform on which to work
4670 document.body[ostart : oend + 1] = []
4671 # iend is now invalid
4672 iend = find_end_of_inset(document.body, i)
4674 retval = get_containing_layout(document.body, i)
4676 document.warning("Can't find containing layout for Chunk!")
4679 (lname, lstart, lend, pstart) = retval
4680 # we now want to work through the various paragraphs, and collect their contents
4684 k = find_token(document.body, "\\begin_layout Plain Layout", k, lend)
4687 j = find_end_of_layout(document.body, k)
4689 document.warning("Can't find end of layout inside chunk!")
4691 parlist.append(document.body[k+1:j])
4693 # we now need to wrap all of these paragraphs in chunks
4696 newlines.extend(["\\begin_layout Chunk", "", "<<" + optarg + ">>=", "\\end_layout", ""])
4697 for stuff in parlist:
4698 newlines.extend(["\\begin_layout Chunk"] + stuff + ["\\end_layout", ""])
4699 newlines.extend(["\\begin_layout Chunk", "", "@", "\\end_layout", ""])
4700 # replace old content with new content
4701 document.body[lstart : lend + 1] = newlines
4702 i = lstart + len(newlines)
4709 supported_versions = ["2.1.0","2.1"]
4712 [415, [convert_undertilde]],
4714 [417, [convert_japanese_encodings]],
4715 [418, [convert_justification]],
4717 [420, [convert_biblio_style]],
4718 [421, [convert_longtable_captions]],
4719 [422, [convert_use_packages]],
4720 [423, [convert_use_mathtools]],
4721 [424, [convert_cite_engine_type]],
4722 # No convert_cancel, since cancel will be loaded automatically
4723 # in format 425 without any possibility to switch it off.
4724 # This has been fixed in format 464.
4728 [428, [convert_cell_rotation]],
4729 [429, [convert_table_rotation]],
4730 [430, [convert_listoflistings]],
4731 [431, [convert_use_amssymb]],
4733 [433, [convert_armenian]],
4741 [441, [convert_mdnomath]],
4746 [446, [convert_latexargs]],
4747 [447, [convert_IEEEtran, convert_AASTeX, convert_AGUTeX, convert_IJMP, convert_SIGPLAN, convert_SIGGRAPH, convert_EuropeCV, convert_Initials, convert_ModernCV]],
4748 [448, [convert_literate]],
4751 [451, [convert_beamerargs, convert_againframe_args, convert_corollary_args, convert_quote_args]],
4752 [452, [convert_beamerblocks]],
4753 [453, [convert_use_stmaryrd]],
4754 [454, [convert_overprint]],
4756 [456, [convert_epigraph]],
4757 [457, [convert_use_stackrel]],
4758 [458, [convert_captioninsets, convert_captionlayouts]],
4763 [463, [convert_encodings]],
4764 [464, [convert_use_cancel]],
4765 [465, [convert_lyxframes, remove_endframes]],
4771 [471, [convert_cite_engine_type_default]],
4774 [474, [convert_chunks, cleanup_beamerargs]],
4778 [473, [revert_chunks]],
4779 [472, [revert_tibetan]],
4780 [471, [revert_aa1,revert_aa2]],
4781 [470, [revert_cite_engine_type_default]],
4782 [469, [revert_forced_local_layout]],
4783 [468, [revert_starred_caption]],
4784 [467, [revert_mbox_fbox]],
4785 [466, [revert_iwona_fonts]],
4786 [465, [revert_powerdot_flexes, revert_powerdot_pause, revert_powerdot_itemargs, revert_powerdot_columns]],
4788 [463, [revert_use_cancel]],
4789 [462, [revert_encodings]],
4790 [461, [revert_new_libertines]],
4791 [460, [revert_kurier_fonts]],
4792 [459, [revert_IEEEtran_3]],
4793 [458, [revert_fragileframe, revert_newframes]],
4794 [457, [revert_captioninsets, revert_captionlayouts]],
4795 [456, [revert_use_stackrel]],
4796 [455, [revert_epigraph]],
4797 [454, [revert_frametitle]],
4798 [453, [revert_overprint]],
4799 [452, [revert_use_stmaryrd]],
4800 [451, [revert_beamerblocks]],
4801 [450, [revert_beamerargs, revert_beamerargs2, revert_beamerargs3, revert_beamerflex]],
4802 [449, [revert_garamondx, revert_garamondx_newtxmath]],
4803 [448, [revert_itemargs]],
4804 [447, [revert_literate]],
4805 [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]],
4806 [445, [revert_latexargs]],
4807 [444, [revert_uop]],
4808 [443, [revert_biolinum]],
4810 [441, [revert_newtxmath]],
4811 [440, [revert_mdnomath]],
4812 [439, [revert_mathfonts]],
4813 [438, [revert_minionpro]],
4814 [437, [revert_ipadeco, revert_ipachar]],
4815 [436, [revert_texgyre]],
4816 [435, [revert_mathdesign]],
4817 [434, [revert_txtt]],
4818 [433, [revert_libertine]],
4819 [432, [revert_armenian]],
4820 [431, [revert_languages, revert_ancientgreek]],
4821 [430, [revert_use_amssymb]],
4822 [429, [revert_listoflistings]],
4823 [428, [revert_table_rotation]],
4824 [427, [revert_cell_rotation]],
4825 [426, [revert_tipa]],
4826 [425, [revert_verbatim]],
4827 [424, [revert_cancel]],
4828 [423, [revert_cite_engine_type]],
4829 [422, [revert_use_mathtools]],
4830 [421, [revert_use_packages]],
4831 [420, [revert_longtable_captions]],
4832 [419, [revert_biblio_style]],
4833 [418, [revert_australian]],
4834 [417, [revert_justification]],
4835 [416, [revert_japanese_encodings]],
4836 [415, [revert_negative_space, revert_math_spaces]],
4837 [414, [revert_undertilde]],
4838 [413, [revert_visible_space]]
4842 if __name__ == "__main__":