1 # -*- coding: utf-8 -*-
2 # This file is part of lyx2lyx
3 # -*- coding: utf-8 -*-
4 # Copyright (C) 2011 The LyX team
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 """ Convert files to the file format generated by lyx 2.1"""
26 # Uncomment only what you need to import, please.
28 from parser_tools import count_pars_in_inset, del_token, find_token, find_token_exact, \
29 find_token_backwards, find_end_of, find_end_of_inset, find_end_of_layout, \
30 find_end_of_sequence, find_re, get_option_value, get_containing_layout, \
31 get_value, get_quoted_value, set_option_value
33 #from parser_tools import find_token, find_end_of, find_tokens, \
34 #find_end_of_inset, find_end_of_layout, \
35 #is_in_inset, del_token, check_token
37 from lyx2lyx_tools import add_to_preamble, put_cmd_in_ert, get_ert
39 #from lyx2lyx_tools import insert_to_preamble, \
40 # lyx2latex, latex_length, revert_flex_inset, \
41 # revert_font_attrs, hex2ratio, str2bool
43 ####################################################################
44 # Private helper functions
46 #def remove_option(lines, m, option):
47 #''' removes option from line m. returns whether we did anything '''
48 #l = lines[m].find(option)
51 #val = lines[m][l:].split('"')[1]
52 #lines[m] = lines[m][:l - 1] + lines[m][l+len(option + '="' + val + '"'):]
56 ###############################################################################
58 ### Conversion and reversion routines
60 ###############################################################################
62 def revert_visible_space(document):
63 "Revert InsetSpace visible into its ERT counterpart"
66 i = find_token(document.body, "\\begin_inset space \\textvisiblespace{}", i)
69 end = find_end_of_inset(document.body, i)
70 subst = put_cmd_in_ert("\\textvisiblespace{}")
71 document.body[i:end + 1] = subst
74 def convert_undertilde(document):
75 " Load undertilde automatically "
76 i = find_token(document.header, "\\use_mathdots" , 0)
78 i = find_token(document.header, "\\use_mhchem" , 0)
80 i = find_token(document.header, "\\use_esint" , 0)
82 document.warning("Malformed LyX document: Can't find \\use_mathdots.")
84 j = find_token(document.preamble, "\\usepackage{undertilde}", 0)
86 document.header.insert(i + 1, "\\use_undertilde 0")
88 document.header.insert(i + 1, "\\use_undertilde 2")
89 del document.preamble[j]
92 def revert_undertilde(document):
93 " Load undertilde if used in the document "
94 undertilde = find_token(document.header, "\\use_undertilde" , 0)
96 document.warning("No \\use_undertilde line. Assuming auto.")
98 val = get_value(document.header, "\\use_undertilde", undertilde)
99 del document.header[undertilde]
103 document.warning("Invalid \\use_undertilde value: " + val + ". Assuming auto.")
104 # probably usedots has not been changed, but be safe.
112 add_to_preamble(document, ["\\usepackage{undertilde}"])
115 # so we are in the auto case. we want to load undertilde if \utilde is used.
118 i = find_token(document.body, '\\begin_inset Formula', i)
121 j = find_end_of_inset(document.body, i)
123 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
126 code = "\n".join(document.body[i:j])
127 if code.find("\\utilde") != -1:
128 add_to_preamble(document, ["\\@ifundefined{utilde}{\\usepackage{undertilde}}"])
133 def revert_negative_space(document):
134 "Revert InsetSpace negmedspace and negthickspace into its TeX-code counterpart"
139 i = find_token(document.body, "\\begin_inset space \\negmedspace{}", i)
141 j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
143 # load amsmath in the preamble if not already loaded if we are at the end of checking
145 i = find_token(document.header, "\\use_amsmath 2", 0)
147 add_to_preamble(document, ["\\@ifundefined{negthickspace}{\\usepackage{amsmath}}"])
151 end = find_end_of_inset(document.body, i)
152 subst = put_cmd_in_ert("\\negmedspace{}")
153 document.body[i:end + 1] = subst
154 j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
157 end = find_end_of_inset(document.body, j)
158 subst = put_cmd_in_ert("\\negthickspace{}")
159 document.body[j:end + 1] = subst
163 def revert_math_spaces(document):
164 "Revert formulas with protected custom space and protected hfills to TeX-code"
167 i = find_token(document.body, "\\begin_inset Formula", i)
170 j = document.body[i].find("\\hspace*")
172 end = find_end_of_inset(document.body, i)
173 subst = put_cmd_in_ert(document.body[i][21:])
174 document.body[i:end + 1] = subst
178 def convert_japanese_encodings(document):
179 " Rename the japanese encodings to names understood by platex "
181 "EUC-JP-pLaTeX": "euc",
183 "SJIS-pLaTeX": "sjis"
185 i = find_token(document.header, "\\inputencoding" , 0)
188 val = get_value(document.header, "\\inputencoding", i)
189 if val in jap_enc_dict.keys():
190 document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
193 def revert_japanese_encodings(document):
194 " Revert the japanese encodings name changes "
196 "euc": "EUC-JP-pLaTeX",
198 "sjis": "SJIS-pLaTeX"
200 i = find_token(document.header, "\\inputencoding" , 0)
203 val = get_value(document.header, "\\inputencoding", i)
204 if val in jap_enc_dict.keys():
205 document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
208 def revert_justification(document):
209 " Revert the \\justification buffer param"
210 if not del_token(document.header, '\\justification', 0):
211 document.warning("Malformed LyX document: Missing \\justification.")
214 def revert_australian(document):
215 "Set English language variants Australian and Newzealand to English"
217 if document.language == "australian" or document.language == "newzealand":
218 document.language = "english"
219 i = find_token(document.header, "\\language", 0)
221 document.header[i] = "\\language english"
224 j = find_token(document.body, "\\lang australian", j)
226 j = find_token(document.body, "\\lang newzealand", 0)
230 document.body[j] = document.body[j].replace("\\lang newzealand", "\\lang english")
232 document.body[j] = document.body[j].replace("\\lang australian", "\\lang english")
236 def convert_biblio_style(document):
237 "Add a sensible default for \\biblio_style based on the citation engine."
238 i = find_token(document.header, "\\cite_engine", 0)
240 engine = get_value(document.header, "\\cite_engine", i).split("_")[0]
241 style = {"basic": "plain", "natbib": "plainnat", "jurabib": "jurabib"}
242 document.header.insert(i + 1, "\\biblio_style " + style[engine])
245 def revert_biblio_style(document):
246 "BibTeX insets with default option use the style defined by \\biblio_style."
247 i = find_token(document.header, "\\biblio_style" , 0)
249 document.warning("No \\biblio_style line. Nothing to do.")
252 default_style = get_value(document.header, "\\biblio_style", i)
253 del document.header[i]
255 # We are looking for bibtex insets having the default option
258 i = find_token(document.body, "\\begin_inset CommandInset bibtex", i)
261 j = find_end_of_inset(document.body, i)
263 document.warning("Malformed LyX document: Can't find end of bibtex inset at line " + str(i))
266 k = find_token(document.body, "options", i, j)
268 options = get_quoted_value(document.body, "options", k)
269 if "default" in options.split(","):
270 document.body[k] = 'options "%s"' \
271 % options.replace("default", default_style)
275 def handle_longtable_captions(document, forward):
278 begin_table = find_token(document.body, '<lyxtabular version=', begin_table)
279 if begin_table == -1:
281 end_table = find_end_of(document.body, begin_table, '<lyxtabular', '</lyxtabular>')
283 document.warning("Malformed LyX document: Could not find end of table.")
286 fline = find_token(document.body, "<features", begin_table, end_table)
288 document.warning("Can't find features for inset at line " + str(begin_table))
291 p = document.body[fline].find("islongtable")
296 numrows = get_option_value(document.body[begin_table], "rows")
298 numrows = int(numrows)
300 document.warning(document.body[begin_table])
301 document.warning("Unable to determine rows!")
302 begin_table = end_table
304 begin_row = begin_table
305 for row in range(numrows):
306 begin_row = find_token(document.body, '<row', begin_row, end_table)
308 document.warning("Can't find row " + str(row + 1))
310 end_row = find_end_of(document.body, begin_row, '<row', '</row>')
312 document.warning("Can't find end of row " + str(row + 1))
315 if (get_option_value(document.body[begin_row], 'caption') == 'true' and
316 get_option_value(document.body[begin_row], 'endfirsthead') != 'true' and
317 get_option_value(document.body[begin_row], 'endhead') != 'true' and
318 get_option_value(document.body[begin_row], 'endfoot') != 'true' and
319 get_option_value(document.body[begin_row], 'endlastfoot') != 'true'):
320 document.body[begin_row] = set_option_value(document.body[begin_row], 'caption', 'true", endfirsthead="true')
321 elif get_option_value(document.body[begin_row], 'caption') == 'true':
322 if get_option_value(document.body[begin_row], 'endfirsthead') == 'true':
323 document.body[begin_row] = set_option_value(document.body[begin_row], 'endfirsthead', 'false')
324 if get_option_value(document.body[begin_row], 'endhead') == 'true':
325 document.body[begin_row] = set_option_value(document.body[begin_row], 'endhead', 'false')
326 if get_option_value(document.body[begin_row], 'endfoot') == 'true':
327 document.body[begin_row] = set_option_value(document.body[begin_row], 'endfoot', 'false')
328 if get_option_value(document.body[begin_row], 'endlastfoot') == 'true':
329 document.body[begin_row] = set_option_value(document.body[begin_row], 'endlastfoot', 'false')
331 # since there could be a tabular inside this one, we
332 # cannot jump to end.
336 def convert_longtable_captions(document):
337 "Add a firsthead flag to caption rows"
338 handle_longtable_captions(document, True)
341 def revert_longtable_captions(document):
342 "remove head/foot flag from caption rows"
343 handle_longtable_captions(document, False)
346 def convert_use_packages(document):
347 "use_xxx yyy => use_package xxx yyy"
348 packages = ["amsmath", "esint", "mathdots", "mhchem", "undertilde"]
350 i = find_token(document.header, "\\use_%s" % p, 0)
352 value = get_value(document.header, "\\use_%s" % p, i)
353 document.header[i] = "\\use_package %s %s" % (p, value)
356 def revert_use_packages(document):
357 "use_package xxx yyy => use_xxx yyy"
358 packages = ["amsmath", "esint", "mathdots", "mhchem", "undertilde"]
359 # the order is arbitrary for the use_package version, and not all packages need to be given.
360 # Ensure a complete list and correct order (important for older LyX versions and especially lyx2lyx)
363 regexp = re.compile(r'(\\use_package\s+%s)' % p)
364 i = find_re(document.header, regexp, j)
366 value = get_value(document.header, "\\use_package %s" % p, i).split()[1]
367 del document.header[i]
369 document.header.insert(j, "\\use_%s %s" % (p, value))
373 def convert_use_mathtools(document):
374 "insert use_package mathtools"
375 i = find_token(document.header, "\\use_package", 0)
377 document.warning("Malformed LyX document: Can't find \\use_package.")
379 j = find_token(document.preamble, "\\usepackage{mathtools}", 0)
381 document.header.insert(i + 1, "\\use_package mathtools 0")
383 document.header.insert(i + 1, "\\use_package mathtools 2")
384 del document.preamble[j]
387 def revert_use_mathtools(document):
388 "remove use_package mathtools"
389 regexp = re.compile(r'(\\use_package\s+mathtools)')
390 i = find_re(document.header, regexp, 0)
391 value = "1" # default is auto
393 value = get_value(document.header, "\\use_package" , i).split()[1]
394 del document.header[i]
395 if value == "2": # on
396 add_to_preamble(document, ["\\usepackage{mathtools}"])
397 elif value == "1": # auto
398 commands = ["mathclap", "mathllap", "mathrlap", \
399 "lgathered", "rgathered", "vcentcolon", "dblcolon", \
400 "coloneqq", "Coloneqq", "coloneq", "Coloneq", "eqqcolon", \
401 "Eqqcolon", "eqcolon", "Eqcolon", "colonapprox", \
402 "Colonapprox", "colonsim", "Colonsim"]
405 i = find_token(document.body, '\\begin_inset Formula', i)
408 j = find_end_of_inset(document.body, i)
410 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
413 code = "\n".join(document.body[i:j])
415 if code.find("\\%s" % c) != -1:
416 add_to_preamble(document, ["\\usepackage{mathtools}"])
421 def convert_use_stmaryrd(document):
422 "insert use_package stmaryrd"
423 i = find_token(document.header, "\\use_package", 0)
425 document.warning("Malformed LyX document: Can't find \\use_package.")
427 j = find_token(document.preamble, "\\usepackage{stmaryrd}", 0)
429 document.header.insert(i + 1, "\\use_package stmaryrd 0")
431 document.header.insert(i + 1, "\\use_package stmaryrd 2")
432 del document.preamble[j]
435 def revert_use_stmaryrd(document):
436 "remove use_package stmaryrd"
437 regexp = re.compile(r'(\\use_package\s+stmaryrd)')
438 i = find_re(document.header, regexp, 0)
439 value = "1" # default is auto
441 value = get_value(document.header, "\\use_package" , i).split()[1]
442 del document.header[i]
443 if value == "2": # on
444 add_to_preamble(document, ["\\usepackage{stmaryrd}"])
445 elif value == "1": # auto
446 commands = ["shortleftarrow", "shortrightarrow", "shortuparrow", \
447 "shortdownarrow", "Yup", "Ydown", "Yleft", "Yright", \
448 "varcurlyvee", "varcurlywedge", "minuso", "baro", \
449 "sslash", "bbslash", "moo", "varotimes", "varoast", \
450 "varobar", "varodot", "varoslash", "varobslash", \
451 "varocircle", "varoplus", "varominus", "boxast", \
452 "boxbar", "boxslash", "boxbslash", "boxcircle", \
453 "boxbox", "boxempty", "merge", "vartimes", \
454 "fatsemi", "sswarrow", "ssearrow", "curlywedgeuparrow", \
455 "curlywedgedownarrow", "fatslash", "fatbslash", "lbag", \
456 "rbag", "varbigcirc", "leftrightarroweq", \
457 "curlyveedownarrow", "curlyveeuparrow", "nnwarrow", \
458 "nnearrow", "leftslice", "rightslice", "varolessthan", \
459 "varogreaterthan", "varovee", "varowedge", "talloblong", \
460 "interleave", "obar", "obslash", "olessthan", \
461 "ogreaterthan", "ovee", "owedge", "oblong", "inplus", \
462 "niplus", "nplus", "subsetplus", "supsetplus", \
463 "subsetpluseq", "supsetpluseq", "Lbag", "Rbag", \
464 "llbracket", "rrbracket", "llparenthesis", \
465 "rrparenthesis", "binampersand", "bindnasrepma", \
466 "trianglelefteqslant", "trianglerighteqslant", \
467 "ntrianglelefteqslant", "ntrianglerighteqslant", \
468 "llfloor", "rrfloor", "llceil", "rrceil", "arrownot", \
469 "Arrownot", "Mapstochar", "mapsfromchar", "Mapsfromchar", \
470 "leftrightarrowtriangle", "leftarrowtriangle", \
471 "rightarrowtriangle", \
472 "bigcurlyvee", "bigcurlywedge", "bigsqcap", "bigbox", \
473 "bigparallel", "biginterleave", "bignplus", \
474 "varcopyright", "longarrownot", "Longarrownot", \
475 "Mapsto", "mapsfrom", "Mapsfrom" "Longmapsto", \
476 "longmapsfrom", "Longmapsfrom"]
477 # commands provided by stmaryrd.sty but LyX uses other packages:
478 # boxdot lightning, bigtriangledown, bigtriangleup
482 i = find_token(document.body, '\\begin_inset Formula', i)
485 j = find_end_of_inset(document.body, i)
487 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
490 code = "\n".join(document.body[i:j])
492 if code.find("\\%s" % c) != -1:
493 add_to_preamble(document, ["\\usepackage{stmaryrd}"])
498 def convert_use_stackrel(document):
499 "insert use_package stackrel"
500 i = find_token(document.header, "\\use_package", 0)
502 document.warning("Malformed LyX document: Can't find \\use_package.")
504 j = find_token(document.preamble, "\\usepackage{stackrel}", 0)
506 document.header.insert(i + 1, "\\use_package stackrel 0")
508 document.header.insert(i + 1, "\\use_package stackrel 2")
509 del document.preamble[j]
512 def revert_use_stackrel(document):
513 "remove use_package stackrel"
514 regexp = re.compile(r'(\\use_package\s+stackrel)')
515 i = find_re(document.header, regexp, 0)
516 value = "1" # default is auto
518 value = get_value(document.header, "\\use_package" , i).split()[1]
519 del document.header[i]
520 if value == "2": # on
521 add_to_preamble(document, ["\\usepackage{stackrel}"])
522 elif value == "1": # auto
523 regcmd = re.compile(r'.*\\stackrel\s*\[')
526 i = find_token(document.body, '\\begin_inset Formula', i)
529 j = find_end_of_inset(document.body, i)
531 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
534 code = "\n".join(document.body[i:j])
535 if regcmd.match(code):
536 add_to_preamble(document, ["\\usepackage{stackrel}"])
541 def convert_cite_engine_type(document):
542 "Determine the \\cite_engine_type from the citation engine."
543 i = find_token(document.header, "\\cite_engine", 0)
546 engine = get_value(document.header, "\\cite_engine", i)
548 engine, type = engine.split("_")
550 type = {"basic": "numerical", "jurabib": "authoryear"}[engine]
551 document.header[i] = "\\cite_engine " + engine
552 document.header.insert(i + 1, "\\cite_engine_type " + type)
555 def revert_cite_engine_type(document):
556 "Natbib had the type appended with an underscore."
557 engine_type = "numerical"
558 i = find_token(document.header, "\\cite_engine_type" , 0)
560 document.warning("No \\cite_engine_type line. Assuming numerical.")
562 engine_type = get_value(document.header, "\\cite_engine_type", i)
563 del document.header[i]
565 # We are looking for the natbib citation engine
566 i = find_token(document.header, "\\cite_engine natbib", 0)
569 document.header[i] = "\\cite_engine natbib_" + engine_type
572 def revert_cancel(document):
573 "add cancel to the preamble if necessary"
574 commands = ["cancelto", "cancel", "bcancel", "xcancel"]
577 i = find_token(document.body, '\\begin_inset Formula', i)
580 j = find_end_of_inset(document.body, i)
582 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
585 code = "\n".join(document.body[i:j])
587 if code.find("\\%s" % c) != -1:
588 add_to_preamble(document, ["\\usepackage{cancel}"])
593 def revert_verbatim(document):
594 " Revert verbatim einvironments completely to TeX-code. "
597 subst_end = ['\end_layout', '', '\\begin_layout Plain Layout',
599 '\\begin_layout Plain Layout', '', '',
602 '\\end_layout', '', '\\end_inset',
603 '', '', '\\end_layout']
604 subst_begin = ['\\begin_layout Standard', '\\noindent',
605 '\\begin_inset ERT', 'status collapsed', '',
606 '\\begin_layout Plain Layout', '', '', '\\backslash',
608 '\\end_layout', '', '\\begin_layout Plain Layout', '']
610 i = find_token(document.body, "\\begin_layout Verbatim", i)
613 j = find_end_of_layout(document.body, i)
615 document.warning("Malformed lyx document: Can't find end of Verbatim layout")
618 # delete all line breaks insets (there are no other insets)
621 n = find_token(document.body, "\\begin_inset Newline newline", l)
623 n = find_token(document.body, "\\begin_inset Newline linebreak", l)
626 m = find_end_of_inset(document.body, n)
627 del(document.body[m:m+1])
628 document.body[n:n+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
631 # consecutive verbatim environments need to be connected
632 k = find_token(document.body, "\\begin_layout Verbatim", j)
633 if k == j + 2 and consecutive == False:
635 document.body[j:j+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
636 document.body[i:i+1] = subst_begin
638 if k == j + 2 and consecutive == True:
639 document.body[j:j+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
640 del(document.body[i:i+1])
642 if k != j + 2 and consecutive == True:
643 document.body[j:j+1] = subst_end
644 # the next paragraph must not be indented
645 document.body[j+19:j+19] = ['\\noindent']
646 del(document.body[i:i+1])
650 document.body[j:j+1] = subst_end
651 # the next paragraph must not be indented
652 document.body[j+19:j+19] = ['\\noindent']
653 document.body[i:i+1] = subst_begin
656 def revert_tipa(document):
657 " Revert native TIPA insets to mathed or ERT. "
660 i = find_token(document.body, "\\begin_inset IPA", i)
663 j = find_end_of_inset(document.body, i)
665 document.warning("Malformed lyx document: Can't find end of IPA inset")
669 n = find_token(document.body, "\\begin_layout", i, j)
671 document.warning("Malformed lyx document: IPA inset has no embedded layout")
674 m = find_end_of_layout(document.body, n)
676 document.warning("Malformed lyx document: Can't find end of embedded layout")
679 content = document.body[n+1:m]
680 p = find_token(document.body, "\\begin_layout", m, j)
681 if p != -1 or len(content) > 1:
683 content = document.body[i+1:j]
685 # IPA insets with multiple pars need to be wrapped by \begin{IPA}...\end{IPA}
686 document.body[i:j+1] = ['\\end_layout', '', '\\begin_layout Standard'] + put_cmd_in_ert("\\begin{IPA}") + ['\\end_layout'] + content + ['\\begin_layout Standard'] + put_cmd_in_ert("\\end{IPA}")
687 add_to_preamble(document, ["\\usepackage{tipa,tipx}"])
689 # single-par IPA insets can be reverted to mathed
690 document.body[i:j+1] = ["\\begin_inset Formula $\\text{\\textipa{" + content[0] + "}}$", "\\end_inset"]
694 def revert_cell_rotation(document):
695 "Revert cell rotations to TeX-code"
697 load_rotating = False
701 # first, let's find out if we need to do anything
702 i = find_token(document.body, '<cell ', i)
705 j = document.body[i].find('rotate="')
707 k = document.body[i].find('"', j + 8)
708 value = document.body[i][j + 8 : k]
710 rgx = re.compile(r' rotate="[^"]+?"')
711 # remove rotate option
712 document.body[i] = rgx.sub('', document.body[i])
714 rgx = re.compile(r' rotate="[^"]+?"')
715 document.body[i] = rgx.sub('rotate="true"', document.body[i])
717 rgx = re.compile(r' rotate="[^"]+?"')
719 # remove rotate option
720 document.body[i] = rgx.sub('', document.body[i])
722 document.body[i + 5 : i + 5] = \
723 put_cmd_in_ert("\\end{turn}")
724 document.body[i + 4 : i + 4] = \
725 put_cmd_in_ert("\\begin{turn}{" + value + "}")
731 add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"])
734 def convert_cell_rotation(document):
735 'Convert cell rotation statements from "true" to "90"'
739 # first, let's find out if we need to do anything
740 i = find_token(document.body, '<cell ', i)
743 j = document.body[i].find('rotate="true"')
745 rgx = re.compile(r'rotate="[^"]+?"')
746 # convert "true" to "90"
747 document.body[i] = rgx.sub('rotate="90"', document.body[i])
752 def revert_table_rotation(document):
753 "Revert table rotations to TeX-code"
755 load_rotating = False
759 # first, let's find out if we need to do anything
760 i = find_token(document.body, '<features ', i)
763 j = document.body[i].find('rotate="')
765 end_table = find_token(document.body, '</lyxtabular>', j)
766 k = document.body[i].find('"', j + 8)
767 value = document.body[i][j + 8 : k]
769 rgx = re.compile(r' rotate="[^"]+?"')
770 # remove rotate option
771 document.body[i] = rgx.sub('', document.body[i])
773 rgx = re.compile(r'rotate="[^"]+?"')
774 document.body[i] = rgx.sub('rotate="true"', document.body[i])
776 rgx = re.compile(r' rotate="[^"]+?"')
778 # remove rotate option
779 document.body[i] = rgx.sub('', document.body[i])
781 document.body[end_table + 3 : end_table + 3] = \
782 put_cmd_in_ert("\\end{turn}")
783 document.body[i - 2 : i - 2] = \
784 put_cmd_in_ert("\\begin{turn}{" + value + "}")
790 add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"])
793 def convert_table_rotation(document):
794 'Convert table rotation statements from "true" to "90"'
798 # first, let's find out if we need to do anything
799 i = find_token(document.body, '<features ', i)
802 j = document.body[i].find('rotate="true"')
804 rgx = re.compile(r'rotate="[^"]+?"')
805 # convert "true" to "90"
806 document.body[i] = rgx.sub('rotate="90"', document.body[i])
811 def convert_listoflistings(document):
812 'Convert ERT \lstlistoflistings to TOC lstlistoflistings inset'
813 # We can support roundtrip because the command is so simple
816 i = find_token(document.body, "\\begin_inset ERT", i)
819 j = find_end_of_inset(document.body, i)
821 document.warning("Malformed lyx document: Can't find end of ERT inset")
824 ert = get_ert(document.body, i)
825 if ert == "\\lstlistoflistings{}":
826 document.body[i:j] = ["\\begin_inset CommandInset toc", "LatexCommand lstlistoflistings", ""]
832 def revert_listoflistings(document):
833 'Convert TOC lstlistoflistings inset to ERT lstlistoflistings'
836 i = find_token(document.body, "\\begin_inset CommandInset toc", i)
839 if document.body[i+1] == "LatexCommand lstlistoflistings":
840 j = find_end_of_inset(document.body, i)
842 document.warning("Malformed lyx document: Can't find end of TOC inset")
845 subst = put_cmd_in_ert("\\lstlistoflistings{}")
846 document.body[i:j+1] = subst
847 add_to_preamble(document, ["\\usepackage{listings}"])
851 def convert_use_amssymb(document):
852 "insert use_package amssymb"
853 regexp = re.compile(r'(\\use_package\s+amsmath)')
854 i = find_re(document.header, regexp, 0)
856 document.warning("Malformed LyX document: Can't find \\use_package amsmath.")
858 value = get_value(document.header, "\\use_package" , i).split()[1]
861 useamsmath = int(value)
863 document.warning("Invalid \\use_package amsmath: " + value + ". Assuming auto.")
865 j = find_token(document.preamble, "\\usepackage{amssymb}", 0)
867 document.header.insert(i + 1, "\\use_package amssymb %d" % useamsmath)
869 document.header.insert(i + 1, "\\use_package amssymb 2")
870 del document.preamble[j]
873 def revert_use_amssymb(document):
874 "remove use_package amssymb"
875 regexp1 = re.compile(r'(\\use_package\s+amsmath)')
876 regexp2 = re.compile(r'(\\use_package\s+amssymb)')
877 i = find_re(document.header, regexp1, 0)
878 j = find_re(document.header, regexp2, 0)
879 value1 = "1" # default is auto
880 value2 = "1" # default is auto
882 value1 = get_value(document.header, "\\use_package" , i).split()[1]
884 value2 = get_value(document.header, "\\use_package" , j).split()[1]
885 del document.header[j]
886 if value1 != value2 and value2 == "2": # on
887 add_to_preamble(document, ["\\usepackage{amssymb}"])
890 def revert_ancientgreek(document):
891 "Set the document language for ancientgreek to greek"
893 if document.language == "ancientgreek":
894 document.language = "greek"
895 i = find_token(document.header, "\\language", 0)
897 document.header[i] = "\\language greek"
900 j = find_token(document.body, "\\lang ancientgreek", j)
904 document.body[j] = document.body[j].replace("\\lang ancientgreek", "\\lang greek")
908 def revert_languages(document):
909 "Set the document language for new supported languages to English"
912 "coptic", "divehi", "hindi", "kurmanji", "lao", "marathi", "occitan", "sanskrit",
913 "syriac", "tamil", "telugu", "urdu"
915 for n in range(len(languages)):
916 if document.language == languages[n]:
917 document.language = "english"
918 i = find_token(document.header, "\\language", 0)
920 document.header[i] = "\\language english"
922 while j < len(document.body):
923 j = find_token(document.body, "\\lang " + languages[n], j)
925 document.body[j] = document.body[j].replace("\\lang " + languages[n], "\\lang english")
928 j = len(document.body)
931 def convert_armenian(document):
932 "Use polyglossia and thus non-TeX fonts for Armenian"
934 if document.language == "armenian":
935 i = find_token(document.header, "\\use_non_tex_fonts", 0)
937 document.header[i] = "\\use_non_tex_fonts true"
940 def revert_armenian(document):
941 "Use ArmTeX and thus TeX fonts for Armenian"
943 if document.language == "armenian":
944 i = find_token(document.header, "\\use_non_tex_fonts", 0)
946 document.header[i] = "\\use_non_tex_fonts false"
949 def revert_libertine(document):
950 " Revert native libertine font definition to LaTeX "
952 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
953 i = find_token(document.header, "\\font_roman libertine", 0)
956 j = find_token(document.header, "\\font_osf true", 0)
959 preamble = "\\usepackage"
961 document.header[j] = "\\font_osf false"
963 preamble += "[lining]"
964 preamble += "{libertine-type1}"
965 add_to_preamble(document, [preamble])
966 document.header[i] = "\\font_roman default"
969 def revert_txtt(document):
970 " Revert native txtt font definition to LaTeX "
972 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
973 i = find_token(document.header, "\\font_typewriter txtt", 0)
975 preamble = "\\renewcommand{\\ttdefault}{txtt}"
976 add_to_preamble(document, [preamble])
977 document.header[i] = "\\font_typewriter default"
980 def revert_mathdesign(document):
981 " Revert native mathdesign font definition to LaTeX "
983 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
989 i = find_token(document.header, "\\font_roman", 0)
992 val = get_value(document.header, "\\font_roman", i)
993 if val in mathdesign_dict.keys():
994 preamble = "\\usepackage[%s" % mathdesign_dict[val]
996 j = find_token(document.header, "\\font_osf true", 0)
999 document.header[j] = "\\font_osf false"
1000 l = find_token(document.header, "\\font_sc true", 0)
1003 document.header[l] = "\\font_sc false"
1005 preamble += ",expert"
1006 preamble += "]{mathdesign}"
1007 add_to_preamble(document, [preamble])
1008 document.header[i] = "\\font_roman default"
1011 def revert_texgyre(document):
1012 " Revert native TeXGyre font definition to LaTeX "
1014 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1015 texgyre_fonts = ["tgadventor", "tgbonum", "tgchorus", "tgcursor", \
1016 "tgheros", "tgpagella", "tgschola", "tgtermes"]
1017 i = find_token(document.header, "\\font_roman", 0)
1019 val = get_value(document.header, "\\font_roman", i)
1020 if val in texgyre_fonts:
1021 preamble = "\\usepackage{%s}" % val
1022 add_to_preamble(document, [preamble])
1023 document.header[i] = "\\font_roman default"
1024 i = find_token(document.header, "\\font_sans", 0)
1026 val = get_value(document.header, "\\font_sans", i)
1027 if val in texgyre_fonts:
1028 preamble = "\\usepackage{%s}" % val
1029 add_to_preamble(document, [preamble])
1030 document.header[i] = "\\font_sans default"
1031 i = find_token(document.header, "\\font_typewriter", 0)
1033 val = get_value(document.header, "\\font_typewriter", i)
1034 if val in texgyre_fonts:
1035 preamble = "\\usepackage{%s}" % val
1036 add_to_preamble(document, [preamble])
1037 document.header[i] = "\\font_typewriter default"
1040 def revert_ipadeco(document):
1041 " Revert IPA decorations to ERT "
1044 i = find_token(document.body, "\\begin_inset IPADeco", i)
1047 end = find_end_of_inset(document.body, i)
1049 document.warning("Can't find end of inset at line " + str(i))
1052 line = document.body[i]
1053 rx = re.compile(r'\\begin_inset IPADeco (.*)$')
1055 decotype = m.group(1)
1056 if decotype != "toptiebar" and decotype != "bottomtiebar":
1057 document.warning("Invalid IPADeco type: " + decotype)
1060 blay = find_token(document.body, "\\begin_layout Plain Layout", i, end)
1062 document.warning("Can't find layout for inset at line " + str(i))
1065 bend = find_end_of_layout(document.body, blay)
1067 document.warning("Malformed LyX document: Could not find end of IPADeco inset's layout.")
1070 substi = ["\\begin_inset ERT", "status collapsed", "",
1071 "\\begin_layout Plain Layout", "", "", "\\backslash",
1072 decotype + "{", "\\end_layout", "", "\\end_inset"]
1073 substj = ["\\size default", "", "\\begin_inset ERT", "status collapsed", "",
1074 "\\begin_layout Plain Layout", "", "}", "\\end_layout", "", "\\end_inset"]
1075 # do the later one first so as not to mess up the numbering
1076 document.body[bend:end + 1] = substj
1077 document.body[i:blay + 1] = substi
1078 i = end + len(substi) + len(substj) - (end - bend) - (blay - i) - 2
1079 add_to_preamble(document, "\\usepackage{tipa}")
1082 def revert_ipachar(document):
1083 ' Revert \\IPAChar to ERT '
1086 while i < len(document.body):
1087 m = re.match(r'(.*)\\IPAChar \\(\w+\{\w+\})(.*)', document.body[i])
1091 ipachar = m.group(2)
1094 '\\begin_inset ERT',
1095 'status collapsed', '',
1096 '\\begin_layout Standard',
1097 '', '', '\\backslash',
1102 document.body[i: i+1] = subst
1107 add_to_preamble(document, "\\usepackage{tone}")
1110 def revert_minionpro(document):
1111 " Revert native MinionPro font definition to LaTeX "
1113 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1114 i = find_token(document.header, "\\font_roman minionpro", 0)
1117 j = find_token(document.header, "\\font_osf true", 0)
1120 preamble = "\\usepackage"
1122 document.header[j] = "\\font_osf false"
1125 preamble += "{MinionPro}"
1126 add_to_preamble(document, [preamble])
1127 document.header[i] = "\\font_roman default"
1130 def revert_mathfonts(document):
1131 " Revert native math font definitions to LaTeX "
1133 i = find_token(document.header, "\\font_math", 0)
1136 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1137 val = get_value(document.header, "\\font_math", i)
1138 if val == "eulervm":
1139 add_to_preamble(document, "\\usepackage{eulervm}")
1140 elif val == "default":
1142 "lmodern": "\\renewcommand{\\rmdefault}{lmr}",
1143 "minionpro": "\\usepackage[onlytext,lf]{MinionPro}",
1144 "minionpro-osf": "\\usepackage[onlytext]{MinionPro}",
1145 "palatino": "\\renewcommand{\\rmdefault}{ppl}",
1146 "palatino-osf": "\\renewcommand{\\rmdefault}{pplj}",
1147 "times": "\\renewcommand{\\rmdefault}{ptm}",
1148 "utopia": "\\renewcommand{\\rmdefault}{futs}",
1149 "utopia-osf": "\\renewcommand{\\rmdefault}{futj}",
1151 j = find_token(document.header, "\\font_roman", 0)
1153 rm = get_value(document.header, "\\font_roman", j)
1154 k = find_token(document.header, "\\font_osf true", 0)
1157 if rm in mathfont_dict.keys():
1158 add_to_preamble(document, mathfont_dict[rm])
1159 document.header[j] = "\\font_roman default"
1161 document.header[k] = "\\font_osf false"
1162 del document.header[i]
1165 def revert_mdnomath(document):
1166 " Revert mathdesign and fourier without math "
1168 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1170 "md-charter": "mdbch",
1171 "md-utopia": "mdput",
1172 "md-garamond": "mdugm"
1174 i = find_token(document.header, "\\font_roman", 0)
1177 val = get_value(document.header, "\\font_roman", i)
1178 if val in mathdesign_dict.keys():
1179 j = find_token(document.header, "\\font_math", 0)
1181 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1182 mval = get_value(document.header, "\\font_math", j)
1183 if mval == "default":
1184 document.header[i] = "\\font_roman default"
1185 add_to_preamble(document, "\\renewcommand{\\rmdefault}{%s}" % mathdesign_dict[val])
1187 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1190 def convert_mdnomath(document):
1191 " Change mathdesign font name "
1193 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1195 "mdbch": "md-charter",
1196 "mdput": "md-utopia",
1197 "mdugm": "md-garamond"
1199 i = find_token(document.header, "\\font_roman", 0)
1202 val = get_value(document.header, "\\font_roman", i)
1203 if val in mathdesign_dict.keys():
1204 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1207 def revert_newtxmath(document):
1208 " Revert native newtxmath definitions to LaTeX "
1210 i = find_token(document.header, "\\font_math", 0)
1213 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1214 val = get_value(document.header, "\\font_math", i)
1216 "libertine-ntxm": "\\usepackage[libertine]{newtxmath}",
1217 "minion-ntxm": "\\usepackage[minion]{newtxmath}",
1218 "newtxmath": "\\usepackage{newtxmath}",
1220 if val in mathfont_dict.keys():
1221 add_to_preamble(document, mathfont_dict[val])
1222 document.header[i] = "\\font_math auto"
1225 def revert_biolinum(document):
1226 " Revert native biolinum font definition to LaTeX "
1228 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1229 i = find_token(document.header, "\\font_sans biolinum", 0)
1232 j = find_token(document.header, "\\font_osf true", 0)
1235 preamble = "\\usepackage"
1238 preamble += "{biolinum-type1}"
1239 add_to_preamble(document, [preamble])
1240 document.header[i] = "\\font_sans default"
1243 def revert_uop(document):
1244 " Revert native URW Classico (Optima) font definition to LaTeX "
1246 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1247 i = find_token(document.header, "\\font_sans uop", 0)
1249 preamble = "\\renewcommand{\\sfdefault}{uop}"
1250 add_to_preamble(document, [preamble])
1251 document.header[i] = "\\font_sans default"
1254 def convert_latexargs(document):
1255 " Convert InsetArgument to new syntax "
1257 if find_token(document.body, "\\begin_inset Argument", 0) == -1:
1261 # A list of layouts (document classes) with only optional or no arguments.
1262 # These can be safely converted to the new syntax
1263 # (I took the liberty to add some of my personal layouts/modules here; JSP)
1264 safe_layouts = ["aa", "aapaper", "aastex", "achemso", "acmsiggraph", "AEA",
1265 "agu-dtd", "agums", "agutex", "amsart", "amsbook", "apa",
1266 "arab-article", "armenian-article", "article-beamer", "article",
1267 "beamer", "book", "broadway", "chess", "cl2emult", "ctex-article",
1268 "ctex-book", "ctex-report", "dinbrief", "docbook-book", "docbook-chapter",
1269 "docbook", "docbook-section", "doublecol-new", "dtk", "ectaart", "egs",
1270 "elsarticle", "elsart", "entcs", "europecv", "extarticle", "extbook",
1271 "extletter", "extreport", "foils", "frletter", "g-brief2", "g-brief",
1272 "heb-article", "heb-letter", "hollywood", "IEEEtran", "ijmpc", "ijmpd",
1273 "iopart", "isprs", "jarticle", "jasatex", "jbook", "jgrga", "jreport",
1274 "jsarticle", "jsbeamer", "jsbook", "jss", "kluwer", "latex8", "letter", "lettre",
1275 "literate-article", "literate-book", "literate-report", "llncs", "ltugboat",
1276 "memoir", "moderncv", "mwart", "mwbk", "mwrep", "paper", "powerdot",
1277 "recipebook", "report", "revtex4", "revtex", "scrartcl", "scrarticle-beamer",
1278 "scrbook", "scrlettr", "scrlttr2", "scrreprt", "seminar", "siamltex",
1279 "sigplanconf", "simplecv", "singlecol", "singlecol-new", "slides", "spie",
1280 "svglobal3", "svglobal", "svjog", "svmono", "svmult", "svprobth", "tarticle",
1281 "tbook", "treport", "tufte-book", "tufte-handout"]
1282 # A list of "safe" modules, same as above
1283 safe_modules = ["biblatex", "beameraddons", "beamersession", "braille", "customHeadersFooters",
1284 "endnotes", "enumitem", "eqs-within-sections", "figs-within-sections", "fix-cm",
1285 "fixltx2e", "foottoend", "hanging", "jscharstyles", "knitr", "lilypond",
1286 "linguistics", "linguisticx", "logicalmkup", "minimalistic", "nomindex", "noweb",
1287 "pdfcomment", "sweave", "tabs-within-sections", "theorems-ams-bytype",
1288 "theorems-ams-extended-bytype", "theorems-ams-extended", "theorems-ams", "theorems-bytype",
1289 "theorems-chap-bytype", "theorems-chap", "theorems-named", "theorems-sec-bytype",
1290 "theorems-sec", "theorems-starred", "theorems-std", "todonotes"]
1291 # Modules we need to take care of
1292 caveat_modules = ["initials"]
1293 # information about the relevant styles in caveat_modules (number of opt and req args)
1294 # use this if we get more caveat_modules. For now, use hard coding (see below).
1295 # initials = [{'Layout' : 'Initial', 'opt' : 1, 'req' : 1}]
1297 # Is this a known safe layout?
1298 safe_layout = document.textclass in safe_layouts
1300 document.warning("Lyx2lyx knows nothing about textclass '%s'. "
1301 "Please check if short title insets have been converted correctly."
1302 % document.textclass)
1303 # Do we use unsafe or unknown modules
1304 mods = document.get_module_list()
1305 unknown_modules = False
1306 used_caveat_modules = list()
1308 if mod in safe_modules:
1310 if mod in caveat_modules:
1311 used_caveat_modules.append(mod)
1313 unknown_modules = True
1314 document.warning("Lyx2lyx knows nothing about module '%s'. "
1315 "Please check if short title insets have been converted correctly."
1320 i = find_token(document.body, "\\begin_inset Argument", i)
1324 if not safe_layout or unknown_modules:
1325 # We cannot do more here since we have no access to this layout.
1326 # InsetArgument itself will do the real work
1327 # (see InsetArgument::updateBuffer())
1328 document.body[i] = "\\begin_inset Argument 999"
1332 # Find containing paragraph layout
1333 parent = get_containing_layout(document.body, i)
1335 document.warning("Malformed lyx document: Can't find parent paragraph layout")
1342 if len(used_caveat_modules) > 0:
1343 # We know for now that this must be the initials module with the Initial layout
1344 # If we get more such modules, we need some automating.
1345 if parent[0] == "Initial":
1346 # Layout has 1 opt and 1 req arg.
1347 # Count the actual arguments
1349 for p in range(parbeg, parend):
1350 if document.body[p] == "\\begin_inset Argument":
1355 # Collect all arguments in this paragraph
1357 for p in range(parbeg, parend):
1358 if document.body[p] == "\\begin_inset Argument":
1360 if allowed_opts != -1:
1361 # We have less arguments than opt + required.
1362 # required must take precedence.
1363 if argnr > allowed_opts and argnr < first_req:
1365 document.body[p] = "\\begin_inset Argument %d" % argnr
1369 def revert_latexargs(document):
1370 " Revert InsetArgument to old syntax "
1373 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
1376 # Search for Argument insets
1377 i = find_token(document.body, "\\begin_inset Argument", i)
1380 m = rx.match(document.body[i])
1382 # No ID: inset already reverted
1385 # Find containing paragraph layout
1386 parent = get_containing_layout(document.body, i)
1388 document.warning("Malformed lyx document: Can't find parent paragraph layout")
1393 realparbeg = parent[3]
1394 # Collect all arguments in this paragraph
1396 for p in range(parbeg, parend):
1397 m = rx.match(document.body[p])
1399 val = int(m.group(1))
1400 j = find_end_of_inset(document.body, p)
1401 # Revert to old syntax
1402 document.body[p] = "\\begin_inset Argument"
1404 document.warning("Malformed lyx document: Can't find end of Argument inset")
1407 args[val] = document.body[p : j + 1]
1409 realparend = realparend - len(document.body[p : j + 1])
1410 # Remove arg inset at this position
1411 del document.body[p : j + 1]
1414 # Now sort the arg insets
1416 for f in sorted(args):
1419 # Insert the sorted arg insets at paragraph begin
1420 document.body[realparbeg : realparbeg] = subst
1422 i = realparbeg + 1 + len(subst)
1425 def revert_Argument_to_TeX_brace(document, line, n, nmax, environment):
1427 Reverts an InsetArgument to TeX-code
1429 revert_Argument_to_TeX_brace(document, LineOfBeginLayout, StartArgument, EndArgument, isEnvironment)
1430 LineOfBeginLayout is the line of the \begin_layout statement
1431 StartArgument is the number of the first argument that needs to be converted
1432 EndArgument is the number of the last argument that needs to be converted or the last defined one
1433 isEnvironment must be true, if the layout id for a LaTeX environment
1436 while lineArg != -1 and n < nmax + 1:
1437 lineArg = find_token(document.body, "\\begin_inset Argument " + str(n), line)
1439 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", lineArg)
1440 # we have to assure that no other inset is in the Argument
1441 beginInset = find_token(document.body, "\\begin_inset", beginPlain)
1442 endInset = find_token(document.body, "\\end_inset", beginPlain)
1445 while beginInset < endInset and beginInset != -1:
1446 beginInset = find_token(document.body, "\\begin_inset", k)
1447 endInset = find_token(document.body, "\\end_inset", l)
1450 if environment == False:
1451 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}{")
1452 del(document.body[lineArg : beginPlain + 1])
1454 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}")
1455 document.body[lineArg : beginPlain + 1] = put_cmd_in_ert("{")
1459 def revert_IEEEtran(document):
1461 Reverts InsetArgument of
1464 Biography without photo
1467 if document.textclass == "IEEEtran":
1473 i = find_token(document.body, "\\begin_layout Page headings", i)
1475 revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1478 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1480 revert_Argument_to_TeX_brace(document, j, 1, 1, True)
1483 k = find_token(document.body, "\\begin_layout Biography", k)
1484 kA = find_token(document.body, "\\begin_layout Biography without photo", k)
1485 if k == kA and k != -1:
1489 # start with the second argument, therefore 2
1490 revert_Argument_to_TeX_brace(document, k, 2, 2, True)
1492 if i == -1 and j == -1 and k == -1:
1496 def convert_TeX_brace_to_Argument(document, line, n, nmax, inset, environment):
1498 Converts TeX code for mandatory arguments to an InsetArgument
1499 The conversion of TeX code for optional arguments must be done with another routine
1500 !!! Be careful if the braces are different in your case as expected here:
1501 - "}{" separates mandatory arguments of commands
1502 - "}" + "{" separates mandatory arguments of commands
1503 - "}" + " " + "{" separates mandatory arguments of commands
1504 - { and } surround a mandatory argument of an environment
1506 convert_TeX_brace_to_Argument(document, LineOfBeginLayout/Inset, StartArgument, EndArgument, isInset, isEnvironment)
1507 LineOfBeginLayout/Inset is the line of the \begin_layout or \begin_inset statement
1508 StartArgument is the number of the first ERT that needs to be converted
1509 EndArgument is the number of the last ERT that needs to be converted
1510 isInset must be true, if braces inside an InsetLayout needs to be converted
1511 isEnvironment must be true, if the layout is for a LaTeX environment
1513 Todo: this routine can currently handle only one mandatory argument of environments
1518 while lineERT != -1 and n < nmax + 1:
1519 lineERT = find_token(document.body, "\\begin_inset ERT", lineERT)
1520 if environment == False and lineERT != -1:
1521 bracePair = find_token(document.body, "}{", lineERT)
1522 # assure that the "}{" is in this ERT
1523 if bracePair == lineERT + 5:
1524 end = find_token(document.body, "\\end_inset", bracePair)
1525 document.body[lineERT : end + 1] = ["\\end_layout", "", "\\end_inset"]
1527 # in the case that n > 1 we have optional arguments before
1528 # therefore detect them if any
1530 # first check if there is an argument
1531 lineArg = find_token(document.body, "\\begin_inset Argument", line)
1532 if lineArg < lineERT and lineArg != -1:
1533 # we have an argument, so now search backwards for its end
1534 # we must now assure that we don't find other insets like e.g. a newline
1535 endInsetArg = lineERT
1536 endLayoutArg = endInsetArg
1537 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
1538 endInsetArg = endInsetArg - 1
1539 endLayoutArg = endInsetArg
1540 endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
1541 endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
1542 line = endInsetArg + 1
1544 document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1546 document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1548 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1552 # now check the case that we have "}" + "{" in two ERTs
1554 endBrace = find_token(document.body, "}", lineERT)
1555 if endBrace == lineERT + 5:
1556 beginBrace = find_token(document.body, "{", endBrace)
1557 # assure that the ERTs are consecutive (11 or 12 depending if there is a space between the ERTs or not)
1558 if beginBrace == endBrace + 11 or beginBrace == endBrace + 12:
1559 end = find_token(document.body, "\\end_inset", beginBrace)
1560 document.body[lineERT : end + 1] = ["\\end_layout", "", "\\end_inset"]
1562 # in the case that n > 1 we have optional arguments before
1563 # therefore detect them if any
1565 # first check if there is an argument
1566 lineArg = find_token(document.body, "\\begin_inset Argument", line)
1567 if lineArg < lineERT and lineArg != -1:
1568 # we have an argument, so now search backwards for its end
1569 # we must now assure that we don't find other insets like e.g. a newline
1570 endInsetArg = lineERT
1571 endLayoutArg = endInsetArg
1572 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
1573 endInsetArg = endInsetArg - 1
1574 endLayoutArg = endInsetArg
1575 endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
1576 endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
1577 line = endInsetArg + 1
1579 document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1581 document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1583 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1586 # set the line where the next argument will be inserted
1587 if beginBrace == endBrace + 11:
1592 lineERT = lineERT + 1
1593 if environment == True and lineERT != -1:
1594 opening = find_token(document.body, "{", lineERT)
1595 if opening == lineERT + 5: # assure that the "{" is in this ERT
1596 end = find_token(document.body, "\\end_inset", opening)
1597 document.body[lineERT : end + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1599 lineERT2 = find_token(document.body, "\\begin_inset ERT", lineERT)
1600 closing = find_token(document.body, "}", lineERT2)
1601 if closing == lineERT2 + 5: # assure that the "}" is in this ERT
1602 end2 = find_token(document.body, "\\end_inset", closing)
1603 document.body[lineERT2 : end2 + 1] = ["\\end_layout", "", "\\end_inset"]
1605 lineERT = lineERT + 1
1608 def convert_IEEEtran(document):
1613 Biography without photo
1616 if document.textclass == "IEEEtran":
1622 i = find_token(document.body, "\\begin_layout Page headings", i)
1624 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1627 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1629 convert_TeX_brace_to_Argument(document, j, 1, 1, False, True)
1632 # assure that we don't handle Biography Biography without photo
1633 k = find_token(document.body, "\\begin_layout Biography", k)
1634 kA = find_token(document.body, "\\begin_layout Biography without photo", k - 1)
1635 if k == kA and k != -1:
1639 # the argument we want to convert is the second one
1640 convert_TeX_brace_to_Argument(document, k, 2, 2, False, True)
1642 if i == -1 and j == -1 and k == -1:
1646 def revert_AASTeX(document):
1647 " Reverts InsetArgument of Altaffilation to TeX-code "
1648 if document.textclass == "aastex":
1652 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1654 revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1660 def convert_AASTeX(document):
1661 " Converts ERT of Altaffilation to InsetArgument "
1662 if document.textclass == "aastex":
1666 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1668 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1674 def revert_AGUTeX(document):
1675 " Reverts InsetArgument of Author affiliation to TeX-code "
1676 if document.textclass == "agutex":
1680 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1682 revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1688 def convert_AGUTeX(document):
1689 " Converts ERT of Author affiliation to InsetArgument "
1690 if document.textclass == "agutex":
1694 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1696 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1702 def revert_IJMP(document):
1703 " Reverts InsetArgument of MarkBoth to TeX-code "
1704 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1708 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1710 revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1716 def convert_IJMP(document):
1717 " Converts ERT of MarkBoth to InsetArgument "
1718 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1722 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1724 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1730 def revert_SIGPLAN(document):
1731 " Reverts InsetArgument of MarkBoth to TeX-code "
1732 if document.textclass == "sigplanconf":
1737 i = find_token(document.body, "\\begin_layout Conference", i)
1739 revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1742 j = find_token(document.body, "\\begin_layout Author", j)
1744 revert_Argument_to_TeX_brace(document, j, 1, 2, False)
1746 if i == -1 and j == -1:
1750 def convert_SIGPLAN(document):
1751 " Converts ERT of MarkBoth to InsetArgument "
1752 if document.textclass == "sigplanconf":
1757 i = find_token(document.body, "\\begin_layout Conference", i)
1759 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1762 j = find_token(document.body, "\\begin_layout Author", j)
1764 convert_TeX_brace_to_Argument(document, j, 1, 2, False, False)
1766 if i == -1 and j == -1:
1770 def revert_SIGGRAPH(document):
1771 " Reverts InsetArgument of Flex CRcat to TeX-code "
1772 if document.textclass == "acmsiggraph":
1776 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1778 revert_Argument_to_TeX_brace(document, i, 1, 3, False)
1784 def convert_SIGGRAPH(document):
1785 " Converts ERT of Flex CRcat to InsetArgument "
1786 if document.textclass == "acmsiggraph":
1790 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1792 convert_TeX_brace_to_Argument(document, i, 1, 3, True, False)
1798 def revert_EuropeCV(document):
1799 " Reverts InsetArgument of Flex CRcat to TeX-code "
1800 if document.textclass == "europecv":
1807 i = find_token(document.body, "\\begin_layout Item", i)
1809 revert_Argument_to_TeX_brace(document, i, 2, 2, False)
1812 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1814 revert_Argument_to_TeX_brace(document, j, 2, 2, False)
1817 k = find_token(document.body, "\\begin_layout Language", k)
1819 revert_Argument_to_TeX_brace(document, k, 2, 6, False)
1822 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1824 revert_Argument_to_TeX_brace(document, m, 2, 6, False)
1826 if i == -1 and j == -1 and k == -1 and m == -1:
1830 def convert_EuropeCV(document):
1831 " Converts ERT of Flex CRcat to InsetArgument "
1832 if document.textclass == "europecv":
1839 i = find_token(document.body, "\\begin_layout Item", i)
1841 convert_TeX_brace_to_Argument(document, i, 2, 2, False, False)
1844 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1846 convert_TeX_brace_to_Argument(document, j, 2, 2, False, False)
1849 k = find_token(document.body, "\\begin_layout Language", k)
1851 convert_TeX_brace_to_Argument(document, k, 2, 6, False, False)
1854 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1856 convert_TeX_brace_to_Argument(document, m, 2, 6, False, False)
1858 if i == -1 and j == -1 and k == -1 and m == -1:
1862 def revert_literate(document):
1863 " Revert Literate document to old format "
1864 if del_token(document.header, "noweb", 0):
1865 document.textclass = "literate-" + document.textclass
1868 i = find_token(document.body, "\\begin_layout Chunk", i)
1871 document.body[i] = "\\begin_layout Scrap"
1875 def convert_literate(document):
1876 " Convert Literate document to new format"
1877 i = find_token(document.header, "\\textclass", 0)
1878 if (i != -1) and "literate-" in document.header[i]:
1879 document.textclass = document.header[i].replace("\\textclass literate-", "")
1880 j = find_token(document.header, "\\begin_modules", 0)
1882 document.header.insert(j + 1, "noweb")
1884 document.header.insert(i + 1, "\\end_modules")
1885 document.header.insert(i + 1, "noweb")
1886 document.header.insert(i + 1, "\\begin_modules")
1889 i = find_token(document.body, "\\begin_layout Scrap", i)
1892 document.body[i] = "\\begin_layout Chunk"
1896 def revert_itemargs(document):
1897 " Reverts \\item arguments to TeX-code "
1900 i = find_token(document.body, "\\begin_inset Argument item:", i)
1903 j = find_end_of_inset(document.body, i)
1904 # Find containing paragraph layout
1905 parent = get_containing_layout(document.body, i)
1907 document.warning("Malformed lyx document: Can't find parent paragraph layout")
1911 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
1912 endPlain = find_end_of_layout(document.body, beginPlain)
1913 content = document.body[beginPlain + 1 : endPlain]
1914 del document.body[i:j+1]
1915 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
1916 document.body[parbeg : parbeg] = subst
1920 def revert_garamondx_newtxmath(document):
1921 " Revert native garamond newtxmath definition to LaTeX "
1923 i = find_token(document.header, "\\font_math", 0)
1926 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1927 val = get_value(document.header, "\\font_math", i)
1928 if val == "garamondx-ntxm":
1929 add_to_preamble(document, "\\usepackage[garamondx]{newtxmath}")
1930 document.header[i] = "\\font_math auto"
1933 def revert_garamondx(document):
1934 " Revert native garamond font definition to LaTeX "
1936 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1937 i = find_token(document.header, "\\font_roman garamondx", 0)
1940 j = find_token(document.header, "\\font_osf true", 0)
1943 preamble = "\\usepackage"
1945 preamble += "[osfI]"
1946 preamble += "{garamondx}"
1947 add_to_preamble(document, [preamble])
1948 document.header[i] = "\\font_roman default"
1951 def convert_beamerargs(document):
1952 " Converts beamer arguments to new layout "
1954 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
1955 if document.textclass not in beamer_classes:
1958 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
1959 list_layouts = ["Itemize", "Enumerate", "Description"]
1960 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
1964 i = find_token(document.body, "\\begin_inset Argument", i)
1967 # Find containing paragraph layout
1968 parent = get_containing_layout(document.body, i)
1970 document.warning("Malformed lyx document: Can't find parent paragraph layout")
1975 layoutname = parent[0]
1976 for p in range(parbeg, parend):
1977 if layoutname in shifted_layouts:
1978 m = rx.match(document.body[p])
1980 argnr = int(m.group(1))
1982 document.body[p] = "\\begin_inset Argument %d" % argnr
1983 if layoutname == "AgainFrame":
1984 m = rx.match(document.body[p])
1986 document.body[p] = "\\begin_inset Argument 3"
1987 if document.body[p + 4] == "\\begin_inset ERT":
1988 if document.body[p + 9].startswith("<"):
1989 # This is an overlay specification
1991 document.body[p + 9] = document.body[p + 9][1:]
1992 if document.body[p + 9].endswith(">"):
1994 document.body[p + 9] = document.body[p + 9][:-1]
1996 document.body[p] = "\\begin_inset Argument 2"
1997 if layoutname in list_layouts:
1998 m = rx.match(document.body[p])
2000 if m.group(1) == "1":
2001 if document.body[p + 4] == "\\begin_inset ERT":
2002 if document.body[p + 9].startswith("<"):
2003 # This is an overlay specification
2005 document.body[p + 9] = document.body[p + 9][1:]
2006 if document.body[p + 9].endswith(">"):
2008 document.body[p + 9] = document.body[p + 9][:-1]
2009 elif layoutname != "Itemize":
2011 document.body[p] = "\\begin_inset Argument 2"
2015 def convert_againframe_args(document):
2016 " Converts beamer AgainFrame to new layout "
2018 # FIXME: This currently only works if the arguments are in one single ERT
2020 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2021 if document.textclass not in beamer_classes:
2026 i = find_token(document.body, "\\begin_layout AgainFrame", i)
2029 parent = get_containing_layout(document.body, i)
2031 document.warning("Wrong parent layout!")
2035 if document.body[parbeg] == "\\begin_inset ERT":
2036 ertcont = parbeg + 5
2037 if document.body[ertcont].startswith("[<"):
2038 # This is a default overlay specification
2040 document.body[ertcont] = document.body[ertcont][2:]
2041 if document.body[ertcont].endswith(">]"):
2043 document.body[ertcont] = document.body[ertcont][:-2]
2044 elif document.body[ertcont].endswith("]"):
2046 tok = document.body[ertcont].find('>][')
2048 subst = [document.body[ertcont][:tok],
2049 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2050 'status collapsed', '', '\\begin_layout Plain Layout',
2051 document.body[ertcont][tok + 3:-1]]
2052 document.body[ertcont : ertcont + 1] = subst
2053 # Convert to ArgInset
2054 document.body[parbeg] = "\\begin_inset Argument 2"
2057 elif document.body[ertcont].startswith("<"):
2058 # This is an overlay specification
2060 document.body[ertcont] = document.body[ertcont][1:]
2061 if document.body[ertcont].endswith(">"):
2063 document.body[ertcont] = document.body[ertcont][:-1]
2064 # Convert to ArgInset
2065 document.body[parbeg] = "\\begin_inset Argument 1"
2066 elif document.body[ertcont].endswith(">]"):
2068 tok = document.body[ertcont].find('>[<')
2070 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2071 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2072 'status collapsed', '', '\\begin_layout Plain Layout',
2073 document.body[ertcont][tok + 3:-2]]
2074 # Convert to ArgInset
2075 document.body[parbeg] = "\\begin_inset Argument 1"
2076 elif document.body[ertcont].endswith("]"):
2078 tok = document.body[ertcont].find('>[<')
2081 tokk = document.body[ertcont].find('>][')
2083 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2084 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2085 'status collapsed', '', '\\begin_layout Plain Layout',
2086 document.body[ertcont][tok + 3:tokk],
2087 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2088 'status collapsed', '', '\\begin_layout Plain Layout',
2089 document.body[ertcont][tokk + 3:-1]]
2091 tokk = document.body[ertcont].find('>[')
2093 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tokk],
2094 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2095 'status collapsed', '', '\\begin_layout Plain Layout',
2096 document.body[ertcont][tokk + 2:-1]]
2097 # Convert to ArgInset
2098 document.body[parbeg] = "\\begin_inset Argument 1"
2101 elif document.body[ertcont].startswith("["):
2102 # This is an ERT option
2104 document.body[ertcont] = document.body[ertcont][1:]
2105 if document.body[ertcont].endswith("]"):
2107 document.body[ertcont] = document.body[ertcont][:-1]
2108 # Convert to ArgInset
2109 document.body[parbeg] = "\\begin_inset Argument 3"
2115 def convert_corollary_args(document):
2116 " Converts beamer corrolary-style ERT arguments native InsetArgs "
2118 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2119 if document.textclass not in beamer_classes:
2122 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2123 for lay in corollary_layouts:
2126 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2129 parent = get_containing_layout(document.body, i)
2131 document.warning("Wrong parent layout!")
2135 if document.body[parbeg] == "\\begin_inset ERT":
2136 ertcont = parbeg + 5
2137 if document.body[ertcont].startswith("<"):
2138 # This is an overlay specification
2140 document.body[ertcont] = document.body[ertcont][1:]
2141 if document.body[ertcont].endswith(">"):
2143 document.body[ertcont] = document.body[ertcont][:-1]
2144 elif document.body[ertcont].endswith("]"):
2146 tok = document.body[ertcont].find('>[')
2148 subst = [document.body[ertcont][:tok],
2149 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2150 'status collapsed', '', '\\begin_layout Plain Layout',
2151 document.body[ertcont][tok + 2:-1]]
2152 document.body[ertcont : ertcont + 1] = subst
2153 # Convert to ArgInset
2154 document.body[parbeg] = "\\begin_inset Argument 1"
2157 elif document.body[ertcont].startswith("["):
2158 # This is an ERT option
2160 document.body[ertcont] = document.body[ertcont][1:]
2161 if document.body[ertcont].endswith("]"):
2163 document.body[ertcont] = document.body[ertcont][:-1]
2164 # Convert to ArgInset
2165 document.body[parbeg] = "\\begin_inset Argument 2"
2172 def convert_quote_args(document):
2173 " Converts beamer quote style ERT args to native InsetArgs "
2175 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2176 if document.textclass not in beamer_classes:
2179 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2180 for lay in quote_layouts:
2183 i = find_token(document.body, "\\begin_layout " + lay, i)
2186 parent = get_containing_layout(document.body, i)
2188 document.warning("Wrong parent layout!")
2192 if document.body[parbeg] == "\\begin_inset ERT":
2193 if document.body[i + 6].startswith("<"):
2194 # This is an overlay specification
2196 document.body[i + 6] = document.body[i + 6][1:]
2197 if document.body[i + 6].endswith(">"):
2199 document.body[i + 6] = document.body[i + 6][:-1]
2200 # Convert to ArgInset
2201 document.body[i + 1] = "\\begin_inset Argument 1"
2205 def revert_beamerargs(document):
2206 " Reverts beamer arguments to old layout "
2208 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2209 if document.textclass not in beamer_classes:
2213 list_layouts = ["Itemize", "Enumerate", "Description"]
2214 headings = ["Part", "Section", "Section*", "Subsection", "Subsection*",
2215 "Subsubsection", "Subsubsection*", "FrameSubtitle", "NoteItem"]
2216 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2217 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2218 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2221 i = find_token(document.body, "\\begin_inset Argument", i)
2224 # Find containing paragraph layout
2225 parent = get_containing_layout(document.body, i)
2227 document.warning("Malformed lyx document: Can't find parent paragraph layout")
2232 realparbeg = parent[3]
2233 layoutname = parent[0]
2235 for p in range(parbeg, parend):
2239 if layoutname in headings:
2240 m = rx.match(document.body[p])
2244 # Find containing paragraph layout
2245 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2246 endPlain = find_end_of_layout(document.body, beginPlain)
2247 endInset = find_end_of_inset(document.body, p)
2248 argcontent = document.body[beginPlain + 1 : endPlain]
2250 realparend = realparend - len(document.body[p : endInset + 1])
2252 del document.body[p : endInset + 1]
2253 if layoutname == "FrameSubtitle":
2254 pre = put_cmd_in_ert("\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2255 elif layoutname == "NoteItem":
2256 pre = put_cmd_in_ert("\\note<") + argcontent + put_cmd_in_ert(">[item]")
2257 elif layoutname.endswith('*'):
2258 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower()[:-1] + "<") + argcontent + put_cmd_in_ert(">*")
2260 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2261 secarg = find_token(document.body, "\\begin_inset Argument 2", parbeg, parend)
2263 # Find containing paragraph layout
2264 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", secarg)
2265 endPlain = find_end_of_layout(document.body, beginPlain)
2266 endInset = find_end_of_inset(document.body, secarg)
2267 argcontent = document.body[beginPlain + 1 : endPlain]
2269 realparend = realparend - len(document.body[secarg : endInset + 1])
2270 del document.body[secarg : endInset + 1]
2271 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2272 pre += put_cmd_in_ert("{")
2273 document.body[parbeg] = "\\begin_layout Standard"
2274 document.body[realparbeg : realparbeg] = pre
2275 pe = find_end_of_layout(document.body, parbeg)
2276 post = put_cmd_in_ert("}")
2277 document.body[pe : pe] = post
2278 realparend += len(pre) + len(post)
2279 if layoutname == "AgainFrame":
2280 m = rx.match(document.body[p])
2284 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2285 endPlain = find_end_of_layout(document.body, beginPlain)
2286 endInset = find_end_of_inset(document.body, p)
2287 content = document.body[beginPlain + 1 : endPlain]
2289 realparend = realparend - len(document.body[p : endInset + 1])
2291 del document.body[p : endInset + 1]
2292 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2293 document.body[realparbeg : realparbeg] = subst
2294 if layoutname == "Overprint":
2295 m = rx.match(document.body[p])
2299 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2300 endPlain = find_end_of_layout(document.body, beginPlain)
2301 endInset = find_end_of_inset(document.body, p)
2302 content = document.body[beginPlain + 1 : endPlain]
2304 realparend = realparend - len(document.body[p : endInset + 1])
2306 del document.body[p : endInset + 1]
2307 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2308 document.body[realparbeg : realparbeg] = subst
2309 if layoutname == "OverlayArea":
2310 m = rx.match(document.body[p])
2314 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2315 endPlain = find_end_of_layout(document.body, beginPlain)
2316 endInset = find_end_of_inset(document.body, p)
2317 content = document.body[beginPlain + 1 : endPlain]
2319 realparend = realparend - len(document.body[p : endInset + 1])
2321 del document.body[p : endInset + 1]
2322 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2323 document.body[realparbeg : realparbeg] = subst
2324 if layoutname in list_layouts:
2325 m = rx.match(document.body[p])
2329 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2330 endPlain = find_end_of_layout(document.body, beginPlain)
2331 endInset = find_end_of_inset(document.body, p)
2332 content = document.body[beginPlain + 1 : endPlain]
2334 realparend = realparend - len(document.body[p : endInset + 1])
2336 del document.body[p : endInset + 1]
2337 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2338 document.body[realparbeg : realparbeg] = subst
2339 elif argnr == "item:1":
2340 j = find_end_of_inset(document.body, i)
2341 # Find containing paragraph layout
2342 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2343 endPlain = find_end_of_layout(document.body, beginPlain)
2344 content = document.body[beginPlain + 1 : endPlain]
2345 del document.body[i:j+1]
2346 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2347 document.body[realparbeg : realparbeg] = subst
2348 elif argnr == "item:2":
2349 j = find_end_of_inset(document.body, i)
2350 # Find containing paragraph layout
2351 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2352 endPlain = find_end_of_layout(document.body, beginPlain)
2353 content = document.body[beginPlain + 1 : endPlain]
2354 del document.body[i:j+1]
2355 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2356 document.body[realparbeg : realparbeg] = subst
2357 if layoutname in quote_layouts:
2358 m = rx.match(document.body[p])
2362 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2363 endPlain = find_end_of_layout(document.body, beginPlain)
2364 endInset = find_end_of_inset(document.body, p)
2365 content = document.body[beginPlain + 1 : endPlain]
2367 realparend = realparend - len(document.body[p : endInset + 1])
2369 del document.body[p : endInset + 1]
2370 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2371 document.body[realparbeg : realparbeg] = subst
2372 if layoutname in corollary_layouts:
2373 m = rx.match(document.body[p])
2377 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2378 endPlain = find_end_of_layout(document.body, beginPlain)
2379 endInset = find_end_of_inset(document.body, p)
2380 content = document.body[beginPlain + 1 : endPlain]
2382 realparend = realparend - len(document.body[p : endInset + 1])
2384 del document.body[p : endInset + 1]
2385 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2386 document.body[realparbeg : realparbeg] = subst
2391 def revert_beamerargs2(document):
2392 " Reverts beamer arguments to old layout, step 2 "
2394 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2395 if document.textclass not in beamer_classes:
2399 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2400 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2401 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2404 i = find_token(document.body, "\\begin_inset Argument", i)
2407 # Find containing paragraph layout
2408 parent = get_containing_layout(document.body, i)
2410 document.warning("Malformed lyx document: Can't find parent paragraph layout")
2415 realparbeg = parent[3]
2416 layoutname = parent[0]
2418 for p in range(parbeg, parend):
2422 if layoutname in shifted_layouts:
2423 m = rx.match(document.body[p])
2427 document.body[p] = "\\begin_inset Argument 1"
2428 if layoutname in corollary_layouts:
2429 m = rx.match(document.body[p])
2433 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2434 endPlain = find_end_of_layout(document.body, beginPlain)
2435 endInset = find_end_of_inset(document.body, p)
2436 content = document.body[beginPlain + 1 : endPlain]
2438 realparend = realparend - len(document.body[p : endInset + 1])
2440 del document.body[p : endInset + 1]
2441 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2442 document.body[realparbeg : realparbeg] = subst
2443 if layoutname == "OverlayArea":
2444 m = rx.match(document.body[p])
2448 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2449 endPlain = find_end_of_layout(document.body, beginPlain)
2450 endInset = find_end_of_inset(document.body, p)
2451 content = document.body[beginPlain + 1 : endPlain]
2453 realparend = realparend - len(document.body[p : endInset + 1])
2455 del document.body[p : endInset + 1]
2456 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2457 document.body[realparbeg : realparbeg] = subst
2458 if layoutname == "AgainFrame":
2459 m = rx.match(document.body[p])
2463 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2464 endPlain = find_end_of_layout(document.body, beginPlain)
2465 endInset = find_end_of_inset(document.body, p)
2466 content = document.body[beginPlain + 1 : endPlain]
2468 realparend = realparend - len(document.body[p : endInset + 1])
2470 del document.body[p : endInset + 1]
2471 subst = put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
2472 document.body[realparbeg : realparbeg] = subst
2476 def revert_beamerargs3(document):
2477 " Reverts beamer arguments to old layout, step 3 "
2479 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2480 if document.textclass not in beamer_classes:
2483 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2486 i = find_token(document.body, "\\begin_inset Argument", i)
2489 # Find containing paragraph layout
2490 parent = get_containing_layout(document.body, i)
2492 document.warning("Malformed lyx document: Can't find parent paragraph layout")
2497 realparbeg = parent[3]
2498 layoutname = parent[0]
2500 for p in range(parbeg, parend):
2504 if layoutname == "AgainFrame":
2505 m = rx.match(document.body[p])
2509 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2510 endPlain = find_end_of_layout(document.body, beginPlain)
2511 endInset = find_end_of_inset(document.body, p)
2512 content = document.body[beginPlain + 1 : endPlain]
2514 realparend = realparend - len(document.body[p : endInset + 1])
2516 del document.body[p : endInset + 1]
2517 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2518 document.body[realparbeg : realparbeg] = subst
2522 def revert_beamerflex(document):
2523 " Reverts beamer Flex insets "
2525 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2526 if document.textclass not in beamer_classes:
2529 new_flexes = {"Bold" : "\\textbf", "Emphasize" : "\\emph", "Only" : "\\only",
2530 "Uncover" : "\\uncover", "Visible" : "\\visible",
2531 "Invisible" : "\\invisible", "Alternative" : "\\alt",
2532 "Beamer_Note" : "\\note"}
2533 old_flexes = {"Alert" : "\\alert", "Structure" : "\\structure"}
2534 rx = re.compile(r'^\\begin_inset Flex (.+)$')
2538 i = find_token(document.body, "\\begin_inset Flex", i)
2541 m = rx.match(document.body[i])
2543 flextype = m.group(1)
2544 z = find_end_of_inset(document.body, i)
2546 document.warning("Can't find end of Flex " + flextype + " inset.")
2549 if flextype in new_flexes:
2550 pre = put_cmd_in_ert(new_flexes[flextype])
2551 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2553 argend = find_end_of_inset(document.body, arg)
2555 document.warning("Can't find end of Argument!")
2558 # Find containing paragraph layout
2559 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2560 endPlain = find_end_of_layout(document.body, beginPlain)
2561 argcontent = document.body[beginPlain + 1 : endPlain]
2563 z = z - len(document.body[arg : argend + 1])
2565 del document.body[arg : argend + 1]
2566 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2567 arg = find_token(document.body, "\\begin_inset Argument 2", i, z)
2569 argend = find_end_of_inset(document.body, arg)
2571 document.warning("Can't find end of Argument!")
2574 # Find containing paragraph layout
2575 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2576 endPlain = find_end_of_layout(document.body, beginPlain)
2577 argcontent = document.body[beginPlain + 1 : endPlain]
2579 z = z - len(document.body[arg : argend + 1])
2581 del document.body[arg : argend + 1]
2582 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2583 pre += put_cmd_in_ert("{")
2584 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2585 endPlain = find_end_of_layout(document.body, beginPlain)
2587 z = z - len(document.body[i : beginPlain + 1])
2589 document.body[i : beginPlain + 1] = pre
2590 post = put_cmd_in_ert("}")
2591 document.body[z - 2 : z + 1] = post
2592 elif flextype in old_flexes:
2593 pre = put_cmd_in_ert(old_flexes[flextype])
2594 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2598 argend = find_end_of_inset(document.body, arg)
2600 document.warning("Can't find end of Argument!")
2603 # Find containing paragraph layout
2604 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2605 endPlain = find_end_of_layout(document.body, beginPlain)
2606 argcontent = document.body[beginPlain + 1 : endPlain]
2608 z = z - len(document.body[arg : argend + 1])
2610 del document.body[arg : argend + 1]
2611 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2612 pre += put_cmd_in_ert("{")
2613 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2614 endPlain = find_end_of_layout(document.body, beginPlain)
2616 z = z - len(document.body[i : beginPlain + 1])
2618 document.body[i : beginPlain + 1] = pre
2619 post = put_cmd_in_ert("}")
2620 document.body[z - 2 : z + 1] = post
2625 def revert_beamerblocks(document):
2626 " Reverts beamer block arguments to ERT "
2628 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2629 if document.textclass not in beamer_classes:
2632 blocks = ["Block", "ExampleBlock", "AlertBlock"]
2634 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2637 i = find_token(document.body, "\\begin_inset Argument", i)
2640 # Find containing paragraph layout
2641 parent = get_containing_layout(document.body, i)
2643 document.warning("Malformed lyx document: Can't find parent paragraph layout")
2648 realparbeg = parent[3]
2649 layoutname = parent[0]
2651 for p in range(parbeg, parend):
2655 if layoutname in blocks:
2656 m = rx.match(document.body[p])
2660 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2661 endPlain = find_end_of_layout(document.body, beginPlain)
2662 endInset = find_end_of_inset(document.body, p)
2663 content = document.body[beginPlain + 1 : endPlain]
2665 realparend = realparend - len(document.body[p : endInset + 1])
2667 del document.body[p : endInset + 1]
2668 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2669 document.body[realparbeg : realparbeg] = subst
2671 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2672 endPlain = find_end_of_layout(document.body, beginPlain)
2673 endInset = find_end_of_inset(document.body, p)
2674 content = document.body[beginPlain + 1 : endPlain]
2676 realparend = realparend - len(document.body[p : endInset + 1])
2678 del document.body[p : endInset + 1]
2679 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2680 document.body[realparbeg : realparbeg] = subst
2685 def convert_beamerblocks(document):
2686 " Converts beamer block ERT args to native InsetArgs "
2688 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2689 if document.textclass not in beamer_classes:
2692 blocks = ["Block", "ExampleBlock", "AlertBlock"]
2696 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2699 parent = get_containing_layout(document.body, i)
2700 if parent == False or parent[1] != i:
2701 document.warning("Wrong parent layout!")
2707 if document.body[parbeg] == "\\begin_inset ERT":
2708 ertcont = parbeg + 5
2710 if document.body[ertcont].startswith("<"):
2711 # This is an overlay specification
2713 document.body[ertcont] = document.body[ertcont][1:]
2714 if document.body[ertcont].endswith(">"):
2716 document.body[ertcont] = document.body[ertcont][:-1]
2717 # Convert to ArgInset
2718 document.body[parbeg] = "\\begin_inset Argument 1"
2719 elif document.body[ertcont].endswith("}"):
2721 tok = document.body[ertcont].find('>{')
2723 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2724 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2725 'status collapsed', '', '\\begin_layout Plain Layout',
2726 document.body[ertcont][tok + 2:-1]]
2727 # Convert to ArgInset
2728 document.body[parbeg] = "\\begin_inset Argument 1"
2729 elif document.body[ertcont].startswith("{"):
2730 # This is the block title
2731 if document.body[ertcont].endswith("}"):
2732 # strip off the braces
2733 document.body[ertcont] = document.body[ertcont][1:-1]
2734 # Convert to ArgInset
2735 document.body[parbeg] = "\\begin_inset Argument 2"
2736 elif count_pars_in_inset(document.body, ertcont) > 1:
2737 # Multipar ERT. Skip this.
2740 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True)
2743 j = find_end_of_layout(document.body, i)
2745 document.warning("end of layout not found!")
2746 k = find_token(document.body, "\\begin_inset Argument", i, j)
2748 document.warning("InsetArgument not found!")
2750 l = find_end_of_inset(document.body, k)
2751 m = find_token(document.body, "\\begin_inset ERT", l, j)
2759 def convert_overprint(document):
2760 " Convert old beamer overprint layouts to ERT "
2762 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2763 if document.textclass not in beamer_classes:
2768 i = find_token(document.body, "\\begin_layout Overprint", i)
2771 # Find end of sequence
2772 j = find_end_of_sequence(document.body, i)
2774 document.warning("Malformed lyx document. Cannot find end of Overprint sequence!")
2778 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
2780 if document.body[j] == "\\end_deeper":
2781 esubst = ["", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
2783 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
2784 endseq = endseq + len(esubst) - len(document.body[j : j])
2785 document.body[j : j] = esubst
2786 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
2788 argend = find_end_of_layout(document.body, argbeg)
2790 document.warning("Malformed lyx document. Cannot find end of Overprint argument!")
2793 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
2794 endPlain = find_end_of_layout(document.body, beginPlain)
2795 content = document.body[beginPlain + 1 : endPlain]
2797 endseq = endseq - len(document.body[argbeg : argend + 1])
2799 del document.body[argbeg : argend + 1]
2800 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2802 endseq = endseq - len(document.body[i : i])
2803 document.body[i : i] = subst + ["\\end_layout"]
2804 endseq += len(subst)
2806 for p in range(i, endseq):
2807 if document.body[p] == "\\begin_layout Overprint":
2808 document.body[p] = "\\begin_layout Standard"
2813 def revert_overprint(document):
2814 " Revert old beamer overprint layouts to ERT "
2816 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2817 if document.textclass not in beamer_classes:
2822 i = find_token(document.body, "\\begin_layout Overprint", i)
2825 # Find end of sequence
2826 j = find_end_of_sequence(document.body, i)
2828 document.warning("Malformed lyx document. Cannot find end of Overprint sequence!")
2832 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
2833 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}")
2834 endseq = endseq + len(esubst) - len(document.body[j : j])
2835 document.body[j : j] = esubst
2836 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
2838 argend = find_end_of_inset(document.body, argbeg)
2840 document.warning("Malformed lyx document. Cannot find end of Overprint argument!")
2843 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
2844 endPlain = find_end_of_layout(document.body, beginPlain)
2845 content = document.body[beginPlain + 1 : endPlain]
2847 endseq = endseq - len(document.body[argbeg : argend])
2849 del document.body[argbeg : argend + 1]
2850 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2852 endseq = endseq - len(document.body[i : i])
2853 document.body[i : i] = subst + ["\\end_layout"]
2854 endseq += len(subst)
2860 if document.body[p] == "\\begin_layout Overprint":
2861 q = find_end_of_layout(document.body, p)
2863 document.warning("Malformed lyx document. Cannot find end of Overprint layout!")
2866 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\onslide")
2867 argbeg = find_token(document.body, "\\begin_inset Argument item:1", p, q)
2869 argend = find_end_of_inset(document.body, argbeg)
2871 document.warning("Malformed lyx document. Cannot find end of Overprint item argument!")
2874 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
2875 endPlain = find_end_of_layout(document.body, beginPlain)
2876 content = document.body[beginPlain + 1 : endPlain]
2878 endseq = endseq - len(document.body[argbeg : argend + 1])
2880 del document.body[argbeg : argend + 1]
2881 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2882 endseq = endseq - len(document.body[p : p + 1]) + len(subst)
2883 document.body[p : p + 1] = subst
2889 def revert_frametitle(document):
2890 " Reverts beamer frametitle layout to ERT "
2892 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2893 if document.textclass not in beamer_classes:
2896 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2899 i = find_token(document.body, "\\begin_layout FrameTitle", i)
2902 j = find_end_of_layout(document.body, i)
2904 document.warning("Malformed lyx document: Can't find end of FrameTitle layout")
2908 document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j]
2909 endlay += len(put_cmd_in_ert("}"))
2910 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\frametitle")
2911 for p in range(i, j):
2914 m = rx.match(document.body[p])
2918 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2919 endPlain = find_end_of_layout(document.body, beginPlain)
2920 endInset = find_end_of_inset(document.body, p)
2921 content = document.body[beginPlain + 1 : endPlain]
2923 endlay = endlay - len(document.body[p : endInset + 1])
2925 del document.body[p : endInset + 1]
2926 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2928 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2929 endPlain = find_end_of_layout(document.body, beginPlain)
2930 endInset = find_end_of_inset(document.body, p)
2931 content = document.body[beginPlain + 1 : endPlain]
2933 endlay = endlay - len(document.body[p : endInset + 1])
2935 del document.body[p : endInset + 1]
2936 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2938 subst += put_cmd_in_ert("{")
2939 document.body[i : i + 1] = subst
2943 def convert_epigraph(document):
2944 " Converts memoir epigraph to new syntax "
2946 if document.textclass != "memoir":
2951 i = find_token(document.body, "\\begin_layout Epigraph", i)
2954 j = find_end_of_layout(document.body, i)
2956 document.warning("Malformed lyx document: Can't find end of Epigraph layout")
2961 ert = find_token(document.body, "\\begin_inset ERT", i, j)
2963 endInset = find_end_of_inset(document.body, ert)
2964 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", ert)
2965 endPlain = find_end_of_layout(document.body, beginPlain)
2966 ertcont = beginPlain + 2
2967 if document.body[ertcont] == "}{":
2969 # Convert to ArgInset
2970 endlay = endlay - 2 * len(document.body[j])
2971 begsubst = ['\\begin_inset Argument post:1', 'status collapsed', '',
2972 '\\begin_layout Plain Layout']
2973 endsubst = ['\\end_layout', '', '\\end_inset', '', document.body[j]]
2974 document.body[j : j + 1] = endsubst
2975 document.body[endInset + 1 : endInset + 1] = begsubst
2977 endlay += len(begsubst) + len(endsubst)
2978 endlay = endlay - len(document.body[ert : endInset + 1])
2979 del document.body[ert : endInset + 1]
2984 def revert_epigraph(document):
2985 " Reverts memoir epigraph argument to ERT "
2987 if document.textclass != "memoir":
2992 i = find_token(document.body, "\\begin_layout Epigraph", i)
2995 j = find_end_of_layout(document.body, i)
2997 document.warning("Malformed lyx document: Can't find end of Epigraph layout")
3002 p = find_token(document.body, "\\begin_layout Argument post:1", i, j)
3004 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
3005 endPlain = find_end_of_layout(document.body, beginPlain)
3006 endInset = find_end_of_inset(document.body, p)
3007 content = document.body[beginPlain + 1 : endPlain]
3009 endlay = endlay - len(document.body[p : endInset + 1])
3011 del document.body[p : endInset + 1]
3012 subst += put_cmd_in_ert("}{") + content
3014 subst += put_cmd_in_ert("}{")
3016 document.body[j : j] = subst + document.body[j : j]
3020 def convert_captioninsets(document):
3021 " Converts caption insets to new syntax "
3025 i = find_token(document.body, "\\begin_inset Caption", i)
3028 document.body[i] = "\\begin_inset Caption Standard"
3033 def revert_captioninsets(document):
3034 " Reverts caption insets to old syntax "
3038 i = find_token(document.body, "\\begin_inset Caption Standard", i)
3041 document.body[i] = "\\begin_inset Caption"
3045 def convert_captionlayouts(document):
3046 " Convert caption layouts to caption insets. "
3049 "Captionabove": "Above",
3050 "Captionbelow": "Below",
3051 "FigCaption" : "FigCaption",
3052 "Table_Caption" : "Table",
3053 "CenteredCaption" : "Centered",
3054 "Bicaption" : "Bicaption",
3059 i = find_token(document.body, "\\begin_layout", i)
3062 val = get_value(document.body, "\\begin_layout", i)
3063 if val in caption_dict.keys():
3064 j = find_end_of_layout(document.body, i)
3066 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3069 document.body[j:j] = ["\\end_layout", "", "\\end_inset", "", ""]
3070 document.body[i:i+1] = ["\\begin_layout %s" % document.default_layout,
3071 "\\begin_inset Caption %s" % caption_dict[val], "",
3072 "\\begin_layout %s" % document.default_layout]
3076 def revert_captionlayouts(document):
3077 " Revert caption insets to caption layouts. "
3080 "Above" : "Captionabove",
3081 "Below" : "Captionbelow",
3082 "FigCaption" : "FigCaption",
3083 "Table" : "Table_Caption",
3084 "Centered" : "CenteredCaption",
3085 "Bicaption" : "Bicaption",
3089 rx = re.compile(r'^\\begin_inset Caption (\S+)$')
3091 i = find_token(document.body, "\\begin_inset Caption", i)
3095 m = rx.match(document.body[i])
3099 if val not in caption_dict.keys():
3103 # We either need to delete the previous \begin_layout line, or we
3104 # need to end the previous layout if this inset is not in the first
3105 # position of the paragraph.
3106 layout_before = find_token_backwards(document.body, "\\begin_layout", i)
3107 if layout_before == -1:
3108 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3110 layout_line = document.body[layout_before]
3111 del_layout_before = True
3112 l = layout_before + 1
3114 if document.body[l] != "":
3115 del_layout_before = False
3118 if del_layout_before:
3119 del document.body[layout_before:i]
3122 document.body[i:i] = ["\\end_layout", ""]
3125 # Find start of layout in the inset and end of inset
3126 j = find_token(document.body, "\\begin_layout", i)
3128 document.warning("Malformed LyX document: Missing `\\begin_layout'.")
3130 k = find_end_of_inset(document.body, i)
3132 document.warning("Malformed LyX document: Missing `\\end_inset'.")
3135 # We either need to delete the following \end_layout line, or we need
3136 # to restart the old layout if this inset is not at the paragraph end.
3137 layout_after = find_token(document.body, "\\end_layout", k)
3138 if layout_after == -1:
3139 document.warning("Malformed LyX document: Missing `\\end_layout'.")
3141 del_layout_after = True
3143 while l < layout_after:
3144 if document.body[l] != "":
3145 del_layout_after = False
3148 if del_layout_after:
3149 del document.body[k+1:layout_after+1]
3151 document.body[k+1:k+1] = [layout_line, ""]
3153 # delete \begin_layout and \end_inset and replace \begin_inset with
3154 # "\begin_layout XXX". This works because we can only have one
3155 # paragraph in the caption inset: The old \end_layout will be recycled.
3156 del document.body[k]
3157 if document.body[k] == "":
3158 del document.body[k]
3159 del document.body[j]
3160 if document.body[j] == "":
3161 del document.body[j]
3162 document.body[i] = "\\begin_layout %s" % caption_dict[val]
3163 if document.body[i+1] == "":
3164 del document.body[i+1]
3172 supported_versions = ["2.1.0","2.1"]
3175 [415, [convert_undertilde]],
3177 [417, [convert_japanese_encodings]],
3180 [420, [convert_biblio_style]],
3181 [421, [convert_longtable_captions]],
3182 [422, [convert_use_packages]],
3183 [423, [convert_use_mathtools]],
3184 [424, [convert_cite_engine_type]],
3188 [428, [convert_cell_rotation]],
3189 [429, [convert_table_rotation]],
3190 [430, [convert_listoflistings]],
3191 [431, [convert_use_amssymb]],
3193 [433, [convert_armenian]],
3201 [441, [convert_mdnomath]],
3206 [446, [convert_latexargs]],
3207 [447, [convert_IEEEtran, convert_AASTeX, convert_AGUTeX, convert_IJMP, convert_SIGPLAN, convert_SIGGRAPH, convert_EuropeCV]],
3208 [448, [convert_literate]],
3211 [451, [convert_beamerargs, convert_againframe_args, convert_corollary_args, convert_quote_args]],
3212 [452, [convert_beamerblocks]],
3213 [453, [convert_use_stmaryrd]],
3214 [454, [convert_overprint]],
3216 [456, [convert_epigraph]],
3217 [457, [convert_use_stackrel]],
3218 [458, [convert_captioninsets, convert_captionlayouts]]
3222 [457, [revert_captioninsets, revert_captionlayouts]],
3223 [456, [revert_use_stackrel]],
3224 [455, [revert_epigraph]],
3225 [454, [revert_frametitle]],
3226 [453, [revert_overprint]],
3227 [452, [revert_use_stmaryrd]],
3228 [451, [revert_beamerblocks]],
3229 [450, [revert_beamerargs, revert_beamerargs2, revert_beamerargs3, revert_beamerflex]],
3230 [449, [revert_garamondx, revert_garamondx_newtxmath]],
3231 [448, [revert_itemargs]],
3232 [447, [revert_literate]],
3233 [446, [revert_IEEEtran, revert_AASTeX, revert_AGUTeX, revert_IJMP, revert_SIGPLAN, revert_SIGGRAPH, revert_EuropeCV]],
3234 [445, [revert_latexargs]],
3235 [444, [revert_uop]],
3236 [443, [revert_biolinum]],
3238 [441, [revert_newtxmath]],
3239 [440, [revert_mdnomath]],
3240 [439, [revert_mathfonts]],
3241 [438, [revert_minionpro]],
3242 [437, [revert_ipadeco, revert_ipachar]],
3243 [436, [revert_texgyre]],
3244 [435, [revert_mathdesign]],
3245 [434, [revert_txtt]],
3246 [433, [revert_libertine]],
3247 [432, [revert_armenian]],
3248 [431, [revert_languages, revert_ancientgreek]],
3249 [430, [revert_use_amssymb]],
3250 [429, [revert_listoflistings]],
3251 [428, [revert_table_rotation]],
3252 [427, [revert_cell_rotation]],
3253 [426, [revert_tipa]],
3254 [425, [revert_verbatim]],
3255 [424, [revert_cancel]],
3256 [423, [revert_cite_engine_type]],
3257 [422, [revert_use_mathtools]],
3258 [421, [revert_use_packages]],
3259 [420, [revert_longtable_captions]],
3260 [419, [revert_biblio_style]],
3261 [418, [revert_australian]],
3262 [417, [revert_justification]],
3263 [416, [revert_japanese_encodings]],
3264 [415, [revert_negative_space, revert_math_spaces]],
3265 [414, [revert_undertilde]],
3266 [413, [revert_visible_space]]
3270 if __name__ == "__main__":