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"
964 preamble += "[lining]"
965 preamble += "{libertine-type1}"
966 add_to_preamble(document, [preamble])
967 document.header[i] = "\\font_roman default"
970 def revert_txtt(document):
971 " Revert native txtt font definition to LaTeX "
973 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
974 i = find_token(document.header, "\\font_typewriter txtt", 0)
976 preamble = "\\renewcommand{\\ttdefault}{txtt}"
977 add_to_preamble(document, [preamble])
978 document.header[i] = "\\font_typewriter default"
981 def revert_mathdesign(document):
982 " Revert native mathdesign font definition to LaTeX "
984 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
990 i = find_token(document.header, "\\font_roman", 0)
993 val = get_value(document.header, "\\font_roman", i)
994 if val in mathdesign_dict.keys():
995 preamble = "\\usepackage[%s" % mathdesign_dict[val]
997 j = find_token(document.header, "\\font_osf true", 0)
1000 document.header[j] = "\\font_osf false"
1001 l = find_token(document.header, "\\font_sc true", 0)
1004 document.header[l] = "\\font_sc false"
1006 preamble += ",expert"
1007 preamble += "]{mathdesign}"
1008 add_to_preamble(document, [preamble])
1009 document.header[i] = "\\font_roman default"
1012 def revert_texgyre(document):
1013 " Revert native TeXGyre font definition to LaTeX "
1015 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1016 texgyre_fonts = ["tgadventor", "tgbonum", "tgchorus", "tgcursor", \
1017 "tgheros", "tgpagella", "tgschola", "tgtermes"]
1018 i = find_token(document.header, "\\font_roman", 0)
1020 val = get_value(document.header, "\\font_roman", i)
1021 if val in texgyre_fonts:
1022 preamble = "\\usepackage{%s}" % val
1023 add_to_preamble(document, [preamble])
1024 document.header[i] = "\\font_roman default"
1025 i = find_token(document.header, "\\font_sans", 0)
1027 val = get_value(document.header, "\\font_sans", i)
1028 if val in texgyre_fonts:
1029 preamble = "\\usepackage{%s}" % val
1030 add_to_preamble(document, [preamble])
1031 document.header[i] = "\\font_sans default"
1032 i = find_token(document.header, "\\font_typewriter", 0)
1034 val = get_value(document.header, "\\font_typewriter", i)
1035 if val in texgyre_fonts:
1036 preamble = "\\usepackage{%s}" % val
1037 add_to_preamble(document, [preamble])
1038 document.header[i] = "\\font_typewriter default"
1041 def revert_ipadeco(document):
1042 " Revert IPA decorations to ERT "
1045 i = find_token(document.body, "\\begin_inset IPADeco", i)
1048 end = find_end_of_inset(document.body, i)
1050 document.warning("Can't find end of inset at line " + str(i))
1053 line = document.body[i]
1054 rx = re.compile(r'\\begin_inset IPADeco (.*)$')
1056 decotype = m.group(1)
1057 if decotype != "toptiebar" and decotype != "bottomtiebar":
1058 document.warning("Invalid IPADeco type: " + decotype)
1061 blay = find_token(document.body, "\\begin_layout Plain Layout", i, end)
1063 document.warning("Can't find layout for inset at line " + str(i))
1066 bend = find_end_of_layout(document.body, blay)
1068 document.warning("Malformed LyX document: Could not find end of IPADeco inset's layout.")
1071 substi = ["\\begin_inset ERT", "status collapsed", "",
1072 "\\begin_layout Plain Layout", "", "", "\\backslash",
1073 decotype + "{", "\\end_layout", "", "\\end_inset"]
1074 substj = ["\\size default", "", "\\begin_inset ERT", "status collapsed", "",
1075 "\\begin_layout Plain Layout", "", "}", "\\end_layout", "", "\\end_inset"]
1076 # do the later one first so as not to mess up the numbering
1077 document.body[bend:end + 1] = substj
1078 document.body[i:blay + 1] = substi
1079 i = end + len(substi) + len(substj) - (end - bend) - (blay - i) - 2
1080 add_to_preamble(document, "\\usepackage{tipa}")
1083 def revert_ipachar(document):
1084 ' Revert \\IPAChar to ERT '
1087 while i < len(document.body):
1088 m = re.match(r'(.*)\\IPAChar \\(\w+\{\w+\})(.*)', document.body[i])
1092 ipachar = m.group(2)
1095 '\\begin_inset ERT',
1096 'status collapsed', '',
1097 '\\begin_layout Standard',
1098 '', '', '\\backslash',
1103 document.body[i: i+1] = subst
1108 add_to_preamble(document, "\\usepackage{tone}")
1111 def revert_minionpro(document):
1112 " Revert native MinionPro font definition to LaTeX "
1114 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1115 i = find_token(document.header, "\\font_roman minionpro", 0)
1118 j = find_token(document.header, "\\font_osf true", 0)
1121 preamble = "\\usepackage"
1123 document.header[j] = "\\font_osf false"
1126 preamble += "{MinionPro}"
1127 add_to_preamble(document, [preamble])
1128 document.header[i] = "\\font_roman default"
1131 def revert_mathfonts(document):
1132 " Revert native math font definitions to LaTeX "
1134 i = find_token(document.header, "\\font_math", 0)
1137 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1138 val = get_value(document.header, "\\font_math", i)
1139 if val == "eulervm":
1140 add_to_preamble(document, "\\usepackage{eulervm}")
1141 elif val == "default":
1143 "lmodern": "\\renewcommand{\\rmdefault}{lmr}",
1144 "minionpro": "\\usepackage[onlytext,lf]{MinionPro}",
1145 "minionpro-osf": "\\usepackage[onlytext]{MinionPro}",
1146 "palatino": "\\renewcommand{\\rmdefault}{ppl}",
1147 "palatino-osf": "\\renewcommand{\\rmdefault}{pplj}",
1148 "times": "\\renewcommand{\\rmdefault}{ptm}",
1149 "utopia": "\\renewcommand{\\rmdefault}{futs}",
1150 "utopia-osf": "\\renewcommand{\\rmdefault}{futj}",
1152 j = find_token(document.header, "\\font_roman", 0)
1154 rm = get_value(document.header, "\\font_roman", j)
1155 k = find_token(document.header, "\\font_osf true", 0)
1158 if rm in mathfont_dict.keys():
1159 add_to_preamble(document, mathfont_dict[rm])
1160 document.header[j] = "\\font_roman default"
1162 document.header[k] = "\\font_osf false"
1163 del document.header[i]
1166 def revert_mdnomath(document):
1167 " Revert mathdesign and fourier without math "
1169 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1171 "md-charter": "mdbch",
1172 "md-utopia": "mdput",
1173 "md-garamond": "mdugm"
1175 i = find_token(document.header, "\\font_roman", 0)
1178 val = get_value(document.header, "\\font_roman", i)
1179 if val in mathdesign_dict.keys():
1180 j = find_token(document.header, "\\font_math", 0)
1182 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1183 mval = get_value(document.header, "\\font_math", j)
1184 if mval == "default":
1185 document.header[i] = "\\font_roman default"
1186 add_to_preamble(document, "\\renewcommand{\\rmdefault}{%s}" % mathdesign_dict[val])
1188 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1191 def convert_mdnomath(document):
1192 " Change mathdesign font name "
1194 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1196 "mdbch": "md-charter",
1197 "mdput": "md-utopia",
1198 "mdugm": "md-garamond"
1200 i = find_token(document.header, "\\font_roman", 0)
1203 val = get_value(document.header, "\\font_roman", i)
1204 if val in mathdesign_dict.keys():
1205 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1208 def revert_newtxmath(document):
1209 " Revert native newtxmath definitions to LaTeX "
1211 i = find_token(document.header, "\\font_math", 0)
1214 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1215 val = get_value(document.header, "\\font_math", i)
1217 "libertine-ntxm": "\\usepackage[libertine]{newtxmath}",
1218 "minion-ntxm": "\\usepackage[minion]{newtxmath}",
1219 "newtxmath": "\\usepackage{newtxmath}",
1221 if val in mathfont_dict.keys():
1222 add_to_preamble(document, mathfont_dict[val])
1223 document.header[i] = "\\font_math auto"
1226 def revert_biolinum(document):
1227 " Revert native biolinum font definition to LaTeX "
1229 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1230 i = find_token(document.header, "\\font_sans biolinum", 0)
1233 j = find_token(document.header, "\\font_osf true", 0)
1236 preamble = "\\usepackage"
1239 preamble += "{biolinum-type1}"
1240 add_to_preamble(document, [preamble])
1241 document.header[i] = "\\font_sans default"
1244 def revert_uop(document):
1245 " Revert native URW Classico (Optima) font definition to LaTeX "
1247 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1248 i = find_token(document.header, "\\font_sans uop", 0)
1250 preamble = "\\renewcommand{\\sfdefault}{uop}"
1251 add_to_preamble(document, [preamble])
1252 document.header[i] = "\\font_sans default"
1255 def convert_latexargs(document):
1256 " Convert InsetArgument to new syntax "
1258 if find_token(document.body, "\\begin_inset Argument", 0) == -1:
1262 # A list of layouts (document classes) with only optional or no arguments.
1263 # These can be safely converted to the new syntax
1264 # (I took the liberty to add some of my personal layouts/modules here; JSP)
1265 safe_layouts = ["aa", "aapaper", "aastex", "achemso", "acmsiggraph", "AEA",
1266 "agu-dtd", "agums", "agutex", "amsart", "amsbook", "apa",
1267 "arab-article", "armenian-article", "article-beamer", "article",
1268 "beamer", "book", "broadway", "chess", "cl2emult", "ctex-article",
1269 "ctex-book", "ctex-report", "dinbrief", "docbook-book", "docbook-chapter",
1270 "docbook", "docbook-section", "doublecol-new", "dtk", "ectaart", "egs",
1271 "elsarticle", "elsart", "entcs", "europecv", "extarticle", "extbook",
1272 "extletter", "extreport", "foils", "frletter", "g-brief2", "g-brief",
1273 "heb-article", "heb-letter", "hollywood", "IEEEtran", "ijmpc", "ijmpd",
1274 "iopart", "isprs", "jarticle", "jasatex", "jbook", "jgrga", "jreport",
1275 "jsarticle", "jsbeamer", "jsbook", "jss", "kluwer", "latex8", "letter", "lettre",
1276 "literate-article", "literate-book", "literate-report", "llncs", "ltugboat",
1277 "memoir", "moderncv", "mwart", "mwbk", "mwrep", "paper", "powerdot",
1278 "recipebook", "report", "revtex4", "revtex", "scrartcl", "scrarticle-beamer",
1279 "scrbook", "scrlettr", "scrlttr2", "scrreprt", "seminar", "siamltex",
1280 "sigplanconf", "simplecv", "singlecol", "singlecol-new", "slides", "spie",
1281 "svglobal3", "svglobal", "svjog", "svmono", "svmult", "svprobth", "tarticle",
1282 "tbook", "treport", "tufte-book", "tufte-handout"]
1283 # A list of "safe" modules, same as above
1284 safe_modules = ["biblatex", "beameraddons", "beamersession", "braille", "customHeadersFooters",
1285 "endnotes", "enumitem", "eqs-within-sections", "figs-within-sections", "fix-cm",
1286 "fixltx2e", "foottoend", "hanging", "jscharstyles", "knitr", "lilypond",
1287 "linguistics", "linguisticx", "logicalmkup", "minimalistic", "nomindex", "noweb",
1288 "pdfcomment", "sweave", "tabs-within-sections", "theorems-ams-bytype",
1289 "theorems-ams-extended-bytype", "theorems-ams-extended", "theorems-ams", "theorems-bytype",
1290 "theorems-chap-bytype", "theorems-chap", "theorems-named", "theorems-sec-bytype",
1291 "theorems-sec", "theorems-starred", "theorems-std", "todonotes"]
1292 # Modules we need to take care of
1293 caveat_modules = ["initials"]
1294 # information about the relevant styles in caveat_modules (number of opt and req args)
1295 # use this if we get more caveat_modules. For now, use hard coding (see below).
1296 # initials = [{'Layout' : 'Initial', 'opt' : 1, 'req' : 1}]
1298 # Is this a known safe layout?
1299 safe_layout = document.textclass in safe_layouts
1301 document.warning("Lyx2lyx knows nothing about textclass '%s'. "
1302 "Please check if short title insets have been converted correctly."
1303 % document.textclass)
1304 # Do we use unsafe or unknown modules
1305 mods = document.get_module_list()
1306 unknown_modules = False
1307 used_caveat_modules = list()
1309 if mod in safe_modules:
1311 if mod in caveat_modules:
1312 used_caveat_modules.append(mod)
1314 unknown_modules = True
1315 document.warning("Lyx2lyx knows nothing about module '%s'. "
1316 "Please check if short title insets have been converted correctly."
1321 i = find_token(document.body, "\\begin_inset Argument", i)
1325 if not safe_layout or unknown_modules:
1326 # We cannot do more here since we have no access to this layout.
1327 # InsetArgument itself will do the real work
1328 # (see InsetArgument::updateBuffer())
1329 document.body[i] = "\\begin_inset Argument 999"
1333 # Find containing paragraph layout
1334 parent = get_containing_layout(document.body, i)
1336 document.warning("Malformed lyx document: Can't find parent paragraph layout")
1343 if len(used_caveat_modules) > 0:
1344 # We know for now that this must be the initials module with the Initial layout
1345 # If we get more such modules, we need some automating.
1346 if parent[0] == "Initial":
1347 # Layout has 1 opt and 1 req arg.
1348 # Count the actual arguments
1350 for p in range(parbeg, parend):
1351 if document.body[p] == "\\begin_inset Argument":
1356 # Collect all arguments in this paragraph
1358 for p in range(parbeg, parend):
1359 if document.body[p] == "\\begin_inset Argument":
1361 if allowed_opts != -1:
1362 # We have less arguments than opt + required.
1363 # required must take precedence.
1364 if argnr > allowed_opts and argnr < first_req:
1366 document.body[p] = "\\begin_inset Argument %d" % argnr
1370 def revert_latexargs(document):
1371 " Revert InsetArgument to old syntax "
1374 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
1377 # Search for Argument insets
1378 i = find_token(document.body, "\\begin_inset Argument", i)
1381 m = rx.match(document.body[i])
1383 # No ID: inset already reverted
1386 # Find containing paragraph layout
1387 parent = get_containing_layout(document.body, i)
1389 document.warning("Malformed lyx document: Can't find parent paragraph layout")
1394 realparbeg = parent[3]
1395 # Collect all arguments in this paragraph
1397 for p in range(parbeg, parend):
1398 m = rx.match(document.body[p])
1400 val = int(m.group(1))
1401 j = find_end_of_inset(document.body, p)
1402 # Revert to old syntax
1403 document.body[p] = "\\begin_inset Argument"
1405 document.warning("Malformed lyx document: Can't find end of Argument inset")
1408 args[val] = document.body[p : j + 1]
1410 realparend = realparend - len(document.body[p : j + 1])
1411 # Remove arg inset at this position
1412 del document.body[p : j + 1]
1415 # Now sort the arg insets
1417 for f in sorted(args):
1420 # Insert the sorted arg insets at paragraph begin
1421 document.body[realparbeg : realparbeg] = subst
1423 i = realparbeg + 1 + len(subst)
1426 def revert_Argument_to_TeX_brace(document, line, n, nmax, environment):
1428 Reverts an InsetArgument to TeX-code
1430 revert_Argument_to_TeX_brace(document, LineOfBeginLayout, StartArgument, EndArgument, isEnvironment)
1431 LineOfBeginLayout is the line of the \begin_layout statement
1432 StartArgument is the number of the first argument that needs to be converted
1433 EndArgument is the number of the last argument that needs to be converted or the last defined one
1434 isEnvironment must be true, if the layout id for a LaTeX environment
1437 while lineArg != -1 and n < nmax + 1:
1438 lineArg = find_token(document.body, "\\begin_inset Argument " + str(n), line)
1440 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", lineArg)
1441 # we have to assure that no other inset is in the Argument
1442 beginInset = find_token(document.body, "\\begin_inset", beginPlain)
1443 endInset = find_token(document.body, "\\end_inset", beginPlain)
1446 while beginInset < endInset and beginInset != -1:
1447 beginInset = find_token(document.body, "\\begin_inset", k)
1448 endInset = find_token(document.body, "\\end_inset", l)
1451 if environment == False:
1452 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}{")
1453 del(document.body[lineArg : beginPlain + 1])
1455 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}")
1456 document.body[lineArg : beginPlain + 1] = put_cmd_in_ert("{")
1460 def convert_TeX_brace_to_Argument(document, line, n, nmax, inset, environment):
1462 Converts TeX code for mandatory arguments to an InsetArgument
1463 The conversion of TeX code for optional arguments must be done with another routine
1464 !!! Be careful if the braces are different in your case as expected here:
1465 - "}{" separates mandatory arguments of commands
1466 - "}" + "{" separates mandatory arguments of commands
1467 - "}" + " " + "{" separates mandatory arguments of commands
1468 - { and } surround a mandatory argument of an environment
1470 convert_TeX_brace_to_Argument(document, LineOfBeginLayout/Inset, StartArgument, EndArgument, isInset, isEnvironment)
1471 LineOfBeginLayout/Inset is the line of the \begin_layout or \begin_inset statement
1472 StartArgument is the number of the first ERT that needs to be converted
1473 EndArgument is the number of the last ERT that needs to be converted
1474 isInset must be true, if braces inside an InsetLayout needs to be converted
1475 isEnvironment must be true, if the layout is for a LaTeX environment
1477 Todo: this routine can currently handle only one mandatory argument of environments
1482 while lineERT != -1 and n < nmax + 1:
1483 lineERT = find_token(document.body, "\\begin_inset ERT", lineERT)
1484 if environment == False and lineERT != -1:
1485 bracePair = find_token(document.body, "}{", lineERT)
1486 # assure that the "}{" is in this ERT
1487 if bracePair == lineERT + 5:
1488 end = find_token(document.body, "\\end_inset", bracePair)
1489 document.body[lineERT : end + 1] = ["\\end_layout", "", "\\end_inset"]
1491 # in the case that n > 1 we have optional arguments before
1492 # therefore detect them if any
1494 # first check if there is an argument
1495 lineArg = find_token(document.body, "\\begin_inset Argument", line)
1496 if lineArg < lineERT and lineArg != -1:
1497 # we have an argument, so now search backwards for its end
1498 # we must now assure that we don't find other insets like e.g. a newline
1499 endInsetArg = lineERT
1500 endLayoutArg = endInsetArg
1501 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
1502 endInsetArg = endInsetArg - 1
1503 endLayoutArg = endInsetArg
1504 endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
1505 endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
1506 line = endInsetArg + 1
1508 document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1510 document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1512 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1516 # now check the case that we have "}" + "{" in two ERTs
1518 endBrace = find_token(document.body, "}", lineERT)
1519 if endBrace == lineERT + 5:
1520 beginBrace = find_token(document.body, "{", endBrace)
1521 # assure that the ERTs are consecutive (11 or 12 depending if there is a space between the ERTs or not)
1522 if beginBrace == endBrace + 11 or beginBrace == endBrace + 12:
1523 end = find_token(document.body, "\\end_inset", beginBrace)
1524 document.body[lineERT : end + 1] = ["\\end_layout", "", "\\end_inset"]
1526 # in the case that n > 1 we have optional arguments before
1527 # therefore detect them if any
1529 # first check if there is an argument
1530 lineArg = find_token(document.body, "\\begin_inset Argument", line)
1531 if lineArg < lineERT and lineArg != -1:
1532 # we have an argument, so now search backwards for its end
1533 # we must now assure that we don't find other insets like e.g. a newline
1534 endInsetArg = lineERT
1535 endLayoutArg = endInsetArg
1536 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
1537 endInsetArg = endInsetArg - 1
1538 endLayoutArg = endInsetArg
1539 endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
1540 endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
1541 line = endInsetArg + 1
1543 document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1545 document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1547 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1550 # set the line where the next argument will be inserted
1551 if beginBrace == endBrace + 11:
1556 lineERT = lineERT + 1
1557 if environment == True and lineERT != -1:
1558 opening = find_token(document.body, "{", lineERT)
1559 if opening == lineERT + 5: # assure that the "{" is in this ERT
1560 end = find_token(document.body, "\\end_inset", opening)
1561 document.body[lineERT : end + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1563 lineERT2 = find_token(document.body, "\\begin_inset ERT", lineERT)
1564 closing = find_token(document.body, "}", lineERT2)
1565 if closing == lineERT2 + 5: # assure that the "}" is in this ERT
1566 end2 = find_token(document.body, "\\end_inset", closing)
1567 document.body[lineERT2 : end2 + 1] = ["\\end_layout", "", "\\end_inset"]
1569 lineERT = lineERT + 1
1572 def revert_IEEEtran(document):
1574 Reverts InsetArgument of
1577 Biography without photo
1580 if document.textclass == "IEEEtran":
1587 i = find_token(document.body, "\\begin_layout Page headings", i)
1589 revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1592 i2 = find_token(document.body, "\\begin_inset Flex Paragraph Start", i2)
1594 revert_Argument_to_TeX_brace(document, i2, 1, 1, False)
1597 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1599 revert_Argument_to_TeX_brace(document, j, 1, 1, True)
1602 k = find_token(document.body, "\\begin_layout Biography", k)
1603 kA = find_token(document.body, "\\begin_layout Biography without photo", k)
1604 if k == kA and k != -1:
1608 # start with the second argument, therefore 2
1609 revert_Argument_to_TeX_brace(document, k, 2, 2, True)
1611 if i == -1 and i2 == -1 and j == -1 and k == -1:
1615 def revert_IEEEtran_2(document):
1617 Reverts Flex Paragraph Start to TeX-code
1619 if document.textclass == "IEEEtran":
1623 begin = find_token(document.body, "\\begin_inset Flex Paragraph Start", begin)
1625 end1 = find_end_of_inset(document.body, begin)
1626 document.body[end1 - 2 : end1 + 1] = put_cmd_in_ert("}")
1627 document.body[begin : begin + 4] = put_cmd_in_ert("\\IEEEPARstart{")
1633 def convert_IEEEtran(document):
1638 Biography without photo
1641 if document.textclass == "IEEEtran":
1647 i = find_token(document.body, "\\begin_layout Page headings", i)
1649 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1652 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1654 convert_TeX_brace_to_Argument(document, j, 1, 1, False, True)
1657 # assure that we don't handle Biography Biography without photo
1658 k = find_token(document.body, "\\begin_layout Biography", k)
1659 kA = find_token(document.body, "\\begin_layout Biography without photo", k - 1)
1660 if k == kA and k != -1:
1664 # the argument we want to convert is the second one
1665 convert_TeX_brace_to_Argument(document, k, 2, 2, False, True)
1667 if i == -1 and j == -1 and k == -1:
1671 def revert_AASTeX(document):
1672 " Reverts InsetArgument of Altaffilation to TeX-code "
1673 if document.textclass == "aastex":
1677 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1679 revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1685 def convert_AASTeX(document):
1686 " Converts ERT of Altaffilation to InsetArgument "
1687 if document.textclass == "aastex":
1691 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1693 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1699 def revert_AGUTeX(document):
1700 " Reverts InsetArgument of Author affiliation to TeX-code "
1701 if document.textclass == "agutex":
1705 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1707 revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1713 def convert_AGUTeX(document):
1714 " Converts ERT of Author affiliation to InsetArgument "
1715 if document.textclass == "agutex":
1719 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1721 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1727 def revert_IJMP(document):
1728 " Reverts InsetArgument of MarkBoth to TeX-code "
1729 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1733 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1735 revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1741 def convert_IJMP(document):
1742 " Converts ERT of MarkBoth to InsetArgument "
1743 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1747 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1749 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1755 def revert_SIGPLAN(document):
1756 " Reverts InsetArguments of SIGPLAN to TeX-code "
1757 if document.textclass == "sigplanconf":
1762 i = find_token(document.body, "\\begin_layout Conference", i)
1764 revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1767 j = find_token(document.body, "\\begin_layout Author", j)
1769 revert_Argument_to_TeX_brace(document, j, 1, 2, False)
1771 if i == -1 and j == -1:
1775 def convert_SIGPLAN(document):
1776 " Converts ERT of SIGPLAN to InsetArgument "
1777 if document.textclass == "sigplanconf":
1782 i = find_token(document.body, "\\begin_layout Conference", i)
1784 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1787 j = find_token(document.body, "\\begin_layout Author", j)
1789 convert_TeX_brace_to_Argument(document, j, 1, 2, False, False)
1791 if i == -1 and j == -1:
1795 def revert_SIGGRAPH(document):
1796 " Reverts InsetArgument of Flex CRcat to TeX-code "
1797 if document.textclass == "acmsiggraph":
1801 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1803 revert_Argument_to_TeX_brace(document, i, 1, 3, False)
1809 def convert_SIGGRAPH(document):
1810 " Converts ERT of Flex CRcat to InsetArgument "
1811 if document.textclass == "acmsiggraph":
1815 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1817 convert_TeX_brace_to_Argument(document, i, 1, 3, True, False)
1823 def revert_EuropeCV(document):
1824 " Reverts InsetArguments of europeCV to TeX-code "
1825 if document.textclass == "europecv":
1832 i = find_token(document.body, "\\begin_layout Item", i)
1834 revert_Argument_to_TeX_brace(document, i, 2, 2, False)
1837 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1839 revert_Argument_to_TeX_brace(document, j, 2, 2, False)
1842 k = find_token(document.body, "\\begin_layout Language", k)
1844 revert_Argument_to_TeX_brace(document, k, 2, 6, False)
1847 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1849 revert_Argument_to_TeX_brace(document, m, 2, 6, False)
1851 if i == -1 and j == -1 and k == -1 and m == -1:
1855 def convert_EuropeCV(document):
1856 " Converts ERT of europeCV to InsetArgument "
1857 if document.textclass == "europecv":
1864 i = find_token(document.body, "\\begin_layout Item", i)
1866 convert_TeX_brace_to_Argument(document, i, 2, 2, False, False)
1869 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1871 convert_TeX_brace_to_Argument(document, j, 2, 2, False, False)
1874 k = find_token(document.body, "\\begin_layout Language", k)
1876 convert_TeX_brace_to_Argument(document, k, 2, 6, False, False)
1879 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1881 convert_TeX_brace_to_Argument(document, m, 2, 6, False, False)
1883 if i == -1 and j == -1 and k == -1 and m == -1:
1887 def revert_ModernCV(document):
1888 " Reverts InsetArguments of modernCV to TeX-code "
1889 if document.textclass == "moderncv":
1897 i = find_token(document.body, "\\begin_layout DoubleItem", i)
1899 revert_Argument_to_TeX_brace(document, i, 1, 3, False)
1902 j = find_token(document.body, "\\begin_layout Entry", j)
1904 revert_Argument_to_TeX_brace(document, j, 1, 5, False)
1907 k = find_token(document.body, "\\begin_layout Item", k)
1909 revert_Argument_to_TeX_brace(document, k, 1, 1, False)
1912 m = find_token(document.body, "\\begin_layout ItemWithComment", m)
1914 revert_Argument_to_TeX_brace(document, m, 1, 2, False)
1915 document.body[m] = document.body[m].replace("\\begin_layout ItemWithComment", "\\begin_layout Language")
1918 o = find_token(document.body, "\\begin_layout DoubleItem", o)
1920 revert_Argument_to_TeX_brace(document, o, 1, 3, False)
1921 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout Computer")
1923 if i == -1 and j == -1 and k == -1 and m == -1 and o == -1:
1927 def convert_ModernCV(document):
1928 " Converts ERT of modernCV to InsetArgument "
1929 if document.textclass == "moderncv":
1937 i = find_token(document.body, "\\begin_layout DoubleItem", i)
1939 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1940 document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout DoubleListItem")
1943 j = find_token(document.body, "\\begin_layout Entry", j)
1945 convert_TeX_brace_to_Argument(document, j, 1, 5, False, False)
1948 k = find_token(document.body, "\\begin_layout Item", k)
1950 convert_TeX_brace_to_Argument(document, k, 1, 1, False, False)
1953 m = find_token(document.body, "\\begin_layout Language", m)
1955 convert_TeX_brace_to_Argument(document, m, 1, 2, False, False)
1957 if i == -1 and j == -1 and k == -1 and m == -1:
1961 def revert_Initials(document):
1962 " Reverts InsetArgument of Initial to TeX-code "
1966 i = find_token(document.body, "\\begin_layout Initial", i)
1968 # first arg (optional) and second arg (first mandatory) are supported in LyX 2.0.x
1969 revert_Argument_to_TeX_brace(document, i, 3, 3, False)
1975 def convert_Initials(document):
1976 " Converts ERT of Initial to InsetArgument "
1980 i = find_token(document.body, "\\begin_layout Initial", i)
1982 convert_TeX_brace_to_Argument(document, i, 3, 3, False, False)
1988 def revert_literate(document):
1989 " Revert Literate document to old format "
1990 if del_token(document.header, "noweb", 0):
1991 document.textclass = "literate-" + document.textclass
1994 i = find_token(document.body, "\\begin_layout Chunk", i)
1997 document.body[i] = "\\begin_layout Scrap"
2001 def convert_literate(document):
2002 " Convert Literate document to new format"
2003 i = find_token(document.header, "\\textclass", 0)
2004 if (i != -1) and "literate-" in document.header[i]:
2005 document.textclass = document.header[i].replace("\\textclass literate-", "")
2006 j = find_token(document.header, "\\begin_modules", 0)
2008 document.header.insert(j + 1, "noweb")
2010 document.header.insert(i + 1, "\\end_modules")
2011 document.header.insert(i + 1, "noweb")
2012 document.header.insert(i + 1, "\\begin_modules")
2015 i = find_token(document.body, "\\begin_layout Scrap", i)
2018 document.body[i] = "\\begin_layout Chunk"
2022 def revert_itemargs(document):
2023 " Reverts \\item arguments to TeX-code "
2026 i = find_token(document.body, "\\begin_inset Argument item:", i)
2029 j = find_end_of_inset(document.body, i)
2030 # Find containing paragraph layout
2031 parent = get_containing_layout(document.body, i)
2033 document.warning("Malformed lyx document: Can't find parent paragraph layout")
2037 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2038 endPlain = find_end_of_layout(document.body, beginPlain)
2039 content = document.body[beginPlain + 1 : endPlain]
2040 del document.body[i:j+1]
2041 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2042 document.body[parbeg : parbeg] = subst
2046 def revert_garamondx_newtxmath(document):
2047 " Revert native garamond newtxmath definition to LaTeX "
2049 i = find_token(document.header, "\\font_math", 0)
2052 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2053 val = get_value(document.header, "\\font_math", i)
2054 if val == "garamondx-ntxm":
2055 add_to_preamble(document, "\\usepackage[garamondx]{newtxmath}")
2056 document.header[i] = "\\font_math auto"
2059 def revert_garamondx(document):
2060 " Revert native garamond font definition to LaTeX "
2062 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
2063 i = find_token(document.header, "\\font_roman garamondx", 0)
2066 j = find_token(document.header, "\\font_osf true", 0)
2069 preamble = "\\usepackage"
2071 preamble += "[osfI]"
2072 preamble += "{garamondx}"
2073 add_to_preamble(document, [preamble])
2074 document.header[i] = "\\font_roman default"
2077 def convert_beamerargs(document):
2078 " Converts beamer arguments to new layout "
2080 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2081 if document.textclass not in beamer_classes:
2084 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2085 list_layouts = ["Itemize", "Enumerate", "Description"]
2086 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
2090 i = find_token(document.body, "\\begin_inset Argument", i)
2093 # Find containing paragraph layout
2094 parent = get_containing_layout(document.body, i)
2096 document.warning("Malformed lyx document: Can't find parent paragraph layout")
2101 layoutname = parent[0]
2102 for p in range(parbeg, parend):
2103 if layoutname in shifted_layouts:
2104 m = rx.match(document.body[p])
2106 argnr = int(m.group(1))
2108 document.body[p] = "\\begin_inset Argument %d" % argnr
2109 if layoutname == "AgainFrame":
2110 m = rx.match(document.body[p])
2112 document.body[p] = "\\begin_inset Argument 3"
2113 if document.body[p + 4] == "\\begin_inset ERT":
2114 if document.body[p + 9].startswith("<"):
2115 # This is an overlay specification
2117 document.body[p + 9] = document.body[p + 9][1:]
2118 if document.body[p + 9].endswith(">"):
2120 document.body[p + 9] = document.body[p + 9][:-1]
2122 document.body[p] = "\\begin_inset Argument 2"
2123 if layoutname in list_layouts:
2124 m = rx.match(document.body[p])
2126 if m.group(1) == "1":
2127 if document.body[p + 4] == "\\begin_inset ERT":
2128 if document.body[p + 9].startswith("<"):
2129 # This is an overlay specification
2131 document.body[p + 9] = document.body[p + 9][1:]
2132 if document.body[p + 9].endswith(">"):
2134 document.body[p + 9] = document.body[p + 9][:-1]
2135 elif layoutname != "Itemize":
2137 document.body[p] = "\\begin_inset Argument 2"
2141 def convert_againframe_args(document):
2142 " Converts beamer AgainFrame to new layout "
2144 # FIXME: This currently only works if the arguments are in one single ERT
2146 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2147 if document.textclass not in beamer_classes:
2152 i = find_token(document.body, "\\begin_layout AgainFrame", i)
2155 parent = get_containing_layout(document.body, i)
2157 document.warning("Wrong parent layout!")
2161 if document.body[parbeg] == "\\begin_inset ERT":
2162 ertcont = parbeg + 5
2163 if document.body[ertcont].startswith("[<"):
2164 # This is a default overlay specification
2166 document.body[ertcont] = document.body[ertcont][2:]
2167 if document.body[ertcont].endswith(">]"):
2169 document.body[ertcont] = document.body[ertcont][:-2]
2170 elif document.body[ertcont].endswith("]"):
2172 tok = document.body[ertcont].find('>][')
2174 subst = [document.body[ertcont][:tok],
2175 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2176 'status collapsed', '', '\\begin_layout Plain Layout',
2177 document.body[ertcont][tok + 3:-1]]
2178 document.body[ertcont : ertcont + 1] = subst
2179 # Convert to ArgInset
2180 document.body[parbeg] = "\\begin_inset Argument 2"
2183 elif document.body[ertcont].startswith("<"):
2184 # This is an overlay specification
2186 document.body[ertcont] = document.body[ertcont][1:]
2187 if document.body[ertcont].endswith(">"):
2189 document.body[ertcont] = document.body[ertcont][:-1]
2190 # Convert to ArgInset
2191 document.body[parbeg] = "\\begin_inset Argument 1"
2192 elif document.body[ertcont].endswith(">]"):
2194 tok = document.body[ertcont].find('>[<')
2196 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2197 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2198 'status collapsed', '', '\\begin_layout Plain Layout',
2199 document.body[ertcont][tok + 3:-2]]
2200 # Convert to ArgInset
2201 document.body[parbeg] = "\\begin_inset Argument 1"
2202 elif document.body[ertcont].endswith("]"):
2204 tok = document.body[ertcont].find('>[<')
2207 tokk = document.body[ertcont].find('>][')
2209 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2210 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2211 'status collapsed', '', '\\begin_layout Plain Layout',
2212 document.body[ertcont][tok + 3:tokk],
2213 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2214 'status collapsed', '', '\\begin_layout Plain Layout',
2215 document.body[ertcont][tokk + 3:-1]]
2217 tokk = document.body[ertcont].find('>[')
2219 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tokk],
2220 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2221 'status collapsed', '', '\\begin_layout Plain Layout',
2222 document.body[ertcont][tokk + 2:-1]]
2223 # Convert to ArgInset
2224 document.body[parbeg] = "\\begin_inset Argument 1"
2227 elif document.body[ertcont].startswith("["):
2228 # This is an ERT option
2230 document.body[ertcont] = document.body[ertcont][1:]
2231 if document.body[ertcont].endswith("]"):
2233 document.body[ertcont] = document.body[ertcont][:-1]
2234 # Convert to ArgInset
2235 document.body[parbeg] = "\\begin_inset Argument 3"
2241 def convert_corollary_args(document):
2242 " Converts beamer corrolary-style ERT arguments native InsetArgs "
2244 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2245 if document.textclass not in beamer_classes:
2248 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2249 for lay in corollary_layouts:
2252 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2255 parent = get_containing_layout(document.body, i)
2257 document.warning("Wrong parent layout!")
2261 if document.body[parbeg] == "\\begin_inset ERT":
2262 ertcont = parbeg + 5
2263 if document.body[ertcont].startswith("<"):
2264 # This is an overlay specification
2266 document.body[ertcont] = document.body[ertcont][1:]
2267 if document.body[ertcont].endswith(">"):
2269 document.body[ertcont] = document.body[ertcont][:-1]
2270 elif document.body[ertcont].endswith("]"):
2272 tok = document.body[ertcont].find('>[')
2274 subst = [document.body[ertcont][:tok],
2275 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2276 'status collapsed', '', '\\begin_layout Plain Layout',
2277 document.body[ertcont][tok + 2:-1]]
2278 document.body[ertcont : ertcont + 1] = subst
2279 # Convert to ArgInset
2280 document.body[parbeg] = "\\begin_inset Argument 1"
2283 elif document.body[ertcont].startswith("["):
2284 # This is an ERT option
2286 document.body[ertcont] = document.body[ertcont][1:]
2287 if document.body[ertcont].endswith("]"):
2289 document.body[ertcont] = document.body[ertcont][:-1]
2290 # Convert to ArgInset
2291 document.body[parbeg] = "\\begin_inset Argument 2"
2298 def convert_quote_args(document):
2299 " Converts beamer quote style ERT args to native InsetArgs "
2301 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2302 if document.textclass not in beamer_classes:
2305 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2306 for lay in quote_layouts:
2309 i = find_token(document.body, "\\begin_layout " + lay, i)
2312 parent = get_containing_layout(document.body, i)
2314 document.warning("Wrong parent layout!")
2318 if document.body[parbeg] == "\\begin_inset ERT":
2319 if document.body[i + 6].startswith("<"):
2320 # This is an overlay specification
2322 document.body[i + 6] = document.body[i + 6][1:]
2323 if document.body[i + 6].endswith(">"):
2325 document.body[i + 6] = document.body[i + 6][:-1]
2326 # Convert to ArgInset
2327 document.body[i + 1] = "\\begin_inset Argument 1"
2331 def revert_beamerargs(document):
2332 " Reverts beamer arguments to old layout "
2334 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2335 if document.textclass not in beamer_classes:
2339 list_layouts = ["Itemize", "Enumerate", "Description"]
2340 headings = ["Part", "Section", "Section*", "Subsection", "Subsection*",
2341 "Subsubsection", "Subsubsection*", "FrameSubtitle", "NoteItem"]
2342 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2343 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2344 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2347 i = find_token(document.body, "\\begin_inset Argument", i)
2350 # Find containing paragraph layout
2351 parent = get_containing_layout(document.body, i)
2353 document.warning("Malformed lyx document: Can't find parent paragraph layout")
2358 realparbeg = parent[3]
2359 layoutname = parent[0]
2361 for p in range(parbeg, parend):
2365 if layoutname in headings:
2366 m = rx.match(document.body[p])
2370 # Find containing paragraph layout
2371 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2372 endPlain = find_end_of_layout(document.body, beginPlain)
2373 endInset = find_end_of_inset(document.body, p)
2374 argcontent = document.body[beginPlain + 1 : endPlain]
2376 realparend = realparend - len(document.body[p : endInset + 1])
2378 del document.body[p : endInset + 1]
2379 if layoutname == "FrameSubtitle":
2380 pre = put_cmd_in_ert("\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2381 elif layoutname == "NoteItem":
2382 pre = put_cmd_in_ert("\\note<") + argcontent + put_cmd_in_ert(">[item]")
2383 elif layoutname.endswith('*'):
2384 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower()[:-1] + "<") + argcontent + put_cmd_in_ert(">*")
2386 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2387 secarg = find_token(document.body, "\\begin_inset Argument 2", parbeg, parend)
2389 # Find containing paragraph layout
2390 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", secarg)
2391 endPlain = find_end_of_layout(document.body, beginPlain)
2392 endInset = find_end_of_inset(document.body, secarg)
2393 argcontent = document.body[beginPlain + 1 : endPlain]
2395 realparend = realparend - len(document.body[secarg : endInset + 1])
2396 del document.body[secarg : endInset + 1]
2397 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2398 pre += put_cmd_in_ert("{")
2399 document.body[parbeg] = "\\begin_layout Standard"
2400 document.body[realparbeg : realparbeg] = pre
2401 pe = find_end_of_layout(document.body, parbeg)
2402 post = put_cmd_in_ert("}")
2403 document.body[pe : pe] = post
2404 realparend += len(pre) + len(post)
2405 if layoutname == "AgainFrame":
2406 m = rx.match(document.body[p])
2410 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2411 endPlain = find_end_of_layout(document.body, beginPlain)
2412 endInset = find_end_of_inset(document.body, p)
2413 content = document.body[beginPlain + 1 : endPlain]
2415 realparend = realparend - len(document.body[p : endInset + 1])
2417 del document.body[p : endInset + 1]
2418 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2419 document.body[realparbeg : realparbeg] = subst
2420 if layoutname == "Overprint":
2421 m = rx.match(document.body[p])
2425 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2426 endPlain = find_end_of_layout(document.body, beginPlain)
2427 endInset = find_end_of_inset(document.body, p)
2428 content = document.body[beginPlain + 1 : endPlain]
2430 realparend = realparend - len(document.body[p : endInset + 1])
2432 del document.body[p : endInset + 1]
2433 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2434 document.body[realparbeg : realparbeg] = subst
2435 if layoutname == "OverlayArea":
2436 m = rx.match(document.body[p])
2440 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2441 endPlain = find_end_of_layout(document.body, beginPlain)
2442 endInset = find_end_of_inset(document.body, p)
2443 content = document.body[beginPlain + 1 : endPlain]
2445 realparend = realparend - len(document.body[p : endInset + 1])
2447 del document.body[p : endInset + 1]
2448 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2449 document.body[realparbeg : realparbeg] = subst
2450 if layoutname in list_layouts:
2451 m = rx.match(document.body[p])
2455 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2456 endPlain = find_end_of_layout(document.body, beginPlain)
2457 endInset = find_end_of_inset(document.body, p)
2458 content = document.body[beginPlain + 1 : endPlain]
2459 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2460 realparend = realparend + len(subst) - len(content)
2461 document.body[beginPlain + 1 : endPlain] = subst
2462 elif argnr == "item:1":
2463 j = find_end_of_inset(document.body, i)
2464 # Find containing paragraph layout
2465 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2466 endPlain = find_end_of_layout(document.body, beginPlain)
2467 content = document.body[beginPlain + 1 : endPlain]
2468 del document.body[i:j+1]
2469 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2470 document.body[realparbeg : realparbeg] = subst
2471 elif argnr == "item:2":
2472 j = find_end_of_inset(document.body, i)
2473 # Find containing paragraph layout
2474 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2475 endPlain = find_end_of_layout(document.body, beginPlain)
2476 content = document.body[beginPlain + 1 : endPlain]
2477 del document.body[i:j+1]
2478 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2479 document.body[realparbeg : realparbeg] = subst
2480 if layoutname in quote_layouts:
2481 m = rx.match(document.body[p])
2485 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2486 endPlain = find_end_of_layout(document.body, beginPlain)
2487 endInset = find_end_of_inset(document.body, p)
2488 content = document.body[beginPlain + 1 : endPlain]
2490 realparend = realparend - len(document.body[p : endInset + 1])
2492 del document.body[p : endInset + 1]
2493 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2494 document.body[realparbeg : realparbeg] = subst
2495 if layoutname in corollary_layouts:
2496 m = rx.match(document.body[p])
2500 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2501 endPlain = find_end_of_layout(document.body, beginPlain)
2502 endInset = find_end_of_inset(document.body, p)
2503 content = document.body[beginPlain + 1 : endPlain]
2505 realparend = realparend - len(document.body[p : endInset + 1])
2507 del document.body[p : endInset + 1]
2508 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2509 document.body[realparbeg : realparbeg] = subst
2514 def revert_beamerargs2(document):
2515 " Reverts beamer arguments to old layout, step 2 "
2517 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2518 if document.textclass not in beamer_classes:
2522 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2523 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2524 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2527 i = find_token(document.body, "\\begin_inset Argument", i)
2530 # Find containing paragraph layout
2531 parent = get_containing_layout(document.body, i)
2533 document.warning("Malformed lyx document: Can't find parent paragraph layout")
2538 realparbeg = parent[3]
2539 layoutname = parent[0]
2541 for p in range(parbeg, parend):
2545 if layoutname in shifted_layouts:
2546 m = rx.match(document.body[p])
2550 document.body[p] = "\\begin_inset Argument 1"
2551 if layoutname in corollary_layouts:
2552 m = rx.match(document.body[p])
2556 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2557 endPlain = find_end_of_layout(document.body, beginPlain)
2558 endInset = find_end_of_inset(document.body, p)
2559 content = document.body[beginPlain + 1 : endPlain]
2561 realparend = realparend - len(document.body[p : endInset + 1])
2563 del document.body[p : endInset + 1]
2564 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2565 document.body[realparbeg : realparbeg] = subst
2566 if layoutname == "OverlayArea":
2567 m = rx.match(document.body[p])
2571 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2572 endPlain = find_end_of_layout(document.body, beginPlain)
2573 endInset = find_end_of_inset(document.body, p)
2574 content = document.body[beginPlain + 1 : endPlain]
2576 realparend = realparend - len(document.body[p : endInset + 1])
2578 del document.body[p : endInset + 1]
2579 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2580 document.body[realparbeg : realparbeg] = subst
2581 if layoutname == "AgainFrame":
2582 m = rx.match(document.body[p])
2586 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2587 endPlain = find_end_of_layout(document.body, beginPlain)
2588 endInset = find_end_of_inset(document.body, p)
2589 content = document.body[beginPlain + 1 : endPlain]
2591 realparend = realparend - len(document.body[p : endInset + 1])
2593 del document.body[p : endInset + 1]
2594 subst = put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
2595 document.body[realparbeg : realparbeg] = subst
2599 def revert_beamerargs3(document):
2600 " Reverts beamer arguments to old layout, step 3 "
2602 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2603 if document.textclass not in beamer_classes:
2606 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2609 i = find_token(document.body, "\\begin_inset Argument", i)
2612 # Find containing paragraph layout
2613 parent = get_containing_layout(document.body, i)
2615 document.warning("Malformed lyx document: Can't find parent paragraph layout")
2620 realparbeg = parent[3]
2621 layoutname = parent[0]
2623 for p in range(parbeg, parend):
2627 if layoutname == "AgainFrame":
2628 m = rx.match(document.body[p])
2632 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2633 endPlain = find_end_of_layout(document.body, beginPlain)
2634 endInset = find_end_of_inset(document.body, p)
2635 content = document.body[beginPlain + 1 : endPlain]
2637 realparend = realparend - len(document.body[p : endInset + 1])
2639 del document.body[p : endInset + 1]
2640 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2641 document.body[realparbeg : realparbeg] = subst
2645 def revert_beamerflex(document):
2646 " Reverts beamer Flex insets "
2648 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2649 if document.textclass not in beamer_classes:
2652 new_flexes = {"Bold" : "\\textbf", "Emphasize" : "\\emph", "Only" : "\\only",
2653 "Uncover" : "\\uncover", "Visible" : "\\visible",
2654 "Invisible" : "\\invisible", "Alternative" : "\\alt",
2655 "Beamer_Note" : "\\note"}
2656 old_flexes = {"Alert" : "\\alert", "Structure" : "\\structure"}
2657 rx = re.compile(r'^\\begin_inset Flex (.+)$')
2661 i = find_token(document.body, "\\begin_inset Flex", i)
2664 m = rx.match(document.body[i])
2666 flextype = m.group(1)
2667 z = find_end_of_inset(document.body, i)
2669 document.warning("Can't find end of Flex " + flextype + " inset.")
2672 if flextype in new_flexes:
2673 pre = put_cmd_in_ert(new_flexes[flextype])
2674 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2676 argend = find_end_of_inset(document.body, arg)
2678 document.warning("Can't find end of Argument!")
2681 # Find containing paragraph layout
2682 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2683 endPlain = find_end_of_layout(document.body, beginPlain)
2684 argcontent = document.body[beginPlain + 1 : endPlain]
2686 z = z - len(document.body[arg : argend + 1])
2688 del document.body[arg : argend + 1]
2689 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2690 arg = find_token(document.body, "\\begin_inset Argument 2", i, z)
2692 argend = find_end_of_inset(document.body, arg)
2694 document.warning("Can't find end of Argument!")
2697 # Find containing paragraph layout
2698 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2699 endPlain = find_end_of_layout(document.body, beginPlain)
2700 argcontent = document.body[beginPlain + 1 : endPlain]
2702 z = z - len(document.body[arg : argend + 1])
2704 del document.body[arg : argend + 1]
2705 if flextype == "Alternative":
2706 pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}")
2708 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2709 pre += put_cmd_in_ert("{")
2710 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2711 endPlain = find_end_of_layout(document.body, beginPlain)
2713 z = z - len(document.body[i : beginPlain + 1])
2715 document.body[i : beginPlain + 1] = pre
2716 post = put_cmd_in_ert("}")
2717 document.body[z - 2 : z + 1] = post
2718 elif flextype in old_flexes:
2719 pre = put_cmd_in_ert(old_flexes[flextype])
2720 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2724 argend = find_end_of_inset(document.body, arg)
2726 document.warning("Can't find end of Argument!")
2729 # Find containing paragraph layout
2730 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2731 endPlain = find_end_of_layout(document.body, beginPlain)
2732 argcontent = document.body[beginPlain + 1 : endPlain]
2734 z = z - len(document.body[arg : argend + 1])
2736 del document.body[arg : argend + 1]
2737 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2738 pre += put_cmd_in_ert("{")
2739 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2740 endPlain = find_end_of_layout(document.body, beginPlain)
2742 z = z - len(document.body[i : beginPlain + 1])
2744 document.body[i : beginPlain + 1] = pre
2745 post = put_cmd_in_ert("}")
2746 document.body[z - 2 : z + 1] = post
2751 def revert_beamerblocks(document):
2752 " Reverts beamer block arguments to ERT "
2754 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2755 if document.textclass not in beamer_classes:
2758 blocks = ["Block", "ExampleBlock", "AlertBlock"]
2760 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2763 i = find_token(document.body, "\\begin_inset Argument", i)
2766 # Find containing paragraph layout
2767 parent = get_containing_layout(document.body, i)
2769 document.warning("Malformed lyx document: Can't find parent paragraph layout")
2774 realparbeg = parent[3]
2775 layoutname = parent[0]
2777 for p in range(parbeg, parend):
2781 if layoutname in blocks:
2782 m = rx.match(document.body[p])
2786 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2787 endPlain = find_end_of_layout(document.body, beginPlain)
2788 endInset = find_end_of_inset(document.body, p)
2789 content = document.body[beginPlain + 1 : endPlain]
2791 realparend = realparend - len(document.body[p : endInset + 1])
2793 del document.body[p : endInset + 1]
2794 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2795 document.body[realparbeg : realparbeg] = subst
2797 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2798 endPlain = find_end_of_layout(document.body, beginPlain)
2799 endInset = find_end_of_inset(document.body, p)
2800 content = document.body[beginPlain + 1 : endPlain]
2802 realparend = realparend - len(document.body[p : endInset + 1])
2804 del document.body[p : endInset + 1]
2805 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2806 document.body[realparbeg : realparbeg] = subst
2811 def convert_beamerblocks(document):
2812 " Converts beamer block ERT args to native InsetArgs "
2814 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2815 if document.textclass not in beamer_classes:
2818 blocks = ["Block", "ExampleBlock", "AlertBlock"]
2822 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2825 parent = get_containing_layout(document.body, i)
2826 if parent == False or parent[1] != i:
2827 document.warning("Wrong parent layout!")
2833 if document.body[parbeg] == "\\begin_inset ERT":
2834 ertcont = parbeg + 5
2836 if document.body[ertcont].startswith("<"):
2837 # This is an overlay specification
2839 document.body[ertcont] = document.body[ertcont][1:]
2840 if document.body[ertcont].endswith(">"):
2842 document.body[ertcont] = document.body[ertcont][:-1]
2843 # Convert to ArgInset
2844 document.body[parbeg] = "\\begin_inset Argument 1"
2845 elif document.body[ertcont].endswith("}"):
2847 tok = document.body[ertcont].find('>{')
2849 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2850 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2851 'status collapsed', '', '\\begin_layout Plain Layout',
2852 document.body[ertcont][tok + 2:-1]]
2853 # Convert to ArgInset
2854 document.body[parbeg] = "\\begin_inset Argument 1"
2855 elif document.body[ertcont].startswith("{"):
2856 # This is the block title
2857 if document.body[ertcont].endswith("}"):
2858 # strip off the braces
2859 document.body[ertcont] = document.body[ertcont][1:-1]
2860 # Convert to ArgInset
2861 document.body[parbeg] = "\\begin_inset Argument 2"
2862 elif count_pars_in_inset(document.body, ertcont) > 1:
2863 # Multipar ERT. Skip this.
2866 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True)
2869 j = find_end_of_layout(document.body, i)
2871 document.warning("end of layout not found!")
2872 k = find_token(document.body, "\\begin_inset Argument", i, j)
2874 document.warning("InsetArgument not found!")
2876 l = find_end_of_inset(document.body, k)
2877 m = find_token(document.body, "\\begin_inset ERT", l, j)
2885 def convert_overprint(document):
2886 " Convert old beamer overprint layouts to ERT "
2888 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2889 if document.textclass not in beamer_classes:
2894 i = find_token(document.body, "\\begin_layout Overprint", i)
2897 # Find end of sequence
2898 j = find_end_of_sequence(document.body, i)
2900 document.warning("Malformed lyx document. Cannot find end of Overprint sequence!")
2904 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
2906 if document.body[j] == "\\end_deeper":
2907 esubst = ["", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
2909 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
2910 endseq = endseq + len(esubst) - len(document.body[j : j])
2911 document.body[j : j] = esubst
2912 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
2914 argend = find_end_of_layout(document.body, argbeg)
2916 document.warning("Malformed lyx document. Cannot find end of Overprint argument!")
2919 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
2920 endPlain = find_end_of_layout(document.body, beginPlain)
2921 content = document.body[beginPlain + 1 : endPlain]
2923 endseq = endseq - len(document.body[argbeg : argend + 1])
2925 del document.body[argbeg : argend + 1]
2926 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2928 endseq = endseq - len(document.body[i : i])
2929 document.body[i : i] = subst + ["\\end_layout"]
2930 endseq += len(subst)
2932 for p in range(i, endseq):
2933 if document.body[p] == "\\begin_layout Overprint":
2934 document.body[p] = "\\begin_layout Standard"
2939 def revert_overprint(document):
2940 " Revert old beamer overprint layouts to ERT "
2942 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2943 if document.textclass not in beamer_classes:
2948 i = find_token(document.body, "\\begin_layout Overprint", i)
2951 # Find end of sequence
2952 j = find_end_of_sequence(document.body, i)
2954 document.warning("Malformed lyx document. Cannot find end of Overprint sequence!")
2958 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
2959 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}")
2960 endseq = endseq + len(esubst) - len(document.body[j : j])
2961 if document.body[j] == "\\end_deeper":
2962 document.body[j : j] = ["\\end_deeper", ""] + esubst
2964 document.body[j : j] = esubst
2967 if document.body[r] == "\\begin_deeper":
2968 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
2970 document.body[r] = ""
2971 document.body[s] = ""
2975 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
2977 argend = find_end_of_inset(document.body, argbeg)
2979 document.warning("Malformed lyx document. Cannot find end of Overprint argument!")
2982 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
2983 endPlain = find_end_of_layout(document.body, beginPlain)
2984 content = document.body[beginPlain + 1 : endPlain]
2986 endseq = endseq - len(document.body[argbeg : argend])
2988 del document.body[argbeg : argend + 1]
2989 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2991 endseq = endseq - len(document.body[i : i])
2992 document.body[i : i] = subst + ["\\end_layout"]
2993 endseq += len(subst)
2999 if document.body[p] == "\\begin_layout Overprint":
3000 q = find_end_of_layout(document.body, p)
3002 document.warning("Malformed lyx document. Cannot find end of Overprint layout!")
3005 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\onslide")
3006 argbeg = find_token(document.body, "\\begin_inset Argument item:1", p, q)
3008 argend = find_end_of_inset(document.body, argbeg)
3010 document.warning("Malformed lyx document. Cannot find end of Overprint item argument!")
3013 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
3014 endPlain = find_end_of_layout(document.body, beginPlain)
3015 content = document.body[beginPlain + 1 : endPlain]
3017 endseq = endseq - len(document.body[argbeg : argend + 1])
3019 del document.body[argbeg : argend + 1]
3020 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3021 endseq = endseq - len(document.body[p : p + 1]) + len(subst)
3022 document.body[p : p + 1] = subst
3028 def revert_frametitle(document):
3029 " Reverts beamer frametitle layout to ERT "
3031 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3032 if document.textclass not in beamer_classes:
3035 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
3038 i = find_token(document.body, "\\begin_layout FrameTitle", i)
3041 j = find_end_of_layout(document.body, i)
3043 document.warning("Malformed lyx document: Can't find end of FrameTitle layout")
3047 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
3048 endlay += len(put_cmd_in_ert("}"))
3049 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\frametitle")
3050 for p in range(i, j):
3053 m = rx.match(document.body[p])
3057 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3058 endPlain = find_end_of_layout(document.body, beginPlain)
3059 endInset = find_end_of_inset(document.body, p)
3060 content = document.body[beginPlain + 1 : endPlain]
3062 endlay = endlay - len(document.body[p : endInset + 1])
3064 del document.body[p : endInset + 1]
3065 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3067 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3068 endPlain = find_end_of_layout(document.body, beginPlain)
3069 endInset = find_end_of_inset(document.body, p)
3070 content = document.body[beginPlain + 1 : endPlain]
3072 endlay = endlay - len(document.body[p : endInset + 1])
3074 del document.body[p : endInset + 1]
3075 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3077 subst += put_cmd_in_ert("{")
3078 document.body[i : i + 1] = subst
3082 def convert_epigraph(document):
3083 " Converts memoir epigraph to new syntax "
3085 if document.textclass != "memoir":
3090 i = find_token(document.body, "\\begin_layout Epigraph", i)
3093 j = find_end_of_layout(document.body, i)
3095 document.warning("Malformed lyx document: Can't find end of Epigraph layout")
3100 ert = find_token(document.body, "\\begin_inset ERT", i, j)
3102 endInset = find_end_of_inset(document.body, ert)
3103 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", ert)
3104 endPlain = find_end_of_layout(document.body, beginPlain)
3105 ertcont = beginPlain + 2
3106 if document.body[ertcont] == "}{":
3108 # Convert to ArgInset
3109 endlay = endlay - 2 * len(document.body[j])
3110 begsubst = ['\\begin_inset Argument post:1', 'status collapsed', '',
3111 '\\begin_layout Plain Layout']
3112 endsubst = ['\\end_layout', '', '\\end_inset', '', document.body[j]]
3113 document.body[j : j + 1] = endsubst
3114 document.body[endInset + 1 : endInset + 1] = begsubst
3116 endlay += len(begsubst) + len(endsubst)
3117 endlay = endlay - len(document.body[ert : endInset + 1])
3118 del document.body[ert : endInset + 1]
3123 def revert_epigraph(document):
3124 " Reverts memoir epigraph argument to ERT "
3126 if document.textclass != "memoir":
3131 i = find_token(document.body, "\\begin_layout Epigraph", i)
3134 j = find_end_of_layout(document.body, i)
3136 document.warning("Malformed lyx document: Can't find end of Epigraph layout")
3141 p = find_token(document.body, "\\begin_layout Argument post:1", i, j)
3143 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3144 endPlain = find_end_of_layout(document.body, beginPlain)
3145 endInset = find_end_of_inset(document.body, p)
3146 content = document.body[beginPlain + 1 : endPlain]
3148 endlay = endlay - len(document.body[p : endInset + 1])
3150 del document.body[p : endInset + 1]
3151 subst += put_cmd_in_ert("}{") + content
3153 subst += put_cmd_in_ert("}{")
3155 document.body[j : j] = subst + document.body[j : j]
3159 def convert_captioninsets(document):
3160 " Converts caption insets to new syntax "
3164 i = find_token(document.body, "\\begin_inset Caption", i)
3167 document.body[i] = "\\begin_inset Caption Standard"
3172 def revert_captioninsets(document):
3173 " Reverts caption insets to old syntax "
3177 i = find_token(document.body, "\\begin_inset Caption Standard", i)
3180 document.body[i] = "\\begin_inset Caption"
3184 def convert_captionlayouts(document):
3185 " Convert caption layouts to caption insets. "
3188 "Captionabove": "Above",
3189 "Captionbelow": "Below",
3190 "FigCaption" : "FigCaption",
3191 "Table_Caption" : "Table",
3192 "CenteredCaption" : "Centered",
3193 "Bicaption" : "Bicaption",
3198 i = find_token(document.body, "\\begin_layout", i)
3201 val = get_value(document.body, "\\begin_layout", i)
3202 if val in caption_dict.keys():
3203 j = find_end_of_layout(document.body, i)
3205 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3208 document.body[j:j] = ["\\end_layout", "", "\\end_inset", "", ""]
3209 document.body[i:i+1] = ["\\begin_layout %s" % document.default_layout,
3210 "\\begin_inset Caption %s" % caption_dict[val], "",
3211 "\\begin_layout %s" % document.default_layout]
3215 def revert_captionlayouts(document):
3216 " Revert caption insets to caption layouts. "
3219 "Above" : "Captionabove",
3220 "Below" : "Captionbelow",
3221 "FigCaption" : "FigCaption",
3222 "Table" : "Table_Caption",
3223 "Centered" : "CenteredCaption",
3224 "Bicaption" : "Bicaption",
3228 rx = re.compile(r'^\\begin_inset Caption (\S+)$')
3230 i = find_token(document.body, "\\begin_inset Caption", i)
3234 m = rx.match(document.body[i])
3238 if val not in caption_dict.keys():
3242 # We either need to delete the previous \begin_layout line, or we
3243 # need to end the previous layout if this inset is not in the first
3244 # position of the paragraph.
3245 layout_before = find_token_backwards(document.body, "\\begin_layout", i)
3246 if layout_before == -1:
3247 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3249 layout_line = document.body[layout_before]
3250 del_layout_before = True
3251 l = layout_before + 1
3253 if document.body[l] != "":
3254 del_layout_before = False
3257 if del_layout_before:
3258 del document.body[layout_before:i]
3261 document.body[i:i] = ["\\end_layout", ""]
3264 # Find start of layout in the inset and end of inset
3265 j = find_token(document.body, "\\begin_layout", i)
3267 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3269 k = find_end_of_inset(document.body, i)
3271 document.warning("Malformed LyX document: Missing `\\end_inset'.")
3274 # We either need to delete the following \end_layout line, or we need
3275 # to restart the old layout if this inset is not at the paragraph end.
3276 layout_after = find_token(document.body, "\\end_layout", k)
3277 if layout_after == -1:
3278 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3280 del_layout_after = True
3282 while l < layout_after:
3283 if document.body[l] != "":
3284 del_layout_after = False
3287 if del_layout_after:
3288 del document.body[k+1:layout_after+1]
3290 document.body[k+1:k+1] = [layout_line, ""]
3292 # delete \begin_layout and \end_inset and replace \begin_inset with
3293 # "\begin_layout XXX". This works because we can only have one
3294 # paragraph in the caption inset: The old \end_layout will be recycled.
3295 del document.body[k]
3296 if document.body[k] == "":
3297 del document.body[k]
3298 del document.body[j]
3299 if document.body[j] == "":
3300 del document.body[j]
3301 document.body[i] = "\\begin_layout %s" % caption_dict[val]
3302 if document.body[i+1] == "":
3303 del document.body[i+1]
3307 def revert_fragileframe(document):
3308 " Reverts beamer FragileFrame layout to ERT "
3310 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3311 if document.textclass not in beamer_classes:
3316 i = find_token(document.body, "\\begin_layout FragileFrame", i)
3319 # Find end of sequence
3320 j = find_end_of_sequence(document.body, i)
3322 document.warning("Malformed lyx document. Cannot find end of FragileFrame sequence!")
3326 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{frame}")
3327 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{frame}")
3328 endseq = endseq + len(esubst) - len(document.body[j : j])
3329 if document.body[j] == "\\end_deeper":
3330 document.body[j : j] = ["\\end_deeper", ""] + esubst
3332 document.body[j : j] = esubst
3333 for q in range(i, j):
3334 if document.body[q] == "\\begin_layout FragileFrame":
3335 document.body[q] = "\\begin_layout %s" % document.default_layout
3338 if document.body[r] == "\\begin_deeper":
3339 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3341 document.body[r] = ""
3342 document.body[s] = ""
3346 for p in range(1, 5):
3347 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, j)
3350 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3351 endPlain = find_end_of_layout(document.body, beginPlain)
3352 endInset = find_end_of_inset(document.body, arg)
3353 content = document.body[beginPlain + 1 : endPlain]
3355 j = j - len(document.body[arg : endInset + 1])
3357 del document.body[arg : endInset + 1]
3358 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3360 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3361 endPlain = find_end_of_layout(document.body, beginPlain)
3362 endInset = find_end_of_inset(document.body, arg)
3363 content = document.body[beginPlain + 1 : endPlain]
3365 j = j - len(document.body[arg : endInset + 1])
3367 del document.body[arg : endInset + 1]
3368 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3370 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3371 endPlain = find_end_of_layout(document.body, beginPlain)
3372 endInset = find_end_of_inset(document.body, arg)
3373 content = document.body[beginPlain + 1 : endPlain]
3375 j = j - len(document.body[arg : endInset + 1])
3377 del document.body[arg : endInset + 1]
3378 subst += put_cmd_in_ert("[fragile,") + content + put_cmd_in_ert("]")
3380 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3381 endPlain = find_end_of_layout(document.body, beginPlain)
3382 endInset = find_end_of_inset(document.body, arg)
3383 content = document.body[beginPlain + 1 : endPlain]
3385 j = j - len(document.body[arg : endInset + 1])
3387 del document.body[arg : endInset + 1]
3388 subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
3390 subst += put_cmd_in_ert("[fragile]")
3392 document.body[i : i + 1] = subst
3396 def revert_newframes(document):
3397 " Reverts beamer Frame and PlainFrame layouts to old forms "
3399 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
3400 if document.textclass not in beamer_classes:
3404 "Frame" : "BeginFrame",
3405 "PlainFrame" : "BeginPlainFrame",
3408 rx = re.compile(r'^\\begin_layout (\S+)$')
3411 i = find_token(document.body, "\\begin_layout", i)
3415 m = rx.match(document.body[i])
3419 if val not in frame_dict.keys():
3422 # Find end of sequence
3423 j = find_end_of_sequence(document.body, i)
3425 document.warning("Malformed lyx document. Cannot find end of Frame sequence!")
3429 subst = ["\\begin_layout %s" % frame_dict[val]]
3430 esubst = ["\\end_layout", "", "\\begin_layout EndFrame", "", "\\end_layout"]
3431 endseq = endseq + len(esubst) - len(document.body[j : j])
3432 if document.body[j] == "\\end_deeper":
3433 document.body[j : j] = ["\\end_deeper", ""] + esubst
3435 document.body[j : j] = esubst
3436 for q in range(i, j):
3437 if document.body[q] == "\\begin_layout %s" % val:
3438 document.body[q] = "\\begin_layout %s" % document.default_layout
3441 if document.body[r] == "\\begin_deeper":
3442 s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper")
3444 document.body[r] = ""
3445 document.body[s] = ""
3449 l = find_end_of_layout(document.body, i)
3450 for p in range(1, 5):
3451 arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, l)
3454 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3455 endPlain = find_end_of_layout(document.body, beginPlain)
3456 endInset = find_end_of_inset(document.body, arg)
3457 content = document.body[beginPlain + 1 : endPlain]
3459 l = l - len(document.body[arg : endInset + 1])
3461 del document.body[arg : endInset + 1]
3462 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
3464 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3465 endPlain = find_end_of_layout(document.body, beginPlain)
3466 endInset = find_end_of_inset(document.body, arg)
3467 content = document.body[beginPlain + 1 : endPlain]
3469 l = l - len(document.body[arg : endInset + 1])
3471 del document.body[arg : endInset + 1]
3472 subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
3474 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3475 endPlain = find_end_of_layout(document.body, beginPlain)
3476 endInset = find_end_of_inset(document.body, arg)
3477 content = document.body[beginPlain + 1 : endPlain]
3479 l = l - len(document.body[arg : endInset + 1])
3481 del document.body[arg : endInset + 1]
3482 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
3484 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
3485 endPlain = find_end_of_layout(document.body, beginPlain)
3486 endInset = find_end_of_inset(document.body, arg)
3487 content = document.body[beginPlain + 1 : endPlain]
3489 l = l - len(document.body[arg : endInset + 1])
3491 del document.body[arg : endInset + 1]
3494 document.body[i : i + 1] = subst
3498 def revert_IEEEtran_3(document):
3500 Reverts Flex Insets to TeX-code
3502 if document.textclass == "IEEEtran":
3508 h = find_token(document.body, "\\begin_inset Flex Author Mark", h)
3510 endh = find_end_of_inset(document.body, h)
3511 document.body[endh - 2 : endh + 1] = put_cmd_in_ert("}")
3512 document.body[h : h + 4] = put_cmd_in_ert("\\IEEEauthorrefmark{")
3515 i = find_token(document.body, "\\begin_inset Flex Author Name", i)
3517 endi = find_end_of_inset(document.body, i)
3518 document.body[endi - 2 : endi + 1] = put_cmd_in_ert("}")
3519 document.body[i : i + 4] = put_cmd_in_ert("\\IEEEauthorblockN{")
3522 j = find_token(document.body, "\\begin_inset Flex Author Affiliation", j)
3524 endj = find_end_of_inset(document.body, j)
3525 document.body[endj - 2 : endj + 1] = put_cmd_in_ert("}")
3526 document.body[j : j + 4] = put_cmd_in_ert("\\IEEEauthorblockA{")
3528 if i == -1 and j == -1 and h == -1:
3532 def revert_kurier_fonts(document):
3533 " Revert kurier font definition to LaTeX "
3535 i = find_token(document.header, "\\font_math", 0)
3537 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
3538 val = get_value(document.header, "\\font_math", i)
3539 if val == "kurier-math":
3540 add_to_preamble(document, "\\let\\Myrmdefault\\rmdefault\n" \
3541 "\\usepackage[math]{kurier}\n" \
3542 "\\renewcommand{\\rmdefault}{\\Myrmdefault}")
3543 document.header[i] = "\\font_math auto"
3545 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
3546 kurier_fonts = ["kurier", "kurierc", "kurierl", "kurierlc"]
3547 k = find_token(document.header, "\\font_sans kurier", 0)
3549 sf = get_value(document.header, "\\font_sans", k)
3550 if sf in kurier_fonts:
3551 add_to_preamble(document, "\\renewcommand{\\sfdefault}{%s}" % sf)
3552 document.header[k] = "\\font_sans default"
3555 def revert_new_libertines(document):
3556 " Revert new libertine font definition to LaTeX "
3558 if find_token(document.header, "\\use_non_tex_fonts true", 0) != -1:
3561 i = find_token(document.header, "\\font_typewriter libertine-mono", 0)
3563 preamble = "\\usepackage"
3564 sc = find_token(document.header, "\\font_tt_scale", 0)
3566 scval = get_value(document.header, "\\font_tt_scale", sc)
3568 preamble += "[scale=%f]" % (float(scval) / 100)
3569 document.header[sc] = "\\font_tt_scale 100"
3570 preamble += "{libertineMono-type1}"
3571 add_to_preamble(document, [preamble])
3572 document.header[i] = "\\font_typewriter default"
3574 k = find_token(document.header, "\\font_sans biolinum", 0)
3576 preamble = "\\usepackage"
3578 j = find_token(document.header, "\\font_osf true", 0)
3583 sc = find_token(document.header, "\\font_sf_scale", 0)
3585 scval = get_value(document.header, "\\font_sf_scale", sc)
3587 options += ",scale=%f" % (float(scval) / 100)
3588 document.header[sc] = "\\font_sf_scale 100"
3590 preamble += "[" + options +"]"
3591 preamble += "{biolinum-type1}"
3592 add_to_preamble(document, [preamble])
3593 document.header[k] = "\\font_sans default"
3600 supported_versions = ["2.1.0","2.1"]
3603 [415, [convert_undertilde]],
3605 [417, [convert_japanese_encodings]],
3608 [420, [convert_biblio_style]],
3609 [421, [convert_longtable_captions]],
3610 [422, [convert_use_packages]],
3611 [423, [convert_use_mathtools]],
3612 [424, [convert_cite_engine_type]],
3616 [428, [convert_cell_rotation]],
3617 [429, [convert_table_rotation]],
3618 [430, [convert_listoflistings]],
3619 [431, [convert_use_amssymb]],
3621 [433, [convert_armenian]],
3629 [441, [convert_mdnomath]],
3634 [446, [convert_latexargs]],
3635 [447, [convert_IEEEtran, convert_AASTeX, convert_AGUTeX, convert_IJMP, convert_SIGPLAN, convert_SIGGRAPH, convert_EuropeCV, convert_Initials, convert_ModernCV]],
3636 [448, [convert_literate]],
3639 [451, [convert_beamerargs, convert_againframe_args, convert_corollary_args, convert_quote_args]],
3640 [452, [convert_beamerblocks]],
3641 [453, [convert_use_stmaryrd]],
3642 [454, [convert_overprint]],
3644 [456, [convert_epigraph]],
3645 [457, [convert_use_stackrel]],
3646 [458, [convert_captioninsets, convert_captionlayouts]],
3654 [461, [revert_new_libertines]],
3655 [460, [revert_kurier_fonts]],
3656 [459, [revert_IEEEtran_3]],
3657 [458, [revert_fragileframe, revert_newframes]],
3658 [457, [revert_captioninsets, revert_captionlayouts]],
3659 [456, [revert_use_stackrel]],
3660 [455, [revert_epigraph]],
3661 [454, [revert_frametitle]],
3662 [453, [revert_overprint]],
3663 [452, [revert_use_stmaryrd]],
3664 [451, [revert_beamerblocks]],
3665 [450, [revert_beamerargs, revert_beamerargs2, revert_beamerargs3, revert_beamerflex]],
3666 [449, [revert_garamondx, revert_garamondx_newtxmath]],
3667 [448, [revert_itemargs]],
3668 [447, [revert_literate]],
3669 [446, [revert_IEEEtran, revert_IEEEtran_2, revert_AASTeX, revert_AGUTeX, revert_IJMP, revert_SIGPLAN, revert_SIGGRAPH, revert_EuropeCV, revert_Initials, revert_ModernCV]],
3670 [445, [revert_latexargs]],
3671 [444, [revert_uop]],
3672 [443, [revert_biolinum]],
3674 [441, [revert_newtxmath]],
3675 [440, [revert_mdnomath]],
3676 [439, [revert_mathfonts]],
3677 [438, [revert_minionpro]],
3678 [437, [revert_ipadeco, revert_ipachar]],
3679 [436, [revert_texgyre]],
3680 [435, [revert_mathdesign]],
3681 [434, [revert_txtt]],
3682 [433, [revert_libertine]],
3683 [432, [revert_armenian]],
3684 [431, [revert_languages, revert_ancientgreek]],
3685 [430, [revert_use_amssymb]],
3686 [429, [revert_listoflistings]],
3687 [428, [revert_table_rotation]],
3688 [427, [revert_cell_rotation]],
3689 [426, [revert_tipa]],
3690 [425, [revert_verbatim]],
3691 [424, [revert_cancel]],
3692 [423, [revert_cite_engine_type]],
3693 [422, [revert_use_mathtools]],
3694 [421, [revert_use_packages]],
3695 [420, [revert_longtable_captions]],
3696 [419, [revert_biblio_style]],
3697 [418, [revert_australian]],
3698 [417, [revert_justification]],
3699 [416, [revert_japanese_encodings]],
3700 [415, [revert_negative_space, revert_math_spaces]],
3701 [414, [revert_undertilde]],
3702 [413, [revert_visible_space]]
3706 if __name__ == "__main__":