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, find_re, \
30 get_option_value, get_containing_layout, get_value, get_quoted_value, set_option_value
32 #from parser_tools import find_token, find_end_of, find_tokens, \
33 #find_end_of_inset, find_end_of_layout, \
34 #is_in_inset, del_token, check_token
36 from lyx2lyx_tools import add_to_preamble, put_cmd_in_ert, get_ert
38 #from lyx2lyx_tools import insert_to_preamble, \
39 # lyx2latex, latex_length, revert_flex_inset, \
40 # revert_font_attrs, hex2ratio, str2bool
42 ####################################################################
43 # Private helper functions
45 #def remove_option(lines, m, option):
46 #''' removes option from line m. returns whether we did anything '''
47 #l = lines[m].find(option)
50 #val = lines[m][l:].split('"')[1]
51 #lines[m] = lines[m][:l - 1] + lines[m][l+len(option + '="' + val + '"'):]
55 ###############################################################################
57 ### Conversion and reversion routines
59 ###############################################################################
61 def revert_visible_space(document):
62 "Revert InsetSpace visible into its ERT counterpart"
65 i = find_token(document.body, "\\begin_inset space \\textvisiblespace{}", i)
68 end = find_end_of_inset(document.body, i)
69 subst = put_cmd_in_ert("\\textvisiblespace{}")
70 document.body[i:end + 1] = subst
73 def convert_undertilde(document):
74 " Load undertilde automatically "
75 i = find_token(document.header, "\\use_mathdots" , 0)
77 i = find_token(document.header, "\\use_mhchem" , 0)
79 i = find_token(document.header, "\\use_esint" , 0)
81 document.warning("Malformed LyX document: Can't find \\use_mathdots.")
83 j = find_token(document.preamble, "\\usepackage{undertilde}", 0)
85 document.header.insert(i + 1, "\\use_undertilde 0")
87 document.header.insert(i + 1, "\\use_undertilde 2")
88 del document.preamble[j]
91 def revert_undertilde(document):
92 " Load undertilde if used in the document "
93 undertilde = find_token(document.header, "\\use_undertilde" , 0)
95 document.warning("No \\use_undertilde line. Assuming auto.")
97 val = get_value(document.header, "\\use_undertilde", undertilde)
98 del document.header[undertilde]
102 document.warning("Invalid \\use_undertilde value: " + val + ". Assuming auto.")
103 # probably usedots has not been changed, but be safe.
111 add_to_preamble(document, ["\\usepackage{undertilde}"])
114 # so we are in the auto case. we want to load undertilde if \utilde is used.
117 i = find_token(document.body, '\\begin_inset Formula', i)
120 j = find_end_of_inset(document.body, i)
122 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
125 code = "\n".join(document.body[i:j])
126 if code.find("\\utilde") != -1:
127 add_to_preamble(document, ["\\@ifundefined{utilde}{\\usepackage{undertilde}}"])
132 def revert_negative_space(document):
133 "Revert InsetSpace negmedspace and negthickspace into its TeX-code counterpart"
138 i = find_token(document.body, "\\begin_inset space \\negmedspace{}", i)
140 j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
142 # load amsmath in the preamble if not already loaded if we are at the end of checking
144 i = find_token(document.header, "\\use_amsmath 2", 0)
146 add_to_preamble(document, ["\\@ifundefined{negthickspace}{\\usepackage{amsmath}}"])
150 end = find_end_of_inset(document.body, i)
151 subst = put_cmd_in_ert("\\negmedspace{}")
152 document.body[i:end + 1] = subst
153 j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
156 end = find_end_of_inset(document.body, j)
157 subst = put_cmd_in_ert("\\negthickspace{}")
158 document.body[j:end + 1] = subst
162 def revert_math_spaces(document):
163 "Revert formulas with protected custom space and protected hfills to TeX-code"
166 i = find_token(document.body, "\\begin_inset Formula", i)
169 j = document.body[i].find("\\hspace*")
171 end = find_end_of_inset(document.body, i)
172 subst = put_cmd_in_ert(document.body[i][21:])
173 document.body[i:end + 1] = subst
177 def convert_japanese_encodings(document):
178 " Rename the japanese encodings to names understood by platex "
180 "EUC-JP-pLaTeX": "euc",
182 "SJIS-pLaTeX": "sjis"
184 i = find_token(document.header, "\\inputencoding" , 0)
187 val = get_value(document.header, "\\inputencoding", i)
188 if val in jap_enc_dict.keys():
189 document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
192 def revert_japanese_encodings(document):
193 " Revert the japanese encodings name changes "
195 "euc": "EUC-JP-pLaTeX",
197 "sjis": "SJIS-pLaTeX"
199 i = find_token(document.header, "\\inputencoding" , 0)
202 val = get_value(document.header, "\\inputencoding", i)
203 if val in jap_enc_dict.keys():
204 document.header[i] = "\\inputencoding %s" % jap_enc_dict[val]
207 def revert_justification(document):
208 " Revert the \\justification buffer param"
209 if not del_token(document.header, '\\justification', 0):
210 document.warning("Malformed LyX document: Missing \\justification.")
213 def revert_australian(document):
214 "Set English language variants Australian and Newzealand to English"
216 if document.language == "australian" or document.language == "newzealand":
217 document.language = "english"
218 i = find_token(document.header, "\\language", 0)
220 document.header[i] = "\\language english"
223 j = find_token(document.body, "\\lang australian", j)
225 j = find_token(document.body, "\\lang newzealand", 0)
229 document.body[j] = document.body[j].replace("\\lang newzealand", "\\lang english")
231 document.body[j] = document.body[j].replace("\\lang australian", "\\lang english")
235 def convert_biblio_style(document):
236 "Add a sensible default for \\biblio_style based on the citation engine."
237 i = find_token(document.header, "\\cite_engine", 0)
239 engine = get_value(document.header, "\\cite_engine", i).split("_")[0]
240 style = {"basic": "plain", "natbib": "plainnat", "jurabib": "jurabib"}
241 document.header.insert(i + 1, "\\biblio_style " + style[engine])
244 def revert_biblio_style(document):
245 "BibTeX insets with default option use the style defined by \\biblio_style."
246 i = find_token(document.header, "\\biblio_style" , 0)
248 document.warning("No \\biblio_style line. Nothing to do.")
251 default_style = get_value(document.header, "\\biblio_style", i)
252 del document.header[i]
254 # We are looking for bibtex insets having the default option
257 i = find_token(document.body, "\\begin_inset CommandInset bibtex", i)
260 j = find_end_of_inset(document.body, i)
262 document.warning("Malformed LyX document: Can't find end of bibtex inset at line " + str(i))
265 k = find_token(document.body, "options", i, j)
267 options = get_quoted_value(document.body, "options", k)
268 if "default" in options.split(","):
269 document.body[k] = 'options "%s"' \
270 % options.replace("default", default_style)
274 def handle_longtable_captions(document, forward):
277 begin_table = find_token(document.body, '<lyxtabular version=', begin_table)
278 if begin_table == -1:
280 end_table = find_end_of(document.body, begin_table, '<lyxtabular', '</lyxtabular>')
282 document.warning("Malformed LyX document: Could not find end of table.")
285 fline = find_token(document.body, "<features", begin_table, end_table)
287 document.warning("Can't find features for inset at line " + str(begin_table))
290 p = document.body[fline].find("islongtable")
295 numrows = get_option_value(document.body[begin_table], "rows")
297 numrows = int(numrows)
299 document.warning(document.body[begin_table])
300 document.warning("Unable to determine rows!")
301 begin_table = end_table
303 begin_row = begin_table
304 for row in range(numrows):
305 begin_row = find_token(document.body, '<row', begin_row, end_table)
307 document.warning("Can't find row " + str(row + 1))
309 end_row = find_end_of(document.body, begin_row, '<row', '</row>')
311 document.warning("Can't find end of row " + str(row + 1))
314 if (get_option_value(document.body[begin_row], 'caption') == 'true' and
315 get_option_value(document.body[begin_row], 'endfirsthead') != 'true' and
316 get_option_value(document.body[begin_row], 'endhead') != 'true' and
317 get_option_value(document.body[begin_row], 'endfoot') != 'true' and
318 get_option_value(document.body[begin_row], 'endlastfoot') != 'true'):
319 document.body[begin_row] = set_option_value(document.body[begin_row], 'caption', 'true", endfirsthead="true')
320 elif get_option_value(document.body[begin_row], 'caption') == 'true':
321 if get_option_value(document.body[begin_row], 'endfirsthead') == 'true':
322 document.body[begin_row] = set_option_value(document.body[begin_row], 'endfirsthead', 'false')
323 if get_option_value(document.body[begin_row], 'endhead') == 'true':
324 document.body[begin_row] = set_option_value(document.body[begin_row], 'endhead', 'false')
325 if get_option_value(document.body[begin_row], 'endfoot') == 'true':
326 document.body[begin_row] = set_option_value(document.body[begin_row], 'endfoot', 'false')
327 if get_option_value(document.body[begin_row], 'endlastfoot') == 'true':
328 document.body[begin_row] = set_option_value(document.body[begin_row], 'endlastfoot', 'false')
330 # since there could be a tabular inside this one, we
331 # cannot jump to end.
335 def convert_longtable_captions(document):
336 "Add a firsthead flag to caption rows"
337 handle_longtable_captions(document, True)
340 def revert_longtable_captions(document):
341 "remove head/foot flag from caption rows"
342 handle_longtable_captions(document, False)
345 def convert_use_packages(document):
346 "use_xxx yyy => use_package xxx yyy"
347 packages = ["amsmath", "esint", "mathdots", "mhchem", "undertilde"]
349 i = find_token(document.header, "\\use_%s" % p, 0)
351 value = get_value(document.header, "\\use_%s" % p, i)
352 document.header[i] = "\\use_package %s %s" % (p, value)
355 def revert_use_packages(document):
356 "use_package xxx yyy => use_xxx yyy"
357 packages = ["amsmath", "esint", "mathdots", "mhchem", "undertilde"]
358 # the order is arbitrary for the use_package version, and not all packages need to be given.
359 # Ensure a complete list and correct order (important for older LyX versions and especially lyx2lyx)
362 regexp = re.compile(r'(\\use_package\s+%s)' % p)
363 i = find_re(document.header, regexp, j)
365 value = get_value(document.header, "\\use_package %s" % p, i).split()[1]
366 del document.header[i]
368 document.header.insert(j, "\\use_%s %s" % (p, value))
372 def convert_use_mathtools(document):
373 "insert use_package mathtools"
374 i = find_token(document.header, "\\use_package", 0)
376 document.warning("Malformed LyX document: Can't find \\use_package.")
378 j = find_token(document.preamble, "\\usepackage{mathtools}", 0)
380 document.header.insert(i + 1, "\\use_package mathtools 0")
382 document.header.insert(i + 1, "\\use_package mathtools 2")
383 del document.preamble[j]
386 def revert_use_mathtools(document):
387 "remove use_package mathtools"
388 regexp = re.compile(r'(\\use_package\s+mathtools)')
389 i = find_re(document.header, regexp, 0)
390 value = "1" # default is auto
392 value = get_value(document.header, "\\use_package" , i).split()[1]
393 del document.header[i]
394 if value == "2": # on
395 add_to_preamble(document, ["\\usepackage{mathtools}"])
396 elif value == "1": # auto
397 commands = ["mathclap", "mathllap", "mathrlap", \
398 "lgathered", "rgathered", "vcentcolon", "dblcolon", \
399 "coloneqq", "Coloneqq", "coloneq", "Coloneq", "eqqcolon", \
400 "Eqqcolon", "eqcolon", "Eqcolon", "colonapprox", \
401 "Colonapprox", "colonsim", "Colonsim"]
404 i = find_token(document.body, '\\begin_inset Formula', i)
407 j = find_end_of_inset(document.body, i)
409 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
412 code = "\n".join(document.body[i:j])
414 if code.find("\\%s" % c) != -1:
415 add_to_preamble(document, ["\\usepackage{mathtools}"])
420 def convert_use_stmaryrd(document):
421 "insert use_package stmaryrd"
422 i = find_token(document.header, "\\use_package", 0)
424 document.warning("Malformed LyX document: Can't find \\use_package.")
426 j = find_token(document.preamble, "\\usepackage{stmaryrd}", 0)
428 document.header.insert(i + 1, "\\use_package stmaryrd 0")
430 document.header.insert(i + 1, "\\use_package stmaryrd 2")
431 del document.preamble[j]
434 def revert_use_stmaryrd(document):
435 "remove use_package stmaryrd"
436 regexp = re.compile(r'(\\use_package\s+stmaryrd)')
437 i = find_re(document.header, regexp, 0)
438 value = "1" # default is auto
440 value = get_value(document.header, "\\use_package" , i).split()[1]
441 del document.header[i]
442 if value == "2": # on
443 add_to_preamble(document, ["\\usepackage{stmaryrd}"])
444 elif value == "1": # auto
445 commands = ["shortleftarrow", "shortrightarrow", "shortuparrow", \
446 "shortdownarrow", "Yup", "Ydown", "Yleft", "Yright", \
447 "varcurlyvee", "varcurlywedge", "minuso", "baro", \
448 "sslash", "bbslash", "moo", "varotimes", "varoast", \
449 "varobar", "varodot", "varoslash", "varobslash", \
450 "varocircle", "varoplus", "varominus", "boxast", \
451 "boxbar", "boxdot", "boxslash", "boxbslash", "boxcircle", \
452 "boxbox", "boxempty", "merge", "vartimes", \
453 "fatsemi", "sswarrow", "ssearrow", "curlywedgeuparrow", \
454 "curlywedgedownarrow", "fatslash", "fatbslash", "lbag", \
455 "rbag", "varbigcirc", "leftrightarroweq", \
456 "curlyveedownarrow", "curlyveeuparrow", "nnwarrow", \
457 "nnearrow", "leftslice", "rightslice", "varolessthan", \
458 "varogreaterthan", "varovee", "varowedge", "talloblong", \
459 "interleave", "obar", "obslash", "olessthan", \
460 "ogreaterthan", "ovee", "owedge", "oblong", "inplus", \
461 "niplus", "nplus", "subsetplus", "supsetplus", \
462 "subsetpluseq", "supsetpluseq", "Lbag", "Rbag", \
463 "llbracket", "rrbracket", "llparenthesis", \
464 "rrparenthesis", "binampersand", "bindnasrepma", \
465 "trianglelefteqslant", "trianglerighteqslant", \
466 "ntrianglelefteqslant", "ntrianglerighteqslant", \
467 "llfloor", "rrfloor", "llceil", "rrceil", "arrownot", \
468 "Arrownot", "Mapstochar", "mapsfromchar", "Mapsfromchar", \
469 "leftrightarrowtriangle", "leftarrowtriangle", \
470 "rightarrowtriangle", \
471 "bigcurlyvee", "bigcurlywedge", "bigsqcap", "bigbox", \
472 "bigparallel", "biginterleave", "bignplus", \
473 "varcopyright", "longarrownot", "Longarrownot", \
474 "Mapsto", "mapsfrom", "Mapsfrom" "Longmapsto", \
475 "longmapsfrom", "Longmapsfrom"]
476 # commands provided by stmaryrd.sty but LyX uses other packages:
477 # lightning, bigtriangledown, bigtriangleup
481 i = find_token(document.body, '\\begin_inset Formula', i)
484 j = find_end_of_inset(document.body, i)
486 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
489 code = "\n".join(document.body[i:j])
491 if code.find("\\%s" % c) != -1:
492 add_to_preamble(document, ["\\usepackage{stmaryrd}"])
497 def convert_cite_engine_type(document):
498 "Determine the \\cite_engine_type from the citation engine."
499 i = find_token(document.header, "\\cite_engine", 0)
502 engine = get_value(document.header, "\\cite_engine", i)
504 engine, type = engine.split("_")
506 type = {"basic": "numerical", "jurabib": "authoryear"}[engine]
507 document.header[i] = "\\cite_engine " + engine
508 document.header.insert(i + 1, "\\cite_engine_type " + type)
511 def revert_cite_engine_type(document):
512 "Natbib had the type appended with an underscore."
513 engine_type = "numerical"
514 i = find_token(document.header, "\\cite_engine_type" , 0)
516 document.warning("No \\cite_engine_type line. Assuming numerical.")
518 engine_type = get_value(document.header, "\\cite_engine_type", i)
519 del document.header[i]
521 # We are looking for the natbib citation engine
522 i = find_token(document.header, "\\cite_engine natbib", 0)
525 document.header[i] = "\\cite_engine natbib_" + engine_type
528 def revert_cancel(document):
529 "add cancel to the preamble if necessary"
530 commands = ["cancelto", "cancel", "bcancel", "xcancel"]
533 i = find_token(document.body, '\\begin_inset Formula', i)
536 j = find_end_of_inset(document.body, i)
538 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
541 code = "\n".join(document.body[i:j])
543 if code.find("\\%s" % c) != -1:
544 add_to_preamble(document, ["\\usepackage{cancel}"])
549 def revert_verbatim(document):
550 " Revert verbatim einvironments completely to TeX-code. "
553 subst_end = ['\end_layout', '', '\\begin_layout Plain Layout',
555 '\\begin_layout Plain Layout', '', '',
558 '\\end_layout', '', '\\end_inset',
559 '', '', '\\end_layout']
560 subst_begin = ['\\begin_layout Standard', '\\noindent',
561 '\\begin_inset ERT', 'status collapsed', '',
562 '\\begin_layout Plain Layout', '', '', '\\backslash',
564 '\\end_layout', '', '\\begin_layout Plain Layout', '']
566 i = find_token(document.body, "\\begin_layout Verbatim", i)
569 j = find_end_of_layout(document.body, i)
571 document.warning("Malformed lyx document: Can't find end of Verbatim layout")
574 # delete all line breaks insets (there are no other insets)
577 n = find_token(document.body, "\\begin_inset Newline newline", l)
579 n = find_token(document.body, "\\begin_inset Newline linebreak", l)
582 m = find_end_of_inset(document.body, n)
583 del(document.body[m:m+1])
584 document.body[n:n+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
587 # consecutive verbatim environments need to be connected
588 k = find_token(document.body, "\\begin_layout Verbatim", j)
589 if k == j + 2 and consecutive == False:
591 document.body[j:j+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
592 document.body[i:i+1] = subst_begin
594 if k == j + 2 and consecutive == True:
595 document.body[j:j+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
596 del(document.body[i:i+1])
598 if k != j + 2 and consecutive == True:
599 document.body[j:j+1] = subst_end
600 # the next paragraph must not be indented
601 document.body[j+19:j+19] = ['\\noindent']
602 del(document.body[i:i+1])
606 document.body[j:j+1] = subst_end
607 # the next paragraph must not be indented
608 document.body[j+19:j+19] = ['\\noindent']
609 document.body[i:i+1] = subst_begin
612 def revert_tipa(document):
613 " Revert native TIPA insets to mathed or ERT. "
616 i = find_token(document.body, "\\begin_inset IPA", i)
619 j = find_end_of_inset(document.body, i)
621 document.warning("Malformed lyx document: Can't find end of IPA inset")
625 n = find_token(document.body, "\\begin_layout", i, j)
627 document.warning("Malformed lyx document: IPA inset has no embedded layout")
630 m = find_end_of_layout(document.body, n)
632 document.warning("Malformed lyx document: Can't find end of embedded layout")
635 content = document.body[n+1:m]
636 p = find_token(document.body, "\\begin_layout", m, j)
637 if p != -1 or len(content) > 1:
639 content = document.body[i+1:j]
641 # IPA insets with multiple pars need to be wrapped by \begin{IPA}...\end{IPA}
642 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}")
643 add_to_preamble(document, ["\\usepackage{tipa,tipx}"])
645 # single-par IPA insets can be reverted to mathed
646 document.body[i:j+1] = ["\\begin_inset Formula $\\text{\\textipa{" + content[0] + "}}$", "\\end_inset"]
650 def revert_cell_rotation(document):
651 "Revert cell rotations to TeX-code"
653 load_rotating = False
657 # first, let's find out if we need to do anything
658 i = find_token(document.body, '<cell ', i)
661 j = document.body[i].find('rotate="')
663 k = document.body[i].find('"', j + 8)
664 value = document.body[i][j + 8 : k]
666 rgx = re.compile(r' rotate="[^"]+?"')
667 # remove rotate option
668 document.body[i] = rgx.sub('', document.body[i])
670 rgx = re.compile(r' rotate="[^"]+?"')
671 document.body[i] = rgx.sub('rotate="true"', document.body[i])
673 rgx = re.compile(r' rotate="[^"]+?"')
675 # remove rotate option
676 document.body[i] = rgx.sub('', document.body[i])
678 document.body[i + 5 : i + 5] = \
679 put_cmd_in_ert("\\end{turn}")
680 document.body[i + 4 : i + 4] = \
681 put_cmd_in_ert("\\begin{turn}{" + value + "}")
687 add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"])
690 def convert_cell_rotation(document):
691 'Convert cell rotation statements from "true" to "90"'
695 # first, let's find out if we need to do anything
696 i = find_token(document.body, '<cell ', i)
699 j = document.body[i].find('rotate="true"')
701 rgx = re.compile(r'rotate="[^"]+?"')
702 # convert "true" to "90"
703 document.body[i] = rgx.sub('rotate="90"', document.body[i])
708 def revert_table_rotation(document):
709 "Revert table rotations to TeX-code"
711 load_rotating = False
715 # first, let's find out if we need to do anything
716 i = find_token(document.body, '<features ', i)
719 j = document.body[i].find('rotate="')
721 end_table = find_token(document.body, '</lyxtabular>', j)
722 k = document.body[i].find('"', j + 8)
723 value = document.body[i][j + 8 : k]
725 rgx = re.compile(r' rotate="[^"]+?"')
726 # remove rotate option
727 document.body[i] = rgx.sub('', document.body[i])
729 rgx = re.compile(r'rotate="[^"]+?"')
730 document.body[i] = rgx.sub('rotate="true"', document.body[i])
732 rgx = re.compile(r' rotate="[^"]+?"')
734 # remove rotate option
735 document.body[i] = rgx.sub('', document.body[i])
737 document.body[end_table + 3 : end_table + 3] = \
738 put_cmd_in_ert("\\end{turn}")
739 document.body[i - 2 : i - 2] = \
740 put_cmd_in_ert("\\begin{turn}{" + value + "}")
746 add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"])
749 def convert_table_rotation(document):
750 'Convert table rotation statements from "true" to "90"'
754 # first, let's find out if we need to do anything
755 i = find_token(document.body, '<features ', i)
758 j = document.body[i].find('rotate="true"')
760 rgx = re.compile(r'rotate="[^"]+?"')
761 # convert "true" to "90"
762 document.body[i] = rgx.sub('rotate="90"', document.body[i])
767 def convert_listoflistings(document):
768 'Convert ERT \lstlistoflistings to TOC lstlistoflistings inset'
769 # We can support roundtrip because the command is so simple
772 i = find_token(document.body, "\\begin_inset ERT", i)
775 j = find_end_of_inset(document.body, i)
777 document.warning("Malformed lyx document: Can't find end of ERT inset")
780 ert = get_ert(document.body, i)
781 if ert == "\\lstlistoflistings{}":
782 document.body[i:j] = ["\\begin_inset CommandInset toc", "LatexCommand lstlistoflistings", ""]
788 def revert_listoflistings(document):
789 'Convert TOC lstlistoflistings inset to ERT lstlistoflistings'
792 i = find_token(document.body, "\\begin_inset CommandInset toc", i)
795 if document.body[i+1] == "LatexCommand lstlistoflistings":
796 j = find_end_of_inset(document.body, i)
798 document.warning("Malformed lyx document: Can't find end of TOC inset")
801 subst = put_cmd_in_ert("\\lstlistoflistings{}")
802 document.body[i:j+1] = subst
803 add_to_preamble(document, ["\\usepackage{listings}"])
807 def convert_use_amssymb(document):
808 "insert use_package amssymb"
809 regexp = re.compile(r'(\\use_package\s+amsmath)')
810 i = find_re(document.header, regexp, 0)
812 document.warning("Malformed LyX document: Can't find \\use_package amsmath.")
814 value = get_value(document.header, "\\use_package" , i).split()[1]
817 useamsmath = int(value)
819 document.warning("Invalid \\use_package amsmath: " + value + ". Assuming auto.")
821 j = find_token(document.preamble, "\\usepackage{amssymb}", 0)
823 document.header.insert(i + 1, "\\use_package amssymb %d" % useamsmath)
825 document.header.insert(i + 1, "\\use_package amssymb 2")
826 del document.preamble[j]
829 def revert_use_amssymb(document):
830 "remove use_package amssymb"
831 regexp1 = re.compile(r'(\\use_package\s+amsmath)')
832 regexp2 = re.compile(r'(\\use_package\s+amssymb)')
833 i = find_re(document.header, regexp1, 0)
834 j = find_re(document.header, regexp2, 0)
835 value1 = "1" # default is auto
836 value2 = "1" # default is auto
838 value1 = get_value(document.header, "\\use_package" , i).split()[1]
840 value2 = get_value(document.header, "\\use_package" , j).split()[1]
841 del document.header[j]
842 if value1 != value2 and value2 == "2": # on
843 add_to_preamble(document, ["\\usepackage{amssymb}"])
846 def revert_ancientgreek(document):
847 "Set the document language for ancientgreek to greek"
849 if document.language == "ancientgreek":
850 document.language = "greek"
851 i = find_token(document.header, "\\language", 0)
853 document.header[i] = "\\language greek"
856 j = find_token(document.body, "\\lang ancientgreek", j)
860 document.body[j] = document.body[j].replace("\\lang ancientgreek", "\\lang greek")
864 def revert_languages(document):
865 "Set the document language for new supported languages to English"
868 "coptic", "divehi", "hindi", "kurmanji", "lao", "marathi", "occitan", "sanskrit",
869 "syriac", "tamil", "telugu", "urdu"
871 for n in range(len(languages)):
872 if document.language == languages[n]:
873 document.language = "english"
874 i = find_token(document.header, "\\language", 0)
876 document.header[i] = "\\language english"
878 while j < len(document.body):
879 j = find_token(document.body, "\\lang " + languages[n], j)
881 document.body[j] = document.body[j].replace("\\lang " + languages[n], "\\lang english")
884 j = len(document.body)
887 def convert_armenian(document):
888 "Use polyglossia and thus non-TeX fonts for Armenian"
890 if document.language == "armenian":
891 i = find_token(document.header, "\\use_non_tex_fonts", 0)
893 document.header[i] = "\\use_non_tex_fonts true"
896 def revert_armenian(document):
897 "Use ArmTeX and thus TeX fonts for Armenian"
899 if document.language == "armenian":
900 i = find_token(document.header, "\\use_non_tex_fonts", 0)
902 document.header[i] = "\\use_non_tex_fonts false"
905 def revert_libertine(document):
906 " Revert native libertine font definition to LaTeX "
908 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
909 i = find_token(document.header, "\\font_roman libertine", 0)
912 j = find_token(document.header, "\\font_osf true", 0)
915 preamble = "\\usepackage"
917 document.header[j] = "\\font_osf false"
919 preamble += "[lining]"
920 preamble += "{libertine-type1}"
921 add_to_preamble(document, [preamble])
922 document.header[i] = "\\font_roman default"
925 def revert_txtt(document):
926 " Revert native txtt font definition to LaTeX "
928 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
929 i = find_token(document.header, "\\font_typewriter txtt", 0)
931 preamble = "\\renewcommand{\\ttdefault}{txtt}"
932 add_to_preamble(document, [preamble])
933 document.header[i] = "\\font_typewriter default"
936 def revert_mathdesign(document):
937 " Revert native mathdesign font definition to LaTeX "
939 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
945 i = find_token(document.header, "\\font_roman", 0)
948 val = get_value(document.header, "\\font_roman", i)
949 if val in mathdesign_dict.keys():
950 preamble = "\\usepackage[%s" % mathdesign_dict[val]
952 j = find_token(document.header, "\\font_osf true", 0)
955 document.header[j] = "\\font_osf false"
956 l = find_token(document.header, "\\font_sc true", 0)
959 document.header[l] = "\\font_sc false"
961 preamble += ",expert"
962 preamble += "]{mathdesign}"
963 add_to_preamble(document, [preamble])
964 document.header[i] = "\\font_roman default"
967 def revert_texgyre(document):
968 " Revert native TeXGyre font definition to LaTeX "
970 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
971 texgyre_fonts = ["tgadventor", "tgbonum", "tgchorus", "tgcursor", \
972 "tgheros", "tgpagella", "tgschola", "tgtermes"]
973 i = find_token(document.header, "\\font_roman", 0)
975 val = get_value(document.header, "\\font_roman", i)
976 if val in texgyre_fonts:
977 preamble = "\\usepackage{%s}" % val
978 add_to_preamble(document, [preamble])
979 document.header[i] = "\\font_roman default"
980 i = find_token(document.header, "\\font_sans", 0)
982 val = get_value(document.header, "\\font_sans", i)
983 if val in texgyre_fonts:
984 preamble = "\\usepackage{%s}" % val
985 add_to_preamble(document, [preamble])
986 document.header[i] = "\\font_sans default"
987 i = find_token(document.header, "\\font_typewriter", 0)
989 val = get_value(document.header, "\\font_typewriter", i)
990 if val in texgyre_fonts:
991 preamble = "\\usepackage{%s}" % val
992 add_to_preamble(document, [preamble])
993 document.header[i] = "\\font_typewriter default"
996 def revert_ipadeco(document):
997 " Revert IPA decorations to ERT "
1000 i = find_token(document.body, "\\begin_inset IPADeco", i)
1003 end = find_end_of_inset(document.body, i)
1005 document.warning("Can't find end of inset at line " + str(i))
1008 line = document.body[i]
1009 rx = re.compile(r'\\begin_inset IPADeco (.*)$')
1011 decotype = m.group(1)
1012 if decotype != "toptiebar" and decotype != "bottomtiebar":
1013 document.warning("Invalid IPADeco type: " + decotype)
1016 blay = find_token(document.body, "\\begin_layout Plain Layout", i, end)
1018 document.warning("Can't find layout for inset at line " + str(i))
1021 bend = find_end_of_layout(document.body, blay)
1023 document.warning("Malformed LyX document: Could not find end of IPADeco inset's layout.")
1026 substi = ["\\begin_inset ERT", "status collapsed", "",
1027 "\\begin_layout Plain Layout", "", "", "\\backslash",
1028 decotype + "{", "\\end_layout", "", "\\end_inset"]
1029 substj = ["\\size default", "", "\\begin_inset ERT", "status collapsed", "",
1030 "\\begin_layout Plain Layout", "", "}", "\\end_layout", "", "\\end_inset"]
1031 # do the later one first so as not to mess up the numbering
1032 document.body[bend:end + 1] = substj
1033 document.body[i:blay + 1] = substi
1034 i = end + len(substi) + len(substj) - (end - bend) - (blay - i) - 2
1035 add_to_preamble(document, "\\usepackage{tipa}")
1038 def revert_ipachar(document):
1039 ' Revert \\IPAChar to ERT '
1042 while i < len(document.body):
1043 m = re.match(r'(.*)\\IPAChar \\(\w+\{\w+\})(.*)', document.body[i])
1047 ipachar = m.group(2)
1050 '\\begin_inset ERT',
1051 'status collapsed', '',
1052 '\\begin_layout Standard',
1053 '', '', '\\backslash',
1058 document.body[i: i+1] = subst
1063 add_to_preamble(document, "\\usepackage{tone}")
1066 def revert_minionpro(document):
1067 " Revert native MinionPro font definition to LaTeX "
1069 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1070 i = find_token(document.header, "\\font_roman minionpro", 0)
1073 j = find_token(document.header, "\\font_osf true", 0)
1076 preamble = "\\usepackage"
1078 document.header[j] = "\\font_osf false"
1081 preamble += "{MinionPro}"
1082 add_to_preamble(document, [preamble])
1083 document.header[i] = "\\font_roman default"
1086 def revert_mathfonts(document):
1087 " Revert native math font definitions to LaTeX "
1089 i = find_token(document.header, "\\font_math", 0)
1092 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1093 val = get_value(document.header, "\\font_math", i)
1094 if val == "eulervm":
1095 add_to_preamble(document, "\\usepackage{eulervm}")
1096 elif val == "default":
1098 "lmodern": "\\renewcommand{\\rmdefault}{lmr}",
1099 "minionpro": "\\usepackage[onlytext,lf]{MinionPro}",
1100 "minionpro-osf": "\\usepackage[onlytext]{MinionPro}",
1101 "palatino": "\\renewcommand{\\rmdefault}{ppl}",
1102 "palatino-osf": "\\renewcommand{\\rmdefault}{pplj}",
1103 "times": "\\renewcommand{\\rmdefault}{ptm}",
1104 "utopia": "\\renewcommand{\\rmdefault}{futs}",
1105 "utopia-osf": "\\renewcommand{\\rmdefault}{futj}",
1107 j = find_token(document.header, "\\font_roman", 0)
1109 rm = get_value(document.header, "\\font_roman", j)
1110 k = find_token(document.header, "\\font_osf true", 0)
1113 if rm in mathfont_dict.keys():
1114 add_to_preamble(document, mathfont_dict[rm])
1115 document.header[j] = "\\font_roman default"
1117 document.header[k] = "\\font_osf false"
1118 del document.header[i]
1121 def revert_mdnomath(document):
1122 " Revert mathdesign and fourier without math "
1124 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1126 "md-charter": "mdbch",
1127 "md-utopia": "mdput",
1128 "md-garamond": "mdugm"
1130 i = find_token(document.header, "\\font_roman", 0)
1133 val = get_value(document.header, "\\font_roman", i)
1134 if val in mathdesign_dict.keys():
1135 j = find_token(document.header, "\\font_math", 0)
1137 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1138 mval = get_value(document.header, "\\font_math", j)
1139 if mval == "default":
1140 document.header[i] = "\\font_roman default"
1141 add_to_preamble(document, "\\renewcommand{\\rmdefault}{%s}" % mathdesign_dict[val])
1143 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1146 def convert_mdnomath(document):
1147 " Change mathdesign font name "
1149 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1151 "mdbch": "md-charter",
1152 "mdput": "md-utopia",
1153 "mdugm": "md-garamond"
1155 i = find_token(document.header, "\\font_roman", 0)
1158 val = get_value(document.header, "\\font_roman", i)
1159 if val in mathdesign_dict.keys():
1160 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1163 def revert_newtxmath(document):
1164 " Revert native newtxmath definitions to LaTeX "
1166 i = find_token(document.header, "\\font_math", 0)
1169 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1170 val = get_value(document.header, "\\font_math", i)
1172 "libertine-ntxm": "\\usepackage[libertine]{newtxmath}",
1173 "minion-ntxm": "\\usepackage[minion]{newtxmath}",
1174 "newtxmath": "\\usepackage{newtxmath}",
1176 if val in mathfont_dict.keys():
1177 add_to_preamble(document, mathfont_dict[val])
1178 document.header[i] = "\\font_math auto"
1181 def revert_biolinum(document):
1182 " Revert native biolinum font definition to LaTeX "
1184 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1185 i = find_token(document.header, "\\font_sans biolinum", 0)
1188 j = find_token(document.header, "\\font_osf true", 0)
1191 preamble = "\\usepackage"
1194 preamble += "{biolinum-type1}"
1195 add_to_preamble(document, [preamble])
1196 document.header[i] = "\\font_sans default"
1199 def revert_uop(document):
1200 " Revert native URW Classico (Optima) font definition to LaTeX "
1202 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1203 i = find_token(document.header, "\\font_sans uop", 0)
1205 preamble = "\\renewcommand{\\sfdefault}{uop}"
1206 add_to_preamble(document, [preamble])
1207 document.header[i] = "\\font_sans default"
1210 def convert_latexargs(document):
1211 " Convert InsetArgument to new syntax "
1213 if find_token(document.body, "\\begin_inset Argument", 0) == -1:
1217 # A list of layouts (document classes) with only optional or no arguments.
1218 # These can be safely converted to the new syntax
1219 # (I took the liberty to add some of my personal layouts/modules here; JSP)
1220 safe_layouts = ["aa", "aapaper", "aastex", "achemso", "acmsiggraph", "AEA",
1221 "agu-dtd", "agums", "agutex", "amsart", "amsbook", "apa",
1222 "arab-article", "armenian-article", "article-beamer", "article",
1223 "beamer", "book", "broadway", "chess", "cl2emult", "ctex-article",
1224 "ctex-book", "ctex-report", "dinbrief", "docbook-book", "docbook-chapter",
1225 "docbook", "docbook-section", "doublecol-new", "dtk", "ectaart", "egs",
1226 "elsarticle", "elsart", "entcs", "europecv", "extarticle", "extbook",
1227 "extletter", "extreport", "foils", "frletter", "g-brief2", "g-brief",
1228 "heb-article", "heb-letter", "hollywood", "IEEEtran", "ijmpc", "ijmpd",
1229 "iopart", "isprs", "jarticle", "jasatex", "jbook", "jgrga", "jreport",
1230 "jsarticle", "jsbeamer", "jsbook", "jss", "kluwer", "latex8", "letter", "lettre",
1231 "literate-article", "literate-book", "literate-report", "llncs", "ltugboat",
1232 "memoir", "moderncv", "mwart", "mwbk", "mwrep", "paper", "powerdot",
1233 "recipebook", "report", "revtex4", "revtex", "scrartcl", "scrarticle-beamer",
1234 "scrbook", "scrlettr", "scrlttr2", "scrreprt", "seminar", "siamltex",
1235 "sigplanconf", "simplecv", "singlecol", "singlecol-new", "slides", "spie",
1236 "svglobal3", "svglobal", "svjog", "svmono", "svmult", "svprobth", "tarticle",
1237 "tbook", "treport", "tufte-book", "tufte-handout"]
1238 # A list of "safe" modules, same as above
1239 safe_modules = ["biblatex", "beameraddons", "beamersession", "braille", "customHeadersFooters",
1240 "endnotes", "enumitem", "eqs-within-sections", "figs-within-sections", "fix-cm",
1241 "fixltx2e", "foottoend", "hanging", "jscharstyles", "knitr", "lilypond",
1242 "linguistics", "linguisticx", "logicalmkup", "minimalistic", "nomindex", "noweb",
1243 "pdfcomment", "sweave", "tabs-within-sections", "theorems-ams-bytype",
1244 "theorems-ams-extended-bytype", "theorems-ams-extended", "theorems-ams", "theorems-bytype",
1245 "theorems-chap-bytype", "theorems-chap", "theorems-named", "theorems-sec-bytype",
1246 "theorems-sec", "theorems-starred", "theorems-std", "todonotes"]
1247 # Modules we need to take care of
1248 caveat_modules = ["initials"]
1249 # information about the relevant styles in caveat_modules (number of opt and req args)
1250 # use this if we get more caveat_modules. For now, use hard coding (see below).
1251 # initials = [{'Layout' : 'Initial', 'opt' : 1, 'req' : 1}]
1253 # Is this a known safe layout?
1254 safe_layout = document.textclass in safe_layouts
1256 document.warning("Lyx2lyx knows nothing about textclass '%s'. "
1257 "Please check if short title insets have been converted correctly."
1258 % document.textclass)
1259 # Do we use unsafe or unknown modules
1260 mods = document.get_module_list()
1261 unknown_modules = False
1262 used_caveat_modules = list()
1264 if mod in safe_modules:
1266 if mod in caveat_modules:
1267 used_caveat_modules.append(mod)
1269 unknown_modules = True
1270 document.warning("Lyx2lyx knows nothing about module '%s'. "
1271 "Please check if short title insets have been converted correctly."
1276 i = find_token(document.body, "\\begin_inset Argument", i)
1280 if not safe_layout or unknown_modules:
1281 # We cannot do more here since we have no access to this layout.
1282 # InsetArgument itself will do the real work
1283 # (see InsetArgument::updateBuffer())
1284 document.body[i] = "\\begin_inset Argument 999"
1288 # Find containing paragraph layout
1289 parent = get_containing_layout(document.body, i)
1291 document.warning("Malformed lyx document: Can't find parent paragraph layout")
1298 if len(used_caveat_modules) > 0:
1299 # We know for now that this must be the initials module with the Initial layout
1300 # If we get more such modules, we need some automating.
1301 if parent[0] == "Initial":
1302 # Layout has 1 opt and 1 req arg.
1303 # Count the actual arguments
1305 for p in range(parbeg, parend):
1306 if document.body[p] == "\\begin_inset Argument":
1311 # Collect all arguments in this paragraph
1313 for p in range(parbeg, parend):
1314 if document.body[p] == "\\begin_inset Argument":
1316 if allowed_opts != -1:
1317 # We have less arguments than opt + required.
1318 # required must take precedence.
1319 if argnr > allowed_opts and argnr < first_req:
1321 document.body[p] = "\\begin_inset Argument %d" % argnr
1325 def revert_latexargs(document):
1326 " Revert InsetArgument to old syntax "
1329 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
1332 # Search for Argument insets
1333 i = find_token(document.body, "\\begin_inset Argument", i)
1336 m = rx.match(document.body[i])
1338 # No ID: inset already reverted
1341 # Find containing paragraph layout
1342 parent = get_containing_layout(document.body, i)
1344 document.warning("Malformed lyx document: Can't find parent paragraph layout")
1349 realparbeg = parent[3]
1350 # Collect all arguments in this paragraph
1352 for p in range(parbeg, parend):
1353 m = rx.match(document.body[p])
1355 val = int(m.group(1))
1356 j = find_end_of_inset(document.body, p)
1357 # Revert to old syntax
1358 document.body[p] = "\\begin_inset Argument"
1360 document.warning("Malformed lyx document: Can't find end of Argument inset")
1363 args[val] = document.body[p : j + 1]
1365 realparend = realparend - len(document.body[p : j + 1])
1366 # Remove arg inset at this position
1367 del document.body[p : j + 1]
1370 # Now sort the arg insets
1372 for f in sorted(args):
1375 # Insert the sorted arg insets at paragraph begin
1376 document.body[realparbeg : realparbeg] = subst
1378 i = realparbeg + 1 + len(subst)
1381 def revert_Argument_to_TeX_brace(document, line, n, nmax, environment):
1383 Reverts an InsetArgument to TeX-code
1385 revert_Argument_to_TeX_brace(document, LineOfBeginLayout, StartArgument, EndArgument, isEnvironment)
1386 LineOfBeginLayout is the line of the \begin_layout statement
1387 StartArgument is the number of the first argument that needs to be converted
1388 EndArgument is the number of the last argument that needs to be converted or the last defined one
1389 isEnvironment must be true, if the layout id for a LaTeX environment
1392 while lineArg != -1 and n < nmax + 1:
1393 lineArg = find_token(document.body, "\\begin_inset Argument " + str(n), line)
1395 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", lineArg)
1396 # we have to assure that no other inset is in the Argument
1397 beginInset = find_token(document.body, "\\begin_inset", beginPlain)
1398 endInset = find_token(document.body, "\\end_inset", beginPlain)
1401 while beginInset < endInset and beginInset != -1:
1402 beginInset = find_token(document.body, "\\begin_inset", k)
1403 endInset = find_token(document.body, "\\end_inset", l)
1406 if environment == False:
1407 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}{")
1408 del(document.body[lineArg : beginPlain + 1])
1410 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}")
1411 document.body[lineArg : beginPlain + 1] = put_cmd_in_ert("{")
1415 def revert_IEEEtran(document):
1417 Reverts InsetArgument of
1420 Biography without photo
1423 if document.textclass == "IEEEtran":
1429 i = find_token(document.body, "\\begin_layout Page headings", i)
1431 revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1434 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1436 revert_Argument_to_TeX_brace(document, j, 1, 1, True)
1439 k = find_token(document.body, "\\begin_layout Biography", k)
1440 kA = find_token(document.body, "\\begin_layout Biography without photo", k)
1441 if k == kA and k != -1:
1445 # start with the second argument, therefore 2
1446 revert_Argument_to_TeX_brace(document, k, 2, 2, True)
1448 if i == -1 and j == -1 and k == -1:
1452 def convert_TeX_brace_to_Argument(document, line, n, nmax, inset, environment):
1454 Converts TeX code for mandatory arguments to an InsetArgument
1455 The conversion of TeX code for optional arguments must be done with another routine
1456 !!! Be careful if the braces are different in your case as expected here:
1457 - "}{" separates mandatory arguments of commands
1458 - "}" + "{" separates mandatory arguments of commands
1459 - "}" + " " + "{" separates mandatory arguments of commands
1460 - { and } surround a mandatory argument of an environment
1462 convert_TeX_brace_to_Argument(document, LineOfBeginLayout/Inset, StartArgument, EndArgument, isInset, isEnvironment)
1463 LineOfBeginLayout/Inset is the line of the \begin_layout or \begin_inset statement
1464 StartArgument is the number of the first ERT that needs to be converted
1465 EndArgument is the number of the last ERT that needs to be converted
1466 isInset must be true, if braces inside an InsetLayout needs to be converted
1467 isEnvironment must be true, if the layout is for a LaTeX environment
1469 Todo: this routine can currently handle only one mandatory argument of environments
1474 while lineERT != -1 and n < nmax + 1:
1475 lineERT = find_token(document.body, "\\begin_inset ERT", lineERT)
1476 if environment == False and lineERT != -1:
1477 bracePair = find_token(document.body, "}{", lineERT)
1478 # assure that the "}{" is in this ERT
1479 if bracePair == lineERT + 5:
1480 end = find_token(document.body, "\\end_inset", bracePair)
1481 document.body[lineERT : end + 1] = ["\\end_layout", "", "\\end_inset"]
1483 # in the case that n > 1 we have optional arguments before
1484 # therefore detect them if any
1486 # first check if there is an argument
1487 lineArg = find_token(document.body, "\\begin_inset Argument", line)
1488 if lineArg < lineERT and lineArg != -1:
1489 # we have an argument, so now search backwards for its end
1490 # we must now assure that we don't find other insets like e.g. a newline
1491 endInsetArg = lineERT
1492 endLayoutArg = endInsetArg
1493 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
1494 endInsetArg = endInsetArg - 1
1495 endLayoutArg = endInsetArg
1496 endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
1497 endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
1498 line = endInsetArg + 1
1500 document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1502 document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1504 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1508 # now check the case that we have "}" + "{" in two ERTs
1510 endBrace = find_token(document.body, "}", lineERT)
1511 if endBrace == lineERT + 5:
1512 beginBrace = find_token(document.body, "{", endBrace)
1513 # assure that the ERTs are consecutive (11 or 12 depending if there is a space between the ERTs or not)
1514 if beginBrace == endBrace + 11 or beginBrace == endBrace + 12:
1515 end = find_token(document.body, "\\end_inset", beginBrace)
1516 document.body[lineERT : end + 1] = ["\\end_layout", "", "\\end_inset"]
1518 # in the case that n > 1 we have optional arguments before
1519 # therefore detect them if any
1521 # first check if there is an argument
1522 lineArg = find_token(document.body, "\\begin_inset Argument", line)
1523 if lineArg < lineERT and lineArg != -1:
1524 # we have an argument, so now search backwards for its end
1525 # we must now assure that we don't find other insets like e.g. a newline
1526 endInsetArg = lineERT
1527 endLayoutArg = endInsetArg
1528 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
1529 endInsetArg = endInsetArg - 1
1530 endLayoutArg = endInsetArg
1531 endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
1532 endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
1533 line = endInsetArg + 1
1535 document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1537 document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1539 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1542 # set the line where the next argument will be inserted
1543 if beginBrace == endBrace + 11:
1548 lineERT = lineERT + 1
1549 if environment == True and lineERT != -1:
1550 opening = find_token(document.body, "{", lineERT)
1551 if opening == lineERT + 5: # assure that the "{" is in this ERT
1552 end = find_token(document.body, "\\end_inset", opening)
1553 document.body[lineERT : end + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1555 lineERT2 = find_token(document.body, "\\begin_inset ERT", lineERT)
1556 closing = find_token(document.body, "}", lineERT2)
1557 if closing == lineERT2 + 5: # assure that the "}" is in this ERT
1558 end2 = find_token(document.body, "\\end_inset", closing)
1559 document.body[lineERT2 : end2 + 1] = ["\\end_layout", "", "\\end_inset"]
1561 lineERT = lineERT + 1
1564 def convert_IEEEtran(document):
1569 Biography without photo
1572 if document.textclass == "IEEEtran":
1578 i = find_token(document.body, "\\begin_layout Page headings", i)
1580 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1583 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1585 convert_TeX_brace_to_Argument(document, j, 1, 1, False, True)
1588 # assure that we don't handle Biography Biography without photo
1589 k = find_token(document.body, "\\begin_layout Biography", k)
1590 kA = find_token(document.body, "\\begin_layout Biography without photo", k - 1)
1591 if k == kA and k != -1:
1595 # the argument we want to convert is the second one
1596 convert_TeX_brace_to_Argument(document, k, 2, 2, False, True)
1598 if i == -1 and j == -1 and k == -1:
1602 def revert_AASTeX(document):
1603 " Reverts InsetArgument of Altaffilation to TeX-code "
1604 if document.textclass == "aastex":
1608 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1610 revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1616 def convert_AASTeX(document):
1617 " Converts ERT of Altaffilation to InsetArgument "
1618 if document.textclass == "aastex":
1622 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1624 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1630 def revert_AGUTeX(document):
1631 " Reverts InsetArgument of Author affiliation to TeX-code "
1632 if document.textclass == "agutex":
1636 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1638 revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1644 def convert_AGUTeX(document):
1645 " Converts ERT of Author affiliation to InsetArgument "
1646 if document.textclass == "agutex":
1650 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1652 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1658 def revert_IJMP(document):
1659 " Reverts InsetArgument of MarkBoth to TeX-code "
1660 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1664 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1666 revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1672 def convert_IJMP(document):
1673 " Converts ERT of MarkBoth to InsetArgument "
1674 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1678 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1680 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1686 def revert_SIGPLAN(document):
1687 " Reverts InsetArgument of MarkBoth to TeX-code "
1688 if document.textclass == "sigplanconf":
1693 i = find_token(document.body, "\\begin_layout Conference", i)
1695 revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1698 j = find_token(document.body, "\\begin_layout Author", j)
1700 revert_Argument_to_TeX_brace(document, j, 1, 2, False)
1702 if i == -1 and j == -1:
1706 def convert_SIGPLAN(document):
1707 " Converts ERT of MarkBoth to InsetArgument "
1708 if document.textclass == "sigplanconf":
1713 i = find_token(document.body, "\\begin_layout Conference", i)
1715 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1718 j = find_token(document.body, "\\begin_layout Author", j)
1720 convert_TeX_brace_to_Argument(document, j, 1, 2, False, False)
1722 if i == -1 and j == -1:
1726 def revert_SIGGRAPH(document):
1727 " Reverts InsetArgument of Flex CRcat to TeX-code "
1728 if document.textclass == "acmsiggraph":
1732 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1734 revert_Argument_to_TeX_brace(document, i, 1, 3, False)
1740 def convert_SIGGRAPH(document):
1741 " Converts ERT of Flex CRcat to InsetArgument "
1742 if document.textclass == "acmsiggraph":
1746 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1748 convert_TeX_brace_to_Argument(document, i, 1, 3, True, False)
1754 def revert_EuropeCV(document):
1755 " Reverts InsetArgument of Flex CRcat to TeX-code "
1756 if document.textclass == "europecv":
1763 i = find_token(document.body, "\\begin_layout Item", i)
1765 revert_Argument_to_TeX_brace(document, i, 2, 2, False)
1768 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1770 revert_Argument_to_TeX_brace(document, j, 2, 2, False)
1773 k = find_token(document.body, "\\begin_layout Language", k)
1775 revert_Argument_to_TeX_brace(document, k, 2, 6, False)
1778 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1780 revert_Argument_to_TeX_brace(document, m, 2, 6, False)
1782 if i == -1 and j == -1 and k == -1 and m == -1:
1786 def convert_EuropeCV(document):
1787 " Converts ERT of Flex CRcat to InsetArgument "
1788 if document.textclass == "europecv":
1795 i = find_token(document.body, "\\begin_layout Item", i)
1797 convert_TeX_brace_to_Argument(document, i, 2, 2, False, False)
1800 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1802 convert_TeX_brace_to_Argument(document, j, 2, 2, False, False)
1805 k = find_token(document.body, "\\begin_layout Language", k)
1807 convert_TeX_brace_to_Argument(document, k, 2, 6, False, False)
1810 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1812 convert_TeX_brace_to_Argument(document, m, 2, 6, False, False)
1814 if i == -1 and j == -1 and k == -1 and m == -1:
1818 def revert_literate(document):
1819 " Revert Literate document to old format "
1820 if del_token(document.header, "noweb", 0):
1821 document.textclass = "literate-" + document.textclass
1824 i = find_token(document.body, "\\begin_layout Chunk", i)
1827 document.body[i] = "\\begin_layout Scrap"
1831 def convert_literate(document):
1832 " Convert Literate document to new format"
1833 i = find_token(document.header, "\\textclass", 0)
1834 if (i != -1) and "literate-" in document.header[i]:
1835 document.textclass = document.header[i].replace("\\textclass literate-", "")
1836 j = find_token(document.header, "\\begin_modules", 0)
1838 document.header.insert(j + 1, "noweb")
1840 document.header.insert(i + 1, "\\end_modules")
1841 document.header.insert(i + 1, "noweb")
1842 document.header.insert(i + 1, "\\begin_modules")
1845 i = find_token(document.body, "\\begin_layout Scrap", i)
1848 document.body[i] = "\\begin_layout Chunk"
1852 def revert_itemargs(document):
1853 " Reverts \\item arguments to TeX-code "
1856 i = find_token(document.body, "\\begin_inset Argument item:", i)
1859 j = find_end_of_inset(document.body, i)
1860 # Find containing paragraph layout
1861 parent = get_containing_layout(document.body, i)
1863 document.warning("Malformed lyx document: Can't find parent paragraph layout")
1867 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
1868 endPlain = find_end_of_layout(document.body, beginPlain)
1869 content = document.body[beginPlain + 1 : endPlain]
1870 del document.body[i:j+1]
1871 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
1872 document.body[parbeg : parbeg] = subst
1876 def revert_garamondx_newtxmath(document):
1877 " Revert native garamond newtxmath definition to LaTeX "
1879 i = find_token(document.header, "\\font_math", 0)
1882 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1883 val = get_value(document.header, "\\font_math", i)
1884 if val == "garamondx-ntxm":
1885 add_to_preamble(document, "\\usepackage[garamondx]{newtxmath}")
1886 document.header[i] = "\\font_math auto"
1889 def revert_garamondx(document):
1890 " Revert native garamond font definition to LaTeX "
1892 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1893 i = find_token(document.header, "\\font_roman garamondx", 0)
1896 j = find_token(document.header, "\\font_osf true", 0)
1899 preamble = "\\usepackage"
1901 preamble += "[osfI]"
1902 preamble += "{garamondx}"
1903 add_to_preamble(document, [preamble])
1904 document.header[i] = "\\font_roman default"
1907 def convert_beamerargs(document):
1908 " Converts beamer arguments to new layout "
1910 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
1911 if document.textclass not in beamer_classes:
1914 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
1915 list_layouts = ["Itemize", "Enumerate", "Description"]
1916 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
1920 i = find_token(document.body, "\\begin_inset Argument", i)
1923 # Find containing paragraph layout
1924 parent = get_containing_layout(document.body, i)
1926 document.warning("Malformed lyx document: Can't find parent paragraph layout")
1931 layoutname = parent[0]
1932 for p in range(parbeg, parend):
1933 if layoutname in shifted_layouts:
1934 m = rx.match(document.body[p])
1936 argnr = int(m.group(1))
1938 document.body[p] = "\\begin_inset Argument %d" % argnr
1939 if layoutname == "AgainFrame":
1940 m = rx.match(document.body[p])
1942 document.body[p] = "\\begin_inset Argument 3"
1943 if document.body[p + 4] == "\\begin_inset ERT":
1944 if document.body[p + 9].startswith("<"):
1945 # This is an overlay specification
1947 document.body[p + 9] = document.body[p + 9][1:]
1948 if document.body[p + 9].endswith(">"):
1950 document.body[p + 9] = document.body[p + 9][:-1]
1952 document.body[p] = "\\begin_inset Argument 2"
1953 if layoutname in list_layouts:
1954 m = rx.match(document.body[p])
1956 if m.group(1) == "1":
1957 if document.body[p + 4] == "\\begin_inset ERT":
1958 if document.body[p + 9].startswith("<"):
1959 # This is an overlay specification
1961 document.body[p + 9] = document.body[p + 9][1:]
1962 if document.body[p + 9].endswith(">"):
1964 document.body[p + 9] = document.body[p + 9][:-1]
1965 elif layoutname != "Itemize":
1967 document.body[p] = "\\begin_inset Argument 2"
1971 def convert_againframe_args(document):
1972 " Converts beamer AgainFrame to new layout "
1974 # FIXME: This currently only works if the arguments are in one single ERT
1976 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
1977 if document.textclass not in beamer_classes:
1982 i = find_token(document.body, "\\begin_layout AgainFrame", i)
1985 parent = get_containing_layout(document.body, i)
1987 document.warning("Wrong parent layout!")
1991 if document.body[parbeg] == "\\begin_inset ERT":
1992 ertcont = parbeg + 5
1993 if document.body[ertcont].startswith("[<"):
1994 # This is a default overlay specification
1996 document.body[ertcont] = document.body[ertcont][2:]
1997 if document.body[ertcont].endswith(">]"):
1999 document.body[ertcont] = document.body[ertcont][:-2]
2000 elif document.body[ertcont].endswith("]"):
2002 tok = document.body[ertcont].find('>][')
2004 subst = [document.body[ertcont][:tok],
2005 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2006 'status collapsed', '', '\\begin_layout Plain Layout',
2007 document.body[ertcont][tok + 3:-1]]
2008 document.body[ertcont : ertcont + 1] = subst
2009 # Convert to ArgInset
2010 document.body[parbeg] = "\\begin_inset Argument 2"
2013 elif document.body[ertcont].startswith("<"):
2014 # This is an overlay specification
2016 document.body[ertcont] = document.body[ertcont][1:]
2017 if document.body[ertcont].endswith(">"):
2019 document.body[ertcont] = document.body[ertcont][:-1]
2020 # Convert to ArgInset
2021 document.body[parbeg] = "\\begin_inset Argument 1"
2022 elif document.body[ertcont].endswith(">]"):
2024 tok = document.body[ertcont].find('>[<')
2026 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2027 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2028 'status collapsed', '', '\\begin_layout Plain Layout',
2029 document.body[ertcont][tok + 3:-2]]
2030 # Convert to ArgInset
2031 document.body[parbeg] = "\\begin_inset Argument 1"
2032 elif document.body[ertcont].endswith("]"):
2034 tok = document.body[ertcont].find('>[<')
2037 tokk = document.body[ertcont].find('>][')
2039 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2040 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2041 'status collapsed', '', '\\begin_layout Plain Layout',
2042 document.body[ertcont][tok + 3:tokk],
2043 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2044 'status collapsed', '', '\\begin_layout Plain Layout',
2045 document.body[ertcont][tokk + 3:-1]]
2047 tokk = document.body[ertcont].find('>[')
2049 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tokk],
2050 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2051 'status collapsed', '', '\\begin_layout Plain Layout',
2052 document.body[ertcont][tokk + 2:-1]]
2053 # Convert to ArgInset
2054 document.body[parbeg] = "\\begin_inset Argument 1"
2057 elif document.body[ertcont].startswith("["):
2058 # This is an ERT option
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 3"
2071 def convert_corollary_args(document):
2072 " Converts beamer corrolary-style ERT arguments native InsetArgs "
2074 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2075 if document.textclass not in beamer_classes:
2078 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2079 for lay in corollary_layouts:
2082 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2085 parent = get_containing_layout(document.body, i)
2087 document.warning("Wrong parent layout!")
2091 if document.body[parbeg] == "\\begin_inset ERT":
2092 ertcont = parbeg + 5
2093 if document.body[ertcont].startswith("<"):
2094 # This is an overlay specification
2096 document.body[ertcont] = document.body[ertcont][1:]
2097 if document.body[ertcont].endswith(">"):
2099 document.body[ertcont] = document.body[ertcont][:-1]
2100 elif document.body[ertcont].endswith("]"):
2102 tok = document.body[ertcont].find('>[')
2104 subst = [document.body[ertcont][:tok],
2105 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2106 'status collapsed', '', '\\begin_layout Plain Layout',
2107 document.body[ertcont][tok + 2:-1]]
2108 document.body[ertcont : ertcont + 1] = subst
2109 # Convert to ArgInset
2110 document.body[parbeg] = "\\begin_inset Argument 1"
2113 elif document.body[ertcont].startswith("["):
2114 # This is an ERT option
2116 document.body[ertcont] = document.body[ertcont][1:]
2117 if document.body[ertcont].endswith("]"):
2119 document.body[ertcont] = document.body[ertcont][:-1]
2120 # Convert to ArgInset
2121 document.body[parbeg] = "\\begin_inset Argument 2"
2128 def convert_quote_args(document):
2129 " Converts beamer quote style ERT args to native InsetArgs "
2131 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2132 if document.textclass not in beamer_classes:
2135 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2136 for lay in quote_layouts:
2139 i = find_token(document.body, "\\begin_layout " + lay, i)
2142 parent = get_containing_layout(document.body, i)
2144 document.warning("Wrong parent layout!")
2148 if document.body[parbeg] == "\\begin_inset ERT":
2149 if document.body[i + 6].startswith("<"):
2150 # This is an overlay specification
2152 document.body[i + 6] = document.body[i + 6][1:]
2153 if document.body[i + 6].endswith(">"):
2155 document.body[i + 6] = document.body[i + 6][:-1]
2156 # Convert to ArgInset
2157 document.body[i + 1] = "\\begin_inset Argument 1"
2161 def revert_beamerargs(document):
2162 " Reverts beamer arguments to old layout "
2164 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2165 if document.textclass not in beamer_classes:
2169 list_layouts = ["Itemize", "Enumerate", "Description"]
2170 headings = ["Part", "Section", "Section*", "Subsection", "Subsection*",
2171 "Subsubsection", "Subsubsection*", "FrameSubtitle", "NoteItem"]
2172 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2173 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2174 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2177 i = find_token(document.body, "\\begin_inset Argument", i)
2180 # Find containing paragraph layout
2181 parent = get_containing_layout(document.body, i)
2183 document.warning("Malformed lyx document: Can't find parent paragraph layout")
2188 realparbeg = parent[3]
2189 layoutname = parent[0]
2191 for p in range(parbeg, parend):
2195 if layoutname in headings:
2196 m = rx.match(document.body[p])
2200 # Find containing paragraph layout
2201 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2202 endPlain = find_end_of_layout(document.body, beginPlain)
2203 endInset = find_end_of_inset(document.body, p)
2204 argcontent = document.body[beginPlain + 1 : endPlain]
2206 realparend = realparend - len(document.body[p : endInset + 1])
2208 del document.body[p : endInset + 1]
2209 if layoutname == "FrameSubtitle":
2210 pre = put_cmd_in_ert("\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2211 elif layoutname == "NoteItem":
2212 pre = put_cmd_in_ert("\\note<") + argcontent + put_cmd_in_ert(">[item]")
2213 elif layoutname.endswith('*'):
2214 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower()[:-1] + "<") + argcontent + put_cmd_in_ert(">*")
2216 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2217 secarg = find_token(document.body, "\\begin_inset Argument 2", parbeg, parend)
2219 # Find containing paragraph layout
2220 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", secarg)
2221 endPlain = find_end_of_layout(document.body, beginPlain)
2222 endInset = find_end_of_inset(document.body, secarg)
2223 argcontent = document.body[beginPlain + 1 : endPlain]
2225 realparend = realparend - len(document.body[secarg : endInset + 1])
2226 del document.body[secarg : endInset + 1]
2227 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2228 pre += put_cmd_in_ert("{")
2229 document.body[parbeg] = "\\begin_layout Standard"
2230 document.body[realparbeg : realparbeg] = pre
2231 pe = find_end_of_layout(document.body, parbeg)
2232 post = put_cmd_in_ert("}")
2233 document.body[pe : pe] = post
2234 realparend += len(pre) + len(post)
2235 if layoutname == "AgainFrame":
2236 m = rx.match(document.body[p])
2240 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2241 endPlain = find_end_of_layout(document.body, beginPlain)
2242 endInset = find_end_of_inset(document.body, p)
2243 content = document.body[beginPlain + 1 : endPlain]
2245 realparend = realparend - len(document.body[p : endInset + 1])
2247 del document.body[p : endInset + 1]
2248 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2249 document.body[realparbeg : realparbeg] = subst
2250 if layoutname == "Overprint":
2251 m = rx.match(document.body[p])
2255 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2256 endPlain = find_end_of_layout(document.body, beginPlain)
2257 endInset = find_end_of_inset(document.body, p)
2258 content = document.body[beginPlain + 1 : endPlain]
2260 realparend = realparend - len(document.body[p : endInset + 1])
2262 del document.body[p : endInset + 1]
2263 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2264 document.body[realparbeg : realparbeg] = subst
2265 if layoutname == "OverlayArea":
2266 m = rx.match(document.body[p])
2270 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2271 endPlain = find_end_of_layout(document.body, beginPlain)
2272 endInset = find_end_of_inset(document.body, p)
2273 content = document.body[beginPlain + 1 : endPlain]
2275 realparend = realparend - len(document.body[p : endInset + 1])
2277 del document.body[p : endInset + 1]
2278 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2279 document.body[realparbeg : realparbeg] = subst
2280 if layoutname in list_layouts:
2281 m = rx.match(document.body[p])
2285 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2286 endPlain = find_end_of_layout(document.body, beginPlain)
2287 endInset = find_end_of_inset(document.body, p)
2288 content = document.body[beginPlain + 1 : endPlain]
2290 realparend = realparend - len(document.body[p : endInset + 1])
2292 del document.body[p : endInset + 1]
2293 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2294 document.body[realparbeg : realparbeg] = subst
2295 elif argnr == "item:1":
2296 j = find_end_of_inset(document.body, i)
2297 # Find containing paragraph layout
2298 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2299 endPlain = find_end_of_layout(document.body, beginPlain)
2300 content = document.body[beginPlain + 1 : endPlain]
2301 del document.body[i:j+1]
2302 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2303 document.body[realparbeg : realparbeg] = subst
2304 elif argnr == "item:2":
2305 j = find_end_of_inset(document.body, i)
2306 # Find containing paragraph layout
2307 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2308 endPlain = find_end_of_layout(document.body, beginPlain)
2309 content = document.body[beginPlain + 1 : endPlain]
2310 del document.body[i:j+1]
2311 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2312 document.body[realparbeg : realparbeg] = subst
2313 if layoutname in quote_layouts:
2314 m = rx.match(document.body[p])
2318 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2319 endPlain = find_end_of_layout(document.body, beginPlain)
2320 endInset = find_end_of_inset(document.body, p)
2321 content = document.body[beginPlain + 1 : endPlain]
2323 realparend = realparend - len(document.body[p : endInset + 1])
2325 del document.body[p : endInset + 1]
2326 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2327 document.body[realparbeg : realparbeg] = subst
2328 if layoutname in corollary_layouts:
2329 m = rx.match(document.body[p])
2333 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2334 endPlain = find_end_of_layout(document.body, beginPlain)
2335 endInset = find_end_of_inset(document.body, p)
2336 content = document.body[beginPlain + 1 : endPlain]
2338 realparend = realparend - len(document.body[p : endInset + 1])
2340 del document.body[p : endInset + 1]
2341 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2342 document.body[realparbeg : realparbeg] = subst
2347 def revert_beamerargs2(document):
2348 " Reverts beamer arguments to old layout, step 2 "
2350 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2351 if document.textclass not in beamer_classes:
2355 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2356 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2357 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2360 i = find_token(document.body, "\\begin_inset Argument", i)
2363 # Find containing paragraph layout
2364 parent = get_containing_layout(document.body, i)
2366 document.warning("Malformed lyx document: Can't find parent paragraph layout")
2371 realparbeg = parent[3]
2372 layoutname = parent[0]
2374 for p in range(parbeg, parend):
2378 if layoutname in shifted_layouts:
2379 m = rx.match(document.body[p])
2383 document.body[p] = "\\begin_inset Argument 1"
2384 if layoutname in corollary_layouts:
2385 m = rx.match(document.body[p])
2389 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2390 endPlain = find_end_of_layout(document.body, beginPlain)
2391 endInset = find_end_of_inset(document.body, p)
2392 content = document.body[beginPlain + 1 : endPlain]
2394 realparend = realparend - len(document.body[p : endInset + 1])
2396 del document.body[p : endInset + 1]
2397 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2398 document.body[realparbeg : realparbeg] = subst
2399 if layoutname == "OverlayArea":
2400 m = rx.match(document.body[p])
2404 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2405 endPlain = find_end_of_layout(document.body, beginPlain)
2406 endInset = find_end_of_inset(document.body, p)
2407 content = document.body[beginPlain + 1 : endPlain]
2409 realparend = realparend - len(document.body[p : endInset + 1])
2411 del document.body[p : endInset + 1]
2412 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2413 document.body[realparbeg : realparbeg] = subst
2414 if layoutname == "AgainFrame":
2415 m = rx.match(document.body[p])
2419 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2420 endPlain = find_end_of_layout(document.body, beginPlain)
2421 endInset = find_end_of_inset(document.body, p)
2422 content = document.body[beginPlain + 1 : endPlain]
2424 realparend = realparend - len(document.body[p : endInset + 1])
2426 del document.body[p : endInset + 1]
2427 subst = put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
2428 document.body[realparbeg : realparbeg] = subst
2432 def revert_beamerargs3(document):
2433 " Reverts beamer arguments to old layout, step 3 "
2435 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2436 if document.textclass not in beamer_classes:
2439 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2442 i = find_token(document.body, "\\begin_inset Argument", i)
2445 # Find containing paragraph layout
2446 parent = get_containing_layout(document.body, i)
2448 document.warning("Malformed lyx document: Can't find parent paragraph layout")
2453 realparbeg = parent[3]
2454 layoutname = parent[0]
2456 for p in range(parbeg, parend):
2460 if layoutname == "AgainFrame":
2461 m = rx.match(document.body[p])
2465 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2466 endPlain = find_end_of_layout(document.body, beginPlain)
2467 endInset = find_end_of_inset(document.body, p)
2468 content = document.body[beginPlain + 1 : endPlain]
2470 realparend = realparend - len(document.body[p : endInset + 1])
2472 del document.body[p : endInset + 1]
2473 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2474 document.body[realparbeg : realparbeg] = subst
2478 def revert_beamerflex(document):
2479 " Reverts beamer Flex insets "
2481 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2482 if document.textclass not in beamer_classes:
2485 new_flexes = {"Emphasize" : "\\emph", "Only" : "\\only", "Uncover" : "\\uncover",
2486 "Visible" : "\\visible", "Invisible" : "\\invisible",
2487 "Alternative" : "\\alt", "Beamer_Note" : "\\note"}
2488 old_flexes = {"Alert" : "\\alert", "Structure" : "\\structure"}
2489 rx = re.compile(r'^\\begin_inset Flex (.+)$')
2493 i = find_token(document.body, "\\begin_inset Flex", i)
2496 m = rx.match(document.body[i])
2498 flextype = m.group(1)
2499 z = find_end_of_inset(document.body, i)
2501 document.warning("Can't find end of Flex " + flextype + " inset.")
2504 if flextype in new_flexes:
2505 pre = put_cmd_in_ert(new_flexes[flextype])
2506 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2508 argend = find_end_of_inset(document.body, arg)
2510 document.warning("Can't find end of Argument!")
2513 # Find containing paragraph layout
2514 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2515 endPlain = find_end_of_layout(document.body, beginPlain)
2516 argcontent = document.body[beginPlain + 1 : endPlain]
2518 z = z - len(document.body[arg : argend + 1])
2520 del document.body[arg : argend + 1]
2521 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2522 arg = find_token(document.body, "\\begin_inset Argument 2", i, z)
2524 argend = find_end_of_inset(document.body, arg)
2526 document.warning("Can't find end of Argument!")
2529 # Find containing paragraph layout
2530 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2531 endPlain = find_end_of_layout(document.body, beginPlain)
2532 argcontent = document.body[beginPlain + 1 : endPlain]
2534 z = z - len(document.body[arg : argend + 1])
2536 del document.body[arg : argend + 1]
2537 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2538 pre += put_cmd_in_ert("{")
2539 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2540 endPlain = find_end_of_layout(document.body, beginPlain)
2542 z = z - len(document.body[i : beginPlain + 1])
2544 document.body[i : beginPlain + 1] = pre
2545 post = put_cmd_in_ert("}")
2546 document.body[z - 2 : z + 1] = post
2547 elif flextype in old_flexes:
2548 pre = put_cmd_in_ert(old_flexes[flextype])
2549 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 pre += put_cmd_in_ert("{")
2568 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2569 endPlain = find_end_of_layout(document.body, beginPlain)
2571 z = z - len(document.body[i : beginPlain + 1])
2573 document.body[i : beginPlain + 1] = pre
2574 post = put_cmd_in_ert("}")
2575 document.body[z - 2 : z + 1] = post
2580 def revert_beamerblocks(document):
2581 " Reverts beamer block arguments to ERT "
2583 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2584 if document.textclass not in beamer_classes:
2587 blocks = ["Block", "ExampleBlock", "AlertBlock"]
2589 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2592 i = find_token(document.body, "\\begin_inset Argument", i)
2595 # Find containing paragraph layout
2596 parent = get_containing_layout(document.body, i)
2598 document.warning("Malformed lyx document: Can't find parent paragraph layout")
2603 realparbeg = parent[3]
2604 layoutname = parent[0]
2606 for p in range(parbeg, parend):
2610 if layoutname in blocks:
2611 m = rx.match(document.body[p])
2615 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2616 endPlain = find_end_of_layout(document.body, beginPlain)
2617 endInset = find_end_of_inset(document.body, p)
2618 content = document.body[beginPlain + 1 : endPlain]
2620 realparend = realparend - len(document.body[p : endInset + 1])
2622 del document.body[p : endInset + 1]
2623 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2624 document.body[realparbeg : realparbeg] = subst
2626 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2627 endPlain = find_end_of_layout(document.body, beginPlain)
2628 endInset = find_end_of_inset(document.body, p)
2629 content = document.body[beginPlain + 1 : endPlain]
2631 realparend = realparend - len(document.body[p : endInset + 1])
2633 del document.body[p : endInset + 1]
2634 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2635 document.body[realparbeg : realparbeg] = subst
2640 def convert_beamerblocks(document):
2641 " Converts beamer block ERT args to native InsetArgs "
2643 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2644 if document.textclass not in beamer_classes:
2647 blocks = ["Block", "ExampleBlock", "AlertBlock"]
2651 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2654 parent = get_containing_layout(document.body, i)
2655 if parent == False or parent[1] != i:
2656 document.warning("Wrong parent layout!")
2662 if document.body[parbeg] == "\\begin_inset ERT":
2663 ertcont = parbeg + 5
2665 if document.body[ertcont].startswith("<"):
2666 # This is an overlay specification
2668 document.body[ertcont] = document.body[ertcont][1:]
2669 if document.body[ertcont].endswith(">"):
2671 document.body[ertcont] = document.body[ertcont][:-1]
2672 # Convert to ArgInset
2673 document.body[parbeg] = "\\begin_inset Argument 1"
2674 elif document.body[ertcont].endswith("}"):
2676 tok = document.body[ertcont].find('>{')
2678 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2679 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2680 'status collapsed', '', '\\begin_layout Plain Layout',
2681 document.body[ertcont][tok + 2:-1]]
2682 # Convert to ArgInset
2683 document.body[parbeg] = "\\begin_inset Argument 1"
2684 elif document.body[ertcont].startswith("{"):
2685 # This is the block title
2686 if document.body[ertcont].endswith("}"):
2687 # strip off the braces
2688 document.body[ertcont] = document.body[ertcont][1:-1]
2689 # Convert to ArgInset
2690 document.body[parbeg] = "\\begin_inset Argument 2"
2691 elif count_pars_in_inset(document.body, ertcont) > 1:
2692 # Multipar ERT. Skip this.
2695 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True)
2698 j = find_end_of_layout(document.body, i)
2700 document.warning("end of layout not found!")
2701 k = find_token(document.body, "\\begin_inset Argument", i, j)
2703 document.warning("InsetArgument not found!")
2705 l = find_end_of_inset(document.body, k)
2706 m = find_token(document.body, "\\begin_inset ERT", l, j)
2719 supported_versions = ["2.1.0","2.1"]
2722 [415, [convert_undertilde]],
2724 [417, [convert_japanese_encodings]],
2727 [420, [convert_biblio_style]],
2728 [421, [convert_longtable_captions]],
2729 [422, [convert_use_packages]],
2730 [423, [convert_use_mathtools]],
2731 [424, [convert_cite_engine_type]],
2735 [428, [convert_cell_rotation]],
2736 [429, [convert_table_rotation]],
2737 [430, [convert_listoflistings]],
2738 [431, [convert_use_amssymb]],
2740 [433, [convert_armenian]],
2748 [441, [convert_mdnomath]],
2753 [446, [convert_latexargs]],
2754 [447, [convert_IEEEtran, convert_AASTeX, convert_AGUTeX, convert_IJMP, convert_SIGPLAN, convert_SIGGRAPH, convert_EuropeCV]],
2755 [448, [convert_literate]],
2758 [451, [convert_beamerargs, convert_againframe_args, convert_corollary_args, convert_quote_args]],
2759 [452, [convert_beamerblocks]],
2760 [453, [convert_use_stmaryrd]]
2764 [452, [revert_use_stmaryrd]],
2765 [451, [revert_beamerblocks]],
2766 [450, [revert_beamerargs, revert_beamerargs2, revert_beamerargs3, revert_beamerflex]],
2767 [449, [revert_garamondx, revert_garamondx_newtxmath]],
2768 [448, [revert_itemargs]],
2769 [447, [revert_literate]],
2770 [446, [revert_IEEEtran, revert_AASTeX, revert_AGUTeX, revert_IJMP, revert_SIGPLAN, revert_SIGGRAPH, revert_EuropeCV]],
2771 [445, [revert_latexargs]],
2772 [444, [revert_uop]],
2773 [443, [revert_biolinum]],
2775 [441, [revert_newtxmath]],
2776 [440, [revert_mdnomath]],
2777 [439, [revert_mathfonts]],
2778 [438, [revert_minionpro]],
2779 [437, [revert_ipadeco, revert_ipachar]],
2780 [436, [revert_texgyre]],
2781 [435, [revert_mathdesign]],
2782 [434, [revert_txtt]],
2783 [433, [revert_libertine]],
2784 [432, [revert_armenian]],
2785 [431, [revert_languages, revert_ancientgreek]],
2786 [430, [revert_use_amssymb]],
2787 [429, [revert_listoflistings]],
2788 [428, [revert_table_rotation]],
2789 [427, [revert_cell_rotation]],
2790 [426, [revert_tipa]],
2791 [425, [revert_verbatim]],
2792 [424, [revert_cancel]],
2793 [423, [revert_cite_engine_type]],
2794 [422, [revert_use_mathtools]],
2795 [421, [revert_use_packages]],
2796 [420, [revert_longtable_captions]],
2797 [419, [revert_biblio_style]],
2798 [418, [revert_australian]],
2799 [417, [revert_justification]],
2800 [416, [revert_japanese_encodings]],
2801 [415, [revert_negative_space, revert_math_spaces]],
2802 [414, [revert_undertilde]],
2803 [413, [revert_visible_space]]
2807 if __name__ == "__main__":