1 # -*- coding: utf-8 -*-
2 # This file is part of lyx2lyx
3 # -*- coding: utf-8 -*-
4 # Copyright (C) 2011 The LyX team
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 """ Convert files to the file format generated by lyx 2.1"""
26 # Uncomment only what you need to import, please.
28 from parser_tools import count_pars_in_inset, del_token, find_token, find_token_exact, \
29 find_token_backwards, find_end_of, find_end_of_inset, find_end_of_layout, \
30 find_end_of_sequence, find_re, get_option_value, get_containing_layout, \
31 get_value, get_quoted_value, set_option_value
33 #from parser_tools import find_token, find_end_of, find_tokens, \
34 #find_end_of_inset, find_end_of_layout, \
35 #is_in_inset, del_token, check_token
37 from lyx2lyx_tools import add_to_preamble, put_cmd_in_ert, get_ert
39 #from lyx2lyx_tools import insert_to_preamble, \
40 # lyx2latex, latex_length, revert_flex_inset, \
41 # revert_font_attrs, hex2ratio, str2bool
43 ####################################################################
44 # Private helper functions
46 #def remove_option(lines, m, option):
47 #''' removes option from line m. returns whether we did anything '''
48 #l = lines[m].find(option)
51 #val = lines[m][l:].split('"')[1]
52 #lines[m] = lines[m][:l - 1] + lines[m][l+len(option + '="' + val + '"'):]
56 ###############################################################################
58 ### Conversion and reversion routines
60 ###############################################################################
62 def revert_visible_space(document):
63 "Revert InsetSpace visible into its ERT counterpart"
66 i = find_token(document.body, "\\begin_inset space \\textvisiblespace{}", i)
69 end = find_end_of_inset(document.body, i)
70 subst = put_cmd_in_ert("\\textvisiblespace{}")
71 document.body[i:end + 1] = subst
74 def convert_undertilde(document):
75 " Load undertilde automatically "
76 i = find_token(document.header, "\\use_mathdots" , 0)
78 i = find_token(document.header, "\\use_mhchem" , 0)
80 i = find_token(document.header, "\\use_esint" , 0)
82 document.warning("Malformed LyX document: Can't find \\use_mathdots.")
84 j = find_token(document.preamble, "\\usepackage{undertilde}", 0)
86 document.header.insert(i + 1, "\\use_undertilde 0")
88 document.header.insert(i + 1, "\\use_undertilde 2")
89 del document.preamble[j]
92 def revert_undertilde(document):
93 " Load undertilde if used in the document "
94 undertilde = find_token(document.header, "\\use_undertilde" , 0)
96 document.warning("No \\use_undertilde line. Assuming auto.")
98 val = get_value(document.header, "\\use_undertilde", undertilde)
99 del document.header[undertilde]
103 document.warning("Invalid \\use_undertilde value: " + val + ". Assuming auto.")
104 # probably usedots has not been changed, but be safe.
112 add_to_preamble(document, ["\\usepackage{undertilde}"])
115 # so we are in the auto case. we want to load undertilde if \utilde is used.
118 i = find_token(document.body, '\\begin_inset Formula', i)
121 j = find_end_of_inset(document.body, i)
123 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
126 code = "\n".join(document.body[i:j])
127 if code.find("\\utilde") != -1:
128 add_to_preamble(document, ["\\@ifundefined{utilde}{\\usepackage{undertilde}}"])
133 def revert_negative_space(document):
134 "Revert InsetSpace negmedspace and negthickspace into its TeX-code counterpart"
139 i = find_token(document.body, "\\begin_inset space \\negmedspace{}", i)
141 j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
143 # load amsmath in the preamble if not already loaded if we are at the end of checking
145 i = find_token(document.header, "\\use_amsmath 2", 0)
147 add_to_preamble(document, ["\\@ifundefined{negthickspace}{\\usepackage{amsmath}}"])
151 end = find_end_of_inset(document.body, i)
152 subst = put_cmd_in_ert("\\negmedspace{}")
153 document.body[i:end + 1] = subst
154 j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
157 end = find_end_of_inset(document.body, j)
158 subst = put_cmd_in_ert("\\negthickspace{}")
159 document.body[j:end + 1] = subst
163 def revert_math_spaces(document):
164 "Revert formulas with protected custom space and protected hfills to TeX-code"
167 i = find_token(document.body, "\\begin_inset Formula", i)
170 j = document.body[i].find("\\hspace*")
172 end = find_end_of_inset(document.body, i)
173 subst = put_cmd_in_ert(document.body[i][21:])
174 document.body[i:end + 1] = subst
178 def convert_japanese_encodings(document):
179 " Rename the japanese encodings to names understood by platex "
181 "EUC-JP-pLaTeX": "euc",
183 "SJIS-pLaTeX": "sjis"
185 i = find_token(document.header, "\\inputencoding" , 0)
188 val = get_value(document.header, "\\inputencoding", i)
189 if val in jap_enc_dict.keys():
190 document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
193 def revert_japanese_encodings(document):
194 " Revert the japanese encodings name changes "
196 "euc": "EUC-JP-pLaTeX",
198 "sjis": "SJIS-pLaTeX"
200 i = find_token(document.header, "\\inputencoding" , 0)
203 val = get_value(document.header, "\\inputencoding", i)
204 if val in jap_enc_dict.keys():
205 document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
208 def revert_justification(document):
209 " Revert the \\justification buffer param"
210 if not del_token(document.header, '\\justification', 0):
211 document.warning("Malformed LyX document: Missing \\justification.")
214 def revert_australian(document):
215 "Set English language variants Australian and Newzealand to English"
217 if document.language == "australian" or document.language == "newzealand":
218 document.language = "english"
219 i = find_token(document.header, "\\language", 0)
221 document.header[i] = "\\language english"
224 j = find_token(document.body, "\\lang australian", j)
226 j = find_token(document.body, "\\lang newzealand", 0)
230 document.body[j] = document.body[j].replace("\\lang newzealand", "\\lang english")
232 document.body[j] = document.body[j].replace("\\lang australian", "\\lang english")
236 def convert_biblio_style(document):
237 "Add a sensible default for \\biblio_style based on the citation engine."
238 i = find_token(document.header, "\\cite_engine", 0)
240 engine = get_value(document.header, "\\cite_engine", i).split("_")[0]
241 style = {"basic": "plain", "natbib": "plainnat", "jurabib": "jurabib"}
242 document.header.insert(i + 1, "\\biblio_style " + style[engine])
245 def revert_biblio_style(document):
246 "BibTeX insets with default option use the style defined by \\biblio_style."
247 i = find_token(document.header, "\\biblio_style" , 0)
249 document.warning("No \\biblio_style line. Nothing to do.")
252 default_style = get_value(document.header, "\\biblio_style", i)
253 del document.header[i]
255 # We are looking for bibtex insets having the default option
258 i = find_token(document.body, "\\begin_inset CommandInset bibtex", i)
261 j = find_end_of_inset(document.body, i)
263 document.warning("Malformed LyX document: Can't find end of bibtex inset at line " + str(i))
266 k = find_token(document.body, "options", i, j)
268 options = get_quoted_value(document.body, "options", k)
269 if "default" in options.split(","):
270 document.body[k] = 'options "%s"' \
271 % options.replace("default", default_style)
275 def handle_longtable_captions(document, forward):
278 begin_table = find_token(document.body, '<lyxtabular version=', begin_table)
279 if begin_table == -1:
281 end_table = find_end_of(document.body, begin_table, '<lyxtabular', '</lyxtabular>')
283 document.warning("Malformed LyX document: Could not find end of table.")
286 fline = find_token(document.body, "<features", begin_table, end_table)
288 document.warning("Can't find features for inset at line " + str(begin_table))
291 p = document.body[fline].find("islongtable")
296 numrows = get_option_value(document.body[begin_table], "rows")
298 numrows = int(numrows)
300 document.warning(document.body[begin_table])
301 document.warning("Unable to determine rows!")
302 begin_table = end_table
304 begin_row = begin_table
305 for row in range(numrows):
306 begin_row = find_token(document.body, '<row', begin_row, end_table)
308 document.warning("Can't find row " + str(row + 1))
310 end_row = find_end_of(document.body, begin_row, '<row', '</row>')
312 document.warning("Can't find end of row " + str(row + 1))
315 if (get_option_value(document.body[begin_row], 'caption') == 'true' and
316 get_option_value(document.body[begin_row], 'endfirsthead') != 'true' and
317 get_option_value(document.body[begin_row], 'endhead') != 'true' and
318 get_option_value(document.body[begin_row], 'endfoot') != 'true' and
319 get_option_value(document.body[begin_row], 'endlastfoot') != 'true'):
320 document.body[begin_row] = set_option_value(document.body[begin_row], 'caption', 'true", endfirsthead="true')
321 elif get_option_value(document.body[begin_row], 'caption') == 'true':
322 if get_option_value(document.body[begin_row], 'endfirsthead') == 'true':
323 document.body[begin_row] = set_option_value(document.body[begin_row], 'endfirsthead', 'false')
324 if get_option_value(document.body[begin_row], 'endhead') == 'true':
325 document.body[begin_row] = set_option_value(document.body[begin_row], 'endhead', 'false')
326 if get_option_value(document.body[begin_row], 'endfoot') == 'true':
327 document.body[begin_row] = set_option_value(document.body[begin_row], 'endfoot', 'false')
328 if get_option_value(document.body[begin_row], 'endlastfoot') == 'true':
329 document.body[begin_row] = set_option_value(document.body[begin_row], 'endlastfoot', 'false')
331 # since there could be a tabular inside this one, we
332 # cannot jump to end.
336 def convert_longtable_captions(document):
337 "Add a firsthead flag to caption rows"
338 handle_longtable_captions(document, True)
341 def revert_longtable_captions(document):
342 "remove head/foot flag from caption rows"
343 handle_longtable_captions(document, False)
346 def convert_use_packages(document):
347 "use_xxx yyy => use_package xxx yyy"
348 packages = ["amsmath", "esint", "mathdots", "mhchem", "undertilde"]
350 i = find_token(document.header, "\\use_%s" % p, 0)
352 value = get_value(document.header, "\\use_%s" % p, i)
353 document.header[i] = "\\use_package %s %s" % (p, value)
356 def revert_use_packages(document):
357 "use_package xxx yyy => use_xxx yyy"
358 packages = ["amsmath", "esint", "mathdots", "mhchem", "undertilde"]
359 # the order is arbitrary for the use_package version, and not all packages need to be given.
360 # Ensure a complete list and correct order (important for older LyX versions and especially lyx2lyx)
363 regexp = re.compile(r'(\\use_package\s+%s)' % p)
364 i = find_re(document.header, regexp, j)
366 value = get_value(document.header, "\\use_package %s" % p, i).split()[1]
367 del document.header[i]
369 document.header.insert(j, "\\use_%s %s" % (p, value))
373 def convert_use_mathtools(document):
374 "insert use_package mathtools"
375 i = find_token(document.header, "\\use_package", 0)
377 document.warning("Malformed LyX document: Can't find \\use_package.")
379 j = find_token(document.preamble, "\\usepackage{mathtools}", 0)
381 document.header.insert(i + 1, "\\use_package mathtools 0")
383 document.header.insert(i + 1, "\\use_package mathtools 2")
384 del document.preamble[j]
387 def revert_use_mathtools(document):
388 "remove use_package mathtools"
389 regexp = re.compile(r'(\\use_package\s+mathtools)')
390 i = find_re(document.header, regexp, 0)
391 value = "1" # default is auto
393 value = get_value(document.header, "\\use_package" , i).split()[1]
394 del document.header[i]
395 if value == "2": # on
396 add_to_preamble(document, ["\\usepackage{mathtools}"])
397 elif value == "1": # auto
398 commands = ["mathclap", "mathllap", "mathrlap", \
399 "lgathered", "rgathered", "vcentcolon", "dblcolon", \
400 "coloneqq", "Coloneqq", "coloneq", "Coloneq", "eqqcolon", \
401 "Eqqcolon", "eqcolon", "Eqcolon", "colonapprox", \
402 "Colonapprox", "colonsim", "Colonsim"]
405 i = find_token(document.body, '\\begin_inset Formula', i)
408 j = find_end_of_inset(document.body, i)
410 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
413 code = "\n".join(document.body[i:j])
415 if code.find("\\%s" % c) != -1:
416 add_to_preamble(document, ["\\usepackage{mathtools}"])
421 def convert_use_stmaryrd(document):
422 "insert use_package stmaryrd"
423 i = find_token(document.header, "\\use_package", 0)
425 document.warning("Malformed LyX document: Can't find \\use_package.")
427 j = find_token(document.preamble, "\\usepackage{stmaryrd}", 0)
429 document.header.insert(i + 1, "\\use_package stmaryrd 0")
431 document.header.insert(i + 1, "\\use_package stmaryrd 2")
432 del document.preamble[j]
435 def revert_use_stmaryrd(document):
436 "remove use_package stmaryrd"
437 regexp = re.compile(r'(\\use_package\s+stmaryrd)')
438 i = find_re(document.header, regexp, 0)
439 value = "1" # default is auto
441 value = get_value(document.header, "\\use_package" , i).split()[1]
442 del document.header[i]
443 if value == "2": # on
444 add_to_preamble(document, ["\\usepackage{stmaryrd}"])
445 elif value == "1": # auto
446 commands = ["shortleftarrow", "shortrightarrow", "shortuparrow", \
447 "shortdownarrow", "Yup", "Ydown", "Yleft", "Yright", \
448 "varcurlyvee", "varcurlywedge", "minuso", "baro", \
449 "sslash", "bbslash", "moo", "varotimes", "varoast", \
450 "varobar", "varodot", "varoslash", "varobslash", \
451 "varocircle", "varoplus", "varominus", "boxast", \
452 "boxbar", "boxslash", "boxbslash", "boxcircle", \
453 "boxbox", "boxempty", "merge", "vartimes", \
454 "fatsemi", "sswarrow", "ssearrow", "curlywedgeuparrow", \
455 "curlywedgedownarrow", "fatslash", "fatbslash", "lbag", \
456 "rbag", "varbigcirc", "leftrightarroweq", \
457 "curlyveedownarrow", "curlyveeuparrow", "nnwarrow", \
458 "nnearrow", "leftslice", "rightslice", "varolessthan", \
459 "varogreaterthan", "varovee", "varowedge", "talloblong", \
460 "interleave", "obar", "obslash", "olessthan", \
461 "ogreaterthan", "ovee", "owedge", "oblong", "inplus", \
462 "niplus", "nplus", "subsetplus", "supsetplus", \
463 "subsetpluseq", "supsetpluseq", "Lbag", "Rbag", \
464 "llbracket", "rrbracket", "llparenthesis", \
465 "rrparenthesis", "binampersand", "bindnasrepma", \
466 "trianglelefteqslant", "trianglerighteqslant", \
467 "ntrianglelefteqslant", "ntrianglerighteqslant", \
468 "llfloor", "rrfloor", "llceil", "rrceil", "arrownot", \
469 "Arrownot", "Mapstochar", "mapsfromchar", "Mapsfromchar", \
470 "leftrightarrowtriangle", "leftarrowtriangle", \
471 "rightarrowtriangle", \
472 "bigcurlyvee", "bigcurlywedge", "bigsqcap", "bigbox", \
473 "bigparallel", "biginterleave", "bignplus", \
474 "varcopyright", "longarrownot", "Longarrownot", \
475 "Mapsto", "mapsfrom", "Mapsfrom" "Longmapsto", \
476 "longmapsfrom", "Longmapsfrom"]
477 # commands provided by stmaryrd.sty but LyX uses other packages:
478 # boxdot lightning, bigtriangledown, bigtriangleup
482 i = find_token(document.body, '\\begin_inset Formula', i)
485 j = find_end_of_inset(document.body, i)
487 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
490 code = "\n".join(document.body[i:j])
492 if code.find("\\%s" % c) != -1:
493 add_to_preamble(document, ["\\usepackage{stmaryrd}"])
498 def convert_use_stackrel(document):
499 "insert use_package stackrel"
500 i = find_token(document.header, "\\use_package", 0)
502 document.warning("Malformed LyX document: Can't find \\use_package.")
504 j = find_token(document.preamble, "\\usepackage{stackrel}", 0)
506 document.header.insert(i + 1, "\\use_package stackrel 0")
508 document.header.insert(i + 1, "\\use_package stackrel 2")
509 del document.preamble[j]
512 def revert_use_stackrel(document):
513 "remove use_package stackrel"
514 regexp = re.compile(r'(\\use_package\s+stackrel)')
515 i = find_re(document.header, regexp, 0)
516 value = "1" # default is auto
518 value = get_value(document.header, "\\use_package" , i).split()[1]
519 del document.header[i]
520 if value == "2": # on
521 add_to_preamble(document, ["\\usepackage{stackrel}"])
522 elif value == "1": # auto
523 regcmd = re.compile(r'.*\\stackrel\s*\[')
526 i = find_token(document.body, '\\begin_inset Formula', i)
529 j = find_end_of_inset(document.body, i)
531 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
534 code = "\n".join(document.body[i:j])
535 if regcmd.match(code):
536 add_to_preamble(document, ["\\usepackage{stackrel}"])
541 def convert_cite_engine_type(document):
542 "Determine the \\cite_engine_type from the citation engine."
543 i = find_token(document.header, "\\cite_engine", 0)
546 engine = get_value(document.header, "\\cite_engine", i)
548 engine, type = engine.split("_")
550 type = {"basic": "numerical", "jurabib": "authoryear"}[engine]
551 document.header[i] = "\\cite_engine " + engine
552 document.header.insert(i + 1, "\\cite_engine_type " + type)
555 def revert_cite_engine_type(document):
556 "Natbib had the type appended with an underscore."
557 engine_type = "numerical"
558 i = find_token(document.header, "\\cite_engine_type" , 0)
560 document.warning("No \\cite_engine_type line. Assuming numerical.")
562 engine_type = get_value(document.header, "\\cite_engine_type", i)
563 del document.header[i]
565 # We are looking for the natbib citation engine
566 i = find_token(document.header, "\\cite_engine natbib", 0)
569 document.header[i] = "\\cite_engine natbib_" + engine_type
572 def revert_cancel(document):
573 "add cancel to the preamble if necessary"
574 commands = ["cancelto", "cancel", "bcancel", "xcancel"]
577 i = find_token(document.body, '\\begin_inset Formula', i)
580 j = find_end_of_inset(document.body, i)
582 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
585 code = "\n".join(document.body[i:j])
587 if code.find("\\%s" % c) != -1:
588 add_to_preamble(document, ["\\usepackage{cancel}"])
593 def revert_verbatim(document):
594 " Revert verbatim einvironments completely to TeX-code. "
597 subst_end = ['\end_layout', '', '\\begin_layout Plain Layout',
599 '\\begin_layout Plain Layout', '', '',
602 '\\end_layout', '', '\\end_inset',
603 '', '', '\\end_layout']
604 subst_begin = ['\\begin_layout Standard', '\\noindent',
605 '\\begin_inset ERT', 'status collapsed', '',
606 '\\begin_layout Plain Layout', '', '', '\\backslash',
608 '\\end_layout', '', '\\begin_layout Plain Layout', '']
610 i = find_token(document.body, "\\begin_layout Verbatim", i)
613 j = find_end_of_layout(document.body, i)
615 document.warning("Malformed lyx document: Can't find end of Verbatim layout")
618 # delete all line breaks insets (there are no other insets)
621 n = find_token(document.body, "\\begin_inset Newline newline", l)
623 n = find_token(document.body, "\\begin_inset Newline linebreak", l)
626 m = find_end_of_inset(document.body, n)
627 del(document.body[m:m+1])
628 document.body[n:n+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
631 # consecutive verbatim environments need to be connected
632 k = find_token(document.body, "\\begin_layout Verbatim", j)
633 if k == j + 2 and consecutive == False:
635 document.body[j:j+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
636 document.body[i:i+1] = subst_begin
638 if k == j + 2 and consecutive == True:
639 document.body[j:j+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
640 del(document.body[i:i+1])
642 if k != j + 2 and consecutive == True:
643 document.body[j:j+1] = subst_end
644 # the next paragraph must not be indented
645 document.body[j+19:j+19] = ['\\noindent']
646 del(document.body[i:i+1])
650 document.body[j:j+1] = subst_end
651 # the next paragraph must not be indented
652 document.body[j+19:j+19] = ['\\noindent']
653 document.body[i:i+1] = subst_begin
656 def revert_tipa(document):
657 " Revert native TIPA insets to mathed or ERT. "
660 i = find_token(document.body, "\\begin_inset IPA", i)
663 j = find_end_of_inset(document.body, i)
665 document.warning("Malformed lyx document: Can't find end of IPA inset")
669 n = find_token(document.body, "\\begin_layout", i, j)
671 document.warning("Malformed lyx document: IPA inset has no embedded layout")
674 m = find_end_of_layout(document.body, n)
676 document.warning("Malformed lyx document: Can't find end of embedded layout")
679 content = document.body[n+1:m]
680 p = find_token(document.body, "\\begin_layout", m, j)
681 if p != -1 or len(content) > 1:
683 content = document.body[i+1:j]
685 # IPA insets with multiple pars need to be wrapped by \begin{IPA}...\end{IPA}
686 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}")
687 add_to_preamble(document, ["\\usepackage{tipa,tipx}"])
689 # single-par IPA insets can be reverted to mathed
690 document.body[i:j+1] = ["\\begin_inset Formula $\\text{\\textipa{" + content[0] + "}}$", "\\end_inset"]
694 def revert_cell_rotation(document):
695 "Revert cell rotations to TeX-code"
697 load_rotating = False
701 # first, let's find out if we need to do anything
702 i = find_token(document.body, '<cell ', i)
705 j = document.body[i].find('rotate="')
707 k = document.body[i].find('"', j + 8)
708 value = document.body[i][j + 8 : k]
710 rgx = re.compile(r' rotate="[^"]+?"')
711 # remove rotate option
712 document.body[i] = rgx.sub('', document.body[i])
714 rgx = re.compile(r' rotate="[^"]+?"')
715 document.body[i] = rgx.sub('rotate="true"', document.body[i])
717 rgx = re.compile(r' rotate="[^"]+?"')
719 # remove rotate option
720 document.body[i] = rgx.sub('', document.body[i])
722 document.body[i + 5 : i + 5] = \
723 put_cmd_in_ert("\\end{turn}")
724 document.body[i + 4 : i + 4] = \
725 put_cmd_in_ert("\\begin{turn}{" + value + "}")
731 add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"])
734 def convert_cell_rotation(document):
735 'Convert cell rotation statements from "true" to "90"'
739 # first, let's find out if we need to do anything
740 i = find_token(document.body, '<cell ', i)
743 j = document.body[i].find('rotate="true"')
745 rgx = re.compile(r'rotate="[^"]+?"')
746 # convert "true" to "90"
747 document.body[i] = rgx.sub('rotate="90"', document.body[i])
752 def revert_table_rotation(document):
753 "Revert table rotations to TeX-code"
755 load_rotating = False
759 # first, let's find out if we need to do anything
760 i = find_token(document.body, '<features ', i)
763 j = document.body[i].find('rotate="')
765 end_table = find_token(document.body, '</lyxtabular>', j)
766 k = document.body[i].find('"', j + 8)
767 value = document.body[i][j + 8 : k]
769 rgx = re.compile(r' rotate="[^"]+?"')
770 # remove rotate option
771 document.body[i] = rgx.sub('', document.body[i])
773 rgx = re.compile(r'rotate="[^"]+?"')
774 document.body[i] = rgx.sub('rotate="true"', document.body[i])
776 rgx = re.compile(r' rotate="[^"]+?"')
778 # remove rotate option
779 document.body[i] = rgx.sub('', document.body[i])
781 document.body[end_table + 3 : end_table + 3] = \
782 put_cmd_in_ert("\\end{turn}")
783 document.body[i - 2 : i - 2] = \
784 put_cmd_in_ert("\\begin{turn}{" + value + "}")
790 add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"])
793 def convert_table_rotation(document):
794 'Convert table rotation statements from "true" to "90"'
798 # first, let's find out if we need to do anything
799 i = find_token(document.body, '<features ', i)
802 j = document.body[i].find('rotate="true"')
804 rgx = re.compile(r'rotate="[^"]+?"')
805 # convert "true" to "90"
806 document.body[i] = rgx.sub('rotate="90"', document.body[i])
811 def convert_listoflistings(document):
812 'Convert ERT \lstlistoflistings to TOC lstlistoflistings inset'
813 # We can support roundtrip because the command is so simple
816 i = find_token(document.body, "\\begin_inset ERT", i)
819 j = find_end_of_inset(document.body, i)
821 document.warning("Malformed lyx document: Can't find end of ERT inset")
824 ert = get_ert(document.body, i)
825 if ert == "\\lstlistoflistings{}":
826 document.body[i:j] = ["\\begin_inset CommandInset toc", "LatexCommand lstlistoflistings", ""]
832 def revert_listoflistings(document):
833 'Convert TOC lstlistoflistings inset to ERT lstlistoflistings'
836 i = find_token(document.body, "\\begin_inset CommandInset toc", i)
839 if document.body[i+1] == "LatexCommand lstlistoflistings":
840 j = find_end_of_inset(document.body, i)
842 document.warning("Malformed lyx document: Can't find end of TOC inset")
845 subst = put_cmd_in_ert("\\lstlistoflistings{}")
846 document.body[i:j+1] = subst
847 add_to_preamble(document, ["\\usepackage{listings}"])
851 def convert_use_amssymb(document):
852 "insert use_package amssymb"
853 regexp = re.compile(r'(\\use_package\s+amsmath)')
854 i = find_re(document.header, regexp, 0)
856 document.warning("Malformed LyX document: Can't find \\use_package amsmath.")
858 value = get_value(document.header, "\\use_package" , i).split()[1]
861 useamsmath = int(value)
863 document.warning("Invalid \\use_package amsmath: " + value + ". Assuming auto.")
865 j = find_token(document.preamble, "\\usepackage{amssymb}", 0)
867 document.header.insert(i + 1, "\\use_package amssymb %d" % useamsmath)
869 document.header.insert(i + 1, "\\use_package amssymb 2")
870 del document.preamble[j]
873 def revert_use_amssymb(document):
874 "remove use_package amssymb"
875 regexp1 = re.compile(r'(\\use_package\s+amsmath)')
876 regexp2 = re.compile(r'(\\use_package\s+amssymb)')
877 i = find_re(document.header, regexp1, 0)
878 j = find_re(document.header, regexp2, 0)
879 value1 = "1" # default is auto
880 value2 = "1" # default is auto
882 value1 = get_value(document.header, "\\use_package" , i).split()[1]
884 value2 = get_value(document.header, "\\use_package" , j).split()[1]
885 del document.header[j]
886 if value1 != value2 and value2 == "2": # on
887 add_to_preamble(document, ["\\usepackage{amssymb}"])
890 def revert_ancientgreek(document):
891 "Set the document language for ancientgreek to greek"
893 if document.language == "ancientgreek":
894 document.language = "greek"
895 i = find_token(document.header, "\\language", 0)
897 document.header[i] = "\\language greek"
900 j = find_token(document.body, "\\lang ancientgreek", j)
904 document.body[j] = document.body[j].replace("\\lang ancientgreek", "\\lang greek")
908 def revert_languages(document):
909 "Set the document language for new supported languages to English"
912 "coptic", "divehi", "hindi", "kurmanji", "lao", "marathi", "occitan", "sanskrit",
913 "syriac", "tamil", "telugu", "urdu"
915 for n in range(len(languages)):
916 if document.language == languages[n]:
917 document.language = "english"
918 i = find_token(document.header, "\\language", 0)
920 document.header[i] = "\\language english"
922 while j < len(document.body):
923 j = find_token(document.body, "\\lang " + languages[n], j)
925 document.body[j] = document.body[j].replace("\\lang " + languages[n], "\\lang english")
928 j = len(document.body)
931 def convert_armenian(document):
932 "Use polyglossia and thus non-TeX fonts for Armenian"
934 if document.language == "armenian":
935 i = find_token(document.header, "\\use_non_tex_fonts", 0)
937 document.header[i] = "\\use_non_tex_fonts true"
940 def revert_armenian(document):
941 "Use ArmTeX and thus TeX fonts for Armenian"
943 if document.language == "armenian":
944 i = find_token(document.header, "\\use_non_tex_fonts", 0)
946 document.header[i] = "\\use_non_tex_fonts false"
949 def revert_libertine(document):
950 " Revert native libertine font definition to LaTeX "
952 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
953 i = find_token(document.header, "\\font_roman libertine", 0)
956 j = find_token(document.header, "\\font_osf true", 0)
959 preamble = "\\usepackage"
961 document.header[j] = "\\font_osf false"
963 preamble += "[lining]"
964 preamble += "{libertine-type1}"
965 add_to_preamble(document, [preamble])
966 document.header[i] = "\\font_roman default"
969 def revert_txtt(document):
970 " Revert native txtt font definition to LaTeX "
972 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
973 i = find_token(document.header, "\\font_typewriter txtt", 0)
975 preamble = "\\renewcommand{\\ttdefault}{txtt}"
976 add_to_preamble(document, [preamble])
977 document.header[i] = "\\font_typewriter default"
980 def revert_mathdesign(document):
981 " Revert native mathdesign font definition to LaTeX "
983 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
989 i = find_token(document.header, "\\font_roman", 0)
992 val = get_value(document.header, "\\font_roman", i)
993 if val in mathdesign_dict.keys():
994 preamble = "\\usepackage[%s" % mathdesign_dict[val]
996 j = find_token(document.header, "\\font_osf true", 0)
999 document.header[j] = "\\font_osf false"
1000 l = find_token(document.header, "\\font_sc true", 0)
1003 document.header[l] = "\\font_sc false"
1005 preamble += ",expert"
1006 preamble += "]{mathdesign}"
1007 add_to_preamble(document, [preamble])
1008 document.header[i] = "\\font_roman default"
1011 def revert_texgyre(document):
1012 " Revert native TeXGyre font definition to LaTeX "
1014 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1015 texgyre_fonts = ["tgadventor", "tgbonum", "tgchorus", "tgcursor", \
1016 "tgheros", "tgpagella", "tgschola", "tgtermes"]
1017 i = find_token(document.header, "\\font_roman", 0)
1019 val = get_value(document.header, "\\font_roman", i)
1020 if val in texgyre_fonts:
1021 preamble = "\\usepackage{%s}" % val
1022 add_to_preamble(document, [preamble])
1023 document.header[i] = "\\font_roman default"
1024 i = find_token(document.header, "\\font_sans", 0)
1026 val = get_value(document.header, "\\font_sans", i)
1027 if val in texgyre_fonts:
1028 preamble = "\\usepackage{%s}" % val
1029 add_to_preamble(document, [preamble])
1030 document.header[i] = "\\font_sans default"
1031 i = find_token(document.header, "\\font_typewriter", 0)
1033 val = get_value(document.header, "\\font_typewriter", i)
1034 if val in texgyre_fonts:
1035 preamble = "\\usepackage{%s}" % val
1036 add_to_preamble(document, [preamble])
1037 document.header[i] = "\\font_typewriter default"
1040 def revert_ipadeco(document):
1041 " Revert IPA decorations to ERT "
1044 i = find_token(document.body, "\\begin_inset IPADeco", i)
1047 end = find_end_of_inset(document.body, i)
1049 document.warning("Can't find end of inset at line " + str(i))
1052 line = document.body[i]
1053 rx = re.compile(r'\\begin_inset IPADeco (.*)$')
1055 decotype = m.group(1)
1056 if decotype != "toptiebar" and decotype != "bottomtiebar":
1057 document.warning("Invalid IPADeco type: " + decotype)
1060 blay = find_token(document.body, "\\begin_layout Plain Layout", i, end)
1062 document.warning("Can't find layout for inset at line " + str(i))
1065 bend = find_end_of_layout(document.body, blay)
1067 document.warning("Malformed LyX document: Could not find end of IPADeco inset's layout.")
1070 substi = ["\\begin_inset ERT", "status collapsed", "",
1071 "\\begin_layout Plain Layout", "", "", "\\backslash",
1072 decotype + "{", "\\end_layout", "", "\\end_inset"]
1073 substj = ["\\size default", "", "\\begin_inset ERT", "status collapsed", "",
1074 "\\begin_layout Plain Layout", "", "}", "\\end_layout", "", "\\end_inset"]
1075 # do the later one first so as not to mess up the numbering
1076 document.body[bend:end + 1] = substj
1077 document.body[i:blay + 1] = substi
1078 i = end + len(substi) + len(substj) - (end - bend) - (blay - i) - 2
1079 add_to_preamble(document, "\\usepackage{tipa}")
1082 def revert_ipachar(document):
1083 ' Revert \\IPAChar to ERT '
1086 while i < len(document.body):
1087 m = re.match(r'(.*)\\IPAChar \\(\w+\{\w+\})(.*)', document.body[i])
1091 ipachar = m.group(2)
1094 '\\begin_inset ERT',
1095 'status collapsed', '',
1096 '\\begin_layout Standard',
1097 '', '', '\\backslash',
1102 document.body[i: i+1] = subst
1107 add_to_preamble(document, "\\usepackage{tone}")
1110 def revert_minionpro(document):
1111 " Revert native MinionPro font definition to LaTeX "
1113 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1114 i = find_token(document.header, "\\font_roman minionpro", 0)
1117 j = find_token(document.header, "\\font_osf true", 0)
1120 preamble = "\\usepackage"
1122 document.header[j] = "\\font_osf false"
1125 preamble += "{MinionPro}"
1126 add_to_preamble(document, [preamble])
1127 document.header[i] = "\\font_roman default"
1130 def revert_mathfonts(document):
1131 " Revert native math font definitions to LaTeX "
1133 i = find_token(document.header, "\\font_math", 0)
1136 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1137 val = get_value(document.header, "\\font_math", i)
1138 if val == "eulervm":
1139 add_to_preamble(document, "\\usepackage{eulervm}")
1140 elif val == "default":
1142 "lmodern": "\\renewcommand{\\rmdefault}{lmr}",
1143 "minionpro": "\\usepackage[onlytext,lf]{MinionPro}",
1144 "minionpro-osf": "\\usepackage[onlytext]{MinionPro}",
1145 "palatino": "\\renewcommand{\\rmdefault}{ppl}",
1146 "palatino-osf": "\\renewcommand{\\rmdefault}{pplj}",
1147 "times": "\\renewcommand{\\rmdefault}{ptm}",
1148 "utopia": "\\renewcommand{\\rmdefault}{futs}",
1149 "utopia-osf": "\\renewcommand{\\rmdefault}{futj}",
1151 j = find_token(document.header, "\\font_roman", 0)
1153 rm = get_value(document.header, "\\font_roman", j)
1154 k = find_token(document.header, "\\font_osf true", 0)
1157 if rm in mathfont_dict.keys():
1158 add_to_preamble(document, mathfont_dict[rm])
1159 document.header[j] = "\\font_roman default"
1161 document.header[k] = "\\font_osf false"
1162 del document.header[i]
1165 def revert_mdnomath(document):
1166 " Revert mathdesign and fourier without math "
1168 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1170 "md-charter": "mdbch",
1171 "md-utopia": "mdput",
1172 "md-garamond": "mdugm"
1174 i = find_token(document.header, "\\font_roman", 0)
1177 val = get_value(document.header, "\\font_roman", i)
1178 if val in mathdesign_dict.keys():
1179 j = find_token(document.header, "\\font_math", 0)
1181 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1182 mval = get_value(document.header, "\\font_math", j)
1183 if mval == "default":
1184 document.header[i] = "\\font_roman default"
1185 add_to_preamble(document, "\\renewcommand{\\rmdefault}{%s}" % mathdesign_dict[val])
1187 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1190 def convert_mdnomath(document):
1191 " Change mathdesign font name "
1193 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1195 "mdbch": "md-charter",
1196 "mdput": "md-utopia",
1197 "mdugm": "md-garamond"
1199 i = find_token(document.header, "\\font_roman", 0)
1202 val = get_value(document.header, "\\font_roman", i)
1203 if val in mathdesign_dict.keys():
1204 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1207 def revert_newtxmath(document):
1208 " Revert native newtxmath definitions to LaTeX "
1210 i = find_token(document.header, "\\font_math", 0)
1213 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1214 val = get_value(document.header, "\\font_math", i)
1216 "libertine-ntxm": "\\usepackage[libertine]{newtxmath}",
1217 "minion-ntxm": "\\usepackage[minion]{newtxmath}",
1218 "newtxmath": "\\usepackage{newtxmath}",
1220 if val in mathfont_dict.keys():
1221 add_to_preamble(document, mathfont_dict[val])
1222 document.header[i] = "\\font_math auto"
1225 def revert_biolinum(document):
1226 " Revert native biolinum font definition to LaTeX "
1228 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1229 i = find_token(document.header, "\\font_sans biolinum", 0)
1232 j = find_token(document.header, "\\font_osf true", 0)
1235 preamble = "\\usepackage"
1238 preamble += "{biolinum-type1}"
1239 add_to_preamble(document, [preamble])
1240 document.header[i] = "\\font_sans default"
1243 def revert_uop(document):
1244 " Revert native URW Classico (Optima) font definition to LaTeX "
1246 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1247 i = find_token(document.header, "\\font_sans uop", 0)
1249 preamble = "\\renewcommand{\\sfdefault}{uop}"
1250 add_to_preamble(document, [preamble])
1251 document.header[i] = "\\font_sans default"
1254 def convert_latexargs(document):
1255 " Convert InsetArgument to new syntax "
1257 if find_token(document.body, "\\begin_inset Argument", 0) == -1:
1261 # A list of layouts (document classes) with only optional or no arguments.
1262 # These can be safely converted to the new syntax
1263 # (I took the liberty to add some of my personal layouts/modules here; JSP)
1264 safe_layouts = ["aa", "aapaper", "aastex", "achemso", "acmsiggraph", "AEA",
1265 "agu-dtd", "agums", "agutex", "amsart", "amsbook", "apa",
1266 "arab-article", "armenian-article", "article-beamer", "article",
1267 "beamer", "book", "broadway", "chess", "cl2emult", "ctex-article",
1268 "ctex-book", "ctex-report", "dinbrief", "docbook-book", "docbook-chapter",
1269 "docbook", "docbook-section", "doublecol-new", "dtk", "ectaart", "egs",
1270 "elsarticle", "elsart", "entcs", "europecv", "extarticle", "extbook",
1271 "extletter", "extreport", "foils", "frletter", "g-brief2", "g-brief",
1272 "heb-article", "heb-letter", "hollywood", "IEEEtran", "ijmpc", "ijmpd",
1273 "iopart", "isprs", "jarticle", "jasatex", "jbook", "jgrga", "jreport",
1274 "jsarticle", "jsbeamer", "jsbook", "jss", "kluwer", "latex8", "letter", "lettre",
1275 "literate-article", "literate-book", "literate-report", "llncs", "ltugboat",
1276 "memoir", "moderncv", "mwart", "mwbk", "mwrep", "paper", "powerdot",
1277 "recipebook", "report", "revtex4", "revtex", "scrartcl", "scrarticle-beamer",
1278 "scrbook", "scrlettr", "scrlttr2", "scrreprt", "seminar", "siamltex",
1279 "sigplanconf", "simplecv", "singlecol", "singlecol-new", "slides", "spie",
1280 "svglobal3", "svglobal", "svjog", "svmono", "svmult", "svprobth", "tarticle",
1281 "tbook", "treport", "tufte-book", "tufte-handout"]
1282 # A list of "safe" modules, same as above
1283 safe_modules = ["biblatex", "beameraddons", "beamersession", "braille", "customHeadersFooters",
1284 "endnotes", "enumitem", "eqs-within-sections", "figs-within-sections", "fix-cm",
1285 "fixltx2e", "foottoend", "hanging", "jscharstyles", "knitr", "lilypond",
1286 "linguistics", "linguisticx", "logicalmkup", "minimalistic", "nomindex", "noweb",
1287 "pdfcomment", "sweave", "tabs-within-sections", "theorems-ams-bytype",
1288 "theorems-ams-extended-bytype", "theorems-ams-extended", "theorems-ams", "theorems-bytype",
1289 "theorems-chap-bytype", "theorems-chap", "theorems-named", "theorems-sec-bytype",
1290 "theorems-sec", "theorems-starred", "theorems-std", "todonotes"]
1291 # Modules we need to take care of
1292 caveat_modules = ["initials"]
1293 # information about the relevant styles in caveat_modules (number of opt and req args)
1294 # use this if we get more caveat_modules. For now, use hard coding (see below).
1295 # initials = [{'Layout' : 'Initial', 'opt' : 1, 'req' : 1}]
1297 # Is this a known safe layout?
1298 safe_layout = document.textclass in safe_layouts
1300 document.warning("Lyx2lyx knows nothing about textclass '%s'. "
1301 "Please check if short title insets have been converted correctly."
1302 % document.textclass)
1303 # Do we use unsafe or unknown modules
1304 mods = document.get_module_list()
1305 unknown_modules = False
1306 used_caveat_modules = list()
1308 if mod in safe_modules:
1310 if mod in caveat_modules:
1311 used_caveat_modules.append(mod)
1313 unknown_modules = True
1314 document.warning("Lyx2lyx knows nothing about module '%s'. "
1315 "Please check if short title insets have been converted correctly."
1320 i = find_token(document.body, "\\begin_inset Argument", i)
1324 if not safe_layout or unknown_modules:
1325 # We cannot do more here since we have no access to this layout.
1326 # InsetArgument itself will do the real work
1327 # (see InsetArgument::updateBuffer())
1328 document.body[i] = "\\begin_inset Argument 999"
1332 # Find containing paragraph layout
1333 parent = get_containing_layout(document.body, i)
1335 document.warning("Malformed lyx document: Can't find parent paragraph layout")
1342 if len(used_caveat_modules) > 0:
1343 # We know for now that this must be the initials module with the Initial layout
1344 # If we get more such modules, we need some automating.
1345 if parent[0] == "Initial":
1346 # Layout has 1 opt and 1 req arg.
1347 # Count the actual arguments
1349 for p in range(parbeg, parend):
1350 if document.body[p] == "\\begin_inset Argument":
1355 # Collect all arguments in this paragraph
1357 for p in range(parbeg, parend):
1358 if document.body[p] == "\\begin_inset Argument":
1360 if allowed_opts != -1:
1361 # We have less arguments than opt + required.
1362 # required must take precedence.
1363 if argnr > allowed_opts and argnr < first_req:
1365 document.body[p] = "\\begin_inset Argument %d" % argnr
1369 def revert_latexargs(document):
1370 " Revert InsetArgument to old syntax "
1373 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
1376 # Search for Argument insets
1377 i = find_token(document.body, "\\begin_inset Argument", i)
1380 m = rx.match(document.body[i])
1382 # No ID: inset already reverted
1385 # Find containing paragraph layout
1386 parent = get_containing_layout(document.body, i)
1388 document.warning("Malformed lyx document: Can't find parent paragraph layout")
1393 realparbeg = parent[3]
1394 # Collect all arguments in this paragraph
1396 for p in range(parbeg, parend):
1397 m = rx.match(document.body[p])
1399 val = int(m.group(1))
1400 j = find_end_of_inset(document.body, p)
1401 # Revert to old syntax
1402 document.body[p] = "\\begin_inset Argument"
1404 document.warning("Malformed lyx document: Can't find end of Argument inset")
1407 args[val] = document.body[p : j + 1]
1409 realparend = realparend - len(document.body[p : j + 1])
1410 # Remove arg inset at this position
1411 del document.body[p : j + 1]
1414 # Now sort the arg insets
1416 for f in sorted(args):
1419 # Insert the sorted arg insets at paragraph begin
1420 document.body[realparbeg : realparbeg] = subst
1422 i = realparbeg + 1 + len(subst)
1425 def revert_Argument_to_TeX_brace(document, line, n, nmax, environment):
1427 Reverts an InsetArgument to TeX-code
1429 revert_Argument_to_TeX_brace(document, LineOfBeginLayout, StartArgument, EndArgument, isEnvironment)
1430 LineOfBeginLayout is the line of the \begin_layout statement
1431 StartArgument is the number of the first argument that needs to be converted
1432 EndArgument is the number of the last argument that needs to be converted or the last defined one
1433 isEnvironment must be true, if the layout id for a LaTeX environment
1436 while lineArg != -1 and n < nmax + 1:
1437 lineArg = find_token(document.body, "\\begin_inset Argument " + str(n), line)
1439 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", lineArg)
1440 # we have to assure that no other inset is in the Argument
1441 beginInset = find_token(document.body, "\\begin_inset", beginPlain)
1442 endInset = find_token(document.body, "\\end_inset", beginPlain)
1445 while beginInset < endInset and beginInset != -1:
1446 beginInset = find_token(document.body, "\\begin_inset", k)
1447 endInset = find_token(document.body, "\\end_inset", l)
1450 if environment == False:
1451 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}{")
1452 del(document.body[lineArg : beginPlain + 1])
1454 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}")
1455 document.body[lineArg : beginPlain + 1] = put_cmd_in_ert("{")
1459 def convert_TeX_brace_to_Argument(document, line, n, nmax, inset, environment):
1461 Converts TeX code for mandatory arguments to an InsetArgument
1462 The conversion of TeX code for optional arguments must be done with another routine
1463 !!! Be careful if the braces are different in your case as expected here:
1464 - "}{" separates mandatory arguments of commands
1465 - "}" + "{" separates mandatory arguments of commands
1466 - "}" + " " + "{" separates mandatory arguments of commands
1467 - { and } surround a mandatory argument of an environment
1469 convert_TeX_brace_to_Argument(document, LineOfBeginLayout/Inset, StartArgument, EndArgument, isInset, isEnvironment)
1470 LineOfBeginLayout/Inset is the line of the \begin_layout or \begin_inset statement
1471 StartArgument is the number of the first ERT that needs to be converted
1472 EndArgument is the number of the last ERT that needs to be converted
1473 isInset must be true, if braces inside an InsetLayout needs to be converted
1474 isEnvironment must be true, if the layout is for a LaTeX environment
1476 Todo: this routine can currently handle only one mandatory argument of environments
1481 while lineERT != -1 and n < nmax + 1:
1482 lineERT = find_token(document.body, "\\begin_inset ERT", lineERT)
1483 if environment == False and lineERT != -1:
1484 bracePair = find_token(document.body, "}{", lineERT)
1485 # assure that the "}{" is in this ERT
1486 if bracePair == lineERT + 5:
1487 end = find_token(document.body, "\\end_inset", bracePair)
1488 document.body[lineERT : end + 1] = ["\\end_layout", "", "\\end_inset"]
1490 # in the case that n > 1 we have optional arguments before
1491 # therefore detect them if any
1493 # first check if there is an argument
1494 lineArg = find_token(document.body, "\\begin_inset Argument", line)
1495 if lineArg < lineERT and lineArg != -1:
1496 # we have an argument, so now search backwards for its end
1497 # we must now assure that we don't find other insets like e.g. a newline
1498 endInsetArg = lineERT
1499 endLayoutArg = endInsetArg
1500 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
1501 endInsetArg = endInsetArg - 1
1502 endLayoutArg = endInsetArg
1503 endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
1504 endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
1505 line = endInsetArg + 1
1507 document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1509 document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1511 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1515 # now check the case that we have "}" + "{" in two ERTs
1517 endBrace = find_token(document.body, "}", lineERT)
1518 if endBrace == lineERT + 5:
1519 beginBrace = find_token(document.body, "{", endBrace)
1520 # assure that the ERTs are consecutive (11 or 12 depending if there is a space between the ERTs or not)
1521 if beginBrace == endBrace + 11 or beginBrace == endBrace + 12:
1522 end = find_token(document.body, "\\end_inset", beginBrace)
1523 document.body[lineERT : end + 1] = ["\\end_layout", "", "\\end_inset"]
1525 # in the case that n > 1 we have optional arguments before
1526 # therefore detect them if any
1528 # first check if there is an argument
1529 lineArg = find_token(document.body, "\\begin_inset Argument", line)
1530 if lineArg < lineERT and lineArg != -1:
1531 # we have an argument, so now search backwards for its end
1532 # we must now assure that we don't find other insets like e.g. a newline
1533 endInsetArg = lineERT
1534 endLayoutArg = endInsetArg
1535 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
1536 endInsetArg = endInsetArg - 1
1537 endLayoutArg = endInsetArg
1538 endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
1539 endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
1540 line = endInsetArg + 1
1542 document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1544 document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1546 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1549 # set the line where the next argument will be inserted
1550 if beginBrace == endBrace + 11:
1555 lineERT = lineERT + 1
1556 if environment == True and lineERT != -1:
1557 opening = find_token(document.body, "{", lineERT)
1558 if opening == lineERT + 5: # assure that the "{" is in this ERT
1559 end = find_token(document.body, "\\end_inset", opening)
1560 document.body[lineERT : end + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1562 lineERT2 = find_token(document.body, "\\begin_inset ERT", lineERT)
1563 closing = find_token(document.body, "}", lineERT2)
1564 if closing == lineERT2 + 5: # assure that the "}" is in this ERT
1565 end2 = find_token(document.body, "\\end_inset", closing)
1566 document.body[lineERT2 : end2 + 1] = ["\\end_layout", "", "\\end_inset"]
1568 lineERT = lineERT + 1
1571 def revert_IEEEtran(document):
1573 Reverts InsetArgument of
1576 Biography without photo
1579 if document.textclass == "IEEEtran":
1585 i = find_token(document.body, "\\begin_layout Page headings", i)
1587 revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1590 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1592 revert_Argument_to_TeX_brace(document, j, 1, 1, True)
1595 k = find_token(document.body, "\\begin_layout Biography", k)
1596 kA = find_token(document.body, "\\begin_layout Biography without photo", k)
1597 if k == kA and k != -1:
1601 # start with the second argument, therefore 2
1602 revert_Argument_to_TeX_brace(document, k, 2, 2, True)
1604 if i == -1 and j == -1 and k == -1:
1608 def convert_IEEEtran(document):
1613 Biography without photo
1616 if document.textclass == "IEEEtran":
1622 i = find_token(document.body, "\\begin_layout Page headings", i)
1624 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1627 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1629 convert_TeX_brace_to_Argument(document, j, 1, 1, False, True)
1632 # assure that we don't handle Biography Biography without photo
1633 k = find_token(document.body, "\\begin_layout Biography", k)
1634 kA = find_token(document.body, "\\begin_layout Biography without photo", k - 1)
1635 if k == kA and k != -1:
1639 # the argument we want to convert is the second one
1640 convert_TeX_brace_to_Argument(document, k, 2, 2, False, True)
1642 if i == -1 and j == -1 and k == -1:
1646 def revert_AASTeX(document):
1647 " Reverts InsetArgument of Altaffilation to TeX-code "
1648 if document.textclass == "aastex":
1652 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1654 revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1660 def convert_AASTeX(document):
1661 " Converts ERT of Altaffilation to InsetArgument "
1662 if document.textclass == "aastex":
1666 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1668 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1674 def revert_AGUTeX(document):
1675 " Reverts InsetArgument of Author affiliation to TeX-code "
1676 if document.textclass == "agutex":
1680 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1682 revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1688 def convert_AGUTeX(document):
1689 " Converts ERT of Author affiliation to InsetArgument "
1690 if document.textclass == "agutex":
1694 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1696 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1702 def revert_IJMP(document):
1703 " Reverts InsetArgument of MarkBoth to TeX-code "
1704 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1708 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1710 revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1716 def convert_IJMP(document):
1717 " Converts ERT of MarkBoth to InsetArgument "
1718 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1722 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1724 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1730 def revert_SIGPLAN(document):
1731 " Reverts InsetArguments of SIGPLAN to TeX-code "
1732 if document.textclass == "sigplanconf":
1737 i = find_token(document.body, "\\begin_layout Conference", i)
1739 revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1742 j = find_token(document.body, "\\begin_layout Author", j)
1744 revert_Argument_to_TeX_brace(document, j, 1, 2, False)
1746 if i == -1 and j == -1:
1750 def convert_SIGPLAN(document):
1751 " Converts ERT of SIGPLAN to InsetArgument "
1752 if document.textclass == "sigplanconf":
1757 i = find_token(document.body, "\\begin_layout Conference", i)
1759 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1762 j = find_token(document.body, "\\begin_layout Author", j)
1764 convert_TeX_brace_to_Argument(document, j, 1, 2, False, False)
1766 if i == -1 and j == -1:
1770 def revert_SIGGRAPH(document):
1771 " Reverts InsetArgument of Flex CRcat to TeX-code "
1772 if document.textclass == "acmsiggraph":
1776 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1778 revert_Argument_to_TeX_brace(document, i, 1, 3, False)
1784 def convert_SIGGRAPH(document):
1785 " Converts ERT of Flex CRcat to InsetArgument "
1786 if document.textclass == "acmsiggraph":
1790 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1792 convert_TeX_brace_to_Argument(document, i, 1, 3, True, False)
1798 def revert_EuropeCV(document):
1799 " Reverts InsetArguments of europeCV to TeX-code "
1800 if document.textclass == "europecv":
1807 i = find_token(document.body, "\\begin_layout Item", i)
1809 revert_Argument_to_TeX_brace(document, i, 2, 2, False)
1812 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1814 revert_Argument_to_TeX_brace(document, j, 2, 2, False)
1817 k = find_token(document.body, "\\begin_layout Language", k)
1819 revert_Argument_to_TeX_brace(document, k, 2, 6, False)
1822 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1824 revert_Argument_to_TeX_brace(document, m, 2, 6, False)
1826 if i == -1 and j == -1 and k == -1 and m == -1:
1830 def convert_EuropeCV(document):
1831 " Converts ERT of europeCV to InsetArgument "
1832 if document.textclass == "europecv":
1839 i = find_token(document.body, "\\begin_layout Item", i)
1841 convert_TeX_brace_to_Argument(document, i, 2, 2, False, False)
1844 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1846 convert_TeX_brace_to_Argument(document, j, 2, 2, False, False)
1849 k = find_token(document.body, "\\begin_layout Language", k)
1851 convert_TeX_brace_to_Argument(document, k, 2, 6, False, False)
1854 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1856 convert_TeX_brace_to_Argument(document, m, 2, 6, False, False)
1858 if i == -1 and j == -1 and k == -1 and m == -1:
1862 def revert_ModernCV(document):
1863 " Reverts InsetArguments of modernCV to TeX-code "
1864 if document.textclass == "moderncv":
1872 i = find_token(document.body, "\\begin_layout DoubleItem", i)
1874 revert_Argument_to_TeX_brace(document, i, 1, 3, False)
1877 j = find_token(document.body, "\\begin_layout Entry", j)
1879 revert_Argument_to_TeX_brace(document, j, 1, 5, False)
1882 k = find_token(document.body, "\\begin_layout Item", k)
1884 revert_Argument_to_TeX_brace(document, k, 1, 1, False)
1887 m = find_token(document.body, "\\begin_layout ItemWithComment", m)
1889 revert_Argument_to_TeX_brace(document, m, 1, 2, False)
1890 document.body[m] = document.body[m].replace("\\begin_layout ItemWithComment", "\\begin_layout Language")
1893 o = find_token(document.body, "\\begin_layout DoubleItem", o)
1895 revert_Argument_to_TeX_brace(document, o, 1, 3, False)
1896 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout Computer")
1898 if i == -1 and j == -1 and k == -1 and m == -1 and o == -1:
1902 def convert_ModernCV(document):
1903 " Converts ERT of modernCV to InsetArgument "
1904 if document.textclass == "moderncv":
1912 i = find_token(document.body, "\\begin_layout DoubleItem", i)
1914 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1915 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout DoubleListItem")
1918 j = find_token(document.body, "\\begin_layout Entry", j)
1920 convert_TeX_brace_to_Argument(document, j, 1, 5, False, False)
1923 k = find_token(document.body, "\\begin_layout Item", k)
1925 convert_TeX_brace_to_Argument(document, k, 1, 1, False, False)
1928 m = find_token(document.body, "\\begin_layout Language", m)
1930 convert_TeX_brace_to_Argument(document, m, 1, 2, False, False)
1932 if i == -1 and j == -1 and k == -1 and m == -1:
1936 def revert_Initials(document):
1937 " Reverts InsetArgument of Initial to TeX-code "
1941 i = find_token(document.body, "\\begin_layout Initial", i)
1943 # first arg (optional) and second arg (first mandatory) are supported in LyX 2.0.x
1944 revert_Argument_to_TeX_brace(document, i, 3, 3, False)
1950 def convert_Initials(document):
1951 " Converts ERT of Initial to InsetArgument "
1955 i = find_token(document.body, "\\begin_layout Initial", i)
1957 convert_TeX_brace_to_Argument(document, i, 3, 3, False, False)
1963 def revert_literate(document):
1964 " Revert Literate document to old format "
1965 if del_token(document.header, "noweb", 0):
1966 document.textclass = "literate-" + document.textclass
1969 i = find_token(document.body, "\\begin_layout Chunk", i)
1972 document.body[i] = "\\begin_layout Scrap"
1976 def convert_literate(document):
1977 " Convert Literate document to new format"
1978 i = find_token(document.header, "\\textclass", 0)
1979 if (i != -1) and "literate-" in document.header[i]:
1980 document.textclass = document.header[i].replace("\\textclass literate-", "")
1981 j = find_token(document.header, "\\begin_modules", 0)
1983 document.header.insert(j + 1, "noweb")
1985 document.header.insert(i + 1, "\\end_modules")
1986 document.header.insert(i + 1, "noweb")
1987 document.header.insert(i + 1, "\\begin_modules")
1990 i = find_token(document.body, "\\begin_layout Scrap", i)
1993 document.body[i] = "\\begin_layout Chunk"
1997 def revert_itemargs(document):
1998 " Reverts \\item arguments to TeX-code "
2001 i = find_token(document.body, "\\begin_inset Argument item:", i)
2004 j = find_end_of_inset(document.body, i)
2005 # Find containing paragraph layout
2006 parent = get_containing_layout(document.body, i)
2008 document.warning("Malformed lyx document: Can't find parent paragraph layout")
2012 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2013 endPlain = find_end_of_layout(document.body, beginPlain)
2014 content = document.body[beginPlain + 1 : endPlain]
2015 del document.body[i:j+1]
2016 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2017 document.body[parbeg : parbeg] = subst
2021 def revert_garamondx_newtxmath(document):
2022 " Revert native garamond newtxmath definition to LaTeX "
2024 i = find_token(document.header, "\\font_math", 0)
2027 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2028 val = get_value(document.header, "\\font_math", i)
2029 if val == "garamondx-ntxm":
2030 add_to_preamble(document, "\\usepackage[garamondx]{newtxmath}")
2031 document.header[i] = "\\font_math auto"
2034 def revert_garamondx(document):
2035 " Revert native garamond font definition to LaTeX "
2037 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2038 i = find_token(document.header, "\\font_roman garamondx", 0)
2041 j = find_token(document.header, "\\font_osf true", 0)
2044 preamble = "\\usepackage"
2046 preamble += "[osfI]"
2047 preamble += "{garamondx}"
2048 add_to_preamble(document, [preamble])
2049 document.header[i] = "\\font_roman default"
2052 def convert_beamerargs(document):
2053 " Converts beamer arguments to new layout "
2055 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2056 if document.textclass not in beamer_classes:
2059 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2060 list_layouts = ["Itemize", "Enumerate", "Description"]
2061 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
2065 i = find_token(document.body, "\\begin_inset Argument", i)
2068 # Find containing paragraph layout
2069 parent = get_containing_layout(document.body, i)
2071 document.warning("Malformed lyx document: Can't find parent paragraph layout")
2076 layoutname = parent[0]
2077 for p in range(parbeg, parend):
2078 if layoutname in shifted_layouts:
2079 m = rx.match(document.body[p])
2081 argnr = int(m.group(1))
2083 document.body[p] = "\\begin_inset Argument %d" % argnr
2084 if layoutname == "AgainFrame":
2085 m = rx.match(document.body[p])
2087 document.body[p] = "\\begin_inset Argument 3"
2088 if document.body[p + 4] == "\\begin_inset ERT":
2089 if document.body[p + 9].startswith("<"):
2090 # This is an overlay specification
2092 document.body[p + 9] = document.body[p + 9][1:]
2093 if document.body[p + 9].endswith(">"):
2095 document.body[p + 9] = document.body[p + 9][:-1]
2097 document.body[p] = "\\begin_inset Argument 2"
2098 if layoutname in list_layouts:
2099 m = rx.match(document.body[p])
2101 if m.group(1) == "1":
2102 if document.body[p + 4] == "\\begin_inset ERT":
2103 if document.body[p + 9].startswith("<"):
2104 # This is an overlay specification
2106 document.body[p + 9] = document.body[p + 9][1:]
2107 if document.body[p + 9].endswith(">"):
2109 document.body[p + 9] = document.body[p + 9][:-1]
2110 elif layoutname != "Itemize":
2112 document.body[p] = "\\begin_inset Argument 2"
2116 def convert_againframe_args(document):
2117 " Converts beamer AgainFrame to new layout "
2119 # FIXME: This currently only works if the arguments are in one single ERT
2121 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2122 if document.textclass not in beamer_classes:
2127 i = find_token(document.body, "\\begin_layout AgainFrame", i)
2130 parent = get_containing_layout(document.body, i)
2132 document.warning("Wrong parent layout!")
2136 if document.body[parbeg] == "\\begin_inset ERT":
2137 ertcont = parbeg + 5
2138 if document.body[ertcont].startswith("[<"):
2139 # This is a default overlay specification
2141 document.body[ertcont] = document.body[ertcont][2:]
2142 if document.body[ertcont].endswith(">]"):
2144 document.body[ertcont] = document.body[ertcont][:-2]
2145 elif document.body[ertcont].endswith("]"):
2147 tok = document.body[ertcont].find('>][')
2149 subst = [document.body[ertcont][:tok],
2150 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2151 'status collapsed', '', '\\begin_layout Plain Layout',
2152 document.body[ertcont][tok + 3:-1]]
2153 document.body[ertcont : ertcont + 1] = subst
2154 # Convert to ArgInset
2155 document.body[parbeg] = "\\begin_inset Argument 2"
2158 elif document.body[ertcont].startswith("<"):
2159 # This is an overlay specification
2161 document.body[ertcont] = document.body[ertcont][1:]
2162 if document.body[ertcont].endswith(">"):
2164 document.body[ertcont] = document.body[ertcont][:-1]
2165 # Convert to ArgInset
2166 document.body[parbeg] = "\\begin_inset Argument 1"
2167 elif document.body[ertcont].endswith(">]"):
2169 tok = document.body[ertcont].find('>[<')
2171 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2172 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2173 'status collapsed', '', '\\begin_layout Plain Layout',
2174 document.body[ertcont][tok + 3:-2]]
2175 # Convert to ArgInset
2176 document.body[parbeg] = "\\begin_inset Argument 1"
2177 elif document.body[ertcont].endswith("]"):
2179 tok = document.body[ertcont].find('>[<')
2182 tokk = document.body[ertcont].find('>][')
2184 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2185 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2186 'status collapsed', '', '\\begin_layout Plain Layout',
2187 document.body[ertcont][tok + 3:tokk],
2188 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2189 'status collapsed', '', '\\begin_layout Plain Layout',
2190 document.body[ertcont][tokk + 3:-1]]
2192 tokk = document.body[ertcont].find('>[')
2194 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tokk],
2195 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2196 'status collapsed', '', '\\begin_layout Plain Layout',
2197 document.body[ertcont][tokk + 2:-1]]
2198 # Convert to ArgInset
2199 document.body[parbeg] = "\\begin_inset Argument 1"
2202 elif document.body[ertcont].startswith("["):
2203 # This is an ERT option
2205 document.body[ertcont] = document.body[ertcont][1:]
2206 if document.body[ertcont].endswith("]"):
2208 document.body[ertcont] = document.body[ertcont][:-1]
2209 # Convert to ArgInset
2210 document.body[parbeg] = "\\begin_inset Argument 3"
2216 def convert_corollary_args(document):
2217 " Converts beamer corrolary-style ERT arguments native InsetArgs "
2219 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2220 if document.textclass not in beamer_classes:
2223 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2224 for lay in corollary_layouts:
2227 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2230 parent = get_containing_layout(document.body, i)
2232 document.warning("Wrong parent layout!")
2236 if document.body[parbeg] == "\\begin_inset ERT":
2237 ertcont = parbeg + 5
2238 if document.body[ertcont].startswith("<"):
2239 # This is an overlay specification
2241 document.body[ertcont] = document.body[ertcont][1:]
2242 if document.body[ertcont].endswith(">"):
2244 document.body[ertcont] = document.body[ertcont][:-1]
2245 elif document.body[ertcont].endswith("]"):
2247 tok = document.body[ertcont].find('>[')
2249 subst = [document.body[ertcont][:tok],
2250 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2251 'status collapsed', '', '\\begin_layout Plain Layout',
2252 document.body[ertcont][tok + 2:-1]]
2253 document.body[ertcont : ertcont + 1] = subst
2254 # Convert to ArgInset
2255 document.body[parbeg] = "\\begin_inset Argument 1"
2258 elif document.body[ertcont].startswith("["):
2259 # This is an ERT option
2261 document.body[ertcont] = document.body[ertcont][1:]
2262 if document.body[ertcont].endswith("]"):
2264 document.body[ertcont] = document.body[ertcont][:-1]
2265 # Convert to ArgInset
2266 document.body[parbeg] = "\\begin_inset Argument 2"
2273 def convert_quote_args(document):
2274 " Converts beamer quote style ERT args to native InsetArgs "
2276 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2277 if document.textclass not in beamer_classes:
2280 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2281 for lay in quote_layouts:
2284 i = find_token(document.body, "\\begin_layout " + lay, i)
2287 parent = get_containing_layout(document.body, i)
2289 document.warning("Wrong parent layout!")
2293 if document.body[parbeg] == "\\begin_inset ERT":
2294 if document.body[i + 6].startswith("<"):
2295 # This is an overlay specification
2297 document.body[i + 6] = document.body[i + 6][1:]
2298 if document.body[i + 6].endswith(">"):
2300 document.body[i + 6] = document.body[i + 6][:-1]
2301 # Convert to ArgInset
2302 document.body[i + 1] = "\\begin_inset Argument 1"
2306 def revert_beamerargs(document):
2307 " Reverts beamer arguments to old layout "
2309 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2310 if document.textclass not in beamer_classes:
2314 list_layouts = ["Itemize", "Enumerate", "Description"]
2315 headings = ["Part", "Section", "Section*", "Subsection", "Subsection*",
2316 "Subsubsection", "Subsubsection*", "FrameSubtitle", "NoteItem"]
2317 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2318 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2319 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2322 i = find_token(document.body, "\\begin_inset Argument", i)
2325 # Find containing paragraph layout
2326 parent = get_containing_layout(document.body, i)
2328 document.warning("Malformed lyx document: Can't find parent paragraph layout")
2333 realparbeg = parent[3]
2334 layoutname = parent[0]
2336 for p in range(parbeg, parend):
2340 if layoutname in headings:
2341 m = rx.match(document.body[p])
2345 # Find containing paragraph layout
2346 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2347 endPlain = find_end_of_layout(document.body, beginPlain)
2348 endInset = find_end_of_inset(document.body, p)
2349 argcontent = document.body[beginPlain + 1 : endPlain]
2351 realparend = realparend - len(document.body[p : endInset + 1])
2353 del document.body[p : endInset + 1]
2354 if layoutname == "FrameSubtitle":
2355 pre = put_cmd_in_ert("\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2356 elif layoutname == "NoteItem":
2357 pre = put_cmd_in_ert("\\note<") + argcontent + put_cmd_in_ert(">[item]")
2358 elif layoutname.endswith('*'):
2359 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower()[:-1] + "<") + argcontent + put_cmd_in_ert(">*")
2361 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2362 secarg = find_token(document.body, "\\begin_inset Argument 2", parbeg, parend)
2364 # Find containing paragraph layout
2365 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", secarg)
2366 endPlain = find_end_of_layout(document.body, beginPlain)
2367 endInset = find_end_of_inset(document.body, secarg)
2368 argcontent = document.body[beginPlain + 1 : endPlain]
2370 realparend = realparend - len(document.body[secarg : endInset + 1])
2371 del document.body[secarg : endInset + 1]
2372 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2373 pre += put_cmd_in_ert("{")
2374 document.body[parbeg] = "\\begin_layout Standard"
2375 document.body[realparbeg : realparbeg] = pre
2376 pe = find_end_of_layout(document.body, parbeg)
2377 post = put_cmd_in_ert("}")
2378 document.body[pe : pe] = post
2379 realparend += len(pre) + len(post)
2380 if layoutname == "AgainFrame":
2381 m = rx.match(document.body[p])
2385 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2386 endPlain = find_end_of_layout(document.body, beginPlain)
2387 endInset = find_end_of_inset(document.body, p)
2388 content = document.body[beginPlain + 1 : endPlain]
2390 realparend = realparend - len(document.body[p : endInset + 1])
2392 del document.body[p : endInset + 1]
2393 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2394 document.body[realparbeg : realparbeg] = subst
2395 if layoutname == "Overprint":
2396 m = rx.match(document.body[p])
2400 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2401 endPlain = find_end_of_layout(document.body, beginPlain)
2402 endInset = find_end_of_inset(document.body, p)
2403 content = document.body[beginPlain + 1 : endPlain]
2405 realparend = realparend - len(document.body[p : endInset + 1])
2407 del document.body[p : endInset + 1]
2408 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2409 document.body[realparbeg : realparbeg] = subst
2410 if layoutname == "OverlayArea":
2411 m = rx.match(document.body[p])
2415 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2416 endPlain = find_end_of_layout(document.body, beginPlain)
2417 endInset = find_end_of_inset(document.body, p)
2418 content = document.body[beginPlain + 1 : endPlain]
2420 realparend = realparend - len(document.body[p : endInset + 1])
2422 del document.body[p : endInset + 1]
2423 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2424 document.body[realparbeg : realparbeg] = subst
2425 if layoutname in list_layouts:
2426 m = rx.match(document.body[p])
2430 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2431 endPlain = find_end_of_layout(document.body, beginPlain)
2432 endInset = find_end_of_inset(document.body, p)
2433 content = document.body[beginPlain + 1 : endPlain]
2434 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2435 realparend = realparend + len(subst) - len(content)
2436 document.body[beginPlain + 1 : endPlain] = subst
2437 elif argnr == "item:1":
2438 j = find_end_of_inset(document.body, i)
2439 # Find containing paragraph layout
2440 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2441 endPlain = find_end_of_layout(document.body, beginPlain)
2442 content = document.body[beginPlain + 1 : endPlain]
2443 del document.body[i:j+1]
2444 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2445 document.body[realparbeg : realparbeg] = subst
2446 elif argnr == "item:2":
2447 j = find_end_of_inset(document.body, i)
2448 # Find containing paragraph layout
2449 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2450 endPlain = find_end_of_layout(document.body, beginPlain)
2451 content = document.body[beginPlain + 1 : endPlain]
2452 del document.body[i:j+1]
2453 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2454 document.body[realparbeg : realparbeg] = subst
2455 if layoutname in quote_layouts:
2456 m = rx.match(document.body[p])
2460 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2461 endPlain = find_end_of_layout(document.body, beginPlain)
2462 endInset = find_end_of_inset(document.body, p)
2463 content = document.body[beginPlain + 1 : endPlain]
2465 realparend = realparend - len(document.body[p : endInset + 1])
2467 del document.body[p : endInset + 1]
2468 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2469 document.body[realparbeg : realparbeg] = subst
2470 if layoutname in corollary_layouts:
2471 m = rx.match(document.body[p])
2475 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2476 endPlain = find_end_of_layout(document.body, beginPlain)
2477 endInset = find_end_of_inset(document.body, p)
2478 content = document.body[beginPlain + 1 : endPlain]
2480 realparend = realparend - len(document.body[p : endInset + 1])
2482 del document.body[p : endInset + 1]
2483 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2484 document.body[realparbeg : realparbeg] = subst
2489 def revert_beamerargs2(document):
2490 " Reverts beamer arguments to old layout, step 2 "
2492 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2493 if document.textclass not in beamer_classes:
2497 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2498 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2499 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2502 i = find_token(document.body, "\\begin_inset Argument", i)
2505 # Find containing paragraph layout
2506 parent = get_containing_layout(document.body, i)
2508 document.warning("Malformed lyx document: Can't find parent paragraph layout")
2513 realparbeg = parent[3]
2514 layoutname = parent[0]
2516 for p in range(parbeg, parend):
2520 if layoutname in shifted_layouts:
2521 m = rx.match(document.body[p])
2525 document.body[p] = "\\begin_inset Argument 1"
2526 if layoutname in corollary_layouts:
2527 m = rx.match(document.body[p])
2531 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2532 endPlain = find_end_of_layout(document.body, beginPlain)
2533 endInset = find_end_of_inset(document.body, p)
2534 content = document.body[beginPlain + 1 : endPlain]
2536 realparend = realparend - len(document.body[p : endInset + 1])
2538 del document.body[p : endInset + 1]
2539 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2540 document.body[realparbeg : realparbeg] = subst
2541 if layoutname == "OverlayArea":
2542 m = rx.match(document.body[p])
2546 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2547 endPlain = find_end_of_layout(document.body, beginPlain)
2548 endInset = find_end_of_inset(document.body, p)
2549 content = document.body[beginPlain + 1 : endPlain]
2551 realparend = realparend - len(document.body[p : endInset + 1])
2553 del document.body[p : endInset + 1]
2554 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2555 document.body[realparbeg : realparbeg] = subst
2556 if layoutname == "AgainFrame":
2557 m = rx.match(document.body[p])
2561 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2562 endPlain = find_end_of_layout(document.body, beginPlain)
2563 endInset = find_end_of_inset(document.body, p)
2564 content = document.body[beginPlain + 1 : endPlain]
2566 realparend = realparend - len(document.body[p : endInset + 1])
2568 del document.body[p : endInset + 1]
2569 subst = put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
2570 document.body[realparbeg : realparbeg] = subst
2574 def revert_beamerargs3(document):
2575 " Reverts beamer arguments to old layout, step 3 "
2577 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2578 if document.textclass not in beamer_classes:
2581 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2584 i = find_token(document.body, "\\begin_inset Argument", i)
2587 # Find containing paragraph layout
2588 parent = get_containing_layout(document.body, i)
2590 document.warning("Malformed lyx document: Can't find parent paragraph layout")
2595 realparbeg = parent[3]
2596 layoutname = parent[0]
2598 for p in range(parbeg, parend):
2602 if layoutname == "AgainFrame":
2603 m = rx.match(document.body[p])
2607 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2608 endPlain = find_end_of_layout(document.body, beginPlain)
2609 endInset = find_end_of_inset(document.body, p)
2610 content = document.body[beginPlain + 1 : endPlain]
2612 realparend = realparend - len(document.body[p : endInset + 1])
2614 del document.body[p : endInset + 1]
2615 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2616 document.body[realparbeg : realparbeg] = subst
2620 def revert_beamerflex(document):
2621 " Reverts beamer Flex insets "
2623 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2624 if document.textclass not in beamer_classes:
2627 new_flexes = {"Bold" : "\\textbf", "Emphasize" : "\\emph", "Only" : "\\only",
2628 "Uncover" : "\\uncover", "Visible" : "\\visible",
2629 "Invisible" : "\\invisible", "Alternative" : "\\alt",
2630 "Beamer_Note" : "\\note"}
2631 old_flexes = {"Alert" : "\\alert", "Structure" : "\\structure"}
2632 rx = re.compile(r'^\\begin_inset Flex (.+)$')
2636 i = find_token(document.body, "\\begin_inset Flex", i)
2639 m = rx.match(document.body[i])
2641 flextype = m.group(1)
2642 z = find_end_of_inset(document.body, i)
2644 document.warning("Can't find end of Flex " + flextype + " inset.")
2647 if flextype in new_flexes:
2648 pre = put_cmd_in_ert(new_flexes[flextype])
2649 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2651 argend = find_end_of_inset(document.body, arg)
2653 document.warning("Can't find end of Argument!")
2656 # Find containing paragraph layout
2657 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2658 endPlain = find_end_of_layout(document.body, beginPlain)
2659 argcontent = document.body[beginPlain + 1 : endPlain]
2661 z = z - len(document.body[arg : argend + 1])
2663 del document.body[arg : argend + 1]
2664 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2665 arg = find_token(document.body, "\\begin_inset Argument 2", i, z)
2667 argend = find_end_of_inset(document.body, arg)
2669 document.warning("Can't find end of Argument!")
2672 # Find containing paragraph layout
2673 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2674 endPlain = find_end_of_layout(document.body, beginPlain)
2675 argcontent = document.body[beginPlain + 1 : endPlain]
2677 z = z - len(document.body[arg : argend + 1])
2679 del document.body[arg : argend + 1]
2680 if flextype == "Alternative":
2681 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
2683 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2684 pre += put_cmd_in_ert("{")
2685 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2686 endPlain = find_end_of_layout(document.body, beginPlain)
2688 z = z - len(document.body[i : beginPlain + 1])
2690 document.body[i : beginPlain + 1] = pre
2691 post = put_cmd_in_ert("}")
2692 document.body[z - 2 : z + 1] = post
2693 elif flextype in old_flexes:
2694 pre = put_cmd_in_ert(old_flexes[flextype])
2695 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2699 argend = find_end_of_inset(document.body, arg)
2701 document.warning("Can't find end of Argument!")
2704 # Find containing paragraph layout
2705 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2706 endPlain = find_end_of_layout(document.body, beginPlain)
2707 argcontent = document.body[beginPlain + 1 : endPlain]
2709 z = z - len(document.body[arg : argend + 1])
2711 del document.body[arg : argend + 1]
2712 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2713 pre += put_cmd_in_ert("{")
2714 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2715 endPlain = find_end_of_layout(document.body, beginPlain)
2717 z = z - len(document.body[i : beginPlain + 1])
2719 document.body[i : beginPlain + 1] = pre
2720 post = put_cmd_in_ert("}")
2721 document.body[z - 2 : z + 1] = post
2726 def revert_beamerblocks(document):
2727 " Reverts beamer block arguments to ERT "
2729 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2730 if document.textclass not in beamer_classes:
2733 blocks = ["Block", "ExampleBlock", "AlertBlock"]
2735 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2738 i = find_token(document.body, "\\begin_inset Argument", i)
2741 # Find containing paragraph layout
2742 parent = get_containing_layout(document.body, i)
2744 document.warning("Malformed lyx document: Can't find parent paragraph layout")
2749 realparbeg = parent[3]
2750 layoutname = parent[0]
2752 for p in range(parbeg, parend):
2756 if layoutname in blocks:
2757 m = rx.match(document.body[p])
2761 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2762 endPlain = find_end_of_layout(document.body, beginPlain)
2763 endInset = find_end_of_inset(document.body, p)
2764 content = document.body[beginPlain + 1 : endPlain]
2766 realparend = realparend - len(document.body[p : endInset + 1])
2768 del document.body[p : endInset + 1]
2769 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2770 document.body[realparbeg : realparbeg] = subst
2772 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2773 endPlain = find_end_of_layout(document.body, beginPlain)
2774 endInset = find_end_of_inset(document.body, p)
2775 content = document.body[beginPlain + 1 : endPlain]
2777 realparend = realparend - len(document.body[p : endInset + 1])
2779 del document.body[p : endInset + 1]
2780 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2781 document.body[realparbeg : realparbeg] = subst
2786 def convert_beamerblocks(document):
2787 " Converts beamer block ERT args to native InsetArgs "
2789 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2790 if document.textclass not in beamer_classes:
2793 blocks = ["Block", "ExampleBlock", "AlertBlock"]
2797 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2800 parent = get_containing_layout(document.body, i)
2801 if parent == False or parent[1] != i:
2802 document.warning("Wrong parent layout!")
2808 if document.body[parbeg] == "\\begin_inset ERT":
2809 ertcont = parbeg + 5
2811 if document.body[ertcont].startswith("<"):
2812 # This is an overlay specification
2814 document.body[ertcont] = document.body[ertcont][1:]
2815 if document.body[ertcont].endswith(">"):
2817 document.body[ertcont] = document.body[ertcont][:-1]
2818 # Convert to ArgInset
2819 document.body[parbeg] = "\\begin_inset Argument 1"
2820 elif document.body[ertcont].endswith("}"):
2822 tok = document.body[ertcont].find('>{')
2824 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2825 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2826 'status collapsed', '', '\\begin_layout Plain Layout',
2827 document.body[ertcont][tok + 2:-1]]
2828 # Convert to ArgInset
2829 document.body[parbeg] = "\\begin_inset Argument 1"
2830 elif document.body[ertcont].startswith("{"):
2831 # This is the block title
2832 if document.body[ertcont].endswith("}"):
2833 # strip off the braces
2834 document.body[ertcont] = document.body[ertcont][1:-1]
2835 # Convert to ArgInset
2836 document.body[parbeg] = "\\begin_inset Argument 2"
2837 elif count_pars_in_inset(document.body, ertcont) > 1:
2838 # Multipar ERT. Skip this.
2841 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True)
2844 j = find_end_of_layout(document.body, i)
2846 document.warning("end of layout not found!")
2847 k = find_token(document.body, "\\begin_inset Argument", i, j)
2849 document.warning("InsetArgument not found!")
2851 l = find_end_of_inset(document.body, k)
2852 m = find_token(document.body, "\\begin_inset ERT", l, j)
2860 def convert_overprint(document):
2861 " Convert old beamer overprint layouts to ERT "
2863 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2864 if document.textclass not in beamer_classes:
2869 i = find_token(document.body, "\\begin_layout Overprint", i)
2872 # Find end of sequence
2873 j = find_end_of_sequence(document.body, i)
2875 document.warning("Malformed lyx document. Cannot find end of Overprint sequence!")
2879 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
2881 if document.body[j] == "\\end_deeper":
2882 esubst = ["", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
2884 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
2885 endseq = endseq + len(esubst) - len(document.body[j : j])
2886 document.body[j : j] = esubst
2887 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
2889 argend = find_end_of_layout(document.body, argbeg)
2891 document.warning("Malformed lyx document. Cannot find end of Overprint argument!")
2894 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
2895 endPlain = find_end_of_layout(document.body, beginPlain)
2896 content = document.body[beginPlain + 1 : endPlain]
2898 endseq = endseq - len(document.body[argbeg : argend + 1])
2900 del document.body[argbeg : argend + 1]
2901 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2903 endseq = endseq - len(document.body[i : i])
2904 document.body[i : i] = subst + ["\\end_layout"]
2905 endseq += len(subst)
2907 for p in range(i, endseq):
2908 if document.body[p] == "\\begin_layout Overprint":
2909 document.body[p] = "\\begin_layout Standard"
2914 def revert_overprint(document):
2915 " Revert old beamer overprint layouts to ERT "
2917 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2918 if document.textclass not in beamer_classes:
2923 i = find_token(document.body, "\\begin_layout Overprint", i)
2926 # Find end of sequence
2927 j = find_end_of_sequence(document.body, i)
2929 document.warning("Malformed lyx document. Cannot find end of Overprint sequence!")
2933 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
2934 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}")
2935 endseq = endseq + len(esubst) - len(document.body[j : j])
2936 if document.body[j] == "\\end_deeper":
2937 document.body[j : j] = ["\\end_deeper", ""] + esubst
2939 document.body[j : j] = esubst
2942 if document.body[r] == "\\begin_deeper":
2943 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
2945 document.body[r] = ""
2946 document.body[s] = ""
2950 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
2952 argend = find_end_of_inset(document.body, argbeg)
2954 document.warning("Malformed lyx document. Cannot find end of Overprint argument!")
2957 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
2958 endPlain = find_end_of_layout(document.body, beginPlain)
2959 content = document.body[beginPlain + 1 : endPlain]
2961 endseq = endseq - len(document.body[argbeg : argend])
2963 del document.body[argbeg : argend + 1]
2964 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2966 endseq = endseq - len(document.body[i : i])
2967 document.body[i : i] = subst + ["\\end_layout"]
2968 endseq += len(subst)
2974 if document.body[p] == "\\begin_layout Overprint":
2975 q = find_end_of_layout(document.body, p)
2977 document.warning("Malformed lyx document. Cannot find end of Overprint layout!")
2980 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\onslide")
2981 argbeg = find_token(document.body, "\\begin_inset Argument item:1", p, q)
2983 argend = find_end_of_inset(document.body, argbeg)
2985 document.warning("Malformed lyx document. Cannot find end of Overprint item argument!")
2988 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
2989 endPlain = find_end_of_layout(document.body, beginPlain)
2990 content = document.body[beginPlain + 1 : endPlain]
2992 endseq = endseq - len(document.body[argbeg : argend + 1])
2994 del document.body[argbeg : argend + 1]
2995 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2996 endseq = endseq - len(document.body[p : p + 1]) + len(subst)
2997 document.body[p : p + 1] = subst
3003 def revert_frametitle(document):
3004 " Reverts beamer frametitle layout to ERT "
3006 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3007 if document.textclass not in beamer_classes:
3010 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3013 i = find_token(document.body, "\\begin_layout FrameTitle", i)
3016 j = find_end_of_layout(document.body, i)
3018 document.warning("Malformed lyx document: Can't find end of FrameTitle layout")
3022 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
3023 endlay += len(put_cmd_in_ert("}"))
3024 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\frametitle")
3025 for p in range(i, j):
3028 m = rx.match(document.body[p])
3032 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3033 endPlain = find_end_of_layout(document.body, beginPlain)
3034 endInset = find_end_of_inset(document.body, p)
3035 content = document.body[beginPlain + 1 : endPlain]
3037 endlay = endlay - len(document.body[p : endInset + 1])
3039 del document.body[p : endInset + 1]
3040 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3042 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3043 endPlain = find_end_of_layout(document.body, beginPlain)
3044 endInset = find_end_of_inset(document.body, p)
3045 content = document.body[beginPlain + 1 : endPlain]
3047 endlay = endlay - len(document.body[p : endInset + 1])
3049 del document.body[p : endInset + 1]
3050 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3052 subst += put_cmd_in_ert("{")
3053 document.body[i : i + 1] = subst
3057 def convert_epigraph(document):
3058 " Converts memoir epigraph to new syntax "
3060 if document.textclass != "memoir":
3065 i = find_token(document.body, "\\begin_layout Epigraph", i)
3068 j = find_end_of_layout(document.body, i)
3070 document.warning("Malformed lyx document: Can't find end of Epigraph layout")
3075 ert = find_token(document.body, "\\begin_inset ERT", i, j)
3077 endInset = find_end_of_inset(document.body, ert)
3078 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", ert)
3079 endPlain = find_end_of_layout(document.body, beginPlain)
3080 ertcont = beginPlain + 2
3081 if document.body[ertcont] == "}{":
3083 # Convert to ArgInset
3084 endlay = endlay - 2 * len(document.body[j])
3085 begsubst = ['\\begin_inset Argument post:1', 'status collapsed', '',
3086 '\\begin_layout Plain Layout']
3087 endsubst = ['\\end_layout', '', '\\end_inset', '', document.body[j]]
3088 document.body[j : j + 1] = endsubst
3089 document.body[endInset + 1 : endInset + 1] = begsubst
3091 endlay += len(begsubst) + len(endsubst)
3092 endlay = endlay - len(document.body[ert : endInset + 1])
3093 del document.body[ert : endInset + 1]
3098 def revert_epigraph(document):
3099 " Reverts memoir epigraph argument to ERT "
3101 if document.textclass != "memoir":
3106 i = find_token(document.body, "\\begin_layout Epigraph", i)
3109 j = find_end_of_layout(document.body, i)
3111 document.warning("Malformed lyx document: Can't find end of Epigraph layout")
3116 p = find_token(document.body, "\\begin_layout Argument post:1", i, j)
3118 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3119 endPlain = find_end_of_layout(document.body, beginPlain)
3120 endInset = find_end_of_inset(document.body, p)
3121 content = document.body[beginPlain + 1 : endPlain]
3123 endlay = endlay - len(document.body[p : endInset + 1])
3125 del document.body[p : endInset + 1]
3126 subst += put_cmd_in_ert("}{") + content
3128 subst += put_cmd_in_ert("}{")
3130 document.body[j : j] = subst + document.body[j : j]
3134 def convert_captioninsets(document):
3135 " Converts caption insets to new syntax "
3139 i = find_token(document.body, "\\begin_inset Caption", i)
3142 document.body[i] = "\\begin_inset Caption Standard"
3147 def revert_captioninsets(document):
3148 " Reverts caption insets to old syntax "
3152 i = find_token(document.body, "\\begin_inset Caption Standard", i)
3155 document.body[i] = "\\begin_inset Caption"
3159 def convert_captionlayouts(document):
3160 " Convert caption layouts to caption insets. "
3163 "Captionabove": "Above",
3164 "Captionbelow": "Below",
3165 "FigCaption" : "FigCaption",
3166 "Table_Caption" : "Table",
3167 "CenteredCaption" : "Centered",
3168 "Bicaption" : "Bicaption",
3173 i = find_token(document.body, "\\begin_layout", i)
3176 val = get_value(document.body, "\\begin_layout", i)
3177 if val in caption_dict.keys():
3178 j = find_end_of_layout(document.body, i)
3180 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3183 document.body[j:j] = ["\\end_layout", "", "\\end_inset", "", ""]
3184 document.body[i:i+1] = ["\\begin_layout %s" % document.default_layout,
3185 "\\begin_inset Caption %s" % caption_dict[val], "",
3186 "\\begin_layout %s" % document.default_layout]
3190 def revert_captionlayouts(document):
3191 " Revert caption insets to caption layouts. "
3194 "Above" : "Captionabove",
3195 "Below" : "Captionbelow",
3196 "FigCaption" : "FigCaption",
3197 "Table" : "Table_Caption",
3198 "Centered" : "CenteredCaption",
3199 "Bicaption" : "Bicaption",
3203 rx = re.compile(r'^\\begin_inset Caption (\S+)$')
3205 i = find_token(document.body, "\\begin_inset Caption", i)
3209 m = rx.match(document.body[i])
3213 if val not in caption_dict.keys():
3217 # We either need to delete the previous \begin_layout line, or we
3218 # need to end the previous layout if this inset is not in the first
3219 # position of the paragraph.
3220 layout_before = find_token_backwards(document.body, "\\begin_layout", i)
3221 if layout_before == -1:
3222 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3224 layout_line = document.body[layout_before]
3225 del_layout_before = True
3226 l = layout_before + 1
3228 if document.body[l] != "":
3229 del_layout_before = False
3232 if del_layout_before:
3233 del document.body[layout_before:i]
3236 document.body[i:i] = ["\\end_layout", ""]
3239 # Find start of layout in the inset and end of inset
3240 j = find_token(document.body, "\\begin_layout", i)
3242 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3244 k = find_end_of_inset(document.body, i)
3246 document.warning("Malformed LyX document: Missing `\\end_inset'.")
3249 # We either need to delete the following \end_layout line, or we need
3250 # to restart the old layout if this inset is not at the paragraph end.
3251 layout_after = find_token(document.body, "\\end_layout", k)
3252 if layout_after == -1:
3253 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3255 del_layout_after = True
3257 while l < layout_after:
3258 if document.body[l] != "":
3259 del_layout_after = False
3262 if del_layout_after:
3263 del document.body[k+1:layout_after+1]
3265 document.body[k+1:k+1] = [layout_line, ""]
3267 # delete \begin_layout and \end_inset and replace \begin_inset with
3268 # "\begin_layout XXX". This works because we can only have one
3269 # paragraph in the caption inset: The old \end_layout will be recycled.
3270 del document.body[k]
3271 if document.body[k] == "":
3272 del document.body[k]
3273 del document.body[j]
3274 if document.body[j] == "":
3275 del document.body[j]
3276 document.body[i] = "\\begin_layout %s" % caption_dict[val]
3277 if document.body[i+1] == "":
3278 del document.body[i+1]
3282 def revert_fragileframe(document):
3283 " Reverts beamer FragileFrame layout to ERT "
3285 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3286 if document.textclass not in beamer_classes:
3291 i = find_token(document.body, "\\begin_layout FragileFrame", i)
3294 # Find end of sequence
3295 j = find_end_of_sequence(document.body, i)
3297 document.warning("Malformed lyx document. Cannot find end of FragileFrame sequence!")
3301 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{frame}")
3302 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{frame}")
3303 endseq = endseq + len(esubst) - len(document.body[j : j])
3304 if document.body[j] == "\\end_deeper":
3305 document.body[j : j] = ["\\end_deeper", ""] + esubst
3307 document.body[j : j] = esubst
3308 for q in range(i, j):
3309 if document.body[q] == "\\begin_layout FragileFrame":
3310 document.body[q] = "\\begin_layout %s" % document.default_layout
3313 if document.body[r] == "\\begin_deeper":
3314 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3316 document.body[r] = ""
3317 document.body[s] = ""
3321 for p in range(1, 5):
3322 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, j)
3325 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3326 endPlain = find_end_of_layout(document.body, beginPlain)
3327 endInset = find_end_of_inset(document.body, arg)
3328 content = document.body[beginPlain + 1 : endPlain]
3330 j = j - len(document.body[arg : endInset + 1])
3332 del document.body[arg : endInset + 1]
3333 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3335 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3336 endPlain = find_end_of_layout(document.body, beginPlain)
3337 endInset = find_end_of_inset(document.body, arg)
3338 content = document.body[beginPlain + 1 : endPlain]
3340 j = j - len(document.body[arg : endInset + 1])
3342 del document.body[arg : endInset + 1]
3343 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3345 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3346 endPlain = find_end_of_layout(document.body, beginPlain)
3347 endInset = find_end_of_inset(document.body, arg)
3348 content = document.body[beginPlain + 1 : endPlain]
3350 j = j - len(document.body[arg : endInset + 1])
3352 del document.body[arg : endInset + 1]
3353 subst += put_cmd_in_ert("[fragile,") + content + put_cmd_in_ert("]")
3355 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3356 endPlain = find_end_of_layout(document.body, beginPlain)
3357 endInset = find_end_of_inset(document.body, arg)
3358 content = document.body[beginPlain + 1 : endPlain]
3360 j = j - len(document.body[arg : endInset + 1])
3362 del document.body[arg : endInset + 1]
3363 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3365 subst += put_cmd_in_ert("[fragile]")
3367 document.body[i : i + 1] = subst
3371 def revert_newframes(document):
3372 " Reverts beamer Frame and PlainFrame layouts to old forms "
3374 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3375 if document.textclass not in beamer_classes:
3379 "Frame" : "BeginFrame",
3380 "PlainFrame" : "BeginPlainFrame",
3383 rx = re.compile(r'^\\begin_layout (\S+)$')
3386 i = find_token(document.body, "\\begin_layout", i)
3390 m = rx.match(document.body[i])
3394 if val not in frame_dict.keys():
3397 # Find end of sequence
3398 j = find_end_of_sequence(document.body, i)
3400 document.warning("Malformed lyx document. Cannot find end of Frame sequence!")
3404 subst = ["\\begin_layout %s" % frame_dict[val]]
3405 esubst = ["\\end_layout", "", "\\begin_layout EndFrame", "", "\\end_layout"]
3406 endseq = endseq + len(esubst) - len(document.body[j : j])
3407 if document.body[j] == "\\end_deeper":
3408 document.body[j : j] = ["\\end_deeper", ""] + esubst
3410 document.body[j : j] = esubst
3411 for q in range(i, j):
3412 if document.body[q] == "\\begin_layout %s" % val:
3413 document.body[q] = "\\begin_layout %s" % document.default_layout
3416 if document.body[r] == "\\begin_deeper":
3417 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3419 document.body[r] = ""
3420 document.body[s] = ""
3424 l = find_end_of_layout(document.body, i)
3425 for p in range(1, 5):
3426 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, l)
3429 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3430 endPlain = find_end_of_layout(document.body, beginPlain)
3431 endInset = find_end_of_inset(document.body, arg)
3432 content = document.body[beginPlain + 1 : endPlain]
3434 l = l - len(document.body[arg : endInset + 1])
3436 del document.body[arg : endInset + 1]
3437 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3439 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3440 endPlain = find_end_of_layout(document.body, beginPlain)
3441 endInset = find_end_of_inset(document.body, arg)
3442 content = document.body[beginPlain + 1 : endPlain]
3444 l = l - len(document.body[arg : endInset + 1])
3446 del document.body[arg : endInset + 1]
3447 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3449 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3450 endPlain = find_end_of_layout(document.body, beginPlain)
3451 endInset = find_end_of_inset(document.body, arg)
3452 content = document.body[beginPlain + 1 : endPlain]
3454 l = l - len(document.body[arg : endInset + 1])
3456 del document.body[arg : endInset + 1]
3457 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3459 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3460 endPlain = find_end_of_layout(document.body, beginPlain)
3461 endInset = find_end_of_inset(document.body, arg)
3462 content = document.body[beginPlain + 1 : endPlain]
3464 l = l - len(document.body[arg : endInset + 1])
3466 del document.body[arg : endInset + 1]
3469 document.body[i : i + 1] = subst
3477 supported_versions = ["2.1.0","2.1"]
3480 [415, [convert_undertilde]],
3482 [417, [convert_japanese_encodings]],
3485 [420, [convert_biblio_style]],
3486 [421, [convert_longtable_captions]],
3487 [422, [convert_use_packages]],
3488 [423, [convert_use_mathtools]],
3489 [424, [convert_cite_engine_type]],
3493 [428, [convert_cell_rotation]],
3494 [429, [convert_table_rotation]],
3495 [430, [convert_listoflistings]],
3496 [431, [convert_use_amssymb]],
3498 [433, [convert_armenian]],
3506 [441, [convert_mdnomath]],
3511 [446, [convert_latexargs]],
3512 [447, [convert_IEEEtran, convert_AASTeX, convert_AGUTeX, convert_IJMP, convert_SIGPLAN, convert_SIGGRAPH, convert_EuropeCV, convert_Initials, convert_ModernCV]],
3513 [448, [convert_literate]],
3516 [451, [convert_beamerargs, convert_againframe_args, convert_corollary_args, convert_quote_args]],
3517 [452, [convert_beamerblocks]],
3518 [453, [convert_use_stmaryrd]],
3519 [454, [convert_overprint]],
3521 [456, [convert_epigraph]],
3522 [457, [convert_use_stackrel]],
3523 [458, [convert_captioninsets, convert_captionlayouts]],
3528 [458, [revert_fragileframe, revert_newframes]],
3529 [457, [revert_captioninsets, revert_captionlayouts]],
3530 [456, [revert_use_stackrel]],
3531 [455, [revert_epigraph]],
3532 [454, [revert_frametitle]],
3533 [453, [revert_overprint]],
3534 [452, [revert_use_stmaryrd]],
3535 [451, [revert_beamerblocks]],
3536 [450, [revert_beamerargs, revert_beamerargs2, revert_beamerargs3, revert_beamerflex]],
3537 [449, [revert_garamondx, revert_garamondx_newtxmath]],
3538 [448, [revert_itemargs]],
3539 [447, [revert_literate]],
3540 [446, [revert_IEEEtran, revert_AASTeX, revert_AGUTeX, revert_IJMP, revert_SIGPLAN, revert_SIGGRAPH, revert_EuropeCV, revert_Initials, revert_ModernCV]],
3541 [445, [revert_latexargs]],
3542 [444, [revert_uop]],
3543 [443, [revert_biolinum]],
3545 [441, [revert_newtxmath]],
3546 [440, [revert_mdnomath]],
3547 [439, [revert_mathfonts]],
3548 [438, [revert_minionpro]],
3549 [437, [revert_ipadeco, revert_ipachar]],
3550 [436, [revert_texgyre]],
3551 [435, [revert_mathdesign]],
3552 [434, [revert_txtt]],
3553 [433, [revert_libertine]],
3554 [432, [revert_armenian]],
3555 [431, [revert_languages, revert_ancientgreek]],
3556 [430, [revert_use_amssymb]],
3557 [429, [revert_listoflistings]],
3558 [428, [revert_table_rotation]],
3559 [427, [revert_cell_rotation]],
3560 [426, [revert_tipa]],
3561 [425, [revert_verbatim]],
3562 [424, [revert_cancel]],
3563 [423, [revert_cite_engine_type]],
3564 [422, [revert_use_mathtools]],
3565 [421, [revert_use_packages]],
3566 [420, [revert_longtable_captions]],
3567 [419, [revert_biblio_style]],
3568 [418, [revert_australian]],
3569 [417, [revert_justification]],
3570 [416, [revert_japanese_encodings]],
3571 [415, [revert_negative_space, revert_math_spaces]],
3572 [414, [revert_undertilde]],
3573 [413, [revert_visible_space]]
3577 if __name__ == "__main__":