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_containing_inset, 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 beginBrance != -1 and (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 # FIXME This version of the routine does not check for and pass over
223 # arguments before n. So it attempts to process the argument in the
224 # document, no matter what has been specified.
226 # The other branch does do that, but probably that code would be better
227 # in a single location: Skip all those arguments, then process the ones
229 end_ERT = find_end_of_inset(document.body, lineERT)
231 document.warning("Can't find end of ERT!!")
233 # Note that this only checks for [ or { at the beginning of a line
235 opening = find_token(document.body, "[", lineERT, end_ERT)
237 opening = find_token(document.body, "{", lineERT, end_ERT)
239 lineERT2 = find_token(document.body, "\\begin_inset ERT", end_ERT, end_layout)
241 # argument in a single ERT
242 # strip off the opening bracket
243 document.body[opening] = document.body[opening][1:]
244 ertcontlastline = end_ERT - 3
245 if (opt and document.body[ertcontlastline].endswith("]")) or document.body[ertcontlastline].endswith("}"):
246 # strip off the closing bracket
247 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
248 end2 = find_token(document.body, "\\end_inset", ertcontlastline)
249 document.body[lineERT : lineERT + 1] = ["\\begin_inset Argument " + str(n)]
251 end_ERT2 = find_end_of_inset(document.body, lineERT2)
253 document.warning("Can't find end of second ERT!!")
256 closing = find_token(document.body, "]", lineERT2, end_ERT2)
258 closing = find_token(document.body, "}", lineERT2, end_ERT2)
259 if closing != -1: # assure that the "}" is in this ERT
260 end2 = find_token(document.body, "\\end_inset", closing)
261 document.body[lineERT2 : end2 + 1] = ["\\end_layout", "", "\\end_inset"]
262 document.body[lineERT : end_ERT + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
265 document.warning("Unable to process argument!")
269 ###############################################################################
271 ### Conversion and reversion routines
273 ###############################################################################
275 def revert_visible_space(document):
276 "Revert InsetSpace visible into its ERT counterpart"
279 i = find_token(document.body, "\\begin_inset space \\textvisiblespace{}", i)
282 end = find_end_of_inset(document.body, i)
283 subst = put_cmd_in_ert("\\textvisiblespace{}")
284 document.body[i:end + 1] = subst
287 undertilde_commands = ["utilde"]
288 def convert_undertilde(document):
289 " Load undertilde automatically "
290 i = find_token(document.header, "\\use_mathdots" , 0)
292 i = find_token(document.header, "\\use_mhchem" , 0)
294 i = find_token(document.header, "\\use_esint" , 0)
296 document.warning("Malformed LyX document: Can't find \\use_mathdots.")
298 j = find_token(document.preamble, "\\usepackage{undertilde}", 0)
300 # package was loaded in the preamble, convert this to header setting for round trip
301 document.header.insert(i + 1, "\\use_undertilde 2") # on
302 del document.preamble[j]
306 j = find_token(document.body, '\\begin_inset Formula', j)
309 k = find_end_of_inset(document.body, j)
311 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(j))
314 code = "\n".join(document.body[j:k])
315 for c in undertilde_commands:
316 if code.find("\\%s" % c) != -1:
317 # at least one of the commands was found - need to switch package off
318 document.header.insert(i + 1, "\\use_undertilde 0") # off
321 # no command was found - set to auto (bug 9069)
322 document.header.insert(i + 1, "\\use_undertilde 1") # auto
326 def revert_undertilde(document):
327 " Load undertilde if used in the document "
328 regexp = re.compile(r'(\\use_undertilde)')
329 i = find_re(document.header, regexp, 0)
330 value = "1" # default is auto
332 value = get_value(document.header, "\\use_undertilde" , i).split()[0]
333 del document.header[i]
334 if value == "2": # on
335 add_to_preamble(document, ["\\usepackage{undertilde}"])
336 elif value == "1": # auto
339 i = find_token(document.body, '\\begin_inset Formula', i)
342 j = find_end_of_inset(document.body, i)
344 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
347 code = "\n".join(document.body[i:j])
348 for c in undertilde_commands:
349 if code.find("\\%s" % c) != -1:
350 add_to_preamble(document, ["\\usepackage{undertilde}"])
355 def revert_negative_space(document):
356 "Revert InsetSpace negmedspace and negthickspace into its TeX-code counterpart"
361 i = find_token(document.body, "\\begin_inset space \\negmedspace{}", i)
363 j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
365 # load amsmath in the preamble if not already loaded if we are at the end of checking
367 i = find_token(document.header, "\\use_amsmath 2", 0)
369 add_to_preamble(document, ["\\@ifundefined{negthickspace}{\\usepackage{amsmath}}"])
373 end = find_end_of_inset(document.body, i)
374 subst = put_cmd_in_ert("\\negmedspace{}")
375 document.body[i:end + 1] = subst
376 j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
379 end = find_end_of_inset(document.body, j)
380 subst = put_cmd_in_ert("\\negthickspace{}")
381 document.body[j:end + 1] = subst
385 def revert_math_spaces(document):
386 "Revert formulas with protected custom space and protected hfills to TeX-code"
389 i = find_token(document.body, "\\begin_inset Formula", i)
392 j = document.body[i].find("\\hspace*")
394 end = find_end_of_inset(document.body, i)
395 subst = put_cmd_in_ert(document.body[i][21:])
396 document.body[i:end + 1] = subst
400 def convert_japanese_encodings(document):
401 " Rename the japanese encodings to names understood by platex "
403 "EUC-JP-pLaTeX": "euc",
405 "SJIS-pLaTeX": "sjis"
407 i = find_token(document.header, "\\inputencoding" , 0)
410 val = get_value(document.header, "\\inputencoding", i)
411 if val in list(jap_enc_dict.keys()):
412 document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
415 def revert_japanese_encodings(document):
416 " Revert the japanese encodings name changes "
418 "euc": "EUC-JP-pLaTeX",
420 "sjis": "SJIS-pLaTeX"
422 i = find_token(document.header, "\\inputencoding" , 0)
425 val = get_value(document.header, "\\inputencoding", i)
426 if val in list(jap_enc_dict.keys()):
427 document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
430 def convert_justification(document):
431 " Add the \\justification buffer param"
432 i = find_token(document.header, "\\suppress_date" , 0)
434 i = find_token(document.header, "\\paperorientation" , 0)
436 i = find_token(document.header, "\\use_indices" , 0)
438 i = find_token(document.header, "\\use_bibtopic" , 0)
440 document.warning("Malformed LyX document: Missing \\suppress_date.")
442 document.header.insert(i + 1, "\\justification true")
445 def revert_justification(document):
446 " Revert the \\justification buffer param"
447 if not del_token(document.header, '\\justification', 0):
448 document.warning("Malformed LyX document: Missing \\justification.")
451 def revert_australian(document):
452 "Set English language variants Australian and Newzealand to English"
454 if document.language == "australian" or document.language == "newzealand":
455 document.language = "english"
456 i = find_token(document.header, "\\language", 0)
458 document.header[i] = "\\language english"
461 j = find_token(document.body, "\\lang australian", j)
463 j = find_token(document.body, "\\lang newzealand", 0)
467 document.body[j] = document.body[j].replace("\\lang newzealand", "\\lang english")
469 document.body[j] = document.body[j].replace("\\lang australian", "\\lang english")
473 def convert_biblio_style(document):
474 "Add a sensible default for \\biblio_style based on the citation engine."
475 i = find_token(document.header, "\\cite_engine", 0)
477 engine = get_value(document.header, "\\cite_engine", i).split("_")[0]
478 style = {"basic": "plain", "natbib": "plainnat", "jurabib": "jurabib"}
479 document.header.insert(i + 1, "\\biblio_style " + style[engine])
482 def revert_biblio_style(document):
483 "BibTeX insets with default option use the style defined by \\biblio_style."
484 i = find_token(document.header, "\\biblio_style" , 0)
486 document.warning("No \\biblio_style line. Nothing to do.")
489 default_style = get_value(document.header, "\\biblio_style", i)
490 del document.header[i]
492 # We are looking for bibtex insets having the default option
495 i = find_token(document.body, "\\begin_inset CommandInset bibtex", i)
498 j = find_end_of_inset(document.body, i)
500 document.warning("Malformed LyX document: Can't find end of bibtex inset at line " + str(i))
503 k = find_token(document.body, "options", i, j)
505 options = get_quoted_value(document.body, "options", k)
506 if "default" in options.split(","):
507 document.body[k] = 'options "%s"' \
508 % options.replace("default", default_style)
512 def handle_longtable_captions(document, forward):
515 begin_table = find_token(document.body, '<lyxtabular version=', begin_table)
516 if begin_table == -1:
518 end_table = find_end_of(document.body, begin_table, '<lyxtabular', '</lyxtabular>')
520 document.warning("Malformed LyX document: Could not find end of table.")
523 fline = find_token(document.body, "<features", begin_table, end_table)
525 document.warning("Can't find features for inset at line " + str(begin_table))
528 p = document.body[fline].find("islongtable")
533 numrows = get_option_value(document.body[begin_table], "rows")
535 numrows = int(numrows)
537 document.warning(document.body[begin_table])
538 document.warning("Unable to determine rows!")
539 begin_table = end_table
541 begin_row = begin_table
542 for row in range(numrows):
543 begin_row = find_token(document.body, '<row', begin_row, end_table)
545 document.warning("Can't find row " + str(row + 1))
547 end_row = find_end_of(document.body, begin_row, '<row', '</row>')
549 document.warning("Can't find end of row " + str(row + 1))
552 if (get_option_value(document.body[begin_row], 'caption') == 'true' and
553 get_option_value(document.body[begin_row], 'endfirsthead') != 'true' and
554 get_option_value(document.body[begin_row], 'endhead') != 'true' and
555 get_option_value(document.body[begin_row], 'endfoot') != 'true' and
556 get_option_value(document.body[begin_row], 'endlastfoot') != 'true'):
557 document.body[begin_row] = set_option_value(document.body[begin_row], 'caption', 'true", endfirsthead="true')
558 elif get_option_value(document.body[begin_row], 'caption') == 'true':
559 if get_option_value(document.body[begin_row], 'endfirsthead') == 'true':
560 document.body[begin_row] = set_option_value(document.body[begin_row], 'endfirsthead', 'false')
561 if get_option_value(document.body[begin_row], 'endhead') == 'true':
562 document.body[begin_row] = set_option_value(document.body[begin_row], 'endhead', 'false')
563 if get_option_value(document.body[begin_row], 'endfoot') == 'true':
564 document.body[begin_row] = set_option_value(document.body[begin_row], 'endfoot', 'false')
565 if get_option_value(document.body[begin_row], 'endlastfoot') == 'true':
566 document.body[begin_row] = set_option_value(document.body[begin_row], 'endlastfoot', 'false')
568 # since there could be a tabular inside this one, we
569 # cannot jump to end.
573 def convert_longtable_captions(document):
574 "Add a firsthead flag to caption rows"
575 handle_longtable_captions(document, True)
578 def revert_longtable_captions(document):
579 "remove head/foot flag from caption rows"
580 handle_longtable_captions(document, False)
583 def convert_use_packages(document):
584 "use_xxx yyy => use_package xxx yyy"
585 packages = ["amsmath", "esint", "mathdots", "mhchem", "undertilde"]
587 i = find_token(document.header, "\\use_%s" % p, 0)
589 value = get_value(document.header, "\\use_%s" % p, i)
590 document.header[i] = "\\use_package %s %s" % (p, value)
593 def revert_use_packages(document):
594 "use_package xxx yyy => use_xxx yyy"
595 packages = ["amsmath", "esint", "mhchem", "mathdots", "undertilde"]
596 # the order is arbitrary for the use_package version, and not all packages need to be given.
597 # Ensure a complete list and correct order (important for older LyX versions and especially lyx2lyx)
598 # first loop: find line with first package
601 regexp = re.compile(r'(\\use_package\s+%s)' % p)
602 i = find_re(document.header, regexp, 0)
603 if i != -1 and (j < 0 or i < j):
605 # second loop: replace or insert packages in front of all existing ones
607 regexp = re.compile(r'(\\use_package\s+%s)' % p)
608 i = find_re(document.header, regexp, 0)
610 value = get_value(document.header, "\\use_package %s" % p, i).split()[1]
611 del document.header[i]
612 document.header.insert(j, "\\use_%s %s" % (p, value))
614 document.header.insert(j, "\\use_%s 1" % p)
618 def convert_use_package(document, pkg, commands, oldauto):
619 # oldauto defines how the version we are converting from behaves:
620 # if it is true, the old version uses the package automatically.
621 # if it is false, the old version never uses the package.
622 i = find_token(document.header, "\\use_package", 0)
624 document.warning("Malformed LyX document: Can't find \\use_package.")
626 j = find_token(document.preamble, "\\usepackage{" + pkg + "}", 0)
628 # package was loaded in the preamble, convert this to header setting for round trip
629 document.header.insert(i + 1, "\\use_package " + pkg + " 2") # on
630 del document.preamble[j]
631 # If oldauto is true we have two options:
632 # We can either set the package to auto - this is correct for files in
633 # format 425 to 463, and may create a conflict for older files which use
634 # any command in commands with a different definition.
635 # Or we can look whether any command in commands is used, and set it to
636 # auto if not and to off if yes. This will not create a conflict, but will
637 # create uncompilable documents for files in format 425 to 463, which use
638 # any command in commands.
639 # We choose the first option since its error is less likely.
641 document.header.insert(i + 1, "\\use_package " + pkg + " 1") # auto
645 j = find_token(document.body, '\\begin_inset Formula', j)
648 k = find_end_of_inset(document.body, j)
650 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(j))
653 code = "\n".join(document.body[j:k])
655 if code.find("\\%s" % c) != -1:
656 # at least one of the commands was found - need to switch package off
657 document.header.insert(i + 1, "\\use_package " + pkg + " 0") # off
660 # no command was found - set to auto (bug 9069)
661 document.header.insert(i + 1, "\\use_package " + pkg + " 1") # auto
664 def revert_use_package(document, pkg, commands, oldauto):
665 # oldauto defines how the version we are reverting to behaves:
666 # if it is true, the old version uses the package automatically.
667 # if it is false, the old version never uses the package.
668 regexp = re.compile(r'(\\use_package\s+%s)' % pkg)
669 i = find_re(document.header, regexp, 0)
670 value = "1" # default is auto
672 value = get_value(document.header, "\\use_package" , i).split()[1]
673 del document.header[i]
674 if value == "2": # on
675 add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
676 elif value == "1" and not oldauto: # auto
679 i = find_token(document.body, '\\begin_inset Formula', i)
682 j = find_end_of_inset(document.body, i)
684 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
687 code = "\n".join(document.body[i:j])
689 if code.find("\\%s" % c) != -1:
690 add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
695 mathtools_commands = ["mathclap", "mathllap", "mathrlap", \
696 "lgathered", "rgathered", "vcentcolon", "dblcolon", \
697 "coloneqq", "Coloneqq", "coloneq", "Coloneq", "eqqcolon", \
698 "Eqqcolon", "eqcolon", "Eqcolon", "colonapprox", \
699 "Colonapprox", "colonsim", "Colonsim"]
700 def convert_use_mathtools(document):
701 "insert use_package mathtools"
702 convert_use_package(document, "mathtools", mathtools_commands, False)
705 def revert_use_mathtools(document):
706 "remove use_package mathtools"
707 revert_use_package(document, "mathtools", mathtools_commands, False)
710 # commands provided by stmaryrd.sty but LyX uses other packages:
711 # boxdot lightning, bigtriangledown, bigtriangleup
712 stmaryrd_commands = ["shortleftarrow", "shortrightarrow", "shortuparrow", \
713 "shortdownarrow", "Yup", "Ydown", "Yleft", "Yright", \
714 "varcurlyvee", "varcurlywedge", "minuso", "baro", \
715 "sslash", "bbslash", "moo", "varotimes", "varoast", \
716 "varobar", "varodot", "varoslash", "varobslash", \
717 "varocircle", "varoplus", "varominus", "boxast", \
718 "boxbar", "boxslash", "boxbslash", "boxcircle", \
719 "boxbox", "boxempty", "merge", "vartimes", \
720 "fatsemi", "sswarrow", "ssearrow", "curlywedgeuparrow", \
721 "curlywedgedownarrow", "fatslash", "fatbslash", "lbag", \
722 "rbag", "varbigcirc", "leftrightarroweq", \
723 "curlyveedownarrow", "curlyveeuparrow", "nnwarrow", \
724 "nnearrow", "leftslice", "rightslice", "varolessthan", \
725 "varogreaterthan", "varovee", "varowedge", "talloblong", \
726 "interleave", "obar", "obslash", "olessthan", \
727 "ogreaterthan", "ovee", "owedge", "oblong", "inplus", \
728 "niplus", "nplus", "subsetplus", "supsetplus", \
729 "subsetpluseq", "supsetpluseq", "Lbag", "Rbag", \
730 "llbracket", "rrbracket", "llparenthesis", \
731 "rrparenthesis", "binampersand", "bindnasrepma", \
732 "trianglelefteqslant", "trianglerighteqslant", \
733 "ntrianglelefteqslant", "ntrianglerighteqslant", \
734 "llfloor", "rrfloor", "llceil", "rrceil", "arrownot", \
735 "Arrownot", "Mapstochar", "mapsfromchar", "Mapsfromchar", \
736 "leftrightarrowtriangle", "leftarrowtriangle", \
737 "rightarrowtriangle", \
738 "bigcurlyvee", "bigcurlywedge", "bigsqcap", "bigbox", \
739 "bigparallel", "biginterleave", "bignplus", \
740 "varcopyright", "longarrownot", "Longarrownot", \
741 "Mapsto", "mapsfrom", "Mapsfrom" "Longmapsto", \
742 "longmapsfrom", "Longmapsfrom"]
743 def convert_use_stmaryrd(document):
744 "insert use_package stmaryrd"
745 convert_use_package(document, "stmaryrd", stmaryrd_commands, False)
748 def revert_use_stmaryrd(document):
749 "remove use_package stmaryrd"
750 revert_use_package(document, "stmaryrd", stmaryrd_commands, False)
753 stackrel_commands = ["stackrel"]
754 def convert_use_stackrel(document):
755 "insert use_package stackrel"
756 convert_use_package(document, "stackrel", stackrel_commands, False)
759 def revert_use_stackrel(document):
760 "remove use_package stackrel"
761 revert_use_package(document, "stackrel", stackrel_commands, False)
764 def convert_cite_engine_type(document):
765 "Determine the \\cite_engine_type from the citation engine."
766 i = find_token(document.header, "\\cite_engine", 0)
769 engine = get_value(document.header, "\\cite_engine", i)
771 engine, type = engine.split("_")
773 type = {"basic": "numerical", "jurabib": "authoryear"}[engine]
774 document.header[i] = "\\cite_engine " + engine
775 document.header.insert(i + 1, "\\cite_engine_type " + type)
778 def revert_cite_engine_type(document):
779 "Natbib had the type appended with an underscore."
780 engine_type = "numerical"
781 i = find_token(document.header, "\\cite_engine_type" , 0)
783 document.warning("No \\cite_engine_type line. Assuming numerical.")
785 engine_type = get_value(document.header, "\\cite_engine_type", i)
786 del document.header[i]
788 # We are looking for the natbib citation engine
789 i = find_token(document.header, "\\cite_engine natbib", 0)
792 document.header[i] = "\\cite_engine natbib_" + engine_type
795 def convert_cite_engine_type_default(document):
796 "Convert \\cite_engine_type to default for the basic citation engine."
797 i = find_token(document.header, "\\cite_engine basic", 0)
800 i = find_token(document.header, "\\cite_engine_type" , 0)
803 document.header[i] = "\\cite_engine_type default"
806 def revert_cite_engine_type_default(document):
807 """Revert \\cite_engine_type default.
809 Revert to numerical for the basic cite engine, otherwise to authoryear."""
810 engine_type = "authoryear"
811 i = find_token(document.header, "\\cite_engine_type default" , 0)
814 j = find_token(document.header, "\\cite_engine basic", 0)
816 engine_type = "numerical"
817 document.header[i] = "\\cite_engine_type " + engine_type
820 cancel_commands = ["cancel", "bcancel", "xcancel", "cancelto"]
821 # this is the same, as revert_use_cancel() except for the default
822 def revert_cancel(document):
823 "add cancel to the preamble if necessary"
824 revert_use_package(document, "cancel", cancel_commands, False)
827 def revert_verbatim(document, starred = False):
828 " Revert verbatim environments completely to TeX-code. "
832 layout_name = "Verbatim"
833 latex_name = "verbatim"
835 layout_name = "Verbatim*"
836 latex_name = "verbatim*"
838 subst_end = ['\\end_layout', '', '\\begin_layout Plain Layout',
840 '\\begin_layout Plain Layout', '', '',
842 'end{%s}' % (latex_name),
843 '\\end_layout', '', '\\end_inset',
844 '', '', '\\end_layout']
845 subst_begin = ['\\begin_layout Standard', '\\noindent',
846 '\\begin_inset ERT', 'status open', '',
847 '\\begin_layout Plain Layout', '', '', '\\backslash',
848 'begin{%s}' % (latex_name),
849 '\\end_layout', '', '\\begin_layout Plain Layout', '']
852 i = find_token(document.body, "\\begin_layout %s" % (layout_name), i)
855 j = find_end_of_layout(document.body, i)
857 document.warning("Malformed LyX document: Can't find end of %s layout" \
861 # delete all line breaks insets (there are no other insets)
864 n = find_token(document.body, "\\begin_inset Newline newline", l, j)
866 n = find_token(document.body, "\\begin_inset Newline linebreak", l, j)
869 m = find_end_of_inset(document.body, n)
870 del(document.body[m:m+1])
871 document.body[n:n+1] = ['\\end_layout', '', '\\begin_layout Plain Layout']
873 # we deleted a line, so the end of the inset moved forward.
874 # FIXME But we also added some lines, didn't we? I think this
877 # consecutive verbatim environments need to be connected
878 k = find_token(document.body, "\\begin_layout %s" % (layout_name), j)
879 if k == j + 2 and consecutive == False:
881 document.body[j:j+1] = ['\\end_layout', '', '\\begin_layout Plain Layout']
882 document.body[i:i+1] = subst_begin
884 if k == j + 2 and consecutive == True:
885 document.body[j:j+1] = ['\\end_layout', '', '\\begin_layout Plain Layout']
886 del(document.body[i:i+1])
888 if k != j + 2 and consecutive == True:
889 document.body[j:j+1] = subst_end
890 # the next paragraph must not be indented
891 # FIXME This seems to be causing problems, because of the
892 # hardcoded use of 19. We should figure out exactly where
893 # this needs to go by searching for the right tag.
894 document.body[j+19:j+19] = ['\\noindent']
895 del(document.body[i:i+1])
899 document.body[j:j+1] = subst_end
900 # the next paragraph must not be indented
901 # FIXME This seems to be causing problems, because of the
902 # hardcoded use of 19. We should figure out exactly where
903 # this needs to go by searching for the right tag.
904 document.body[j+19:j+19] = ['\\noindent']
905 document.body[i:i+1] = subst_begin
908 def revert_tipa(document):
909 " Revert native TIPA insets to mathed or ERT. "
912 i = find_token(document.body, "\\begin_inset IPA", i)
915 j = find_end_of_inset(document.body, i)
917 document.warning("Malformed LyX document: Can't find end of IPA inset")
921 n = find_token(document.body, "\\begin_layout", i, j)
923 document.warning("Malformed LyX document: IPA inset has no embedded layout")
926 m = find_end_of_layout(document.body, n)
928 document.warning("Malformed LyX document: Can't find end of embedded layout")
931 content = document.body[n+1:m]
932 p = find_token(document.body, "\\begin_layout", m, j)
933 if p != -1 or len(content) > 1:
935 content = document.body[i+1:j]
937 # IPA insets with multiple pars need to be wrapped by \begin{IPA}...\end{IPA}
938 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}")
939 add_to_preamble(document, ["\\usepackage{tipa,tipx}"])
941 # single-par IPA insets can be reverted to mathed
942 document.body[i:j+1] = ["\\begin_inset Formula $\\text{\\textipa{" + content[0] + "}}$", "\\end_inset"]
946 def revert_cell_rotation(document):
947 "Revert cell rotations to TeX-code"
949 load_rotating = False
953 # first, let's find out if we need to do anything
954 i = find_token(document.body, '<cell ', i)
957 j = document.body[i].find('rotate="')
959 k = document.body[i].find('"', j + 8)
960 value = document.body[i][j + 8 : k]
962 rgx = re.compile(r' rotate="[^"]+?"')
963 # remove rotate option
964 document.body[i] = rgx.sub('', document.body[i])
966 rgx = re.compile(r' rotate="[^"]+?"')
967 document.body[i] = rgx.sub(' rotate="true"', document.body[i])
969 rgx = re.compile(r' rotate="[^"]+?"')
971 # remove rotate option
972 document.body[i] = rgx.sub('', document.body[i])
974 document.body[i + 5 : i + 5] = \
975 put_cmd_in_ert("\\end{turn}")
976 document.body[i + 4 : i + 4] = \
977 put_cmd_in_ert("\\begin{turn}{" + value + "}")
983 add_to_preamble(document, ["\\@ifundefined{turnbox}{\\usepackage{rotating}}{}"])
986 def convert_cell_rotation(document):
987 'Convert cell rotation statements from "true" to "90"'
991 # first, let's find out if we need to do anything
992 i = find_token(document.body, '<cell ', i)
995 j = document.body[i].find('rotate="true"')
997 rgx = re.compile(r'rotate="[^"]+?"')
998 # convert "true" to "90"
999 document.body[i] = rgx.sub('rotate="90"', document.body[i])
1004 def revert_table_rotation(document):
1005 "Revert table rotations to TeX-code"
1007 load_rotating = False
1011 # first, let's find out if we need to do anything
1012 i = find_token(document.body, '<features ', i)
1015 j = document.body[i].find('rotate="')
1017 end_table = find_token(document.body, '</lyxtabular>', j)
1018 k = document.body[i].find('"', j + 8)
1019 value = document.body[i][j + 8 : k]
1021 rgx = re.compile(r' rotate="[^"]+?"')
1022 # remove rotate option
1023 document.body[i] = rgx.sub('', document.body[i])
1025 rgx = re.compile(r'rotate="[^"]+?"')
1026 document.body[i] = rgx.sub('rotate="true"', document.body[i])
1028 rgx = re.compile(r' rotate="[^"]+?"')
1029 load_rotating = True
1030 # remove rotate option
1031 document.body[i] = rgx.sub('', document.body[i])
1033 document.body[end_table + 3 : end_table + 3] = \
1034 put_cmd_in_ert("\\end{turn}")
1035 document.body[i - 2 : i - 2] = \
1036 put_cmd_in_ert("\\begin{turn}{" + value + "}")
1042 add_to_preamble(document, ["\\@ifundefined{turnbox}{\\usepackage{rotating}}{}"])
1045 def convert_table_rotation(document):
1046 'Convert table rotation statements from "true" to "90"'
1050 # first, let's find out if we need to do anything
1051 i = find_token(document.body, '<features ', i)
1054 j = document.body[i].find('rotate="true"')
1056 rgx = re.compile(r'rotate="[^"]+?"')
1057 # convert "true" to "90"
1058 document.body[i] = rgx.sub('rotate="90"', document.body[i])
1063 def convert_listoflistings(document):
1064 'Convert ERT \lstlistoflistings to TOC lstlistoflistings inset'
1065 # We can support roundtrip because the command is so simple
1068 i = find_token(document.body, "\\begin_inset ERT", i)
1071 j = find_end_of_inset(document.body, i)
1073 document.warning("Malformed LyX document: Can't find end of ERT inset")
1076 ert = get_ert(document.body, i)
1077 if ert == "\\lstlistoflistings{}":
1078 document.body[i:j] = ["\\begin_inset CommandInset toc", "LatexCommand lstlistoflistings", ""]
1084 def revert_listoflistings(document):
1085 'Convert TOC lstlistoflistings inset to ERT lstlistoflistings'
1088 i = find_token(document.body, "\\begin_inset CommandInset toc", i)
1091 if document.body[i+1] == "LatexCommand lstlistoflistings":
1092 j = find_end_of_inset(document.body, i)
1094 document.warning("Malformed LyX document: Can't find end of TOC inset")
1097 subst = put_cmd_in_ert("\\lstlistoflistings{}")
1098 document.body[i:j+1] = subst
1099 add_to_preamble(document, ["\\usepackage{listings}"])
1103 def convert_use_amssymb(document):
1104 "insert use_package amssymb"
1105 regexp = re.compile(r'(\\use_package\s+amsmath)')
1106 i = find_re(document.header, regexp, 0)
1108 document.warning("Malformed LyX document: Can't find \\use_package amsmath.")
1110 value = get_value(document.header, "\\use_package" , i).split()[1]
1113 useamsmath = int(value)
1115 document.warning("Invalid \\use_package amsmath: " + value + ". Assuming auto.")
1117 j = find_token(document.preamble, "\\usepackage{amssymb}", 0)
1119 document.header.insert(i + 1, "\\use_package amssymb %d" % useamsmath)
1121 document.header.insert(i + 1, "\\use_package amssymb 2")
1122 del document.preamble[j]
1125 def revert_use_amssymb(document):
1126 "remove use_package amssymb"
1127 regexp1 = re.compile(r'(\\use_package\s+amsmath)')
1128 regexp2 = re.compile(r'(\\use_package\s+amssymb)')
1129 i = find_re(document.header, regexp1, 0)
1130 j = find_re(document.header, regexp2, 0)
1131 value1 = "1" # default is auto
1132 value2 = "1" # default is auto
1134 value1 = get_value(document.header, "\\use_package" , i).split()[1]
1136 value2 = get_value(document.header, "\\use_package" , j).split()[1]
1137 del document.header[j]
1138 if value1 != value2 and value2 == "2": # on
1139 add_to_preamble(document, ["\\usepackage{amssymb}"])
1142 def convert_use_cancel(document):
1143 "insert use_package cancel"
1144 convert_use_package(document, "cancel", cancel_commands, True)
1147 def revert_use_cancel(document):
1148 "remove use_package cancel"
1149 revert_use_package(document, "cancel", cancel_commands, True)
1152 def revert_ancientgreek(document):
1153 "Set the document language for ancientgreek to greek"
1155 if document.language == "ancientgreek":
1156 document.language = "greek"
1157 i = find_token(document.header, "\\language", 0)
1159 document.header[i] = "\\language greek"
1162 j = find_token(document.body, "\\lang ancientgreek", j)
1166 document.body[j] = document.body[j].replace("\\lang ancientgreek", "\\lang greek")
1170 def revert_languages(document):
1171 "Set the document language for new supported languages to English"
1174 "coptic", "divehi", "hindi", "kurmanji", "lao", "marathi", "occitan", "sanskrit",
1175 "syriac", "tamil", "telugu", "urdu"
1177 for n in range(len(languages)):
1178 if document.language == languages[n]:
1179 document.language = "english"
1180 i = find_token(document.header, "\\language", 0)
1182 document.header[i] = "\\language english"
1184 while j < len(document.body):
1185 j = find_token(document.body, "\\lang " + languages[n], j)
1187 document.body[j] = document.body[j].replace("\\lang " + languages[n], "\\lang english")
1190 j = len(document.body)
1193 def convert_armenian(document):
1194 "Use polyglossia and thus non-TeX fonts for Armenian"
1196 if document.language == "armenian":
1197 i = find_token(document.header, "\\use_non_tex_fonts", 0)
1199 document.header[i] = "\\use_non_tex_fonts true"
1202 def revert_armenian(document):
1203 "Use ArmTeX and thus TeX fonts for Armenian"
1205 if document.language == "armenian":
1206 i = find_token(document.header, "\\use_non_tex_fonts", 0)
1208 document.header[i] = "\\use_non_tex_fonts false"
1211 def revert_libertine(document):
1212 " Revert native libertine font definition to LaTeX "
1214 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1215 i = find_token(document.header, "\\font_roman libertine", 0)
1218 j = find_token(document.header, "\\font_osf true", 0)
1221 preamble = "\\usepackage"
1223 document.header[j] = "\\font_osf false"
1226 preamble += "[lining]"
1227 preamble += "{libertine-type1}"
1228 add_to_preamble(document, [preamble])
1229 document.header[i] = "\\font_roman default"
1232 def revert_txtt(document):
1233 " Revert native txtt font definition to LaTeX "
1235 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1236 i = find_token(document.header, "\\font_typewriter txtt", 0)
1238 preamble = "\\renewcommand{\\ttdefault}{txtt}"
1239 add_to_preamble(document, [preamble])
1240 document.header[i] = "\\font_typewriter default"
1243 def revert_mathdesign(document):
1244 " Revert native mathdesign font definition to LaTeX "
1246 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1252 i = find_token(document.header, "\\font_roman", 0)
1255 val = get_value(document.header, "\\font_roman", i)
1256 if val in list(mathdesign_dict.keys()):
1257 preamble = "\\usepackage[%s" % mathdesign_dict[val]
1259 j = find_token(document.header, "\\font_osf true", 0)
1262 document.header[j] = "\\font_osf false"
1263 l = find_token(document.header, "\\font_sc true", 0)
1266 document.header[l] = "\\font_sc false"
1268 preamble += ",expert"
1269 preamble += "]{mathdesign}"
1270 add_to_preamble(document, [preamble])
1271 document.header[i] = "\\font_roman default"
1274 def revert_texgyre(document):
1275 " Revert native TeXGyre font definition to LaTeX "
1277 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1278 texgyre_fonts = ["tgadventor", "tgbonum", "tgchorus", "tgcursor", \
1279 "tgheros", "tgpagella", "tgschola", "tgtermes"]
1280 i = find_token(document.header, "\\font_roman", 0)
1282 val = get_value(document.header, "\\font_roman", i)
1283 if val in texgyre_fonts:
1284 preamble = "\\usepackage{%s}" % val
1285 add_to_preamble(document, [preamble])
1286 document.header[i] = "\\font_roman default"
1287 i = find_token(document.header, "\\font_sans", 0)
1289 val = get_value(document.header, "\\font_sans", i)
1290 if val in texgyre_fonts:
1291 preamble = "\\usepackage{%s}" % val
1292 add_to_preamble(document, [preamble])
1293 document.header[i] = "\\font_sans default"
1294 i = find_token(document.header, "\\font_typewriter", 0)
1296 val = get_value(document.header, "\\font_typewriter", i)
1297 if val in texgyre_fonts:
1298 preamble = "\\usepackage{%s}" % val
1299 add_to_preamble(document, [preamble])
1300 document.header[i] = "\\font_typewriter default"
1303 def revert_ipadeco(document):
1304 " Revert IPA decorations to ERT "
1307 i = find_token(document.body, "\\begin_inset IPADeco", i)
1310 end = find_end_of_inset(document.body, i)
1312 document.warning("Can't find end of inset at line " + str(i))
1315 line = document.body[i]
1316 rx = re.compile(r'\\begin_inset IPADeco (.*)$')
1318 decotype = m.group(1)
1319 if decotype != "toptiebar" and decotype != "bottomtiebar":
1320 document.warning("Invalid IPADeco type: " + decotype)
1323 blay = find_token(document.body, "\\begin_layout Plain Layout", i, end)
1325 document.warning("Can't find layout for inset at line " + str(i))
1328 bend = find_end_of_layout(document.body, blay)
1330 document.warning("Malformed LyX document: Could not find end of IPADeco inset's layout.")
1333 substi = ["\\begin_inset ERT", "status collapsed", "",
1334 "\\begin_layout Plain Layout", "", "", "\\backslash",
1335 decotype + "{", "\\end_layout", "", "\\end_inset"]
1336 substj = ["\\size default", "", "\\begin_inset ERT", "status collapsed", "",
1337 "\\begin_layout Plain Layout", "", "}", "\\end_layout", "", "\\end_inset"]
1338 # do the later one first so as not to mess up the numbering
1339 document.body[bend:end + 1] = substj
1340 document.body[i:blay + 1] = substi
1341 i = end + len(substi) + len(substj) - (end - bend) - (blay - i) - 2
1342 add_to_preamble(document, "\\usepackage{tipa}")
1345 def revert_ipachar(document):
1346 ' Revert \\IPAChar to ERT '
1349 while i < len(document.body):
1350 m = re.match(r'(.*)\\IPAChar \\(\w+\{\w+\})(.*)', document.body[i])
1354 ipachar = m.group(2)
1357 '\\begin_inset ERT',
1358 'status collapsed', '',
1359 '\\begin_layout Standard',
1360 '', '', '\\backslash',
1365 document.body[i: i+1] = subst
1370 add_to_preamble(document, "\\usepackage{tone}")
1373 def revert_minionpro(document):
1374 " Revert native MinionPro font definition to LaTeX "
1376 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1377 i = find_token(document.header, "\\font_roman minionpro", 0)
1380 j = find_token(document.header, "\\font_osf true", 0)
1383 preamble = "\\usepackage"
1385 document.header[j] = "\\font_osf false"
1388 preamble += "{MinionPro}"
1389 add_to_preamble(document, [preamble])
1390 document.header[i] = "\\font_roman default"
1393 def revert_mathfonts(document):
1394 " Revert native math font definitions to LaTeX "
1396 i = find_token(document.header, "\\font_math", 0)
1399 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1400 val = get_value(document.header, "\\font_math", i)
1401 if val == "eulervm":
1402 add_to_preamble(document, "\\usepackage{eulervm}")
1403 elif val == "default":
1405 "lmodern": "\\renewcommand{\\rmdefault}{lmr}",
1406 "minionpro": "\\usepackage[onlytext,lf]{MinionPro}",
1407 "minionpro-osf": "\\usepackage[onlytext]{MinionPro}",
1408 "palatino": "\\renewcommand{\\rmdefault}{ppl}",
1409 "palatino-osf": "\\renewcommand{\\rmdefault}{pplj}",
1410 "times": "\\renewcommand{\\rmdefault}{ptm}",
1411 "utopia": "\\renewcommand{\\rmdefault}{futs}",
1412 "utopia-osf": "\\renewcommand{\\rmdefault}{futj}",
1414 j = find_token(document.header, "\\font_roman", 0)
1416 rm = get_value(document.header, "\\font_roman", j)
1417 k = find_token(document.header, "\\font_osf true", 0)
1420 if rm in list(mathfont_dict.keys()):
1421 add_to_preamble(document, mathfont_dict[rm])
1422 document.header[j] = "\\font_roman default"
1424 document.header[k] = "\\font_osf false"
1425 del document.header[i]
1428 def revert_mdnomath(document):
1429 " Revert mathdesign and fourier without math "
1431 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1433 "md-charter": "mdbch",
1434 "md-utopia": "mdput",
1435 "md-garamond": "mdugm"
1437 i = find_token(document.header, "\\font_roman", 0)
1440 val = get_value(document.header, "\\font_roman", i)
1441 if val in list(mathdesign_dict.keys()):
1442 j = find_token(document.header, "\\font_math", 0)
1444 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1445 mval = get_value(document.header, "\\font_math", j)
1446 if mval == "default":
1447 document.header[i] = "\\font_roman default"
1448 add_to_preamble(document, "\\renewcommand{\\rmdefault}{%s}" % mathdesign_dict[val])
1450 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1453 def convert_mathfonts(document):
1454 document.header.insert(-1, "\\font_math auto")
1457 def convert_mdnomath(document):
1458 " Change mathdesign font name "
1460 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1462 "mdbch": "md-charter",
1463 "mdput": "md-utopia",
1464 "mdugm": "md-garamond"
1466 i = find_token(document.header, "\\font_roman", 0)
1469 val = get_value(document.header, "\\font_roman", i)
1470 if val in list(mathdesign_dict.keys()):
1471 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1474 def revert_newtxmath(document):
1475 " Revert native newtxmath definitions to LaTeX "
1477 i = find_token(document.header, "\\font_math", 0)
1480 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1481 val = get_value(document.header, "\\font_math", i)
1483 "libertine-ntxm": "\\usepackage[libertine]{newtxmath}",
1484 "minion-ntxm": "\\usepackage[minion]{newtxmath}",
1485 "newtxmath": "\\usepackage{newtxmath}",
1487 if val in list(mathfont_dict.keys()):
1488 add_to_preamble(document, mathfont_dict[val])
1489 document.header[i] = "\\font_math auto"
1492 def revert_biolinum(document):
1493 " Revert native biolinum font definition to LaTeX "
1495 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1496 i = find_token(document.header, "\\font_sans biolinum", 0)
1499 j = find_token(document.header, "\\font_osf true", 0)
1502 preamble = "\\usepackage"
1505 preamble += "{biolinum-type1}"
1506 add_to_preamble(document, [preamble])
1507 document.header[i] = "\\font_sans default"
1510 def revert_uop(document):
1511 " Revert native URW Classico (Optima) font definition to LaTeX "
1513 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1514 i = find_token(document.header, "\\font_sans uop", 0)
1516 preamble = "\\renewcommand{\\sfdefault}{uop}"
1517 add_to_preamble(document, [preamble])
1518 document.header[i] = "\\font_sans default"
1521 def convert_latexargs(document):
1522 " Convert InsetArgument to new syntax "
1524 if find_token(document.body, "\\begin_inset Argument", 0) == -1:
1528 # A list of layouts (document classes) with only optional or no arguments.
1529 # These can be safely converted to the new syntax
1530 # (I took the liberty to add some of my personal layouts/modules here; JSP)
1531 safe_layouts = ["aa", "aapaper", "aastex", "achemso", "acmsiggraph", "AEA",
1532 "agu-dtd", "agums", "agutex", "amsart", "amsbook", "apa",
1533 "arab-article", "armenian-article", "article-beamer", "article",
1534 "beamer", "book", "broadway", "chess", "cl2emult", "ctex-article",
1535 "ctex-book", "ctex-report", "dinbrief", "docbook-book", "docbook-chapter",
1536 "docbook", "docbook-section", "doublecol-new", "dtk", "ectaart", "egs",
1537 "elsarticle", "elsart", "entcs", "europecv", "extarticle", "extbook",
1538 "extletter", "extreport", "foils", "frletter", "g-brief2", "g-brief",
1539 "heb-article", "heb-letter", "hollywood", "IEEEtran", "ijmpc", "ijmpd",
1540 "iopart", "isprs", "jarticle", "jasatex", "jbook", "jgrga", "jreport",
1541 "jsarticle", "jsbeamer", "jsbook", "jss", "kluwer", "latex8", "letter", "lettre",
1542 "literate-article", "literate-book", "literate-report", "llncs", "ltugboat",
1543 "memoir", "moderncv", "mwart", "mwbk", "mwrep", "paper", "powerdot",
1544 "recipebook", "report", "revtex4", "revtex", "scrartcl", "scrarticle-beamer",
1545 "scrbook", "scrlettr", "scrlttr2", "scrreprt", "seminar", "siamltex",
1546 "sigplanconf", "simplecv", "singlecol", "singlecol-new", "slides", "spie",
1547 "svglobal3", "svglobal", "svjog", "svmono", "svmult", "svprobth", "tarticle",
1548 "tbook", "treport", "tufte-book", "tufte-handout"]
1549 # A list of "safe" modules, same as above
1550 safe_modules = ["biblatex", "beameraddons", "beamer-resenumerate", "beamersession", "braille",
1551 "customHeadersFooters", "endnotes", "enumitem", "eqs-within-sections", "figs-within-sections",
1552 "fix-cm", "fixltx2e", "foottoend", "hanging", "jscharstyles", "knitr", "lilypond",
1553 "linguistics", "linguisticx", "logicalmkup", "minimalistic", "nomindex", "noweb",
1554 "pdfcomment", "sweave", "tabs-within-sections", "theorems-ams-bytype",
1555 "theorems-ams-extended-bytype", "theorems-ams-extended", "theorems-ams", "theorems-bytype",
1556 "theorems-chap-bytype", "theorems-chap", "theorems-named", "theorems-sec-bytype",
1557 "theorems-sec", "theorems-starred", "theorems-std", "todonotes"]
1558 # Modules we need to take care of
1559 caveat_modules = ["initials"]
1560 # information about the relevant styles in caveat_modules (number of opt and req args)
1561 # use this if we get more caveat_modules. For now, use hard coding (see below).
1562 # initials = [{'Layout' : 'Initial', 'opt' : 1, 'req' : 1}]
1564 # Is this a known safe layout?
1565 safe_layout = document.textclass in safe_layouts
1567 document.warning("Lyx2lyx knows nothing about textclass '%s'. "
1568 "Please check if short title insets have been converted correctly."
1569 % document.textclass)
1570 # Do we use unsafe or unknown modules
1571 mods = document.get_module_list()
1572 unknown_modules = False
1573 used_caveat_modules = list()
1575 if mod in safe_modules:
1577 if mod in caveat_modules:
1578 used_caveat_modules.append(mod)
1580 unknown_modules = True
1581 document.warning("Lyx2lyx knows nothing about module '%s'. "
1582 "Please check if short title insets have been converted correctly."
1587 i = find_token(document.body, "\\begin_inset Argument", i)
1591 if not safe_layout or unknown_modules:
1592 # We cannot do more here since we have no access to this layout.
1593 # InsetArgument itself will do the real work
1594 # (see InsetArgument::updateBuffer())
1595 document.body[i] = "\\begin_inset Argument 999"
1599 # Find containing paragraph layout
1600 parent = get_containing_layout(document.body, i)
1602 document.warning("Malformed LyX document: Can't find parent paragraph layout")
1609 if len(used_caveat_modules) > 0:
1610 # We know for now that this must be the initials module with the Initial layout
1611 # If we get more such modules, we need some automating.
1612 if parent[0] == "Initial":
1613 # Layout has 1 opt and 1 req arg.
1614 # Count the actual arguments
1616 for p in range(parbeg, parend):
1617 if document.body[p] == "\\begin_inset Argument":
1622 # Collect all arguments in this paragraph
1624 for p in range(parbeg, parend):
1625 if document.body[p] == "\\begin_inset Argument":
1627 if allowed_opts != -1:
1628 # We have less arguments than opt + required.
1629 # required must take precedence.
1630 if argnr > allowed_opts and argnr < first_req:
1632 document.body[p] = "\\begin_inset Argument %d" % argnr
1636 def revert_latexargs(document):
1637 " Revert InsetArgument to old syntax "
1640 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
1643 # Search for Argument insets
1644 i = find_token(document.body, "\\begin_inset Argument", i)
1647 m = rx.match(document.body[i])
1649 # No ID: inset already reverted
1652 # Find containing paragraph layout
1653 parent = get_containing_layout(document.body, i)
1655 document.warning("Malformed LyX document: Can't find parent paragraph layout")
1660 # Do not set realparbeg to parent[3], since this does not work if we
1661 # have another inset (e.g. label or index) before the first argument
1662 # inset (this is the case in the user guide of LyX 2.0.8)
1664 # Collect all arguments in this paragraph
1666 for p in range(parbeg, parend):
1667 m = rx.match(document.body[p])
1670 # This is the first argument inset
1672 val = int(m.group(1))
1673 j = find_end_of_inset(document.body, p)
1674 # Revert to old syntax
1675 document.body[p] = "\\begin_inset Argument"
1677 document.warning("Malformed LyX document: Can't find end of Argument inset")
1680 args[val] = document.body[p : j + 1]
1682 realparend = realparend - len(document.body[p : j + 1])
1683 # Remove arg inset at this position
1684 del document.body[p : j + 1]
1688 # No argument inset found
1689 realparbeg = parent[3]
1690 # Now sort the arg insets
1692 for f in sorted(args):
1695 # Insert the sorted arg insets at paragraph begin
1696 document.body[realparbeg : realparbeg] = subst
1698 i = realparbeg + 1 + len(subst)
1701 def revert_IEEEtran(document):
1703 Reverts InsetArgument of
1706 Biography without photo
1709 if document.textclass != "IEEEtran":
1712 layouts = {"Page headings": False,
1713 "Biography without photo": True}
1715 for layout in list(layouts.keys()):
1718 i = find_token(document.body, '\\begin_layout ' + layout, i)
1721 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, layouts[layout], False)
1726 i = find_token(document.body, '\\begin_inset Flex Paragraph Start', i)
1729 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1734 i = find_token_exact(document.body, "\\begin_layout Biography", i)
1738 if document.body[i] == "\\begin_layout Biography without photo":
1742 # start with the second argument, therefore 2
1743 revert_Argument_to_TeX_brace(document, i, 0, 2, 2, True, False)
1747 def revert_IEEEtran_2(document):
1749 Reverts Flex Paragraph Start to TeX-code
1751 if document.textclass == "IEEEtran":
1754 begin = find_token(document.body, "\\begin_inset Flex Paragraph Start", begin)
1757 end1 = find_end_of_inset(document.body, begin)
1758 document.body[end1 - 2 : end1 + 1] = put_cmd_in_ert("}")
1759 document.body[begin : begin + 4] = put_cmd_in_ert("\\IEEEPARstart{")
1763 def convert_IEEEtran(document):
1768 Biography without photo
1771 if document.textclass != "IEEEtran":
1774 layouts = {"Page headings": False,
1775 "Biography without photo": True}
1777 for layout in list(layouts.keys()):
1780 i = find_token(document.body, '\\begin_layout ' + layout, i)
1783 convert_TeX_brace_to_Argument(document, i, 1, 1, False, layouts[layout], False)
1788 i = find_token_exact(document.body, "\\begin_layout Biography", i)
1792 if document.body[i] == "\\begin_layout Biography without photo":
1796 # the argument we want to convert is the second one
1797 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, False)
1801 def revert_AASTeX(document):
1802 " Reverts InsetArgument of Altaffilation to TeX-code "
1803 if document.textclass == "aastex":
1806 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1809 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1813 def convert_AASTeX(document):
1814 " Converts ERT of Altaffilation to InsetArgument "
1815 if document.textclass == "aastex":
1818 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1821 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1825 def revert_AGUTeX(document):
1826 " Reverts InsetArgument of Author affiliation to TeX-code "
1827 if document.textclass == "agutex":
1830 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1833 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1837 def convert_AGUTeX(document):
1838 " Converts ERT of Author affiliation to InsetArgument "
1839 if document.textclass == "agutex":
1842 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1845 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1849 def revert_IJMP(document):
1850 " Reverts InsetArgument of MarkBoth to TeX-code "
1851 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1854 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1857 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1861 def convert_IJMP(document):
1862 " Converts ERT of MarkBoth to InsetArgument "
1863 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1866 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1869 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1873 def revert_SIGPLAN(document):
1874 " Reverts InsetArguments of SIGPLAN to TeX-code "
1875 if document.textclass == "sigplanconf":
1880 i = find_token(document.body, "\\begin_layout Conference", i)
1882 revert_Argument_to_TeX_brace(document, i, 0, 1, 1, False, False)
1885 j = find_token(document.body, "\\begin_layout Author", j)
1887 revert_Argument_to_TeX_brace(document, j, 0, 1, 2, False, False)
1889 if i == -1 and j == -1:
1893 def convert_SIGPLAN(document):
1894 " Converts ERT of SIGPLAN to InsetArgument "
1895 if document.textclass == "sigplanconf":
1900 i = find_token(document.body, "\\begin_layout Conference", i)
1902 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
1905 j = find_token(document.body, "\\begin_layout Author", j)
1907 convert_TeX_brace_to_Argument(document, j, 1, 2, False, False, False)
1909 if i == -1 and j == -1:
1913 def revert_SIGGRAPH(document):
1914 " Reverts InsetArgument of Flex CRcat to TeX-code "
1915 if document.textclass == "acmsiggraph":
1918 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1921 revert_Argument_to_TeX_brace(document, i, 0, 1, 3, False, False)
1925 def convert_SIGGRAPH(document):
1926 " Converts ERT of Flex CRcat to InsetArgument "
1927 if document.textclass == "acmsiggraph":
1930 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1933 convert_TeX_brace_to_Argument(document, i, 1, 3, True, False, False)
1937 def revert_EuropeCV(document):
1938 " Reverts InsetArguments of europeCV to TeX-code "
1939 if document.textclass == "europecv":
1946 i = find_token(document.body, "\\begin_layout Item", i)
1948 revert_Argument_to_TeX_brace(document, i, 0, 2, 2, False, False)
1951 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1953 revert_Argument_to_TeX_brace(document, j, 0, 2, 2, False, False)
1956 k = find_token(document.body, "\\begin_layout Language", k)
1958 revert_Argument_to_TeX_brace(document, k, 0, 2, 6, False, False)
1961 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1963 revert_Argument_to_TeX_brace(document, m, 0, 2, 6, False, False)
1965 if i == -1 and j == -1 and k == -1 and m == -1:
1969 def convert_EuropeCV(document):
1970 " Converts ERT of europeCV to InsetArgument "
1971 if document.textclass == "europecv":
1978 i = find_token(document.body, "\\begin_layout Item", i)
1980 convert_TeX_brace_to_Argument(document, i, 2, 2, False, False, False)
1983 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1985 convert_TeX_brace_to_Argument(document, j, 2, 2, False, False, False)
1988 k = find_token(document.body, "\\begin_layout Language", k)
1990 convert_TeX_brace_to_Argument(document, k, 2, 6, False, False, False)
1993 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1995 convert_TeX_brace_to_Argument(document, m, 2, 6, False, False, False)
1997 if i == -1 and j == -1 and k == -1 and m == -1:
2001 def revert_ModernCV(document):
2002 " Reverts InsetArguments of modernCV to TeX-code "
2003 if document.textclass == "moderncv":
2011 j = find_token(document.body, "\\begin_layout Entry", j)
2013 revert_Argument_to_TeX_brace(document, j, 0, 1, 5, False, False)
2016 k = find_token(document.body, "\\begin_layout Item", k)
2018 revert_Argument_to_TeX_brace(document, k, 0, 1, 1, False, False)
2021 m = find_token(document.body, "\\begin_layout ItemWithComment", m)
2023 revert_Argument_to_TeX_brace(document, m, 0, 1, 2, False, False)
2024 document.body[m] = document.body[m].replace("\\begin_layout ItemWithComment", "\\begin_layout Language")
2027 o = find_token(document.body, "\\begin_layout DoubleItem", o)
2029 revert_Argument_to_TeX_brace(document, o, 0, 1, 3, False, False)
2030 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout Computer")
2033 p = find_token(document.body, "\\begin_layout Social", p)
2035 revert_Argument_to_TeX_brace(document, p, 0, 1, 1, False, True)
2037 if j == -1 and k == -1 and m == -1 and o == -1 and p == -1:
2041 def revert_ModernCV_2(document):
2042 " Reverts the Flex:Column inset of modernCV to TeX-code "
2043 if document.textclass == "moderncv":
2047 flex = find_token(document.body, "\\begin_inset Flex Column", flex)
2050 flexEnd = find_end_of_inset(document.body, flex)
2051 wasOpt = revert_Argument_to_TeX_brace(document, flex, flexEnd, 1, 1, False, True)
2052 revert_Argument_to_TeX_brace(document, flex, 0, 2, 2, False, False)
2053 flexEnd = find_end_of_inset(document.body, flex)
2055 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn")
2057 document.body[flex + 0 : flex + 4] = put_cmd_in_ert("\\cvcolumn{")
2058 document.body[flexEnd + 4 : flexEnd + 7] = put_cmd_in_ert("}")
2062 def revert_ModernCV_3(document):
2063 " Reverts the Column style of modernCV to TeX-code "
2064 if document.textclass == "moderncv":
2065 # revert the layouts
2066 revert_ModernCV(document)
2068 # get the position of the end of the last column inset
2069 LastFlexEnd = revert_ModernCV_2(document)
2071 p = find_token(document.body, "\\begin_layout Columns", p)
2074 pEnd = find_end_of_layout(document.body, p)
2075 document.body[p] = document.body[p].replace("\\begin_layout Columns", "\\begin_layout Standard")
2076 if LastFlexEnd != -1:
2077 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\begin{cvcolumns}")
2078 document.body[LastFlexEnd + 24 : LastFlexEnd + 24] = put_cmd_in_ert("\\end{cvcolumns}")
2082 def revert_ModernCV_4(document):
2083 " Reverts the style Social to TeX-code "
2084 if document.textclass == "moderncv":
2085 # revert the layouts
2086 revert_ModernCV(document)
2089 p = find_token(document.body, "\\begin_layout Social", p)
2092 pEnd = find_end_of_layout(document.body, p)
2093 document.body[p] = document.body[p].replace("\\begin_layout Social", "\\begin_layout Standard")
2094 document.body[p + 1 : p + 1] = put_cmd_in_ert("\\social")
2095 hasOpt = find_token(document.body, "[", p + 9)
2097 document.body[p + 30 : p + 30] = put_cmd_in_ert("{")
2098 document.body[p + 41 : p + 41] = put_cmd_in_ert("}")
2100 document.body[p + 11 : p + 11] = put_cmd_in_ert("{")
2101 document.body[p + 21 : p + 21] = put_cmd_in_ert("}")
2105 def convert_ModernCV(document):
2106 " Converts ERT of modernCV to InsetArgument "
2107 if document.textclass == "moderncv":
2115 i = find_token(document.body, "\\begin_layout DoubleItem", i)
2117 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False, False)
2118 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout DoubleListItem")
2121 j = find_token(document.body, "\\begin_layout Entry", j)
2123 convert_TeX_brace_to_Argument(document, j, 1, 5, False, False, False)
2126 k = find_token(document.body, "\\begin_layout Item", k)
2128 convert_TeX_brace_to_Argument(document, k, 1, 1, False, False, False)
2131 m = find_token(document.body, "\\begin_layout Language", m)
2133 convert_TeX_brace_to_Argument(document, m, 1, 2, False, False, False)
2135 if i == -1 and j == -1 and k == -1 and m == -1:
2139 def revert_Initials(document):
2140 " Reverts InsetArgument of Initial to TeX-code "
2143 i = find_token(document.body, "\\begin_layout Initial", i)
2146 # first arg (optional) and second arg (first mandatory) are supported in LyX 2.0.x
2147 revert_Argument_to_TeX_brace(document, i, 0, 3, 3, False, False)
2151 def convert_Initials(document):
2152 " Converts ERT of Initial to InsetArgument "
2155 i = find_token(document.body, "\\begin_layout Initial", i)
2158 convert_TeX_brace_to_Argument(document, i, 3, 3, False, False, False)
2162 def revert_literate(document):
2163 " Revert Literate document to old format "
2164 if del_token(document.header, "noweb", 0):
2165 document.textclass = "literate-" + document.textclass
2168 i = find_token(document.body, "\\begin_layout Chunk", i)
2171 document.body[i] = "\\begin_layout Scrap"
2175 def convert_literate(document):
2176 " Convert Literate document to new format"
2177 i = find_token(document.header, "\\textclass", 0)
2178 if (i != -1) and "literate-" in document.header[i]:
2179 document.textclass = document.header[i].replace("\\textclass literate-", "")
2180 j = find_token(document.header, "\\begin_modules", 0)
2182 document.header.insert(j + 1, "noweb")
2184 document.header.insert(i + 1, "\\end_modules")
2185 document.header.insert(i + 1, "noweb")
2186 document.header.insert(i + 1, "\\begin_modules")
2189 i = find_token(document.body, "\\begin_layout Scrap", i)
2192 document.body[i] = "\\begin_layout Chunk"
2196 def revert_itemargs(document):
2197 " Reverts \\item arguments to TeX-code "
2200 i = find_token(document.body, "\\begin_inset Argument item:", i)
2203 j = find_end_of_inset(document.body, i)
2204 # Find containing paragraph layout
2205 parent = get_containing_layout(document.body, i)
2207 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2211 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2212 endPlain = find_end_of_layout(document.body, beginPlain)
2213 content = document.body[beginPlain + 1 : endPlain]
2214 del document.body[i:j+1]
2215 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2216 document.body[parbeg : parbeg] = subst
2220 def revert_garamondx_newtxmath(document):
2221 " Revert native garamond newtxmath definition to LaTeX "
2223 i = find_token(document.header, "\\font_math", 0)
2226 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2227 val = get_value(document.header, "\\font_math", i)
2228 if val == "garamondx-ntxm":
2229 add_to_preamble(document, "\\usepackage[garamondx]{newtxmath}")
2230 document.header[i] = "\\font_math auto"
2233 def revert_garamondx(document):
2234 " Revert native garamond font definition to LaTeX "
2236 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2237 i = find_token(document.header, "\\font_roman garamondx", 0)
2240 j = find_token(document.header, "\\font_osf true", 0)
2243 preamble = "\\usepackage"
2245 preamble += "[osfI]"
2246 preamble += "{garamondx}"
2247 add_to_preamble(document, [preamble])
2248 document.header[i] = "\\font_roman default"
2251 def convert_beamerargs(document):
2252 " Converts beamer arguments to new layout "
2254 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2255 if document.textclass not in beamer_classes:
2258 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2259 list_layouts = ["Itemize", "Enumerate", "Description"]
2260 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
2264 i = find_token(document.body, "\\begin_inset Argument", i)
2267 # Find containing paragraph layout
2268 parent = get_containing_layout(document.body, i)
2270 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2275 layoutname = parent[0]
2276 for p in range(parbeg, parend):
2277 if layoutname in shifted_layouts:
2278 m = rx.match(document.body[p])
2280 argnr = int(m.group(1))
2282 document.body[p] = "\\begin_inset Argument %d" % argnr
2283 if layoutname == "AgainFrame":
2284 m = rx.match(document.body[p])
2286 document.body[p] = "\\begin_inset Argument 3"
2287 if document.body[p + 4] == "\\begin_inset ERT":
2288 if document.body[p + 9].startswith("<"):
2289 # This is an overlay specification
2291 document.body[p + 9] = document.body[p + 9][1:]
2292 if document.body[p + 9].endswith(">"):
2294 document.body[p + 9] = document.body[p + 9][:-1]
2296 document.body[p] = "\\begin_inset Argument 2"
2297 if layoutname in list_layouts:
2298 m = rx.match(document.body[p])
2300 if m.group(1) == "1":
2301 if document.body[p + 4] == "\\begin_inset ERT":
2302 if document.body[p + 9].startswith("<"):
2303 # This is an overlay specification
2305 document.body[p + 9] = document.body[p + 9][1:]
2306 if document.body[p + 9].endswith(">"):
2308 document.body[p + 9] = document.body[p + 9][:-1]
2309 elif document.body[p + 4].startswith("<"):
2310 # This is an overlay specification (without ERT)
2312 document.body[p + 4] = document.body[p + 4][1:]
2313 if document.body[p + 4].endswith(">"):
2315 document.body[p + 4] = document.body[p + 4][:-1]
2316 elif layoutname != "Itemize":
2318 document.body[p] = "\\begin_inset Argument 2"
2323 # Helper function for the frame conversion routines
2325 # FIXME: This method currently requires the arguments to be either
2326 # * In one (whole) ERT each: <ERT>[<arg1>]</ERT><ERT><arg2></ERT><ERT>[arg3]</ERT>
2327 # * Altogether in one whole ERT: <ERT>[<arg1>]<arg2>[arg3]</ERT>
2328 # If individual arguments mix ERT and non-ERT or are splitted
2329 # over several ERTs, the parsing fails.
2330 def convert_beamerframeargs(document, i, parbeg):
2333 if document.body[parbeg] != "\\begin_inset ERT":
2335 ertend = find_end_of_inset(document.body, parbeg)
2337 document.warning("Malformed LyX document: missing ERT \\end_inset")
2339 ertcont = parbeg + 5
2340 if document.body[ertcont].startswith("[<"):
2341 # This is a default overlay specification
2343 document.body[ertcont] = document.body[ertcont][2:]
2344 if document.body[ertcont].endswith(">]"):
2346 document.body[ertcont] = document.body[ertcont][:-2]
2347 elif document.body[ertcont].endswith("]"):
2349 tok = document.body[ertcont].find('>][')
2351 subst = [document.body[ertcont][:tok],
2352 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2353 'status collapsed', '', '\\begin_layout Plain Layout',
2354 document.body[ertcont][tok + 3:-1]]
2355 document.body[ertcont : ertcont + 1] = subst
2357 # Convert to ArgInset
2358 document.body[parbeg] = "\\begin_inset Argument 2"
2359 elif document.body[ertcont].startswith("<"):
2360 # This is an overlay specification
2362 document.body[ertcont] = document.body[ertcont][1:]
2363 if document.body[ertcont].endswith(">"):
2365 document.body[ertcont] = document.body[ertcont][:-1]
2366 # Convert to ArgInset
2367 document.body[parbeg] = "\\begin_inset Argument 1"
2368 elif document.body[ertcont].endswith(">]"):
2370 tok = document.body[ertcont].find('>[<')
2372 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2373 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2374 'status collapsed', '', '\\begin_layout Plain Layout',
2375 document.body[ertcont][tok + 3:-2]]
2376 # Convert to ArgInset
2377 document.body[parbeg] = "\\begin_inset Argument 1"
2379 elif document.body[ertcont].endswith("]"):
2381 tok = document.body[ertcont].find('>[<')
2384 tokk = document.body[ertcont].find('>][')
2386 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2387 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2388 'status collapsed', '', '\\begin_layout Plain Layout',
2389 document.body[ertcont][tok + 3:tokk],
2390 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2391 'status collapsed', '', '\\begin_layout Plain Layout',
2392 document.body[ertcont][tokk + 3:-1]]
2395 tokk = document.body[ertcont].find('>[')
2397 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tokk],
2398 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2399 'status collapsed', '', '\\begin_layout Plain Layout',
2400 document.body[ertcont][tokk + 2:-1]]
2402 # Convert to ArgInset
2403 document.body[parbeg] = "\\begin_inset Argument 1"
2404 elif document.body[ertcont].startswith("["):
2405 # This is an ERT option
2407 document.body[ertcont] = document.body[ertcont][1:]
2408 if document.body[ertcont].endswith("]"):
2410 document.body[ertcont] = document.body[ertcont][:-1]
2411 # Convert to ArgInset
2412 document.body[parbeg] = "\\begin_inset Argument 3"
2418 def convert_againframe_args(document):
2419 " Converts beamer AgainFrame to new layout "
2421 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2422 if document.textclass not in beamer_classes:
2427 i = find_token(document.body, "\\begin_layout AgainFrame", i)
2430 parent = get_containing_layout(document.body, i)
2432 document.warning("Wrong parent layout!")
2436 # Convert ERT arguments
2437 # FIXME: See restrictions in convert_beamerframeargs method
2438 ertend = convert_beamerframeargs(document, i, parbeg)
2444 def convert_corollary_args(document):
2445 " Converts beamer corrolary-style ERT arguments native InsetArgs "
2447 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2448 if document.textclass not in beamer_classes:
2451 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2452 for lay in corollary_layouts:
2455 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2458 parent = get_containing_layout(document.body, i)
2460 document.warning("Wrong parent layout!")
2464 if document.body[parbeg] == "\\begin_inset ERT":
2465 ertcontfirstline = parbeg + 5
2466 # Find the last ERT in this paragraph (which might also be the first)
2467 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
2468 if lastertbeg == -1:
2469 document.warning("Last ERT not found!")
2471 lastertend = find_end_of_inset(document.body, lastertbeg)
2472 if lastertend == -1:
2473 document.warning("End of last ERT not found!")
2475 ertcontlastline = lastertend - 3
2476 if document.body[ertcontfirstline].startswith("<"):
2477 # This is an overlay specification
2479 document.body[ertcontfirstline] = document.body[ertcontfirstline][1:]
2480 if document.body[ertcontlastline].endswith(">"):
2482 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
2483 if ertcontfirstline < ertcontlastline:
2484 # Multiline ERT. Might contain TeX code. Embrace in ERT.
2485 document.body[ertcontlastline : ertcontlastline + 1] = [
2486 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
2487 document.body[ertcontfirstline : ertcontfirstline + 1] = [
2488 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
2489 'status collapsed', '', '\\begin_layout Plain Layout',
2490 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
2491 document.body[ertcontfirstline]]
2493 # Convert to ArgInset
2494 document.body[parbeg] = "\\begin_inset Argument 1"
2495 elif document.body[ertcontlastline].endswith("]"):
2497 tok = document.body[ertcontfirstline].find('>[')
2499 if ertcontfirstline < ertcontlastline:
2500 # Multiline ERT. Might contain TeX code. Embrace in ERT.
2501 document.body[ertcontlastline : ertcontlastline + 1] = [
2502 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
2503 document.body[ertcontfirstline : ertcontfirstline + 1] = [document.body[ertcontfirstline][:tok],
2504 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2505 'status collapsed', '', '\\begin_layout Plain Layout',
2506 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
2507 document.body[ertcontfirstline][tok + 2:-1]]
2509 document.body[ertcontfirstline : ertcontfirstline + 1] = [document.body[ertcontfirstline][:tok],
2510 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2511 'status collapsed', '', '\\begin_layout Plain Layout',
2512 document.body[ertcontfirstline][tok + 2:-1]]
2513 # Convert to ArgInset
2514 document.body[parbeg] = "\\begin_inset Argument 1"
2517 elif document.body[ertcontlastline].startswith("["):
2518 if document.body[ertcontlastline].endswith("]"):
2519 # This is an ERT option
2521 document.body[ertcontlastline] = document.body[ertcontlastline][1:]
2523 document.body[ertcontlastline] = document.body[ertcontlastline][:-1]
2524 # Convert to ArgInset
2525 document.body[parbeg] = "\\begin_inset Argument 2"
2527 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, True)
2534 def convert_quote_args(document):
2535 " Converts beamer quote style ERT args to native InsetArgs "
2537 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2538 if document.textclass not in beamer_classes:
2541 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2542 for lay in quote_layouts:
2545 i = find_token(document.body, "\\begin_layout " + lay, i)
2548 parent = get_containing_layout(document.body, i)
2550 document.warning("Wrong parent layout!")
2554 if document.body[parbeg] == "\\begin_inset ERT":
2555 if document.body[i + 6].startswith("<"):
2556 # This is an overlay specification
2558 document.body[i + 6] = document.body[i + 6][1:]
2559 if document.body[i + 6].endswith(">"):
2561 document.body[i + 6] = document.body[i + 6][:-1]
2562 # Convert to ArgInset
2563 document.body[i + 1] = "\\begin_inset Argument 1"
2567 def cleanup_beamerargs(document):
2568 " Clean up empty ERTs (conversion artefacts) "
2570 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2571 if document.textclass not in beamer_classes:
2576 i = find_token(document.body, "\\begin_inset Argument", i)
2579 j = find_end_of_inset(document.body, i)
2581 document.warning("Malformed LyX document: Can't find end of Argument inset")
2585 ertbeg = find_token(document.body, "\\begin_inset ERT", i, j)
2588 ertend = find_end_of_inset(document.body, ertbeg)
2590 document.warning("Malformed LyX document: Can't find end of ERT inset")
2592 stripped = [line for line in document.body[ertbeg : ertend + 1] if line.strip()]
2593 if len(stripped) == 5:
2594 # This is an empty ERT
2595 offset = len(document.body[ertbeg : ertend + 1])
2596 del document.body[ertbeg : ertend + 1]
2603 def revert_beamerargs(document):
2604 " Reverts beamer arguments to old layout "
2606 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2607 if document.textclass not in beamer_classes:
2611 list_layouts = ["Itemize", "Enumerate", "Description"]
2612 headings = ["Part", "Section", "Section*", "Subsection", "Subsection*",
2613 "Subsubsection", "Subsubsection*", "FrameSubtitle", "NoteItem"]
2614 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2615 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2616 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2619 i = find_token(document.body, "\\begin_inset Argument", i)
2622 # Find containing paragraph layout
2623 parent = get_containing_layout(document.body, i)
2625 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2630 realparbeg = parent[3]
2631 layoutname = parent[0]
2633 for p in range(parbeg, parend):
2637 if layoutname in headings:
2638 m = rx.match(document.body[p])
2642 # Find containing paragraph layout
2643 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2644 endPlain = find_end_of_layout(document.body, beginPlain)
2645 endInset = find_end_of_inset(document.body, p)
2646 argcontent = document.body[beginPlain + 1 : endPlain]
2648 realparend = realparend - len(document.body[p : endInset + 1])
2650 del document.body[p : endInset + 1]
2651 if layoutname == "FrameSubtitle":
2652 pre = put_cmd_in_ert("\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2653 elif layoutname == "NoteItem":
2654 pre = put_cmd_in_ert("\\note<") + argcontent + put_cmd_in_ert(">[item]")
2655 elif layoutname.endswith('*'):
2656 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower()[:-1] + "<") + argcontent + put_cmd_in_ert(">*")
2658 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2659 secarg = find_token(document.body, "\\begin_inset Argument 2", parbeg, parend)
2661 # Find containing paragraph layout
2662 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", secarg)
2663 endPlain = find_end_of_layout(document.body, beginPlain)
2664 endInset = find_end_of_inset(document.body, secarg)
2665 argcontent = document.body[beginPlain + 1 : endPlain]
2667 realparend = realparend - len(document.body[secarg : endInset + 1])
2668 del document.body[secarg : endInset + 1]
2669 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2670 pre += put_cmd_in_ert("{")
2671 document.body[parbeg] = "\\begin_layout Standard"
2672 document.body[realparbeg : realparbeg] = pre
2673 pe = find_end_of_layout(document.body, parbeg)
2674 post = put_cmd_in_ert("}")
2675 document.body[pe : pe] = post
2676 realparend += len(pre) + len(post)
2677 if layoutname == "AgainFrame":
2678 m = rx.match(document.body[p])
2682 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2683 endPlain = find_end_of_layout(document.body, beginPlain)
2684 endInset = find_end_of_inset(document.body, p)
2685 content = document.body[beginPlain + 1 : endPlain]
2687 realparend = realparend - len(document.body[p : endInset + 1])
2689 del document.body[p : endInset + 1]
2690 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2691 document.body[realparbeg : realparbeg] = subst
2692 if layoutname == "Overprint":
2693 m = rx.match(document.body[p])
2697 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2698 endPlain = find_end_of_layout(document.body, beginPlain)
2699 endInset = find_end_of_inset(document.body, p)
2700 content = document.body[beginPlain + 1 : endPlain]
2702 realparend = realparend - len(document.body[p : endInset + 1])
2704 del document.body[p : endInset + 1]
2705 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2706 document.body[realparbeg : realparbeg] = subst
2707 if layoutname == "OverlayArea":
2708 m = rx.match(document.body[p])
2712 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2713 endPlain = find_end_of_layout(document.body, beginPlain)
2714 endInset = find_end_of_inset(document.body, p)
2715 content = document.body[beginPlain + 1 : endPlain]
2717 realparend = realparend - len(document.body[p : endInset + 1])
2719 del document.body[p : endInset + 1]
2720 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2721 document.body[realparbeg : realparbeg] = subst
2722 if layoutname in list_layouts:
2723 m = rx.match(document.body[p])
2727 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2728 endPlain = find_end_of_layout(document.body, beginPlain)
2729 endInset = find_end_of_inset(document.body, p)
2730 content = document.body[beginPlain + 1 : endPlain]
2731 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2732 realparend = realparend + len(subst) - len(content)
2733 document.body[beginPlain + 1 : endPlain] = subst
2734 elif argnr == "item:1":
2735 j = find_end_of_inset(document.body, i)
2736 # Find containing paragraph layout
2737 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2738 endPlain = find_end_of_layout(document.body, beginPlain)
2739 content = document.body[beginPlain + 1 : endPlain]
2740 del document.body[i:j+1]
2741 if layoutname == "Description":
2742 # Description only has one (overlay) item arg
2743 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2744 # This must be put after the first space (begin of decription body
2745 # in LyX's arkward description list syntax)
2746 # Try to find that place ...
2747 rxx = re.compile(r'^([^\\ ]+ )(.*)$')
2748 for q in range(parbeg, parend):
2749 m = rxx.match(document.body[q])
2751 # We found it. Now insert the ERT argument just there:
2752 document.body[q : q] = [m.group(1), ''] + subst + ['', m.group(2)]
2755 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2756 document.body[realparbeg : realparbeg] = subst
2757 elif argnr == "item:2":
2758 j = find_end_of_inset(document.body, i)
2759 # Find containing paragraph layout
2760 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2761 endPlain = find_end_of_layout(document.body, beginPlain)
2762 content = document.body[beginPlain + 1 : endPlain]
2763 del document.body[i:j+1]
2764 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2765 document.body[realparbeg : realparbeg] = subst
2766 if layoutname in quote_layouts:
2767 m = rx.match(document.body[p])
2771 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2772 endPlain = find_end_of_layout(document.body, beginPlain)
2773 endInset = find_end_of_inset(document.body, p)
2774 content = document.body[beginPlain + 1 : endPlain]
2776 realparend = realparend - len(document.body[p : endInset + 1])
2778 del document.body[p : endInset + 1]
2779 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2780 document.body[realparbeg : realparbeg] = subst
2781 if layoutname in corollary_layouts:
2782 m = rx.match(document.body[p])
2786 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2787 endPlain = find_end_of_layout(document.body, beginPlain)
2788 endInset = find_end_of_inset(document.body, p)
2789 content = document.body[beginPlain + 1 : endPlain]
2791 realparend = realparend - len(document.body[p : endInset + 1])
2793 del document.body[p : endInset + 1]
2794 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2795 document.body[realparbeg : realparbeg] = subst
2800 def revert_beamerargs2(document):
2801 " Reverts beamer arguments to old layout, step 2 "
2803 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2804 if document.textclass not in beamer_classes:
2808 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2809 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2810 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2813 i = find_token(document.body, "\\begin_inset Argument", i)
2816 # Find containing paragraph layout
2817 parent = get_containing_layout(document.body, i)
2819 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2824 realparbeg = parent[3]
2825 layoutname = parent[0]
2827 for p in range(parbeg, parend):
2831 if layoutname in shifted_layouts:
2832 m = rx.match(document.body[p])
2836 document.body[p] = "\\begin_inset Argument 1"
2837 if layoutname in corollary_layouts:
2838 m = rx.match(document.body[p])
2842 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2843 endPlain = find_end_of_layout(document.body, beginPlain)
2844 endInset = find_end_of_inset(document.body, p)
2845 content = document.body[beginPlain + 1 : endPlain]
2847 realparend = realparend - len(document.body[p : endInset + 1])
2849 del document.body[p : endInset + 1]
2850 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2851 document.body[realparbeg : realparbeg] = subst
2852 if layoutname == "OverlayArea":
2853 m = rx.match(document.body[p])
2857 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2858 endPlain = find_end_of_layout(document.body, beginPlain)
2859 endInset = find_end_of_inset(document.body, p)
2860 content = document.body[beginPlain + 1 : endPlain]
2862 realparend = realparend - len(document.body[p : endInset + 1])
2864 del document.body[p : endInset + 1]
2865 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2866 document.body[realparbeg : realparbeg] = subst
2867 if layoutname == "AgainFrame":
2868 m = rx.match(document.body[p])
2872 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2873 endPlain = find_end_of_layout(document.body, beginPlain)
2874 endInset = find_end_of_inset(document.body, p)
2875 content = document.body[beginPlain + 1 : endPlain]
2877 realparend = realparend - len(document.body[p : endInset + 1])
2879 del document.body[p : endInset + 1]
2880 subst = put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
2881 document.body[realparbeg : realparbeg] = subst
2885 def revert_beamerargs3(document):
2886 " Reverts beamer arguments to old layout, step 3 "
2888 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2889 if document.textclass not in beamer_classes:
2892 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2895 i = find_token(document.body, "\\begin_inset Argument", i)
2898 # Find containing paragraph layout
2899 parent = get_containing_layout(document.body, i)
2901 document.warning("Malformed LyX document: Can't find parent paragraph layout")
2906 realparbeg = parent[3]
2907 layoutname = parent[0]
2909 for p in range(parbeg, parend):
2913 if layoutname == "AgainFrame":
2914 m = rx.match(document.body[p])
2918 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2919 endPlain = find_end_of_layout(document.body, beginPlain)
2920 endInset = find_end_of_inset(document.body, p)
2921 content = document.body[beginPlain + 1 : endPlain]
2923 realparend = realparend - len(document.body[p : endInset + 1])
2925 del document.body[p : endInset + 1]
2926 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2927 document.body[realparbeg : realparbeg] = subst
2931 def revert_beamerflex(document):
2932 " Reverts beamer Flex insets "
2934 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2935 if document.textclass not in beamer_classes:
2938 new_flexes = {"Bold" : "\\textbf", "Emphasize" : "\\emph", "Only" : "\\only",
2939 "Uncover" : "\\uncover", "Visible" : "\\visible",
2940 "Invisible" : "\\invisible", "Alternative" : "\\alt",
2941 "Beamer_Note" : "\\note"}
2942 old_flexes = {"Alert" : "\\alert", "Structure" : "\\structure"}
2943 rx = re.compile(r'^\\begin_inset Flex (.+)$')
2947 i = find_token(document.body, "\\begin_inset Flex", i)
2950 m = rx.match(document.body[i])
2952 flextype = m.group(1)
2953 z = find_end_of_inset(document.body, i)
2955 document.warning("Can't find end of Flex " + flextype + " inset.")
2958 if flextype in new_flexes:
2959 pre = put_cmd_in_ert(new_flexes[flextype])
2960 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2962 argend = find_end_of_inset(document.body, arg)
2964 document.warning("Can't find end of Argument!")
2967 # Find containing paragraph layout
2968 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2969 endPlain = find_end_of_layout(document.body, beginPlain)
2970 argcontent = document.body[beginPlain + 1 : endPlain]
2972 z = z - len(document.body[arg : argend + 1])
2974 del document.body[arg : argend + 1]
2975 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2976 arg = find_token(document.body, "\\begin_inset Argument 2", i, z)
2978 argend = find_end_of_inset(document.body, arg)
2980 document.warning("Can't find end of Argument!")
2983 # Find containing paragraph layout
2984 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2985 endPlain = find_end_of_layout(document.body, beginPlain)
2986 argcontent = document.body[beginPlain + 1 : endPlain]
2988 z = z - len(document.body[arg : argend + 1])
2990 del document.body[arg : argend + 1]
2991 if flextype == "Alternative":
2992 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
2994 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2995 pre += put_cmd_in_ert("{")
2996 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2997 endPlain = find_end_of_layout(document.body, beginPlain)
2999 z = z - len(document.body[i : beginPlain + 1])
3001 document.body[i : beginPlain + 1] = pre
3002 post = put_cmd_in_ert("}")
3003 document.body[z - 2 : z + 1] = post
3004 elif flextype in old_flexes:
3005 pre = put_cmd_in_ert(old_flexes[flextype])
3006 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
3010 argend = find_end_of_inset(document.body, arg)
3012 document.warning("Can't find end of Argument!")
3015 # Find containing paragraph layout
3016 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3017 endPlain = find_end_of_layout(document.body, beginPlain)
3018 argcontent = document.body[beginPlain + 1 : endPlain]
3020 z = z - len(document.body[arg : argend + 1])
3022 del document.body[arg : argend + 1]
3023 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
3024 pre += put_cmd_in_ert("{")
3025 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
3026 endPlain = find_end_of_layout(document.body, beginPlain)
3028 z = z - len(document.body[i : beginPlain + 1])
3030 document.body[i : beginPlain + 1] = pre
3031 post = put_cmd_in_ert("}")
3032 document.body[z - 2 : z + 1] = post
3037 def revert_beamerblocks(document):
3038 " Reverts beamer block arguments to ERT "
3040 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3041 if document.textclass not in beamer_classes:
3044 blocks = ["Block", "ExampleBlock", "AlertBlock"]
3046 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3049 i = find_token(document.body, "\\begin_inset Argument", i)
3052 # Find containing paragraph layout
3053 parent = get_containing_layout(document.body, i)
3055 document.warning("Malformed LyX document: Can't find parent paragraph layout")
3060 realparbeg = parent[3]
3061 layoutname = parent[0]
3063 for p in range(parbeg, parend):
3067 if layoutname in blocks:
3068 m = rx.match(document.body[p])
3072 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3073 endPlain = find_end_of_layout(document.body, beginPlain)
3074 endInset = find_end_of_inset(document.body, p)
3075 content = document.body[beginPlain + 1 : endPlain]
3077 realparend = realparend - len(document.body[p : endInset + 1])
3079 del document.body[p : endInset + 1]
3080 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3081 document.body[realparbeg : realparbeg] = subst
3083 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3084 endPlain = find_end_of_layout(document.body, beginPlain)
3085 endInset = find_end_of_inset(document.body, p)
3086 content = document.body[beginPlain + 1 : endPlain]
3088 realparend = realparend - len(document.body[p : endInset + 1])
3090 del document.body[p : endInset + 1]
3091 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3092 document.body[realparbeg : realparbeg] = subst
3097 def convert_beamerblocks(document):
3098 " Converts beamer block ERT args to native InsetArgs "
3100 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3101 if document.textclass not in beamer_classes:
3104 blocks = ["Block", "ExampleBlock", "AlertBlock"]
3108 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
3111 parent = get_containing_layout(document.body, i)
3112 if parent == False or parent[1] != i:
3113 document.warning("Wrong parent layout!")
3120 # If the paragraph starts with a language switch, adjust parbeg
3121 if len(document.body[parbeg]) == 0 and parbeg < parend \
3122 and document.body[parbeg + 1].startswith("\\lang"):
3124 if document.body[parbeg] == "\\begin_inset ERT":
3125 ertcontfirstline = parbeg + 5
3129 # Find the last ERT in this paragraph used for arguments
3130 # (which might also be the first)
3131 lastertbeg = find_token_backwards(document.body, "\\begin_inset ERT", j)
3132 if lastertbeg == -1:
3133 document.warning("Last ERT not found!")
3135 lastertend = find_end_of_inset(document.body, lastertbeg)
3136 if lastertend == -1:
3137 document.warning("End of last ERT not found!")
3139 # Is this ERT really used for an argument?
3140 # Note: This will fail when non-argument ERTs actually use brackets
3142 regexp = re.compile(r'.*[>\]\}]', re.IGNORECASE)
3143 cbracket = find_re(document.body, regexp, lastertbeg, lastertend)
3146 if lastertbeg == parbeg:
3149 if lastertbeg == -1 or lastertend == -1:
3151 ertcontlastline = lastertend - 3
3153 if document.body[ertcontfirstline].lstrip().startswith("<"):
3154 # This is an overlay specification
3156 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3157 if document.body[ertcontlastline].rstrip().endswith(">"):
3159 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3160 # Convert to ArgInset
3161 document.body[parbeg] = "\\begin_inset Argument 1"
3162 elif document.body[ertcontlastline].rstrip().endswith("}"):
3164 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3166 ertcontdivline = ertcontfirstline
3167 tok = document.body[ertcontdivline].find('>{')
3169 regexp = re.compile(r'.*>\{', re.IGNORECASE)
3170 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3171 tok = document.body[ertcontdivline].find('>{')
3173 if ertcontfirstline < ertcontlastline:
3174 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3175 document.body[ertcontlastline : ertcontlastline + 1] = [
3176 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3177 if ertcontdivline == ertcontfirstline:
3178 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3179 '\\end_layout', '', '\\end_inset', '',
3180 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3181 'status collapsed', '', '\\begin_layout Plain Layout',
3182 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3183 document.body[ertcontdivline][tok + 2:]]
3185 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3186 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3187 'status collapsed', '', '\\begin_layout Plain Layout',
3188 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3189 document.body[ertcontdivline][tok + 2:]]
3191 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3192 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3193 'status collapsed', '', '\\begin_layout Plain Layout',
3194 document.body[ertcontdivline][tok + 2:]]
3196 # check if have delimiters in two different ERTs
3197 tok = document.body[ertcontdivline].find('>')
3199 regexp = re.compile(r'.*>', re.IGNORECASE)
3200 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3201 tok = document.body[ertcontdivline].find('>')
3203 tokk = document.body[ertcontdivline].find('{')
3205 regexp = re.compile(r'.*\{', re.IGNORECASE)
3206 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, lastertend)
3207 tokk = document.body[ertcontdivlinetwo].find('{')
3209 if ertcontfirstline < ertcontlastline:
3210 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3211 document.body[ertcontlastline : ertcontlastline + 1] = [
3212 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3213 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3214 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3215 '\\end_inset', '', '', '\\begin_inset Argument 2',
3216 'status collapsed', '', '\\begin_layout Plain Layout',
3217 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3218 document.body[ertcontdivlinetwo][tokk + 1:]]
3220 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3221 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
3222 'status collapsed', '', '\\begin_layout Plain Layout',
3223 document.body[ertcontdivlinetwo][tokk + 1:]]
3224 # Convert to ArgInset
3225 if ertcontfirstline < ertcontlastline:
3226 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3227 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 1',
3228 'status collapsed', '', '\\begin_layout Plain Layout',
3229 '\\begin_inset ERT', '']
3231 document.body[parbeg] = "\\begin_inset Argument 1"
3232 elif document.body[ertcontfirstline].lstrip().startswith("{"):
3233 # This is the block title
3234 if document.body[ertcontlastline].rstrip().endswith("}"):
3235 # strip off the braces
3236 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3237 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3238 if ertcontfirstline < ertcontlastline:
3239 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3240 document.body[parend : parend + 1] = [
3241 document.body[parend], '\\end_inset', '', '\\end_layout']
3242 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3243 'status collapsed', '', '\\begin_layout Plain Layout',
3244 '\\begin_inset ERT', '']
3246 # Convert to ArgInset
3247 document.body[parbeg] = "\\begin_inset Argument 2"
3248 # the overlay argument can also follow the title, so ...
3249 elif document.body[ertcontlastline].rstrip().endswith(">"):
3251 document.body[ertcontfirstline] = document.body[ertcontfirstline].lstrip()[1:]
3253 document.body[ertcontlastline] = document.body[ertcontlastline].rstrip()[:-1]
3255 ertcontdivline = ertcontfirstline
3256 tok = document.body[ertcontdivline].find('}<')
3258 regexp = re.compile(r'.*\}<', re.IGNORECASE)
3259 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3260 tok = document.body[ertcontdivline].find('}<')
3262 if ertcontfirstline < ertcontlastline:
3263 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3264 document.body[ertcontlastline : ertcontlastline + 1] = [
3265 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3266 if ertcontdivline == ertcontfirstline:
3267 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3268 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3269 'status collapsed', '', '\\begin_layout Plain Layout',
3270 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3271 document.body[ertcontdivline][tok + 2:]]
3273 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3274 '\\end_layout', '', '\\end_inset', '',
3275 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3276 'status collapsed', '', '\\begin_layout Plain Layout',
3277 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3278 document.body[ertcontdivline][tok + 2:]]
3280 document.body[ertcontdivline : ertcontdivline + 1] = [document.body[ertcontdivline][:tok],
3281 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3282 'status collapsed', '', '\\begin_layout Plain Layout',
3283 document.body[ertcontdivline][tok + 2:]]
3285 # check if have delimiters in two different ERTs
3286 tok = document.body[ertcontdivline].find('}')
3288 regexp = re.compile(r'.*\}', re.IGNORECASE)
3289 ertcontdivline = find_re(document.body, regexp, ertcontfirstline, lastertend)
3290 tok = document.body[ertcontdivline].find('}')
3292 tokk = document.body[ertcontdivline].find('<')
3294 regexp = re.compile(r'.*<', re.IGNORECASE)
3295 ertcontdivlinetwo = find_re(document.body, regexp, ertcontfirstline, lastertend)
3296 tokk = document.body[ertcontdivlinetwo].find('<')
3298 if ertcontfirstline < ertcontlastline:
3299 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3300 document.body[ertcontlastline : ertcontlastline + 1] = [
3301 document.body[ertcontlastline], '\\end_layout', '', '\\end_inset']
3302 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3303 '\\end_layout', '', '\\end_inset', '', '\\end_layout', '',
3304 '\\end_inset', '', '', '\\begin_inset Argument 1',
3305 'status collapsed', '', '\\begin_layout Plain Layout',
3306 '\\begin_inset ERT', '', 'status open' '', '\\begin_layout Plain Layout',
3307 document.body[ertcontdivlinetwo][tokk + 1:]]
3309 document.body[ertcontdivline : ertcontdivlinetwo + 1] = [document.body[ertcontdivline][:tok],
3310 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 1',
3311 'status collapsed', '', '\\begin_layout Plain Layout',
3312 document.body[ertcontdivlinetwo][tokk + 1:]]
3313 # Convert to ArgInset
3314 if ertcontfirstline < ertcontlastline:
3315 # Multiline ERT. Might contain TeX code. Embrace in ERT.
3316 document.body[parbeg : parbeg + 1] = ['\\begin_inset Argument 2',
3317 'status collapsed', '', '\\begin_layout Plain Layout',
3318 '\\begin_inset ERT', '']
3320 document.body[parbeg] = "\\begin_inset Argument 2"
3321 elif count_pars_in_inset(document.body, ertcontfirstline) > 1:
3322 # Multipar ERT. Skip this.
3325 # ERT has contents after the closing bracket. We cannot convert this.
3326 # convert_TeX_brace_to_Argument cannot either.
3327 #convert_TeX_brace_to_Argument(document, i, 2, 2, False, True, False)
3331 j = find_end_of_layout(document.body, i)
3333 document.warning("end of layout not found!")
3334 k = find_token(document.body, "\\begin_inset Argument", i, j)
3336 document.warning("InsetArgument not found!")
3338 l = find_end_of_inset(document.body, k)
3339 m = find_token(document.body, "\\begin_inset ERT", l, j)
3342 ertcontfirstline = m + 5
3347 def convert_overprint(document):
3348 " Convert old beamer overprint layouts to ERT "
3350 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3351 if document.textclass not in beamer_classes:
3356 i = find_token(document.body, "\\begin_layout Overprint", i)
3359 # Find end of sequence
3360 j = find_end_of_sequence(document.body, i)
3362 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3366 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3368 if document.body[j] == "\\end_deeper":
3369 esubst = ["", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3371 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
3372 endseq = endseq + len(esubst) - len(document.body[j : j])
3373 document.body[j : j] = esubst
3374 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3376 argend = find_end_of_layout(document.body, argbeg)
3378 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3381 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3382 endPlain = find_end_of_layout(document.body, beginPlain)
3383 content = document.body[beginPlain + 1 : endPlain]
3385 endseq = endseq - len(document.body[argbeg : argend + 1])
3387 del document.body[argbeg : argend + 1]
3388 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3390 endseq = endseq - len(document.body[i : i])
3391 document.body[i : i] = subst + ["\\end_layout"]
3392 endseq += len(subst)
3394 for p in range(i, endseq):
3395 if document.body[p] == "\\begin_layout Overprint":
3396 document.body[p] = "\\begin_layout Standard"
3401 def revert_overprint(document):
3402 " Revert old beamer overprint layouts to ERT "
3404 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3405 if document.textclass not in beamer_classes:
3410 i = find_token(document.body, "\\begin_layout Overprint", i)
3413 # Find end of sequence
3414 j = find_end_of_sequence(document.body, i)
3416 document.warning("Malformed LyX document. Cannot find end of Overprint sequence!")
3420 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
3421 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}")
3422 endseq = endseq + len(esubst) - len(document.body[j : j])
3423 if document.body[j] == "\\end_deeper":
3424 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3426 document.body[j : j] = ["\\end_layout", ""] + esubst
3429 if document.body[r] == "\\begin_deeper":
3430 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3432 document.body[r] = ""
3433 document.body[s] = ""
3437 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
3439 # Is this really our argument?
3440 nested = find_token(document.body, "\\begin_deeper", i, argbeg)
3442 argend = find_end_of_inset(document.body, argbeg)
3444 document.warning("Malformed LyX document. Cannot find end of Overprint argument!")
3447 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3448 endPlain = find_end_of_layout(document.body, beginPlain)
3449 content = document.body[beginPlain + 1 : endPlain]
3451 endseq = endseq - len(document.body[argbeg : argend])
3453 del document.body[argbeg : argend + 1]
3454 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3456 endseq = endseq - len(document.body[i : i])
3457 document.body[i : i] = subst + ["\\end_layout"]
3458 endseq += len(subst)
3464 if document.body[p] == "\\begin_layout Overprint":
3465 q = find_end_of_layout(document.body, p)
3467 document.warning("Malformed LyX document. Cannot find end of Overprint layout!")
3470 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\onslide")
3471 argbeg = find_token(document.body, "\\begin_inset Argument item:1", p, q)
3473 argend = find_end_of_inset(document.body, argbeg)
3475 document.warning("Malformed LyX document. Cannot find end of Overprint item argument!")
3478 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3479 endPlain = find_end_of_layout(document.body, beginPlain)
3480 content = document.body[beginPlain + 1 : endPlain]
3482 endseq = endseq - len(document.body[argbeg : argend + 1])
3484 del document.body[argbeg : argend + 1]
3485 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3486 endseq = endseq - len(document.body[p : p + 1]) + len(subst)
3487 document.body[p : p + 1] = subst
3493 def revert_frametitle(document):
3494 " Reverts beamer frametitle layout to ERT "
3496 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3497 if document.textclass not in beamer_classes:
3500 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3503 i = find_token(document.body, "\\begin_layout FrameTitle", i)
3506 j = find_end_of_layout(document.body, i)
3508 document.warning("Malformed LyX document: Can't find end of FrameTitle layout")
3512 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
3513 endlay += len(put_cmd_in_ert("}"))
3514 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\frametitle")
3515 for p in range(i, j):
3518 m = rx.match(document.body[p])
3522 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3523 endPlain = find_end_of_layout(document.body, beginPlain)
3524 endInset = find_end_of_inset(document.body, p)
3525 content = document.body[beginPlain + 1 : endPlain]
3527 endlay = endlay - len(document.body[p : endInset + 1])
3529 del document.body[p : endInset + 1]
3530 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3532 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3533 endPlain = find_end_of_layout(document.body, beginPlain)
3534 endInset = find_end_of_inset(document.body, p)
3535 content = document.body[beginPlain + 1 : endPlain]
3537 endlay = endlay - len(document.body[p : endInset + 1])
3539 del document.body[p : endInset + 1]
3540 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3542 subst += put_cmd_in_ert("{")
3543 document.body[i : i + 1] = subst
3547 def convert_epigraph(document):
3548 " Converts memoir epigraph to new syntax "
3550 if document.textclass != "memoir":
3555 i = find_token(document.body, "\\begin_layout Epigraph", i)
3558 j = find_end_of_layout(document.body, i)
3560 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3565 ert = find_token(document.body, "\\begin_inset ERT", i, j)
3567 endInset = find_end_of_inset(document.body, ert)
3568 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", ert)
3569 endPlain = find_end_of_layout(document.body, beginPlain)
3570 ertcont = beginPlain + 2
3571 if document.body[ertcont] == "}{":
3573 # Convert to ArgInset
3574 endlay = endlay - 2 * len(document.body[j])
3575 begsubst = ['\\begin_inset Argument post:1', 'status collapsed', '',
3576 '\\begin_layout Plain Layout']
3577 endsubst = ['\\end_layout', '', '\\end_inset', '', document.body[j]]
3578 document.body[j : j + 1] = endsubst
3579 document.body[endInset + 1 : endInset + 1] = begsubst
3581 endlay += len(begsubst) + len(endsubst)
3582 endlay = endlay - len(document.body[ert : endInset + 1])
3583 del document.body[ert : endInset + 1]
3588 def revert_epigraph(document):
3589 " Reverts memoir epigraph argument to ERT "
3591 if document.textclass != "memoir":
3596 i = find_token(document.body, "\\begin_layout Epigraph", i)
3599 j = find_end_of_layout(document.body, i)
3601 document.warning("Malformed LyX document: Can't find end of Epigraph layout")
3606 p = find_token(document.body, "\\begin_layout Argument post:1", i, j)
3608 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3609 endPlain = find_end_of_layout(document.body, beginPlain)
3610 endInset = find_end_of_inset(document.body, p)
3611 content = document.body[beginPlain + 1 : endPlain]
3613 endlay = endlay - len(document.body[p : endInset + 1])
3615 del document.body[p : endInset + 1]
3616 subst += put_cmd_in_ert("}{") + content
3618 subst += put_cmd_in_ert("}{")
3620 document.body[j : j] = subst + document.body[j : j]
3624 def convert_captioninsets(document):
3625 " Converts caption insets to new syntax "
3629 i = find_token(document.body, "\\begin_inset Caption", i)
3632 document.body[i] = "\\begin_inset Caption Standard"
3636 def revert_captioninsets(document):
3637 " Reverts caption insets to old syntax "
3641 i = find_token(document.body, "\\begin_inset Caption Standard", i)
3644 document.body[i] = "\\begin_inset Caption"
3648 def convert_captionlayouts(document):
3649 " Convert caption layouts to caption insets. "
3652 "Captionabove": "Above",
3653 "Captionbelow": "Below",
3654 "FigCaption" : "FigCaption",
3655 "Table_Caption" : "Table",
3656 "CenteredCaption" : "Centered",
3657 "Bicaption" : "Bicaption",
3662 i = find_token(document.body, "\\begin_layout", i)
3665 val = get_value(document.body, "\\begin_layout", i)
3666 if val in list(caption_dict.keys()):
3667 j = find_end_of_layout(document.body, i)
3669 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3672 document.body[j:j] = ["\\end_layout", "", "\\end_inset", "", ""]
3673 document.body[i:i+1] = ["\\begin_layout %s" % document.default_layout,
3674 "\\begin_inset Caption %s" % caption_dict[val], "",
3675 "\\begin_layout %s" % document.default_layout]
3679 def revert_captionlayouts(document):
3680 " Revert caption insets to caption layouts. "
3683 "Above" : "Captionabove",
3684 "Below" : "Captionbelow",
3685 "FigCaption" : "FigCaption",
3686 "Table" : "Table_Caption",
3687 "Centered" : "CenteredCaption",
3688 "Bicaption" : "Bicaption",
3692 rx = re.compile(r'^\\begin_inset Caption (\S+)$')
3694 i = find_token(document.body, "\\begin_inset Caption", i)
3698 m = rx.match(document.body[i])
3702 if val not in list(caption_dict.keys()):
3706 # We either need to delete the previous \begin_layout line, or we
3707 # need to end the previous layout if this inset is not in the first
3708 # position of the paragraph.
3709 layout_before = find_token_backwards(document.body, "\\begin_layout", i)
3710 if layout_before == -1:
3711 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3713 layout_line = document.body[layout_before]
3714 del_layout_before = True
3715 l = layout_before + 1
3717 if document.body[l] != "":
3718 del_layout_before = False
3721 if del_layout_before:
3722 del document.body[layout_before:i]
3725 document.body[i:i] = ["\\end_layout", ""]
3728 # Find start of layout in the inset and end of inset
3729 j = find_token(document.body, "\\begin_layout", i)
3731 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3733 k = find_end_of_inset(document.body, i)
3735 document.warning("Malformed LyX document: Missing `\\end_inset'.")
3738 # We either need to delete the following \end_layout line, or we need
3739 # to restart the old layout if this inset is not at the paragraph end.
3740 layout_after = find_token(document.body, "\\end_layout", k)
3741 if layout_after == -1:
3742 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3744 del_layout_after = True
3746 while l < layout_after:
3747 if document.body[l] != "":
3748 del_layout_after = False
3751 if del_layout_after:
3752 del document.body[k+1:layout_after+1]
3754 document.body[k+1:k+1] = [layout_line, ""]
3756 # delete \begin_layout and \end_inset and replace \begin_inset with
3757 # "\begin_layout XXX". This works because we can only have one
3758 # paragraph in the caption inset: The old \end_layout will be recycled.
3759 del document.body[k]
3760 if document.body[k] == "":
3761 del document.body[k]
3762 del document.body[j]
3763 if document.body[j] == "":
3764 del document.body[j]
3765 document.body[i] = "\\begin_layout %s" % caption_dict[val]
3766 if document.body[i+1] == "":
3767 del document.body[i+1]
3771 def revert_fragileframe(document):
3772 " Reverts beamer FragileFrame layout to ERT "
3774 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3775 if document.textclass not in beamer_classes:
3780 i = find_token(document.body, "\\begin_layout FragileFrame", i)
3783 # Find end of sequence
3784 j = find_end_of_sequence(document.body, i)
3786 document.warning("Malformed LyX document. Cannot find end of FragileFrame sequence!")
3790 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{frame}")
3791 esubst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\end{frame}")
3792 endseq = endseq + len(esubst) - len(document.body[j : j])
3793 if document.body[j] == "\\end_deeper":
3794 document.body[j : j] = [""] + esubst + ["", "\\end_layout"]
3796 document.body[j : j] = esubst
3797 for q in range(i, j):
3798 if document.body[q] == "\\begin_layout FragileFrame":
3799 document.body[q] = "\\begin_layout %s" % document.default_layout
3802 if document.body[r] == "\\begin_deeper":
3803 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3805 document.body[r] = ""
3806 document.body[s] = ""
3810 for p in range(1, 5):
3811 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, j)
3814 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3815 endPlain = find_end_of_layout(document.body, beginPlain)
3816 endInset = find_end_of_inset(document.body, arg)
3817 content = document.body[beginPlain + 1 : endPlain]
3819 j = j - len(document.body[arg : endInset + 1])
3821 del document.body[arg : endInset + 1]
3822 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3824 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3825 endPlain = find_end_of_layout(document.body, beginPlain)
3826 endInset = find_end_of_inset(document.body, arg)
3827 content = document.body[beginPlain + 1 : endPlain]
3829 j = j - len(document.body[arg : endInset + 1])
3831 del document.body[arg : endInset + 1]
3832 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3834 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3835 endPlain = find_end_of_layout(document.body, beginPlain)
3836 endInset = find_end_of_inset(document.body, arg)
3837 content = document.body[beginPlain + 1 : endPlain]
3839 j = j - len(document.body[arg : endInset + 1])
3841 del document.body[arg : endInset + 1]
3842 subst += put_cmd_in_ert("[fragile,") + content + put_cmd_in_ert("]")
3844 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3845 endPlain = find_end_of_layout(document.body, beginPlain)
3846 endInset = find_end_of_inset(document.body, arg)
3847 content = document.body[beginPlain + 1 : endPlain]
3849 j = j - len(document.body[arg : endInset + 1])
3851 del document.body[arg : endInset + 1]
3852 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3854 subst += put_cmd_in_ert("[fragile]")
3856 document.body[i : i + 1] = subst
3860 def revert_newframes(document):
3861 " Reverts beamer Frame and PlainFrame layouts to old forms "
3863 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3864 if document.textclass not in beamer_classes:
3868 "Frame" : "BeginFrame",
3869 "PlainFrame" : "BeginPlainFrame",
3872 rx = re.compile(r'^\\begin_layout (\S+)$')
3875 i = find_token(document.body, "\\begin_layout", i)
3879 m = rx.match(document.body[i])
3883 if val not in list(frame_dict.keys()):
3886 # Find end of sequence
3887 j = find_end_of_sequence(document.body, i)
3889 document.warning("Malformed LyX document. Cannot find end of Frame sequence!")
3893 subst = ["\\begin_layout %s" % frame_dict[val]]
3894 esubst = ["", "\\begin_layout EndFrame", "", "\\end_layout"]
3895 endseq = endseq + len(esubst) - len(document.body[j : j])
3896 if document.body[j] == "\\end_deeper":
3897 document.body[j : j] = esubst
3899 document.body[j+1 : j+1] = esubst
3900 for q in range(i, j):
3901 if document.body[q] == "\\begin_layout %s" % val:
3902 document.body[q] = "\\begin_layout %s" % document.default_layout
3905 if document.body[r] == "\\begin_deeper":
3906 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3908 document.body[r] = ""
3909 document.body[s] = ""
3913 l = find_end_of_layout(document.body, i)
3914 for p in range(1, 5):
3915 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, l)
3918 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3919 endPlain = find_end_of_layout(document.body, beginPlain)
3920 endInset = find_end_of_inset(document.body, arg)
3921 content = document.body[beginPlain + 1 : endPlain]
3923 l = l - len(document.body[arg : endInset + 1])
3925 del document.body[arg : endInset + 1]
3926 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3928 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3929 endPlain = find_end_of_layout(document.body, beginPlain)
3930 endInset = find_end_of_inset(document.body, arg)
3931 content = document.body[beginPlain + 1 : endPlain]
3933 l = l - len(document.body[arg : endInset + 1])
3935 del document.body[arg : endInset + 1]
3936 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3938 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3939 endPlain = find_end_of_layout(document.body, beginPlain)
3940 endInset = find_end_of_inset(document.body, arg)
3941 content = document.body[beginPlain + 1 : endPlain]
3943 l = l - len(document.body[arg : endInset + 1])
3945 del document.body[arg : endInset + 1]
3946 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3948 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3949 endPlain = find_end_of_layout(document.body, beginPlain)
3950 endInset = find_end_of_inset(document.body, arg)
3951 content = document.body[beginPlain + 1 : endPlain]
3953 l = l - len(document.body[arg : endInset + 1])
3955 del document.body[arg : endInset + 1]
3958 document.body[i : i + 1] = subst
3961 # known encodings that do not change their names (same LyX and LaTeX names)
3962 known_enc_tuple = ("auto", "default", "ansinew", "applemac", "armscii8", "ascii",
3963 "cp437", "cp437de", "cp850", "cp852", "cp855", "cp858", "cp862", "cp865", "cp866",
3964 "cp1250", "cp1251", "cp1252", "cp1255", "cp1256", "cp1257", "koi8-r", "koi8-u",
3965 "pt154", "pt254", "tis620-0", "utf8", "utf8x", "utf8-plain")
3967 def convert_encodings(document):
3968 "Use the LyX names of the encodings instead of the LaTeX names."
3969 LaTeX2LyX_enc_dict = {
3970 "8859-6": "iso8859-6",
3971 "8859-8": "iso8859-8",
3973 "euc": "euc-jp-platex",
3978 "iso88595": "iso8859-5",
3979 "iso-8859-7": "iso8859-7",
3981 "jis": "jis-platex",
3983 "l7xenc": "iso8859-13",
3984 "latin1": "iso8859-1",
3985 "latin2": "iso8859-2",
3986 "latin3": "iso8859-3",
3987 "latin4": "iso8859-4",
3988 "latin5": "iso8859-9",
3989 "latin9": "iso8859-15",
3990 "latin10": "iso8859-16",
3991 "SJIS": "shift-jis",
3992 "sjis": "shift-jis-platex",
3995 i = find_token(document.header, "\\inputencoding" , 0)
3998 val = get_value(document.header, "\\inputencoding", i)
3999 if val in list(LaTeX2LyX_enc_dict.keys()):
4000 document.header[i] = "\\inputencoding %s" % LaTeX2LyX_enc_dict[val]
4001 elif val not in known_enc_tuple:
4002 document.warning("Ignoring unknown input encoding: `%s'" % val)
4005 def revert_encodings(document):
4006 """Revert to using the LaTeX names of the encodings instead of the LyX names.
4007 Also revert utf8-platex to sjis, the language default when using Japanese.
4009 LyX2LaTeX_enc_dict = {
4014 "euc-jp-platex": "euc",
4017 "iso8859-1": "latin1",
4018 "iso8859-2": "latin2",
4019 "iso8859-3": "latin3",
4020 "iso8859-4": "latin4",
4021 "iso8859-5": "iso88595",
4022 "iso8859-6": "8859-6",
4023 "iso8859-7": "iso-8859-7",
4024 "iso8859-8": "8859-8",
4025 "iso8859-9": "latin5",
4026 "iso8859-13": "l7xenc",
4027 "iso8859-15": "latin9",
4028 "iso8859-16": "latin10",
4030 "jis-platex": "jis",
4031 "shift-jis": "SJIS",
4032 "shift-jis-platex": "sjis",
4034 "utf8-platex": "sjis"
4036 i = find_token(document.header, "\\inputencoding" , 0)
4039 val = get_value(document.header, "\\inputencoding", i)
4040 if val in list(LyX2LaTeX_enc_dict.keys()):
4041 document.header[i] = "\\inputencoding %s" % LyX2LaTeX_enc_dict[val]
4042 elif val not in known_enc_tuple:
4043 document.warning("Ignoring unknown input encoding: `%s'" % val)
4046 def revert_IEEEtran_3(document):
4048 Reverts Flex Insets to TeX-code
4050 if document.textclass == "IEEEtran":
4056 h = find_token(document.body, "\\begin_inset Flex Author Mark", h)
4058 endh = find_end_of_inset(document.body, h)
4059 document.body[endh - 2 : endh + 1] = put_cmd_in_ert("}")
4060 document.body[h : h + 4] = put_cmd_in_ert("\\IEEEauthorrefmark{")
4063 i = find_token(document.body, "\\begin_inset Flex Author Name", i)
4065 endi = find_end_of_inset(document.body, i)
4066 document.body[endi - 2 : endi + 1] = put_cmd_in_ert("}")
4067 document.body[i : i + 4] = put_cmd_in_ert("\\IEEEauthorblockN{")
4070 j = find_token(document.body, "\\begin_inset Flex Author Affiliation", j)
4072 endj = find_end_of_inset(document.body, j)
4073 document.body[endj - 2 : endj + 1] = put_cmd_in_ert("}")
4074 document.body[j : j + 4] = put_cmd_in_ert("\\IEEEauthorblockA{")
4076 if i == -1 and j == -1 and h == -1:
4080 def revert_kurier_fonts(document):
4081 " Revert kurier font definition to LaTeX "
4083 i = find_token(document.header, "\\font_math", 0)
4085 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4086 val = get_value(document.header, "\\font_math", i)
4087 if val == "kurier-math":
4088 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
4089 "\\usepackage[math]{kurier}\n" \
4090 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
4091 document.header[i] = "\\font_math auto"
4093 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4094 kurier_fonts = ["kurier", "kurierc", "kurierl", "kurierlc"]
4095 k = find_token(document.header, "\\font_sans kurier", 0)
4097 sf = get_value(document.header, "\\font_sans", k)
4098 if sf in kurier_fonts:
4099 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4100 document.header[k] = "\\font_sans default"
4102 def revert_iwona_fonts(document):
4103 " Revert iwona font definition to LaTeX "
4105 i = find_token(document.header, "\\font_math", 0)
4107 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4108 val = get_value(document.header, "\\font_math", i)
4109 if val == "iwona-math":
4110 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
4111 "\\usepackage[math]{iwona}\n" \
4112 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
4113 document.header[i] = "\\font_math auto"
4115 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
4116 iwona_fonts = ["iwona", "iwonac", "iwonal", "iwonalc"]
4117 k = find_token(document.header, "\\font_sans iwona", 0)
4119 sf = get_value(document.header, "\\font_sans", k)
4120 if sf in iwona_fonts:
4121 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
4122 document.header[k] = "\\font_sans default"
4125 def revert_new_libertines(document):
4126 " Revert new libertine font definition to LaTeX "
4128 if find_token(document.header, "\\use_non_tex_fonts true", 0) != -1:
4131 i = find_token(document.header, "\\font_typewriter libertine-mono", 0)
4133 preamble = "\\usepackage"
4134 sc = find_token(document.header, "\\font_tt_scale", 0)
4136 scval = get_value(document.header, "\\font_tt_scale", sc)
4138 preamble += "[scale=%f]" % (float(scval) / 100)
4139 document.header[sc] = "\\font_tt_scale 100"
4140 preamble += "{libertineMono-type1}"
4141 add_to_preamble(document, [preamble])
4142 document.header[i] = "\\font_typewriter default"
4144 k = find_token(document.header, "\\font_sans biolinum", 0)
4146 preamble = "\\usepackage"
4148 j = find_token(document.header, "\\font_osf true", 0)
4153 sc = find_token(document.header, "\\font_sf_scale", 0)
4155 scval = get_value(document.header, "\\font_sf_scale", sc)
4157 options += ",scale=%f" % (float(scval) / 100)
4158 document.header[sc] = "\\font_sf_scale 100"
4160 preamble += "[" + options +"]"
4161 preamble += "{biolinum-type1}"
4162 add_to_preamble(document, [preamble])
4163 document.header[k] = "\\font_sans default"
4166 def convert_lyxframes(document):
4167 " Converts old beamer frames to new style "
4169 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4170 if document.textclass not in beamer_classes:
4173 framebeg = ["BeginFrame", "BeginPlainFrame"]
4174 frameend = ["Frame", "PlainFrame", "EndFrame", "BeginFrame", "BeginPlainFrame", "AgainFrame",
4175 "Section", "Section*", "Subsection", "Subsection*", "Subsubsection", "Subsubsection*"]
4176 for lay in framebeg:
4179 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
4182 parent = get_containing_layout(document.body, i)
4183 if parent == False or parent[1] != i:
4184 document.warning("Wrong parent layout!")
4187 frametype = parent[0]
4191 # Step I: Convert ERT arguments
4192 # FIXME: See restrictions in convert_beamerframeargs method
4193 ertend = convert_beamerframeargs(document, i, parbeg)
4196 # Step II: Now rename the layout and convert the title to an argument
4197 j = find_end_of_layout(document.body, i)
4198 document.body[j : j + 1] = ['\\end_layout', '', '\\end_inset', '', '\\end_layout']
4199 if lay == "BeginFrame":
4200 document.body[i] = "\\begin_layout Frame"
4202 document.body[i] = "\\begin_layout PlainFrame"
4203 document.body[ertend + 1 : ertend + 1] = ['\\begin_inset Argument 4',
4204 'status open', '', '\\begin_layout Plain Layout']
4205 # Step III: find real frame end
4208 inInset = get_containing_inset(document.body, i)
4210 fend = find_token(document.body, "\\begin_layout", jj)
4212 document.warning("Malformed LyX document: No real frame end!")
4214 val = get_value(document.body, "\\begin_layout", fend)
4215 if val not in frameend:
4218 # is this frame nested in an inset (e.g., Note)?
4219 if inInset != False:
4220 # if so, end the frame inside the inset
4221 if inInset[2] < fend:
4223 if val == frametype:
4224 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4225 # consider explicit EndFrames between two identical frame types
4226 elif val == "EndFrame":
4227 nextlayout = find_token(document.body, "\\begin_layout", fend + 1)
4228 if nextlayout != -1 and get_value(document.body, "\\begin_layout", nextlayout) == frametype:
4229 document.body[fend : fend] = ['\\end_deeper', '', '\\begin_layout Separator', '', '\\end_layout']
4231 document.body[fend : fend] = ['\\end_deeper']
4233 document.body[fend : fend] = ['\\end_deeper']
4234 document.body[j + 1 : j + 1] = ['', '\\begin_deeper']
4239 def remove_endframes(document):
4240 " Remove deprecated beamer endframes "
4242 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
4243 if document.textclass not in beamer_classes:
4248 i = find_token_exact(document.body, "\\begin_layout EndFrame", i)
4251 j = find_end_of_layout(document.body, i)
4253 document.warning("Malformed LyX document: Missing \\end_layout to EndFrame")
4256 del document.body[i : j + 1]
4259 def revert_powerdot_flexes(document):
4260 " Reverts powerdot flex insets "
4262 if document.textclass != "powerdot":
4265 flexes = {"Onslide" : "\\onslide",
4266 "Onslide*" : "\\onslide*",
4267 "Onslide+" : "\\onslide+"}
4268 rx = re.compile(r'^\\begin_inset Flex (.+)$')
4272 i = find_token(document.body, "\\begin_inset Flex", i)
4275 m = rx.match(document.body[i])
4277 flextype = m.group(1)
4278 z = find_end_of_inset(document.body, i)
4280 document.warning("Can't find end of Flex " + flextype + " inset.")
4283 if flextype in flexes:
4284 pre = put_cmd_in_ert(flexes[flextype])
4285 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
4287 argend = find_end_of_inset(document.body, arg)
4289 document.warning("Can't find end of Argument!")
4292 # Find containing paragraph layout
4293 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
4294 endPlain = find_end_of_layout(document.body, beginPlain)
4295 argcontent = document.body[beginPlain + 1 : endPlain]
4297 z = z - len(document.body[arg : argend + 1])
4299 del document.body[arg : argend + 1]
4300 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
4301 pre += put_cmd_in_ert("{")
4302 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4303 endPlain = find_end_of_layout(document.body, beginPlain)
4305 z = z - len(document.body[i : beginPlain + 1])
4307 document.body[i : beginPlain + 1] = pre
4308 post = put_cmd_in_ert("}")
4309 document.body[z - 2 : z + 1] = post
4313 def revert_powerdot_pause(document):
4314 " Reverts powerdot pause layout to ERT "
4316 if document.textclass != "powerdot":
4321 i = find_token(document.body, "\\begin_layout Pause", i)
4324 j = find_end_of_layout(document.body, i)
4326 document.warning("Malformed LyX document: Can't find end of Pause layout")
4330 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\pause")
4331 for p in range(i, j):
4334 arg = find_token(document.body, "\\begin_inset Argument 1", i, j)
4336 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4337 endPlain = find_end_of_layout(document.body, beginPlain)
4338 endInset = find_end_of_inset(document.body, p)
4339 content = document.body[beginPlain + 1 : endPlain]
4341 endlay = endlay - len(document.body[p : endInset + 1])
4343 del document.body[p : endInset + 1]
4344 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4346 document.body[i : i + 1] = subst
4350 def revert_powerdot_itemargs(document):
4351 " Reverts powerdot item arguments to ERT "
4353 if document.textclass != "powerdot":
4357 list_layouts = ["Itemize", "ItemizeType1", "Enumerate", "EnumerateType1"]
4358 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4361 i = find_token(document.body, "\\begin_inset Argument", i)
4364 # Find containing paragraph layout
4365 parent = get_containing_layout(document.body, i)
4367 document.warning("Malformed LyX document: Can't find parent paragraph layout")
4372 realparbeg = parent[3]
4373 layoutname = parent[0]
4375 for p in range(parbeg, parend):
4379 if layoutname in list_layouts:
4380 m = rx.match(document.body[p])
4383 if argnr == "item:1":
4384 j = find_end_of_inset(document.body, i)
4385 # Find containing paragraph layout
4386 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4387 endPlain = find_end_of_layout(document.body, beginPlain)
4388 content = document.body[beginPlain + 1 : endPlain]
4389 del document.body[i:j+1]
4390 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4391 document.body[realparbeg : realparbeg] = subst
4392 elif argnr == "item:2":
4393 j = find_end_of_inset(document.body, i)
4394 # Find containing paragraph layout
4395 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
4396 endPlain = find_end_of_layout(document.body, beginPlain)
4397 content = document.body[beginPlain + 1 : endPlain]
4398 del document.body[i:j+1]
4399 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
4400 document.body[realparbeg : realparbeg] = subst
4405 def revert_powerdot_columns(document):
4406 " Reverts powerdot twocolumn to TeX-code "
4407 if document.textclass != "powerdot":
4410 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
4413 i = find_token(document.body, "\\begin_layout Twocolumn", i)
4416 j = find_end_of_layout(document.body, i)
4418 document.warning("Malformed LyX document: Can't find end of Twocolumn layout")
4422 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
4423 endlay += len(put_cmd_in_ert("}"))
4424 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\twocolumn")
4425 for p in range(i, j):
4428 m = rx.match(document.body[p])
4432 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4433 endPlain = find_end_of_layout(document.body, beginPlain)
4434 endInset = find_end_of_inset(document.body, p)
4435 content = document.body[beginPlain + 1 : endPlain]
4437 endlay = endlay - len(document.body[p : endInset + 1])
4439 del document.body[p : endInset + 1]
4440 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
4442 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
4443 endPlain = find_end_of_layout(document.body, beginPlain)
4444 endInset = find_end_of_inset(document.body, p)
4445 content = document.body[beginPlain + 1 : endPlain]
4447 endlay = endlay - len(document.body[p : endInset + 1])
4449 del document.body[p : endInset + 1]
4450 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
4452 subst += put_cmd_in_ert("{")
4453 document.body[i : i + 1] = subst
4457 def revert_mbox_fbox(document):
4458 'Convert revert mbox/fbox boxes to TeX-code'
4461 i = find_token(document.body, "\\begin_inset Box", i)
4464 j = find_token(document.body, "width", i)
4466 document.warning("Malformed LyX document: Can't find box width")
4468 width = get_value(document.body, "width", j)
4469 k = find_end_of_inset(document.body, j)
4471 document.warning("Malformed LyX document: Can't find end of box inset")
4474 BeginLayout = find_token(document.body, "\\begin_layout Plain Layout", j)
4475 EndLayout = find_end_of_layout(document.body, BeginLayout)
4476 # replace if width is ""
4478 document.body[EndLayout:k + 1] = put_cmd_in_ert("}")
4479 if document.body[i] == "\\begin_inset Box Frameless":
4480 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\mbox{")
4481 if document.body[i] == "\\begin_inset Box Boxed":
4482 document.body[i:BeginLayout + 1] = put_cmd_in_ert("\\fbox{")
4486 def revert_starred_caption(document):
4487 " Reverts unnumbered longtable caption insets "
4491 i = find_token(document.body, "\\begin_inset Caption LongTableNoNumber", i)
4494 # This is not equivalent, but since the caption inset is a full blown
4495 # text inset a true conversion to ERT is too difficult.
4496 document.body[i] = "\\begin_inset Caption Standard"
4500 def revert_forced_local_layout(document):
4503 i = find_token(document.header, "\\begin_forced_local_layout", i)
4506 j = find_end_of(document.header, i, "\\begin_forced_local_layout", "\\end_forced_local_layout")
4508 # this should not happen
4510 regexp = re.compile(r'\s*forcelocal', re.IGNORECASE)
4511 k = find_re(document.header, regexp, i, j)
4513 del document.header[k]
4515 k = find_re(document.header, regexp, i, j)
4516 k = find_token(document.header, "\\begin_local_layout", 0)
4518 document.header[i] = "\\begin_local_layout"
4519 document.header[j] = "\\end_local_layout"
4521 l = find_end_of(document.header, k, "\\begin_local_layout", "\\end_local_layout")
4523 # this should not happen
4525 lines = document.header[i+1 : j]
4527 document.header[k+1 : k+1] = lines
4528 document.header[i : j ] = []
4530 document.header[i : j ] = []
4531 document.header[k+1 : k+1] = lines
4534 def revert_aa1(document):
4535 " Reverts InsetArguments of aa to TeX-code "
4536 if document.textclass == "aa":
4540 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4542 revert_Argument_to_TeX_brace(document, i, 0, 1, 4, False, False)
4548 def revert_aa2(document):
4549 " Reverts InsetArguments of aa to TeX-code "
4550 if document.textclass == "aa":
4554 i = find_token(document.body, "\\begin_layout Abstract (structured)", i)
4556 document.body[i] = "\\begin_layout Abstract"
4562 def revert_tibetan(document):
4563 "Set the document language for Tibetan to English"
4565 if document.language == "tibetan":
4566 document.language = "english"
4567 i = find_token(document.header, "\\language", 0)
4569 document.header[i] = "\\language english"
4571 while j < len(document.body):
4572 j = find_token(document.body, "\\lang tibetan", j)
4574 document.body[j] = document.body[j].replace("\\lang tibetan", "\\lang english")
4577 j = len(document.body)
4586 # The idea here is that we will have a sequence of chunk paragraphs.
4587 # We want to convert them to paragraphs in one or several chunk insets.
4588 # Individual chunks are terminated by the character @ on the last line.
4589 # This line will be discarded, and following lines are treated as new
4590 # chunks, which go into their own insets.
4591 # The first line of a chunk should look like: <<CONTENT>>=
4592 # We will discard the delimiters, and put the CONTENT into the
4593 # optional argument of the inset, if the CONTENT is non-empty.
4594 def convert_chunks(document):
4595 first_re = re.compile(r'<<(.*)>>=(.*)')
4598 # find start of a block of chunks
4599 i = find_token(document.body, "\\begin_layout Chunk", file_pos)
4605 chunk_started = False
4608 # process the one we just found
4609 j = find_end_of_layout(document.body, i)
4611 document.warning("Malformed LyX documents. Can't find end of Chunk layout!")
4612 # there is no point continuing, as we will run into the same error again.
4614 this_chunk = "".join(document.body[i + 1:j])
4616 # there may be empty lines between chunks
4617 # we just skip them.
4618 if not chunk_started:
4619 if this_chunk != "":
4621 chunk_started = True
4624 contents.append(document.body[i + 1:j])
4626 # look for potential chunk terminator
4627 # on the last line of the chunk paragraph
4628 if document.body[j - 1] == "@":
4631 # look for subsequent chunk paragraph
4632 i = find_token(document.body, "\\begin_layout", j)
4636 if get_value(document.body, "\\begin_layout", i) != "Chunk":
4639 file_pos = end = j + 1
4641 # The last chunk should simply have an "@" in it
4642 # or at least end with "@" (can happen if @ is
4643 # preceded by a newline)
4645 if len(contents) > 0:
4646 lastpar = ''.join(contents[-1])
4647 if not lastpar.endswith("@"):
4648 document.warning("Unexpected chunk content: chunk not terminated by '@'!")
4649 if len(contents) == 0:
4650 # convert empty chunk layouts to Standard
4651 document.body[start] = "\\begin_layout Standard"
4655 # chunk par only contains "@". Just drop it.
4658 # chunk par contains more. Only drop the "@".
4661 # The first line should look like: <<CONTENT>>=
4662 # We want the CONTENT
4663 optarg = ' '.join(contents[0])
4665 # We can already have real chunk content in
4666 # the first par (separated from the options by a newline).
4667 # We collect such stuff to re-insert it later.
4670 match = first_re.search(optarg)
4672 optarg = match.groups()[0]
4673 if match.groups()[1] != "":
4675 for c in contents[0]:
4676 if c.endswith(">>="):
4680 postoptstuff.append(c)
4681 # We have stripped everything. This can be deleted.
4684 newstuff = ['\\begin_layout Standard']
4686 # Maintain paragraph parameters
4687 par_params = ["\\noindent", "\\indent", "\\indent-toggle", "\\leftindent",
4688 "\\start_of_appendix", "\\paragraph_spacing", "\\align",
4689 "\\labelwidthstring"]
4692 if document.body[parms].split(' ', 1)[0] not in par_params:
4694 newstuff.extend([document.body[parms]])
4698 ['\\begin_inset Flex Chunk',
4700 '\\begin_layout Plain Layout', ''])
4702 # If we have a non-empty optional argument, insert it.
4703 if match and optarg != "":
4705 ['\\begin_inset Argument 1',
4707 '\\begin_layout Plain Layout',
4712 # Since we already opened a Plain layout, the first paragraph
4713 # does not need to do that.
4716 # we need to replace newlines with new layouts
4718 started_text = False
4719 for lno in range(0,len(postoptstuff)):
4720 if postoptstuff[lno].startswith("\\begin_inset Newline newline"):
4722 elif start_newline != -1:
4723 if postoptstuff[lno].startswith("\\end_inset"):
4724 # replace that bit, but only if we already have some text
4725 # and we're not at the end except for a blank line
4726 if started_text and \
4727 (lno != len(postoptstuff) - 2 or postoptstuff[-1] != ""):
4728 newstuff.extend(['\\end_layout', '\n', '\\begin_layout Plain Layout', '\n'])
4732 newstuff.extend([postoptstuff[lno]])
4733 newstuff.append('\\end_layout')
4737 newstuff.extend(['', '\\begin_layout Plain Layout', ''])
4741 newstuff.append('\\end_layout')
4743 newstuff.extend(['', '\\end_inset', '', '\\end_layout', ''])
4745 document.body[start:end] = newstuff
4747 file_pos += len(newstuff) - (end - start)
4750 def revert_chunks(document):
4753 i = find_token(document.body, "\\begin_inset Flex Chunk", i)
4757 iend = find_end_of_inset(document.body, i)
4759 document.warning("Can't find end of Chunk!")
4763 # Look for optional argument
4765 ostart = find_token(document.body, "\\begin_inset Argument 1", i, iend)
4767 oend = find_end_of_inset(document.body, ostart)
4768 k = find_token(document.body, "\\begin_layout Plain Layout", ostart, oend)
4770 document.warning("Malformed LyX document: Can't find argument contents!")
4772 m = find_end_of_layout(document.body, k)
4773 optarg = "".join(document.body[k+1:m])
4775 # We now remove the optional argument, so we have something
4776 # uniform on which to work
4777 document.body[ostart : oend + 1] = []
4778 # iend is now invalid
4779 iend = find_end_of_inset(document.body, i)
4781 retval = get_containing_layout(document.body, i)
4783 document.warning("Can't find containing layout for Chunk!")
4786 (lname, lstart, lend, pstart) = retval
4787 # we now want to work through the various paragraphs, and collect their contents
4791 k = find_token(document.body, "\\begin_layout Plain Layout", k, lend)
4794 j = find_end_of_layout(document.body, k)
4796 document.warning("Can't find end of layout inside chunk!")
4798 parlist.append(document.body[k+1:j])
4800 # we now need to wrap all of these paragraphs in chunks
4802 newlines.extend(["\\begin_layout Chunk", "", "<<" + optarg + ">>=", "\\end_layout", ""])
4803 for stuff in parlist:
4804 newlines.extend(["\\begin_layout Chunk"] + stuff + ["\\end_layout", ""])
4805 newlines.extend(["\\begin_layout Chunk", "", "@", "\\end_layout", ""])
4806 # replace old content with new content
4807 document.body[lstart : lend + 1] = newlines
4808 i = lstart + len(newlines)
4815 supported_versions = ["2.1.0","2.1"]
4818 [415, [convert_undertilde]],
4820 [417, [convert_japanese_encodings]],
4821 [418, [convert_justification]],
4823 [420, [convert_biblio_style]],
4824 [421, [convert_longtable_captions]],
4825 [422, [convert_use_packages]],
4826 [423, [convert_use_mathtools]],
4827 [424, [convert_cite_engine_type]],
4828 # No convert_cancel, since cancel will be loaded automatically
4829 # in format 425 without any possibility to switch it off.
4830 # This has been fixed in format 464.
4834 [428, [convert_cell_rotation]],
4835 [429, [convert_table_rotation]],
4836 [430, [convert_listoflistings]],
4837 [431, [convert_use_amssymb]],
4839 [433, [convert_armenian]],
4846 [440, [convert_mathfonts]],
4847 [441, [convert_mdnomath]],
4852 [446, [convert_latexargs]],
4853 [447, [convert_IEEEtran, convert_AASTeX, convert_AGUTeX, convert_IJMP, convert_SIGPLAN, convert_SIGGRAPH, convert_EuropeCV, convert_Initials, convert_ModernCV]],
4854 [448, [convert_literate]],
4857 [451, [convert_beamerargs, convert_againframe_args, convert_corollary_args, convert_quote_args]],
4858 [452, [convert_beamerblocks]],
4859 [453, [convert_use_stmaryrd]],
4860 [454, [convert_overprint]],
4862 [456, [convert_epigraph]],
4863 [457, [convert_use_stackrel]],
4864 [458, [convert_captioninsets, convert_captionlayouts]],
4869 [463, [convert_encodings]],
4870 [464, [convert_use_cancel]],
4871 [465, [convert_lyxframes, remove_endframes]],
4877 [471, [convert_cite_engine_type_default]],
4880 [474, [convert_chunks, cleanup_beamerargs]],
4884 [473, [revert_chunks]],
4885 [472, [revert_tibetan]],
4886 [471, [revert_aa1,revert_aa2]],
4887 [470, [revert_cite_engine_type_default]],
4888 [469, [revert_forced_local_layout]],
4889 [468, [revert_starred_caption]],
4890 [467, [revert_mbox_fbox]],
4891 [466, [revert_iwona_fonts]],
4892 [465, [revert_powerdot_flexes, revert_powerdot_pause, revert_powerdot_itemargs, revert_powerdot_columns]],
4894 [463, [revert_use_cancel]],
4895 [462, [revert_encodings]],
4896 [461, [revert_new_libertines]],
4897 [460, [revert_kurier_fonts]],
4898 [459, [revert_IEEEtran_3]],
4899 [458, [revert_fragileframe, revert_newframes]],
4900 [457, [revert_captioninsets, revert_captionlayouts]],
4901 [456, [revert_use_stackrel]],
4902 [455, [revert_epigraph]],
4903 [454, [revert_frametitle]],
4904 [453, [revert_overprint]],
4905 [452, [revert_use_stmaryrd]],
4906 [451, [revert_beamerblocks]],
4907 [450, [revert_beamerargs, revert_beamerargs2, revert_beamerargs3, revert_beamerflex]],
4908 [449, [revert_garamondx, revert_garamondx_newtxmath]],
4909 [448, [revert_itemargs]],
4910 [447, [revert_literate]],
4911 [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]],
4912 [445, [revert_latexargs]],
4913 [444, [revert_uop]],
4914 [443, [revert_biolinum]],
4916 [441, [revert_newtxmath]],
4917 [440, [revert_mdnomath]],
4918 [439, [revert_mathfonts]],
4919 [438, [revert_minionpro]],
4920 [437, [revert_ipadeco, revert_ipachar]],
4921 [436, [revert_texgyre]],
4922 [435, [revert_mathdesign]],
4923 [434, [revert_txtt]],
4924 [433, [revert_libertine]],
4925 [432, [revert_armenian]],
4926 [431, [revert_languages, revert_ancientgreek]],
4927 [430, [revert_use_amssymb]],
4928 [429, [revert_listoflistings]],
4929 [428, [revert_table_rotation]],
4930 [427, [revert_cell_rotation]],
4931 [426, [revert_tipa]],
4932 [425, [revert_verbatim]],
4933 [424, [revert_cancel]],
4934 [423, [revert_cite_engine_type]],
4935 [422, [revert_use_mathtools]],
4936 [421, [revert_use_packages]],
4937 [420, [revert_longtable_captions]],
4938 [419, [revert_biblio_style]],
4939 [418, [revert_australian]],
4940 [417, [revert_justification]],
4941 [416, [revert_japanese_encodings]],
4942 [415, [revert_negative_space, revert_math_spaces]],
4943 [414, [revert_undertilde]],
4944 [413, [revert_visible_space]]
4948 if __name__ == "__main__":