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 revert_IEEEtran(document):
1461 Reverts InsetArgument of
1464 Biography without photo
1467 if document.textclass == "IEEEtran":
1473 i = find_token(document.body, "\\begin_layout Page headings", i)
1475 revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1478 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1480 revert_Argument_to_TeX_brace(document, j, 1, 1, True)
1483 k = find_token(document.body, "\\begin_layout Biography", k)
1484 kA = find_token(document.body, "\\begin_layout Biography without photo", k)
1485 if k == kA and k != -1:
1489 # start with the second argument, therefore 2
1490 revert_Argument_to_TeX_brace(document, k, 2, 2, True)
1492 if i == -1 and j == -1 and k == -1:
1496 def convert_TeX_brace_to_Argument(document, line, n, nmax, inset, environment):
1498 Converts TeX code for mandatory arguments to an InsetArgument
1499 The conversion of TeX code for optional arguments must be done with another routine
1500 !!! Be careful if the braces are different in your case as expected here:
1501 - "}{" separates mandatory arguments of commands
1502 - "}" + "{" separates mandatory arguments of commands
1503 - "}" + " " + "{" separates mandatory arguments of commands
1504 - { and } surround a mandatory argument of an environment
1506 convert_TeX_brace_to_Argument(document, LineOfBeginLayout/Inset, StartArgument, EndArgument, isInset, isEnvironment)
1507 LineOfBeginLayout/Inset is the line of the \begin_layout or \begin_inset statement
1508 StartArgument is the number of the first ERT that needs to be converted
1509 EndArgument is the number of the last ERT that needs to be converted
1510 isInset must be true, if braces inside an InsetLayout needs to be converted
1511 isEnvironment must be true, if the layout is for a LaTeX environment
1513 Todo: this routine can currently handle only one mandatory argument of environments
1518 while lineERT != -1 and n < nmax + 1:
1519 lineERT = find_token(document.body, "\\begin_inset ERT", lineERT)
1520 if environment == False and lineERT != -1:
1521 bracePair = find_token(document.body, "}{", lineERT)
1522 # assure that the "}{" is in this ERT
1523 if bracePair == lineERT + 5:
1524 end = find_token(document.body, "\\end_inset", bracePair)
1525 document.body[lineERT : end + 1] = ["\\end_layout", "", "\\end_inset"]
1527 # in the case that n > 1 we have optional arguments before
1528 # therefore detect them if any
1530 # first check if there is an argument
1531 lineArg = find_token(document.body, "\\begin_inset Argument", line)
1532 if lineArg < lineERT and lineArg != -1:
1533 # we have an argument, so now search backwards for its end
1534 # we must now assure that we don't find other insets like e.g. a newline
1535 endInsetArg = lineERT
1536 endLayoutArg = endInsetArg
1537 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
1538 endInsetArg = endInsetArg - 1
1539 endLayoutArg = endInsetArg
1540 endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
1541 endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
1542 line = endInsetArg + 1
1544 document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1546 document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1548 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1552 # now check the case that we have "}" + "{" in two ERTs
1554 endBrace = find_token(document.body, "}", lineERT)
1555 if endBrace == lineERT + 5:
1556 beginBrace = find_token(document.body, "{", endBrace)
1557 # assure that the ERTs are consecutive (11 or 12 depending if there is a space between the ERTs or not)
1558 if beginBrace == endBrace + 11 or beginBrace == endBrace + 12:
1559 end = find_token(document.body, "\\end_inset", beginBrace)
1560 document.body[lineERT : end + 1] = ["\\end_layout", "", "\\end_inset"]
1562 # in the case that n > 1 we have optional arguments before
1563 # therefore detect them if any
1565 # first check if there is an argument
1566 lineArg = find_token(document.body, "\\begin_inset Argument", line)
1567 if lineArg < lineERT and lineArg != -1:
1568 # we have an argument, so now search backwards for its end
1569 # we must now assure that we don't find other insets like e.g. a newline
1570 endInsetArg = lineERT
1571 endLayoutArg = endInsetArg
1572 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
1573 endInsetArg = endInsetArg - 1
1574 endLayoutArg = endInsetArg
1575 endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
1576 endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
1577 line = endInsetArg + 1
1579 document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1581 document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1583 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1586 # set the line where the next argument will be inserted
1587 if beginBrace == endBrace + 11:
1592 lineERT = lineERT + 1
1593 if environment == True and lineERT != -1:
1594 opening = find_token(document.body, "{", lineERT)
1595 if opening == lineERT + 5: # assure that the "{" is in this ERT
1596 end = find_token(document.body, "\\end_inset", opening)
1597 document.body[lineERT : end + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1599 lineERT2 = find_token(document.body, "\\begin_inset ERT", lineERT)
1600 closing = find_token(document.body, "}", lineERT2)
1601 if closing == lineERT2 + 5: # assure that the "}" is in this ERT
1602 end2 = find_token(document.body, "\\end_inset", closing)
1603 document.body[lineERT2 : end2 + 1] = ["\\end_layout", "", "\\end_inset"]
1605 lineERT = lineERT + 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 InsetArgument of MarkBoth 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 MarkBoth 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 InsetArgument of Flex CRcat 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 Flex CRcat 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_Initials(document):
1863 " Reverts InsetArgument of Initial to TeX-code "
1867 i = find_token(document.body, "\\begin_layout Initial", i)
1869 # first arg (optional) and second arg (first mandatory) are supported in LyX 2.0.x
1870 revert_Argument_to_TeX_brace(document, i, 3, 3, False)
1876 def convert_Initials(document):
1877 " Converts ERT of Initial to InsetArgument "
1881 i = find_token(document.body, "\\begin_layout Initial", i)
1883 convert_TeX_brace_to_Argument(document, i, 3, 3, False, False)
1889 def revert_literate(document):
1890 " Revert Literate document to old format "
1891 if del_token(document.header, "noweb", 0):
1892 document.textclass = "literate-" + document.textclass
1895 i = find_token(document.body, "\\begin_layout Chunk", i)
1898 document.body[i] = "\\begin_layout Scrap"
1902 def convert_literate(document):
1903 " Convert Literate document to new format"
1904 i = find_token(document.header, "\\textclass", 0)
1905 if (i != -1) and "literate-" in document.header[i]:
1906 document.textclass = document.header[i].replace("\\textclass literate-", "")
1907 j = find_token(document.header, "\\begin_modules", 0)
1909 document.header.insert(j + 1, "noweb")
1911 document.header.insert(i + 1, "\\end_modules")
1912 document.header.insert(i + 1, "noweb")
1913 document.header.insert(i + 1, "\\begin_modules")
1916 i = find_token(document.body, "\\begin_layout Scrap", i)
1919 document.body[i] = "\\begin_layout Chunk"
1923 def revert_itemargs(document):
1924 " Reverts \\item arguments to TeX-code "
1927 i = find_token(document.body, "\\begin_inset Argument item:", i)
1930 j = find_end_of_inset(document.body, i)
1931 # Find containing paragraph layout
1932 parent = get_containing_layout(document.body, i)
1934 document.warning("Malformed lyx document: Can't find parent paragraph layout")
1938 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
1939 endPlain = find_end_of_layout(document.body, beginPlain)
1940 content = document.body[beginPlain + 1 : endPlain]
1941 del document.body[i:j+1]
1942 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
1943 document.body[parbeg : parbeg] = subst
1947 def revert_garamondx_newtxmath(document):
1948 " Revert native garamond newtxmath definition to LaTeX "
1950 i = find_token(document.header, "\\font_math", 0)
1953 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1954 val = get_value(document.header, "\\font_math", i)
1955 if val == "garamondx-ntxm":
1956 add_to_preamble(document, "\\usepackage[garamondx]{newtxmath}")
1957 document.header[i] = "\\font_math auto"
1960 def revert_garamondx(document):
1961 " Revert native garamond font definition to LaTeX "
1963 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1964 i = find_token(document.header, "\\font_roman garamondx", 0)
1967 j = find_token(document.header, "\\font_osf true", 0)
1970 preamble = "\\usepackage"
1972 preamble += "[osfI]"
1973 preamble += "{garamondx}"
1974 add_to_preamble(document, [preamble])
1975 document.header[i] = "\\font_roman default"
1978 def convert_beamerargs(document):
1979 " Converts beamer arguments to new layout "
1981 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
1982 if document.textclass not in beamer_classes:
1985 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
1986 list_layouts = ["Itemize", "Enumerate", "Description"]
1987 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
1991 i = find_token(document.body, "\\begin_inset Argument", i)
1994 # Find containing paragraph layout
1995 parent = get_containing_layout(document.body, i)
1997 document.warning("Malformed lyx document: Can't find parent paragraph layout")
2002 layoutname = parent[0]
2003 for p in range(parbeg, parend):
2004 if layoutname in shifted_layouts:
2005 m = rx.match(document.body[p])
2007 argnr = int(m.group(1))
2009 document.body[p] = "\\begin_inset Argument %d" % argnr
2010 if layoutname == "AgainFrame":
2011 m = rx.match(document.body[p])
2013 document.body[p] = "\\begin_inset Argument 3"
2014 if document.body[p + 4] == "\\begin_inset ERT":
2015 if document.body[p + 9].startswith("<"):
2016 # This is an overlay specification
2018 document.body[p + 9] = document.body[p + 9][1:]
2019 if document.body[p + 9].endswith(">"):
2021 document.body[p + 9] = document.body[p + 9][:-1]
2023 document.body[p] = "\\begin_inset Argument 2"
2024 if layoutname in list_layouts:
2025 m = rx.match(document.body[p])
2027 if m.group(1) == "1":
2028 if document.body[p + 4] == "\\begin_inset ERT":
2029 if document.body[p + 9].startswith("<"):
2030 # This is an overlay specification
2032 document.body[p + 9] = document.body[p + 9][1:]
2033 if document.body[p + 9].endswith(">"):
2035 document.body[p + 9] = document.body[p + 9][:-1]
2036 elif layoutname != "Itemize":
2038 document.body[p] = "\\begin_inset Argument 2"
2042 def convert_againframe_args(document):
2043 " Converts beamer AgainFrame to new layout "
2045 # FIXME: This currently only works if the arguments are in one single ERT
2047 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2048 if document.textclass not in beamer_classes:
2053 i = find_token(document.body, "\\begin_layout AgainFrame", i)
2056 parent = get_containing_layout(document.body, i)
2058 document.warning("Wrong parent layout!")
2062 if document.body[parbeg] == "\\begin_inset ERT":
2063 ertcont = parbeg + 5
2064 if document.body[ertcont].startswith("[<"):
2065 # This is a default overlay specification
2067 document.body[ertcont] = document.body[ertcont][2:]
2068 if document.body[ertcont].endswith(">]"):
2070 document.body[ertcont] = document.body[ertcont][:-2]
2071 elif document.body[ertcont].endswith("]"):
2073 tok = document.body[ertcont].find('>][')
2075 subst = [document.body[ertcont][:tok],
2076 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2077 'status collapsed', '', '\\begin_layout Plain Layout',
2078 document.body[ertcont][tok + 3:-1]]
2079 document.body[ertcont : ertcont + 1] = subst
2080 # Convert to ArgInset
2081 document.body[parbeg] = "\\begin_inset Argument 2"
2084 elif document.body[ertcont].startswith("<"):
2085 # This is an overlay specification
2087 document.body[ertcont] = document.body[ertcont][1:]
2088 if document.body[ertcont].endswith(">"):
2090 document.body[ertcont] = document.body[ertcont][:-1]
2091 # Convert to ArgInset
2092 document.body[parbeg] = "\\begin_inset Argument 1"
2093 elif document.body[ertcont].endswith(">]"):
2095 tok = document.body[ertcont].find('>[<')
2097 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2098 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2099 'status collapsed', '', '\\begin_layout Plain Layout',
2100 document.body[ertcont][tok + 3:-2]]
2101 # Convert to ArgInset
2102 document.body[parbeg] = "\\begin_inset Argument 1"
2103 elif document.body[ertcont].endswith("]"):
2105 tok = document.body[ertcont].find('>[<')
2108 tokk = document.body[ertcont].find('>][')
2110 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2111 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2112 'status collapsed', '', '\\begin_layout Plain Layout',
2113 document.body[ertcont][tok + 3:tokk],
2114 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2115 'status collapsed', '', '\\begin_layout Plain Layout',
2116 document.body[ertcont][tokk + 3:-1]]
2118 tokk = document.body[ertcont].find('>[')
2120 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tokk],
2121 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2122 'status collapsed', '', '\\begin_layout Plain Layout',
2123 document.body[ertcont][tokk + 2:-1]]
2124 # Convert to ArgInset
2125 document.body[parbeg] = "\\begin_inset Argument 1"
2128 elif document.body[ertcont].startswith("["):
2129 # This is an ERT option
2131 document.body[ertcont] = document.body[ertcont][1:]
2132 if document.body[ertcont].endswith("]"):
2134 document.body[ertcont] = document.body[ertcont][:-1]
2135 # Convert to ArgInset
2136 document.body[parbeg] = "\\begin_inset Argument 3"
2142 def convert_corollary_args(document):
2143 " Converts beamer corrolary-style ERT arguments native InsetArgs "
2145 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2146 if document.textclass not in beamer_classes:
2149 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2150 for lay in corollary_layouts:
2153 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2156 parent = get_containing_layout(document.body, i)
2158 document.warning("Wrong parent layout!")
2162 if document.body[parbeg] == "\\begin_inset ERT":
2163 ertcont = parbeg + 5
2164 if document.body[ertcont].startswith("<"):
2165 # This is an overlay specification
2167 document.body[ertcont] = document.body[ertcont][1:]
2168 if document.body[ertcont].endswith(">"):
2170 document.body[ertcont] = document.body[ertcont][:-1]
2171 elif document.body[ertcont].endswith("]"):
2173 tok = document.body[ertcont].find('>[')
2175 subst = [document.body[ertcont][:tok],
2176 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2177 'status collapsed', '', '\\begin_layout Plain Layout',
2178 document.body[ertcont][tok + 2:-1]]
2179 document.body[ertcont : ertcont + 1] = subst
2180 # Convert to ArgInset
2181 document.body[parbeg] = "\\begin_inset Argument 1"
2184 elif document.body[ertcont].startswith("["):
2185 # This is an ERT option
2187 document.body[ertcont] = document.body[ertcont][1:]
2188 if document.body[ertcont].endswith("]"):
2190 document.body[ertcont] = document.body[ertcont][:-1]
2191 # Convert to ArgInset
2192 document.body[parbeg] = "\\begin_inset Argument 2"
2199 def convert_quote_args(document):
2200 " Converts beamer quote style ERT args to native InsetArgs "
2202 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2203 if document.textclass not in beamer_classes:
2206 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2207 for lay in quote_layouts:
2210 i = find_token(document.body, "\\begin_layout " + lay, i)
2213 parent = get_containing_layout(document.body, i)
2215 document.warning("Wrong parent layout!")
2219 if document.body[parbeg] == "\\begin_inset ERT":
2220 if document.body[i + 6].startswith("<"):
2221 # This is an overlay specification
2223 document.body[i + 6] = document.body[i + 6][1:]
2224 if document.body[i + 6].endswith(">"):
2226 document.body[i + 6] = document.body[i + 6][:-1]
2227 # Convert to ArgInset
2228 document.body[i + 1] = "\\begin_inset Argument 1"
2232 def revert_beamerargs(document):
2233 " Reverts beamer arguments to old layout "
2235 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2236 if document.textclass not in beamer_classes:
2240 list_layouts = ["Itemize", "Enumerate", "Description"]
2241 headings = ["Part", "Section", "Section*", "Subsection", "Subsection*",
2242 "Subsubsection", "Subsubsection*", "FrameSubtitle", "NoteItem"]
2243 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2244 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2245 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2248 i = find_token(document.body, "\\begin_inset Argument", i)
2251 # Find containing paragraph layout
2252 parent = get_containing_layout(document.body, i)
2254 document.warning("Malformed lyx document: Can't find parent paragraph layout")
2259 realparbeg = parent[3]
2260 layoutname = parent[0]
2262 for p in range(parbeg, parend):
2266 if layoutname in headings:
2267 m = rx.match(document.body[p])
2271 # Find containing paragraph layout
2272 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2273 endPlain = find_end_of_layout(document.body, beginPlain)
2274 endInset = find_end_of_inset(document.body, p)
2275 argcontent = document.body[beginPlain + 1 : endPlain]
2277 realparend = realparend - len(document.body[p : endInset + 1])
2279 del document.body[p : endInset + 1]
2280 if layoutname == "FrameSubtitle":
2281 pre = put_cmd_in_ert("\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2282 elif layoutname == "NoteItem":
2283 pre = put_cmd_in_ert("\\note<") + argcontent + put_cmd_in_ert(">[item]")
2284 elif layoutname.endswith('*'):
2285 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower()[:-1] + "<") + argcontent + put_cmd_in_ert(">*")
2287 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2288 secarg = find_token(document.body, "\\begin_inset Argument 2", parbeg, parend)
2290 # Find containing paragraph layout
2291 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", secarg)
2292 endPlain = find_end_of_layout(document.body, beginPlain)
2293 endInset = find_end_of_inset(document.body, secarg)
2294 argcontent = document.body[beginPlain + 1 : endPlain]
2296 realparend = realparend - len(document.body[secarg : endInset + 1])
2297 del document.body[secarg : endInset + 1]
2298 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2299 pre += put_cmd_in_ert("{")
2300 document.body[parbeg] = "\\begin_layout Standard"
2301 document.body[realparbeg : realparbeg] = pre
2302 pe = find_end_of_layout(document.body, parbeg)
2303 post = put_cmd_in_ert("}")
2304 document.body[pe : pe] = post
2305 realparend += len(pre) + len(post)
2306 if layoutname == "AgainFrame":
2307 m = rx.match(document.body[p])
2311 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2312 endPlain = find_end_of_layout(document.body, beginPlain)
2313 endInset = find_end_of_inset(document.body, p)
2314 content = document.body[beginPlain + 1 : endPlain]
2316 realparend = realparend - len(document.body[p : endInset + 1])
2318 del document.body[p : endInset + 1]
2319 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2320 document.body[realparbeg : realparbeg] = subst
2321 if layoutname == "Overprint":
2322 m = rx.match(document.body[p])
2326 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2327 endPlain = find_end_of_layout(document.body, beginPlain)
2328 endInset = find_end_of_inset(document.body, p)
2329 content = document.body[beginPlain + 1 : endPlain]
2331 realparend = realparend - len(document.body[p : endInset + 1])
2333 del document.body[p : endInset + 1]
2334 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2335 document.body[realparbeg : realparbeg] = subst
2336 if layoutname == "OverlayArea":
2337 m = rx.match(document.body[p])
2341 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2342 endPlain = find_end_of_layout(document.body, beginPlain)
2343 endInset = find_end_of_inset(document.body, p)
2344 content = document.body[beginPlain + 1 : endPlain]
2346 realparend = realparend - len(document.body[p : endInset + 1])
2348 del document.body[p : endInset + 1]
2349 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2350 document.body[realparbeg : realparbeg] = subst
2351 if layoutname in list_layouts:
2352 m = rx.match(document.body[p])
2356 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2357 endPlain = find_end_of_layout(document.body, beginPlain)
2358 endInset = find_end_of_inset(document.body, p)
2359 content = document.body[beginPlain + 1 : endPlain]
2360 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2361 realparend = realparend + len(subst) - len(content)
2362 document.body[beginPlain + 1 : endPlain] = subst
2363 elif argnr == "item:1":
2364 j = find_end_of_inset(document.body, i)
2365 # Find containing paragraph layout
2366 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2367 endPlain = find_end_of_layout(document.body, beginPlain)
2368 content = document.body[beginPlain + 1 : endPlain]
2369 del document.body[i:j+1]
2370 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2371 document.body[realparbeg : realparbeg] = subst
2372 elif argnr == "item:2":
2373 j = find_end_of_inset(document.body, i)
2374 # Find containing paragraph layout
2375 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2376 endPlain = find_end_of_layout(document.body, beginPlain)
2377 content = document.body[beginPlain + 1 : endPlain]
2378 del document.body[i:j+1]
2379 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2380 document.body[realparbeg : realparbeg] = subst
2381 if layoutname in quote_layouts:
2382 m = rx.match(document.body[p])
2386 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2387 endPlain = find_end_of_layout(document.body, beginPlain)
2388 endInset = find_end_of_inset(document.body, p)
2389 content = document.body[beginPlain + 1 : endPlain]
2391 realparend = realparend - len(document.body[p : endInset + 1])
2393 del document.body[p : endInset + 1]
2394 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2395 document.body[realparbeg : realparbeg] = subst
2396 if layoutname in corollary_layouts:
2397 m = rx.match(document.body[p])
2401 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2402 endPlain = find_end_of_layout(document.body, beginPlain)
2403 endInset = find_end_of_inset(document.body, p)
2404 content = document.body[beginPlain + 1 : endPlain]
2406 realparend = realparend - len(document.body[p : endInset + 1])
2408 del document.body[p : endInset + 1]
2409 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2410 document.body[realparbeg : realparbeg] = subst
2415 def revert_beamerargs2(document):
2416 " Reverts beamer arguments to old layout, step 2 "
2418 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2419 if document.textclass not in beamer_classes:
2423 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2424 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2425 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2428 i = find_token(document.body, "\\begin_inset Argument", i)
2431 # Find containing paragraph layout
2432 parent = get_containing_layout(document.body, i)
2434 document.warning("Malformed lyx document: Can't find parent paragraph layout")
2439 realparbeg = parent[3]
2440 layoutname = parent[0]
2442 for p in range(parbeg, parend):
2446 if layoutname in shifted_layouts:
2447 m = rx.match(document.body[p])
2451 document.body[p] = "\\begin_inset Argument 1"
2452 if layoutname in corollary_layouts:
2453 m = rx.match(document.body[p])
2457 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2458 endPlain = find_end_of_layout(document.body, beginPlain)
2459 endInset = find_end_of_inset(document.body, p)
2460 content = document.body[beginPlain + 1 : endPlain]
2462 realparend = realparend - len(document.body[p : endInset + 1])
2464 del document.body[p : endInset + 1]
2465 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2466 document.body[realparbeg : realparbeg] = subst
2467 if layoutname == "OverlayArea":
2468 m = rx.match(document.body[p])
2472 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2473 endPlain = find_end_of_layout(document.body, beginPlain)
2474 endInset = find_end_of_inset(document.body, p)
2475 content = document.body[beginPlain + 1 : endPlain]
2477 realparend = realparend - len(document.body[p : endInset + 1])
2479 del document.body[p : endInset + 1]
2480 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2481 document.body[realparbeg : realparbeg] = subst
2482 if layoutname == "AgainFrame":
2483 m = rx.match(document.body[p])
2487 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2488 endPlain = find_end_of_layout(document.body, beginPlain)
2489 endInset = find_end_of_inset(document.body, p)
2490 content = document.body[beginPlain + 1 : endPlain]
2492 realparend = realparend - len(document.body[p : endInset + 1])
2494 del document.body[p : endInset + 1]
2495 subst = put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
2496 document.body[realparbeg : realparbeg] = subst
2500 def revert_beamerargs3(document):
2501 " Reverts beamer arguments to old layout, step 3 "
2503 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2504 if document.textclass not in beamer_classes:
2507 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2510 i = find_token(document.body, "\\begin_inset Argument", i)
2513 # Find containing paragraph layout
2514 parent = get_containing_layout(document.body, i)
2516 document.warning("Malformed lyx document: Can't find parent paragraph layout")
2521 realparbeg = parent[3]
2522 layoutname = parent[0]
2524 for p in range(parbeg, parend):
2528 if layoutname == "AgainFrame":
2529 m = rx.match(document.body[p])
2533 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2534 endPlain = find_end_of_layout(document.body, beginPlain)
2535 endInset = find_end_of_inset(document.body, p)
2536 content = document.body[beginPlain + 1 : endPlain]
2538 realparend = realparend - len(document.body[p : endInset + 1])
2540 del document.body[p : endInset + 1]
2541 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2542 document.body[realparbeg : realparbeg] = subst
2546 def revert_beamerflex(document):
2547 " Reverts beamer Flex insets "
2549 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2550 if document.textclass not in beamer_classes:
2553 new_flexes = {"Bold" : "\\textbf", "Emphasize" : "\\emph", "Only" : "\\only",
2554 "Uncover" : "\\uncover", "Visible" : "\\visible",
2555 "Invisible" : "\\invisible", "Alternative" : "\\alt",
2556 "Beamer_Note" : "\\note"}
2557 old_flexes = {"Alert" : "\\alert", "Structure" : "\\structure"}
2558 rx = re.compile(r'^\\begin_inset Flex (.+)$')
2562 i = find_token(document.body, "\\begin_inset Flex", i)
2565 m = rx.match(document.body[i])
2567 flextype = m.group(1)
2568 z = find_end_of_inset(document.body, i)
2570 document.warning("Can't find end of Flex " + flextype + " inset.")
2573 if flextype in new_flexes:
2574 pre = put_cmd_in_ert(new_flexes[flextype])
2575 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2577 argend = find_end_of_inset(document.body, arg)
2579 document.warning("Can't find end of Argument!")
2582 # Find containing paragraph layout
2583 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2584 endPlain = find_end_of_layout(document.body, beginPlain)
2585 argcontent = document.body[beginPlain + 1 : endPlain]
2587 z = z - len(document.body[arg : argend + 1])
2589 del document.body[arg : argend + 1]
2590 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2591 arg = find_token(document.body, "\\begin_inset Argument 2", i, z)
2593 argend = find_end_of_inset(document.body, arg)
2595 document.warning("Can't find end of Argument!")
2598 # Find containing paragraph layout
2599 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2600 endPlain = find_end_of_layout(document.body, beginPlain)
2601 argcontent = document.body[beginPlain + 1 : endPlain]
2603 z = z - len(document.body[arg : argend + 1])
2605 del document.body[arg : argend + 1]
2606 if flextype == "Alternative":
2607 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
2609 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2610 pre += put_cmd_in_ert("{")
2611 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2612 endPlain = find_end_of_layout(document.body, beginPlain)
2614 z = z - len(document.body[i : beginPlain + 1])
2616 document.body[i : beginPlain + 1] = pre
2617 post = put_cmd_in_ert("}")
2618 document.body[z - 2 : z + 1] = post
2619 elif flextype in old_flexes:
2620 pre = put_cmd_in_ert(old_flexes[flextype])
2621 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2625 argend = find_end_of_inset(document.body, arg)
2627 document.warning("Can't find end of Argument!")
2630 # Find containing paragraph layout
2631 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2632 endPlain = find_end_of_layout(document.body, beginPlain)
2633 argcontent = document.body[beginPlain + 1 : endPlain]
2635 z = z - len(document.body[arg : argend + 1])
2637 del document.body[arg : argend + 1]
2638 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2639 pre += put_cmd_in_ert("{")
2640 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2641 endPlain = find_end_of_layout(document.body, beginPlain)
2643 z = z - len(document.body[i : beginPlain + 1])
2645 document.body[i : beginPlain + 1] = pre
2646 post = put_cmd_in_ert("}")
2647 document.body[z - 2 : z + 1] = post
2652 def revert_beamerblocks(document):
2653 " Reverts beamer block arguments to ERT "
2655 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2656 if document.textclass not in beamer_classes:
2659 blocks = ["Block", "ExampleBlock", "AlertBlock"]
2661 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2664 i = find_token(document.body, "\\begin_inset Argument", i)
2667 # Find containing paragraph layout
2668 parent = get_containing_layout(document.body, i)
2670 document.warning("Malformed lyx document: Can't find parent paragraph layout")
2675 realparbeg = parent[3]
2676 layoutname = parent[0]
2678 for p in range(parbeg, parend):
2682 if layoutname in blocks:
2683 m = rx.match(document.body[p])
2687 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2688 endPlain = find_end_of_layout(document.body, beginPlain)
2689 endInset = find_end_of_inset(document.body, p)
2690 content = document.body[beginPlain + 1 : endPlain]
2692 realparend = realparend - len(document.body[p : endInset + 1])
2694 del document.body[p : endInset + 1]
2695 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2696 document.body[realparbeg : realparbeg] = subst
2698 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2699 endPlain = find_end_of_layout(document.body, beginPlain)
2700 endInset = find_end_of_inset(document.body, p)
2701 content = document.body[beginPlain + 1 : endPlain]
2703 realparend = realparend - len(document.body[p : endInset + 1])
2705 del document.body[p : endInset + 1]
2706 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2707 document.body[realparbeg : realparbeg] = subst
2712 def convert_beamerblocks(document):
2713 " Converts beamer block ERT args to native InsetArgs "
2715 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2716 if document.textclass not in beamer_classes:
2719 blocks = ["Block", "ExampleBlock", "AlertBlock"]
2723 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2726 parent = get_containing_layout(document.body, i)
2727 if parent == False or parent[1] != i:
2728 document.warning("Wrong parent layout!")
2734 if document.body[parbeg] == "\\begin_inset ERT":
2735 ertcont = parbeg + 5
2737 if document.body[ertcont].startswith("<"):
2738 # This is an overlay specification
2740 document.body[ertcont] = document.body[ertcont][1:]
2741 if document.body[ertcont].endswith(">"):
2743 document.body[ertcont] = document.body[ertcont][:-1]
2744 # Convert to ArgInset
2745 document.body[parbeg] = "\\begin_inset Argument 1"
2746 elif document.body[ertcont].endswith("}"):
2748 tok = document.body[ertcont].find('>{')
2750 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2751 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2752 'status collapsed', '', '\\begin_layout Plain Layout',
2753 document.body[ertcont][tok + 2:-1]]
2754 # Convert to ArgInset
2755 document.body[parbeg] = "\\begin_inset Argument 1"
2756 elif document.body[ertcont].startswith("{"):
2757 # This is the block title
2758 if document.body[ertcont].endswith("}"):
2759 # strip off the braces
2760 document.body[ertcont] = document.body[ertcont][1:-1]
2761 # Convert to ArgInset
2762 document.body[parbeg] = "\\begin_inset Argument 2"
2763 elif count_pars_in_inset(document.body, ertcont) > 1:
2764 # Multipar ERT. Skip this.
2767 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True)
2770 j = find_end_of_layout(document.body, i)
2772 document.warning("end of layout not found!")
2773 k = find_token(document.body, "\\begin_inset Argument", i, j)
2775 document.warning("InsetArgument not found!")
2777 l = find_end_of_inset(document.body, k)
2778 m = find_token(document.body, "\\begin_inset ERT", l, j)
2786 def convert_overprint(document):
2787 " Convert old beamer overprint layouts to ERT "
2789 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2790 if document.textclass not in beamer_classes:
2795 i = find_token(document.body, "\\begin_layout Overprint", i)
2798 # Find end of sequence
2799 j = find_end_of_sequence(document.body, i)
2801 document.warning("Malformed lyx document. Cannot find end of Overprint sequence!")
2805 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
2807 if document.body[j] == "\\end_deeper":
2808 esubst = ["", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
2810 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
2811 endseq = endseq + len(esubst) - len(document.body[j : j])
2812 document.body[j : j] = esubst
2813 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
2815 argend = find_end_of_layout(document.body, argbeg)
2817 document.warning("Malformed lyx document. Cannot find end of Overprint argument!")
2820 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
2821 endPlain = find_end_of_layout(document.body, beginPlain)
2822 content = document.body[beginPlain + 1 : endPlain]
2824 endseq = endseq - len(document.body[argbeg : argend + 1])
2826 del document.body[argbeg : argend + 1]
2827 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2829 endseq = endseq - len(document.body[i : i])
2830 document.body[i : i] = subst + ["\\end_layout"]
2831 endseq += len(subst)
2833 for p in range(i, endseq):
2834 if document.body[p] == "\\begin_layout Overprint":
2835 document.body[p] = "\\begin_layout Standard"
2840 def revert_overprint(document):
2841 " Revert old beamer overprint layouts to ERT "
2843 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2844 if document.textclass not in beamer_classes:
2849 i = find_token(document.body, "\\begin_layout Overprint", i)
2852 # Find end of sequence
2853 j = find_end_of_sequence(document.body, i)
2855 document.warning("Malformed lyx document. Cannot find end of Overprint sequence!")
2859 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
2860 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}")
2861 endseq = endseq + len(esubst) - len(document.body[j : j])
2862 if document.body[j] == "\\end_deeper":
2863 document.body[j : j] = ["\\end_deeper", ""] + esubst
2865 document.body[j : j] = esubst
2868 if document.body[r] == "\\begin_deeper":
2869 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
2871 document.body[r] = ""
2872 document.body[s] = ""
2876 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
2878 argend = find_end_of_inset(document.body, argbeg)
2880 document.warning("Malformed lyx document. Cannot find end of Overprint argument!")
2883 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
2884 endPlain = find_end_of_layout(document.body, beginPlain)
2885 content = document.body[beginPlain + 1 : endPlain]
2887 endseq = endseq - len(document.body[argbeg : argend])
2889 del document.body[argbeg : argend + 1]
2890 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2892 endseq = endseq - len(document.body[i : i])
2893 document.body[i : i] = subst + ["\\end_layout"]
2894 endseq += len(subst)
2900 if document.body[p] == "\\begin_layout Overprint":
2901 q = find_end_of_layout(document.body, p)
2903 document.warning("Malformed lyx document. Cannot find end of Overprint layout!")
2906 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\onslide")
2907 argbeg = find_token(document.body, "\\begin_inset Argument item:1", p, q)
2909 argend = find_end_of_inset(document.body, argbeg)
2911 document.warning("Malformed lyx document. Cannot find end of Overprint item argument!")
2914 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
2915 endPlain = find_end_of_layout(document.body, beginPlain)
2916 content = document.body[beginPlain + 1 : endPlain]
2918 endseq = endseq - len(document.body[argbeg : argend + 1])
2920 del document.body[argbeg : argend + 1]
2921 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2922 endseq = endseq - len(document.body[p : p + 1]) + len(subst)
2923 document.body[p : p + 1] = subst
2929 def revert_frametitle(document):
2930 " Reverts beamer frametitle layout to ERT "
2932 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2933 if document.textclass not in beamer_classes:
2936 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2939 i = find_token(document.body, "\\begin_layout FrameTitle", i)
2942 j = find_end_of_layout(document.body, i)
2944 document.warning("Malformed lyx document: Can't find end of FrameTitle layout")
2948 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
2949 endlay += len(put_cmd_in_ert("}"))
2950 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\frametitle")
2951 for p in range(i, j):
2954 m = rx.match(document.body[p])
2958 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2959 endPlain = find_end_of_layout(document.body, beginPlain)
2960 endInset = find_end_of_inset(document.body, p)
2961 content = document.body[beginPlain + 1 : endPlain]
2963 endlay = endlay - len(document.body[p : endInset + 1])
2965 del document.body[p : endInset + 1]
2966 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2968 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2969 endPlain = find_end_of_layout(document.body, beginPlain)
2970 endInset = find_end_of_inset(document.body, p)
2971 content = document.body[beginPlain + 1 : endPlain]
2973 endlay = endlay - len(document.body[p : endInset + 1])
2975 del document.body[p : endInset + 1]
2976 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2978 subst += put_cmd_in_ert("{")
2979 document.body[i : i + 1] = subst
2983 def convert_epigraph(document):
2984 " Converts memoir epigraph to new syntax "
2986 if document.textclass != "memoir":
2991 i = find_token(document.body, "\\begin_layout Epigraph", i)
2994 j = find_end_of_layout(document.body, i)
2996 document.warning("Malformed lyx document: Can't find end of Epigraph layout")
3001 ert = find_token(document.body, "\\begin_inset ERT", i, j)
3003 endInset = find_end_of_inset(document.body, ert)
3004 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", ert)
3005 endPlain = find_end_of_layout(document.body, beginPlain)
3006 ertcont = beginPlain + 2
3007 if document.body[ertcont] == "}{":
3009 # Convert to ArgInset
3010 endlay = endlay - 2 * len(document.body[j])
3011 begsubst = ['\\begin_inset Argument post:1', 'status collapsed', '',
3012 '\\begin_layout Plain Layout']
3013 endsubst = ['\\end_layout', '', '\\end_inset', '', document.body[j]]
3014 document.body[j : j + 1] = endsubst
3015 document.body[endInset + 1 : endInset + 1] = begsubst
3017 endlay += len(begsubst) + len(endsubst)
3018 endlay = endlay - len(document.body[ert : endInset + 1])
3019 del document.body[ert : endInset + 1]
3024 def revert_epigraph(document):
3025 " Reverts memoir epigraph argument to ERT "
3027 if document.textclass != "memoir":
3032 i = find_token(document.body, "\\begin_layout Epigraph", i)
3035 j = find_end_of_layout(document.body, i)
3037 document.warning("Malformed lyx document: Can't find end of Epigraph layout")
3042 p = find_token(document.body, "\\begin_layout Argument post:1", i, j)
3044 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3045 endPlain = find_end_of_layout(document.body, beginPlain)
3046 endInset = find_end_of_inset(document.body, p)
3047 content = document.body[beginPlain + 1 : endPlain]
3049 endlay = endlay - len(document.body[p : endInset + 1])
3051 del document.body[p : endInset + 1]
3052 subst += put_cmd_in_ert("}{") + content
3054 subst += put_cmd_in_ert("}{")
3056 document.body[j : j] = subst + document.body[j : j]
3060 def convert_captioninsets(document):
3061 " Converts caption insets to new syntax "
3065 i = find_token(document.body, "\\begin_inset Caption", i)
3068 document.body[i] = "\\begin_inset Caption Standard"
3073 def revert_captioninsets(document):
3074 " Reverts caption insets to old syntax "
3078 i = find_token(document.body, "\\begin_inset Caption Standard", i)
3081 document.body[i] = "\\begin_inset Caption"
3085 def convert_captionlayouts(document):
3086 " Convert caption layouts to caption insets. "
3089 "Captionabove": "Above",
3090 "Captionbelow": "Below",
3091 "FigCaption" : "FigCaption",
3092 "Table_Caption" : "Table",
3093 "CenteredCaption" : "Centered",
3094 "Bicaption" : "Bicaption",
3099 i = find_token(document.body, "\\begin_layout", i)
3102 val = get_value(document.body, "\\begin_layout", i)
3103 if val in caption_dict.keys():
3104 j = find_end_of_layout(document.body, i)
3106 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3109 document.body[j:j] = ["\\end_layout", "", "\\end_inset", "", ""]
3110 document.body[i:i+1] = ["\\begin_layout %s" % document.default_layout,
3111 "\\begin_inset Caption %s" % caption_dict[val], "",
3112 "\\begin_layout %s" % document.default_layout]
3116 def revert_captionlayouts(document):
3117 " Revert caption insets to caption layouts. "
3120 "Above" : "Captionabove",
3121 "Below" : "Captionbelow",
3122 "FigCaption" : "FigCaption",
3123 "Table" : "Table_Caption",
3124 "Centered" : "CenteredCaption",
3125 "Bicaption" : "Bicaption",
3129 rx = re.compile(r'^\\begin_inset Caption (\S+)$')
3131 i = find_token(document.body, "\\begin_inset Caption", i)
3135 m = rx.match(document.body[i])
3139 if val not in caption_dict.keys():
3143 # We either need to delete the previous \begin_layout line, or we
3144 # need to end the previous layout if this inset is not in the first
3145 # position of the paragraph.
3146 layout_before = find_token_backwards(document.body, "\\begin_layout", i)
3147 if layout_before == -1:
3148 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3150 layout_line = document.body[layout_before]
3151 del_layout_before = True
3152 l = layout_before + 1
3154 if document.body[l] != "":
3155 del_layout_before = False
3158 if del_layout_before:
3159 del document.body[layout_before:i]
3162 document.body[i:i] = ["\\end_layout", ""]
3165 # Find start of layout in the inset and end of inset
3166 j = find_token(document.body, "\\begin_layout", i)
3168 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3170 k = find_end_of_inset(document.body, i)
3172 document.warning("Malformed LyX document: Missing `\\end_inset'.")
3175 # We either need to delete the following \end_layout line, or we need
3176 # to restart the old layout if this inset is not at the paragraph end.
3177 layout_after = find_token(document.body, "\\end_layout", k)
3178 if layout_after == -1:
3179 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3181 del_layout_after = True
3183 while l < layout_after:
3184 if document.body[l] != "":
3185 del_layout_after = False
3188 if del_layout_after:
3189 del document.body[k+1:layout_after+1]
3191 document.body[k+1:k+1] = [layout_line, ""]
3193 # delete \begin_layout and \end_inset and replace \begin_inset with
3194 # "\begin_layout XXX". This works because we can only have one
3195 # paragraph in the caption inset: The old \end_layout will be recycled.
3196 del document.body[k]
3197 if document.body[k] == "":
3198 del document.body[k]
3199 del document.body[j]
3200 if document.body[j] == "":
3201 del document.body[j]
3202 document.body[i] = "\\begin_layout %s" % caption_dict[val]
3203 if document.body[i+1] == "":
3204 del document.body[i+1]
3208 def revert_fragileframe(document):
3209 " Reverts beamer FragileFrame layout to ERT "
3211 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3212 if document.textclass not in beamer_classes:
3217 i = find_token(document.body, "\\begin_layout FragileFrame", i)
3220 # Find end of sequence
3221 j = find_end_of_sequence(document.body, i)
3223 document.warning("Malformed lyx document. Cannot find end of FragileFrame sequence!")
3227 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{frame}")
3228 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{frame}")
3229 endseq = endseq + len(esubst) - len(document.body[j : j])
3230 if document.body[j] == "\\end_deeper":
3231 document.body[j : j] = ["\\end_deeper", ""] + esubst
3233 document.body[j : j] = esubst
3234 for q in range(i, j):
3235 if document.body[q] == "\\begin_layout FragileFrame":
3236 document.body[q] = "\\begin_layout %s" % document.default_layout
3239 if document.body[r] == "\\begin_deeper":
3240 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3242 document.body[r] = ""
3243 document.body[s] = ""
3247 for p in range(1, 5):
3248 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, j)
3251 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3252 endPlain = find_end_of_layout(document.body, beginPlain)
3253 endInset = find_end_of_inset(document.body, arg)
3254 content = document.body[beginPlain + 1 : endPlain]
3256 j = j - len(document.body[arg : endInset + 1])
3258 del document.body[arg : endInset + 1]
3259 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3261 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3262 endPlain = find_end_of_layout(document.body, beginPlain)
3263 endInset = find_end_of_inset(document.body, arg)
3264 content = document.body[beginPlain + 1 : endPlain]
3266 j = j - len(document.body[arg : endInset + 1])
3268 del document.body[arg : endInset + 1]
3269 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3271 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3272 endPlain = find_end_of_layout(document.body, beginPlain)
3273 endInset = find_end_of_inset(document.body, arg)
3274 content = document.body[beginPlain + 1 : endPlain]
3276 j = j - len(document.body[arg : endInset + 1])
3278 del document.body[arg : endInset + 1]
3279 subst += put_cmd_in_ert("[fragile,") + content + put_cmd_in_ert("]")
3281 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3282 endPlain = find_end_of_layout(document.body, beginPlain)
3283 endInset = find_end_of_inset(document.body, arg)
3284 content = document.body[beginPlain + 1 : endPlain]
3286 j = j - len(document.body[arg : endInset + 1])
3288 del document.body[arg : endInset + 1]
3289 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3291 subst += put_cmd_in_ert("[fragile]")
3293 document.body[i : i + 1] = subst
3297 def revert_newframes(document):
3298 " Reverts beamer Frame and PlainFrame layouts to old forms "
3300 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3301 if document.textclass not in beamer_classes:
3305 "Frame" : "BeginFrame",
3306 "PlainFrame" : "BeginPlainFrame",
3309 rx = re.compile(r'^\\begin_layout (\S+)$')
3312 i = find_token(document.body, "\\begin_layout", i)
3316 m = rx.match(document.body[i])
3320 if val not in frame_dict.keys():
3323 # Find end of sequence
3324 j = find_end_of_sequence(document.body, i)
3326 document.warning("Malformed lyx document. Cannot find end of Frame sequence!")
3330 subst = ["\\begin_layout %s" % frame_dict[val]]
3331 esubst = ["\\end_layout", "", "\\begin_layout EndFrame", "", "\\end_layout"]
3332 endseq = endseq + len(esubst) - len(document.body[j : j])
3333 if document.body[j] == "\\end_deeper":
3334 document.body[j : j] = ["\\end_deeper", ""] + esubst
3336 document.body[j : j] = esubst
3337 for q in range(i, j):
3338 if document.body[q] == "\\begin_layout %s" % val:
3339 document.body[q] = "\\begin_layout %s" % document.default_layout
3342 if document.body[r] == "\\begin_deeper":
3343 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3345 document.body[r] = ""
3346 document.body[s] = ""
3350 l = find_end_of_layout(document.body, i)
3351 for p in range(1, 5):
3352 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, l)
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 l = l - 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 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3366 endPlain = find_end_of_layout(document.body, beginPlain)
3367 endInset = find_end_of_inset(document.body, arg)
3368 content = document.body[beginPlain + 1 : endPlain]
3370 l = l - len(document.body[arg : endInset + 1])
3372 del document.body[arg : endInset + 1]
3373 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3375 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3376 endPlain = find_end_of_layout(document.body, beginPlain)
3377 endInset = find_end_of_inset(document.body, arg)
3378 content = document.body[beginPlain + 1 : endPlain]
3380 l = l - len(document.body[arg : endInset + 1])
3382 del document.body[arg : endInset + 1]
3383 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3385 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3386 endPlain = find_end_of_layout(document.body, beginPlain)
3387 endInset = find_end_of_inset(document.body, arg)
3388 content = document.body[beginPlain + 1 : endPlain]
3390 l = l - len(document.body[arg : endInset + 1])
3392 del document.body[arg : endInset + 1]
3395 document.body[i : i + 1] = subst
3403 supported_versions = ["2.1.0","2.1"]
3406 [415, [convert_undertilde]],
3408 [417, [convert_japanese_encodings]],
3411 [420, [convert_biblio_style]],
3412 [421, [convert_longtable_captions]],
3413 [422, [convert_use_packages]],
3414 [423, [convert_use_mathtools]],
3415 [424, [convert_cite_engine_type]],
3419 [428, [convert_cell_rotation]],
3420 [429, [convert_table_rotation]],
3421 [430, [convert_listoflistings]],
3422 [431, [convert_use_amssymb]],
3424 [433, [convert_armenian]],
3432 [441, [convert_mdnomath]],
3437 [446, [convert_latexargs]],
3438 [447, [convert_IEEEtran, convert_AASTeX, convert_AGUTeX, convert_IJMP, convert_SIGPLAN, convert_SIGGRAPH, convert_EuropeCV, convert_Initials]],
3439 [448, [convert_literate]],
3442 [451, [convert_beamerargs, convert_againframe_args, convert_corollary_args, convert_quote_args]],
3443 [452, [convert_beamerblocks]],
3444 [453, [convert_use_stmaryrd]],
3445 [454, [convert_overprint]],
3447 [456, [convert_epigraph]],
3448 [457, [convert_use_stackrel]],
3449 [458, [convert_captioninsets, convert_captionlayouts]],
3454 [458, [revert_fragileframe, revert_newframes]],
3455 [457, [revert_captioninsets, revert_captionlayouts]],
3456 [456, [revert_use_stackrel]],
3457 [455, [revert_epigraph]],
3458 [454, [revert_frametitle]],
3459 [453, [revert_overprint]],
3460 [452, [revert_use_stmaryrd]],
3461 [451, [revert_beamerblocks]],
3462 [450, [revert_beamerargs, revert_beamerargs2, revert_beamerargs3, revert_beamerflex]],
3463 [449, [revert_garamondx, revert_garamondx_newtxmath]],
3464 [448, [revert_itemargs]],
3465 [447, [revert_literate]],
3466 [446, [revert_IEEEtran, revert_AASTeX, revert_AGUTeX, revert_IJMP, revert_SIGPLAN, revert_SIGGRAPH, revert_EuropeCV, revert_Initials]],
3467 [445, [revert_latexargs]],
3468 [444, [revert_uop]],
3469 [443, [revert_biolinum]],
3471 [441, [revert_newtxmath]],
3472 [440, [revert_mdnomath]],
3473 [439, [revert_mathfonts]],
3474 [438, [revert_minionpro]],
3475 [437, [revert_ipadeco, revert_ipachar]],
3476 [436, [revert_texgyre]],
3477 [435, [revert_mathdesign]],
3478 [434, [revert_txtt]],
3479 [433, [revert_libertine]],
3480 [432, [revert_armenian]],
3481 [431, [revert_languages, revert_ancientgreek]],
3482 [430, [revert_use_amssymb]],
3483 [429, [revert_listoflistings]],
3484 [428, [revert_table_rotation]],
3485 [427, [revert_cell_rotation]],
3486 [426, [revert_tipa]],
3487 [425, [revert_verbatim]],
3488 [424, [revert_cancel]],
3489 [423, [revert_cite_engine_type]],
3490 [422, [revert_use_mathtools]],
3491 [421, [revert_use_packages]],
3492 [420, [revert_longtable_captions]],
3493 [419, [revert_biblio_style]],
3494 [418, [revert_australian]],
3495 [417, [revert_justification]],
3496 [416, [revert_japanese_encodings]],
3497 [415, [revert_negative_space, revert_math_spaces]],
3498 [414, [revert_undertilde]],
3499 [413, [revert_visible_space]]
3503 if __name__ == "__main__":