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", "boxdot", "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 # 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_cite_engine_type(document):
499 "Determine the \\cite_engine_type from the citation engine."
500 i = find_token(document.header, "\\cite_engine", 0)
503 engine = get_value(document.header, "\\cite_engine", i)
505 engine, type = engine.split("_")
507 type = {"basic": "numerical", "jurabib": "authoryear"}[engine]
508 document.header[i] = "\\cite_engine " + engine
509 document.header.insert(i + 1, "\\cite_engine_type " + type)
512 def revert_cite_engine_type(document):
513 "Natbib had the type appended with an underscore."
514 engine_type = "numerical"
515 i = find_token(document.header, "\\cite_engine_type" , 0)
517 document.warning("No \\cite_engine_type line. Assuming numerical.")
519 engine_type = get_value(document.header, "\\cite_engine_type", i)
520 del document.header[i]
522 # We are looking for the natbib citation engine
523 i = find_token(document.header, "\\cite_engine natbib", 0)
526 document.header[i] = "\\cite_engine natbib_" + engine_type
529 def revert_cancel(document):
530 "add cancel to the preamble if necessary"
531 commands = ["cancelto", "cancel", "bcancel", "xcancel"]
534 i = find_token(document.body, '\\begin_inset Formula', i)
537 j = find_end_of_inset(document.body, i)
539 document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
542 code = "\n".join(document.body[i:j])
544 if code.find("\\%s" % c) != -1:
545 add_to_preamble(document, ["\\usepackage{cancel}"])
550 def revert_verbatim(document):
551 " Revert verbatim einvironments completely to TeX-code. "
554 subst_end = ['\end_layout', '', '\\begin_layout Plain Layout',
556 '\\begin_layout Plain Layout', '', '',
559 '\\end_layout', '', '\\end_inset',
560 '', '', '\\end_layout']
561 subst_begin = ['\\begin_layout Standard', '\\noindent',
562 '\\begin_inset ERT', 'status collapsed', '',
563 '\\begin_layout Plain Layout', '', '', '\\backslash',
565 '\\end_layout', '', '\\begin_layout Plain Layout', '']
567 i = find_token(document.body, "\\begin_layout Verbatim", i)
570 j = find_end_of_layout(document.body, i)
572 document.warning("Malformed lyx document: Can't find end of Verbatim layout")
575 # delete all line breaks insets (there are no other insets)
578 n = find_token(document.body, "\\begin_inset Newline newline", l)
580 n = find_token(document.body, "\\begin_inset Newline linebreak", l)
583 m = find_end_of_inset(document.body, n)
584 del(document.body[m:m+1])
585 document.body[n:n+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
588 # consecutive verbatim environments need to be connected
589 k = find_token(document.body, "\\begin_layout Verbatim", j)
590 if k == j + 2 and consecutive == False:
592 document.body[j:j+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
593 document.body[i:i+1] = subst_begin
595 if k == j + 2 and consecutive == True:
596 document.body[j:j+1] = ['\end_layout', '', '\\begin_layout Plain Layout']
597 del(document.body[i:i+1])
599 if k != j + 2 and consecutive == True:
600 document.body[j:j+1] = subst_end
601 # the next paragraph must not be indented
602 document.body[j+19:j+19] = ['\\noindent']
603 del(document.body[i:i+1])
607 document.body[j:j+1] = subst_end
608 # the next paragraph must not be indented
609 document.body[j+19:j+19] = ['\\noindent']
610 document.body[i:i+1] = subst_begin
613 def revert_tipa(document):
614 " Revert native TIPA insets to mathed or ERT. "
617 i = find_token(document.body, "\\begin_inset IPA", i)
620 j = find_end_of_inset(document.body, i)
622 document.warning("Malformed lyx document: Can't find end of IPA inset")
626 n = find_token(document.body, "\\begin_layout", i, j)
628 document.warning("Malformed lyx document: IPA inset has no embedded layout")
631 m = find_end_of_layout(document.body, n)
633 document.warning("Malformed lyx document: Can't find end of embedded layout")
636 content = document.body[n+1:m]
637 p = find_token(document.body, "\\begin_layout", m, j)
638 if p != -1 or len(content) > 1:
640 content = document.body[i+1:j]
642 # IPA insets with multiple pars need to be wrapped by \begin{IPA}...\end{IPA}
643 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}")
644 add_to_preamble(document, ["\\usepackage{tipa,tipx}"])
646 # single-par IPA insets can be reverted to mathed
647 document.body[i:j+1] = ["\\begin_inset Formula $\\text{\\textipa{" + content[0] + "}}$", "\\end_inset"]
651 def revert_cell_rotation(document):
652 "Revert cell rotations to TeX-code"
654 load_rotating = False
658 # first, let's find out if we need to do anything
659 i = find_token(document.body, '<cell ', i)
662 j = document.body[i].find('rotate="')
664 k = document.body[i].find('"', j + 8)
665 value = document.body[i][j + 8 : k]
667 rgx = re.compile(r' rotate="[^"]+?"')
668 # remove rotate option
669 document.body[i] = rgx.sub('', document.body[i])
671 rgx = re.compile(r' rotate="[^"]+?"')
672 document.body[i] = rgx.sub('rotate="true"', document.body[i])
674 rgx = re.compile(r' rotate="[^"]+?"')
676 # remove rotate option
677 document.body[i] = rgx.sub('', document.body[i])
679 document.body[i + 5 : i + 5] = \
680 put_cmd_in_ert("\\end{turn}")
681 document.body[i + 4 : i + 4] = \
682 put_cmd_in_ert("\\begin{turn}{" + value + "}")
688 add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"])
691 def convert_cell_rotation(document):
692 'Convert cell rotation statements from "true" to "90"'
696 # first, let's find out if we need to do anything
697 i = find_token(document.body, '<cell ', i)
700 j = document.body[i].find('rotate="true"')
702 rgx = re.compile(r'rotate="[^"]+?"')
703 # convert "true" to "90"
704 document.body[i] = rgx.sub('rotate="90"', document.body[i])
709 def revert_table_rotation(document):
710 "Revert table rotations to TeX-code"
712 load_rotating = False
716 # first, let's find out if we need to do anything
717 i = find_token(document.body, '<features ', i)
720 j = document.body[i].find('rotate="')
722 end_table = find_token(document.body, '</lyxtabular>', j)
723 k = document.body[i].find('"', j + 8)
724 value = document.body[i][j + 8 : k]
726 rgx = re.compile(r' rotate="[^"]+?"')
727 # remove rotate option
728 document.body[i] = rgx.sub('', document.body[i])
730 rgx = re.compile(r'rotate="[^"]+?"')
731 document.body[i] = rgx.sub('rotate="true"', document.body[i])
733 rgx = re.compile(r' rotate="[^"]+?"')
735 # remove rotate option
736 document.body[i] = rgx.sub('', document.body[i])
738 document.body[end_table + 3 : end_table + 3] = \
739 put_cmd_in_ert("\\end{turn}")
740 document.body[i - 2 : i - 2] = \
741 put_cmd_in_ert("\\begin{turn}{" + value + "}")
747 add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"])
750 def convert_table_rotation(document):
751 'Convert table rotation statements from "true" to "90"'
755 # first, let's find out if we need to do anything
756 i = find_token(document.body, '<features ', i)
759 j = document.body[i].find('rotate="true"')
761 rgx = re.compile(r'rotate="[^"]+?"')
762 # convert "true" to "90"
763 document.body[i] = rgx.sub('rotate="90"', document.body[i])
768 def convert_listoflistings(document):
769 'Convert ERT \lstlistoflistings to TOC lstlistoflistings inset'
770 # We can support roundtrip because the command is so simple
773 i = find_token(document.body, "\\begin_inset ERT", i)
776 j = find_end_of_inset(document.body, i)
778 document.warning("Malformed lyx document: Can't find end of ERT inset")
781 ert = get_ert(document.body, i)
782 if ert == "\\lstlistoflistings{}":
783 document.body[i:j] = ["\\begin_inset CommandInset toc", "LatexCommand lstlistoflistings", ""]
789 def revert_listoflistings(document):
790 'Convert TOC lstlistoflistings inset to ERT lstlistoflistings'
793 i = find_token(document.body, "\\begin_inset CommandInset toc", i)
796 if document.body[i+1] == "LatexCommand lstlistoflistings":
797 j = find_end_of_inset(document.body, i)
799 document.warning("Malformed lyx document: Can't find end of TOC inset")
802 subst = put_cmd_in_ert("\\lstlistoflistings{}")
803 document.body[i:j+1] = subst
804 add_to_preamble(document, ["\\usepackage{listings}"])
808 def convert_use_amssymb(document):
809 "insert use_package amssymb"
810 regexp = re.compile(r'(\\use_package\s+amsmath)')
811 i = find_re(document.header, regexp, 0)
813 document.warning("Malformed LyX document: Can't find \\use_package amsmath.")
815 value = get_value(document.header, "\\use_package" , i).split()[1]
818 useamsmath = int(value)
820 document.warning("Invalid \\use_package amsmath: " + value + ". Assuming auto.")
822 j = find_token(document.preamble, "\\usepackage{amssymb}", 0)
824 document.header.insert(i + 1, "\\use_package amssymb %d" % useamsmath)
826 document.header.insert(i + 1, "\\use_package amssymb 2")
827 del document.preamble[j]
830 def revert_use_amssymb(document):
831 "remove use_package amssymb"
832 regexp1 = re.compile(r'(\\use_package\s+amsmath)')
833 regexp2 = re.compile(r'(\\use_package\s+amssymb)')
834 i = find_re(document.header, regexp1, 0)
835 j = find_re(document.header, regexp2, 0)
836 value1 = "1" # default is auto
837 value2 = "1" # default is auto
839 value1 = get_value(document.header, "\\use_package" , i).split()[1]
841 value2 = get_value(document.header, "\\use_package" , j).split()[1]
842 del document.header[j]
843 if value1 != value2 and value2 == "2": # on
844 add_to_preamble(document, ["\\usepackage{amssymb}"])
847 def revert_ancientgreek(document):
848 "Set the document language for ancientgreek to greek"
850 if document.language == "ancientgreek":
851 document.language = "greek"
852 i = find_token(document.header, "\\language", 0)
854 document.header[i] = "\\language greek"
857 j = find_token(document.body, "\\lang ancientgreek", j)
861 document.body[j] = document.body[j].replace("\\lang ancientgreek", "\\lang greek")
865 def revert_languages(document):
866 "Set the document language for new supported languages to English"
869 "coptic", "divehi", "hindi", "kurmanji", "lao", "marathi", "occitan", "sanskrit",
870 "syriac", "tamil", "telugu", "urdu"
872 for n in range(len(languages)):
873 if document.language == languages[n]:
874 document.language = "english"
875 i = find_token(document.header, "\\language", 0)
877 document.header[i] = "\\language english"
879 while j < len(document.body):
880 j = find_token(document.body, "\\lang " + languages[n], j)
882 document.body[j] = document.body[j].replace("\\lang " + languages[n], "\\lang english")
885 j = len(document.body)
888 def convert_armenian(document):
889 "Use polyglossia and thus non-TeX fonts for Armenian"
891 if document.language == "armenian":
892 i = find_token(document.header, "\\use_non_tex_fonts", 0)
894 document.header[i] = "\\use_non_tex_fonts true"
897 def revert_armenian(document):
898 "Use ArmTeX and thus TeX fonts for Armenian"
900 if document.language == "armenian":
901 i = find_token(document.header, "\\use_non_tex_fonts", 0)
903 document.header[i] = "\\use_non_tex_fonts false"
906 def revert_libertine(document):
907 " Revert native libertine font definition to LaTeX "
909 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
910 i = find_token(document.header, "\\font_roman libertine", 0)
913 j = find_token(document.header, "\\font_osf true", 0)
916 preamble = "\\usepackage"
918 document.header[j] = "\\font_osf false"
920 preamble += "[lining]"
921 preamble += "{libertine-type1}"
922 add_to_preamble(document, [preamble])
923 document.header[i] = "\\font_roman default"
926 def revert_txtt(document):
927 " Revert native txtt font definition to LaTeX "
929 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
930 i = find_token(document.header, "\\font_typewriter txtt", 0)
932 preamble = "\\renewcommand{\\ttdefault}{txtt}"
933 add_to_preamble(document, [preamble])
934 document.header[i] = "\\font_typewriter default"
937 def revert_mathdesign(document):
938 " Revert native mathdesign font definition to LaTeX "
940 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
946 i = find_token(document.header, "\\font_roman", 0)
949 val = get_value(document.header, "\\font_roman", i)
950 if val in mathdesign_dict.keys():
951 preamble = "\\usepackage[%s" % mathdesign_dict[val]
953 j = find_token(document.header, "\\font_osf true", 0)
956 document.header[j] = "\\font_osf false"
957 l = find_token(document.header, "\\font_sc true", 0)
960 document.header[l] = "\\font_sc false"
962 preamble += ",expert"
963 preamble += "]{mathdesign}"
964 add_to_preamble(document, [preamble])
965 document.header[i] = "\\font_roman default"
968 def revert_texgyre(document):
969 " Revert native TeXGyre font definition to LaTeX "
971 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
972 texgyre_fonts = ["tgadventor", "tgbonum", "tgchorus", "tgcursor", \
973 "tgheros", "tgpagella", "tgschola", "tgtermes"]
974 i = find_token(document.header, "\\font_roman", 0)
976 val = get_value(document.header, "\\font_roman", i)
977 if val in texgyre_fonts:
978 preamble = "\\usepackage{%s}" % val
979 add_to_preamble(document, [preamble])
980 document.header[i] = "\\font_roman default"
981 i = find_token(document.header, "\\font_sans", 0)
983 val = get_value(document.header, "\\font_sans", i)
984 if val in texgyre_fonts:
985 preamble = "\\usepackage{%s}" % val
986 add_to_preamble(document, [preamble])
987 document.header[i] = "\\font_sans default"
988 i = find_token(document.header, "\\font_typewriter", 0)
990 val = get_value(document.header, "\\font_typewriter", i)
991 if val in texgyre_fonts:
992 preamble = "\\usepackage{%s}" % val
993 add_to_preamble(document, [preamble])
994 document.header[i] = "\\font_typewriter default"
997 def revert_ipadeco(document):
998 " Revert IPA decorations to ERT "
1001 i = find_token(document.body, "\\begin_inset IPADeco", i)
1004 end = find_end_of_inset(document.body, i)
1006 document.warning("Can't find end of inset at line " + str(i))
1009 line = document.body[i]
1010 rx = re.compile(r'\\begin_inset IPADeco (.*)$')
1012 decotype = m.group(1)
1013 if decotype != "toptiebar" and decotype != "bottomtiebar":
1014 document.warning("Invalid IPADeco type: " + decotype)
1017 blay = find_token(document.body, "\\begin_layout Plain Layout", i, end)
1019 document.warning("Can't find layout for inset at line " + str(i))
1022 bend = find_end_of_layout(document.body, blay)
1024 document.warning("Malformed LyX document: Could not find end of IPADeco inset's layout.")
1027 substi = ["\\begin_inset ERT", "status collapsed", "",
1028 "\\begin_layout Plain Layout", "", "", "\\backslash",
1029 decotype + "{", "\\end_layout", "", "\\end_inset"]
1030 substj = ["\\size default", "", "\\begin_inset ERT", "status collapsed", "",
1031 "\\begin_layout Plain Layout", "", "}", "\\end_layout", "", "\\end_inset"]
1032 # do the later one first so as not to mess up the numbering
1033 document.body[bend:end + 1] = substj
1034 document.body[i:blay + 1] = substi
1035 i = end + len(substi) + len(substj) - (end - bend) - (blay - i) - 2
1036 add_to_preamble(document, "\\usepackage{tipa}")
1039 def revert_ipachar(document):
1040 ' Revert \\IPAChar to ERT '
1043 while i < len(document.body):
1044 m = re.match(r'(.*)\\IPAChar \\(\w+\{\w+\})(.*)', document.body[i])
1048 ipachar = m.group(2)
1051 '\\begin_inset ERT',
1052 'status collapsed', '',
1053 '\\begin_layout Standard',
1054 '', '', '\\backslash',
1059 document.body[i: i+1] = subst
1064 add_to_preamble(document, "\\usepackage{tone}")
1067 def revert_minionpro(document):
1068 " Revert native MinionPro font definition to LaTeX "
1070 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1071 i = find_token(document.header, "\\font_roman minionpro", 0)
1074 j = find_token(document.header, "\\font_osf true", 0)
1077 preamble = "\\usepackage"
1079 document.header[j] = "\\font_osf false"
1082 preamble += "{MinionPro}"
1083 add_to_preamble(document, [preamble])
1084 document.header[i] = "\\font_roman default"
1087 def revert_mathfonts(document):
1088 " Revert native math font definitions to LaTeX "
1090 i = find_token(document.header, "\\font_math", 0)
1093 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1094 val = get_value(document.header, "\\font_math", i)
1095 if val == "eulervm":
1096 add_to_preamble(document, "\\usepackage{eulervm}")
1097 elif val == "default":
1099 "lmodern": "\\renewcommand{\\rmdefault}{lmr}",
1100 "minionpro": "\\usepackage[onlytext,lf]{MinionPro}",
1101 "minionpro-osf": "\\usepackage[onlytext]{MinionPro}",
1102 "palatino": "\\renewcommand{\\rmdefault}{ppl}",
1103 "palatino-osf": "\\renewcommand{\\rmdefault}{pplj}",
1104 "times": "\\renewcommand{\\rmdefault}{ptm}",
1105 "utopia": "\\renewcommand{\\rmdefault}{futs}",
1106 "utopia-osf": "\\renewcommand{\\rmdefault}{futj}",
1108 j = find_token(document.header, "\\font_roman", 0)
1110 rm = get_value(document.header, "\\font_roman", j)
1111 k = find_token(document.header, "\\font_osf true", 0)
1114 if rm in mathfont_dict.keys():
1115 add_to_preamble(document, mathfont_dict[rm])
1116 document.header[j] = "\\font_roman default"
1118 document.header[k] = "\\font_osf false"
1119 del document.header[i]
1122 def revert_mdnomath(document):
1123 " Revert mathdesign and fourier without math "
1125 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1127 "md-charter": "mdbch",
1128 "md-utopia": "mdput",
1129 "md-garamond": "mdugm"
1131 i = find_token(document.header, "\\font_roman", 0)
1134 val = get_value(document.header, "\\font_roman", i)
1135 if val in mathdesign_dict.keys():
1136 j = find_token(document.header, "\\font_math", 0)
1138 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1139 mval = get_value(document.header, "\\font_math", j)
1140 if mval == "default":
1141 document.header[i] = "\\font_roman default"
1142 add_to_preamble(document, "\\renewcommand{\\rmdefault}{%s}" % mathdesign_dict[val])
1144 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1147 def convert_mdnomath(document):
1148 " Change mathdesign font name "
1150 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1152 "mdbch": "md-charter",
1153 "mdput": "md-utopia",
1154 "mdugm": "md-garamond"
1156 i = find_token(document.header, "\\font_roman", 0)
1159 val = get_value(document.header, "\\font_roman", i)
1160 if val in mathdesign_dict.keys():
1161 document.header[i] = "\\font_roman %s" % mathdesign_dict[val]
1164 def revert_newtxmath(document):
1165 " Revert native newtxmath definitions to LaTeX "
1167 i = find_token(document.header, "\\font_math", 0)
1170 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1171 val = get_value(document.header, "\\font_math", i)
1173 "libertine-ntxm": "\\usepackage[libertine]{newtxmath}",
1174 "minion-ntxm": "\\usepackage[minion]{newtxmath}",
1175 "newtxmath": "\\usepackage{newtxmath}",
1177 if val in mathfont_dict.keys():
1178 add_to_preamble(document, mathfont_dict[val])
1179 document.header[i] = "\\font_math auto"
1182 def revert_biolinum(document):
1183 " Revert native biolinum font definition to LaTeX "
1185 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1186 i = find_token(document.header, "\\font_sans biolinum", 0)
1189 j = find_token(document.header, "\\font_osf true", 0)
1192 preamble = "\\usepackage"
1195 preamble += "{biolinum-type1}"
1196 add_to_preamble(document, [preamble])
1197 document.header[i] = "\\font_sans default"
1200 def revert_uop(document):
1201 " Revert native URW Classico (Optima) font definition to LaTeX "
1203 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1204 i = find_token(document.header, "\\font_sans uop", 0)
1206 preamble = "\\renewcommand{\\sfdefault}{uop}"
1207 add_to_preamble(document, [preamble])
1208 document.header[i] = "\\font_sans default"
1211 def convert_latexargs(document):
1212 " Convert InsetArgument to new syntax "
1214 if find_token(document.body, "\\begin_inset Argument", 0) == -1:
1218 # A list of layouts (document classes) with only optional or no arguments.
1219 # These can be safely converted to the new syntax
1220 # (I took the liberty to add some of my personal layouts/modules here; JSP)
1221 safe_layouts = ["aa", "aapaper", "aastex", "achemso", "acmsiggraph", "AEA",
1222 "agu-dtd", "agums", "agutex", "amsart", "amsbook", "apa",
1223 "arab-article", "armenian-article", "article-beamer", "article",
1224 "beamer", "book", "broadway", "chess", "cl2emult", "ctex-article",
1225 "ctex-book", "ctex-report", "dinbrief", "docbook-book", "docbook-chapter",
1226 "docbook", "docbook-section", "doublecol-new", "dtk", "ectaart", "egs",
1227 "elsarticle", "elsart", "entcs", "europecv", "extarticle", "extbook",
1228 "extletter", "extreport", "foils", "frletter", "g-brief2", "g-brief",
1229 "heb-article", "heb-letter", "hollywood", "IEEEtran", "ijmpc", "ijmpd",
1230 "iopart", "isprs", "jarticle", "jasatex", "jbook", "jgrga", "jreport",
1231 "jsarticle", "jsbeamer", "jsbook", "jss", "kluwer", "latex8", "letter", "lettre",
1232 "literate-article", "literate-book", "literate-report", "llncs", "ltugboat",
1233 "memoir", "moderncv", "mwart", "mwbk", "mwrep", "paper", "powerdot",
1234 "recipebook", "report", "revtex4", "revtex", "scrartcl", "scrarticle-beamer",
1235 "scrbook", "scrlettr", "scrlttr2", "scrreprt", "seminar", "siamltex",
1236 "sigplanconf", "simplecv", "singlecol", "singlecol-new", "slides", "spie",
1237 "svglobal3", "svglobal", "svjog", "svmono", "svmult", "svprobth", "tarticle",
1238 "tbook", "treport", "tufte-book", "tufte-handout"]
1239 # A list of "safe" modules, same as above
1240 safe_modules = ["biblatex", "beameraddons", "beamersession", "braille", "customHeadersFooters",
1241 "endnotes", "enumitem", "eqs-within-sections", "figs-within-sections", "fix-cm",
1242 "fixltx2e", "foottoend", "hanging", "jscharstyles", "knitr", "lilypond",
1243 "linguistics", "linguisticx", "logicalmkup", "minimalistic", "nomindex", "noweb",
1244 "pdfcomment", "sweave", "tabs-within-sections", "theorems-ams-bytype",
1245 "theorems-ams-extended-bytype", "theorems-ams-extended", "theorems-ams", "theorems-bytype",
1246 "theorems-chap-bytype", "theorems-chap", "theorems-named", "theorems-sec-bytype",
1247 "theorems-sec", "theorems-starred", "theorems-std", "todonotes"]
1248 # Modules we need to take care of
1249 caveat_modules = ["initials"]
1250 # information about the relevant styles in caveat_modules (number of opt and req args)
1251 # use this if we get more caveat_modules. For now, use hard coding (see below).
1252 # initials = [{'Layout' : 'Initial', 'opt' : 1, 'req' : 1}]
1254 # Is this a known safe layout?
1255 safe_layout = document.textclass in safe_layouts
1257 document.warning("Lyx2lyx knows nothing about textclass '%s'. "
1258 "Please check if short title insets have been converted correctly."
1259 % document.textclass)
1260 # Do we use unsafe or unknown modules
1261 mods = document.get_module_list()
1262 unknown_modules = False
1263 used_caveat_modules = list()
1265 if mod in safe_modules:
1267 if mod in caveat_modules:
1268 used_caveat_modules.append(mod)
1270 unknown_modules = True
1271 document.warning("Lyx2lyx knows nothing about module '%s'. "
1272 "Please check if short title insets have been converted correctly."
1277 i = find_token(document.body, "\\begin_inset Argument", i)
1281 if not safe_layout or unknown_modules:
1282 # We cannot do more here since we have no access to this layout.
1283 # InsetArgument itself will do the real work
1284 # (see InsetArgument::updateBuffer())
1285 document.body[i] = "\\begin_inset Argument 999"
1289 # Find containing paragraph layout
1290 parent = get_containing_layout(document.body, i)
1292 document.warning("Malformed lyx document: Can't find parent paragraph layout")
1299 if len(used_caveat_modules) > 0:
1300 # We know for now that this must be the initials module with the Initial layout
1301 # If we get more such modules, we need some automating.
1302 if parent[0] == "Initial":
1303 # Layout has 1 opt and 1 req arg.
1304 # Count the actual arguments
1306 for p in range(parbeg, parend):
1307 if document.body[p] == "\\begin_inset Argument":
1312 # Collect all arguments in this paragraph
1314 for p in range(parbeg, parend):
1315 if document.body[p] == "\\begin_inset Argument":
1317 if allowed_opts != -1:
1318 # We have less arguments than opt + required.
1319 # required must take precedence.
1320 if argnr > allowed_opts and argnr < first_req:
1322 document.body[p] = "\\begin_inset Argument %d" % argnr
1326 def revert_latexargs(document):
1327 " Revert InsetArgument to old syntax "
1330 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
1333 # Search for Argument insets
1334 i = find_token(document.body, "\\begin_inset Argument", i)
1337 m = rx.match(document.body[i])
1339 # No ID: inset already reverted
1342 # Find containing paragraph layout
1343 parent = get_containing_layout(document.body, i)
1345 document.warning("Malformed lyx document: Can't find parent paragraph layout")
1350 realparbeg = parent[3]
1351 # Collect all arguments in this paragraph
1353 for p in range(parbeg, parend):
1354 m = rx.match(document.body[p])
1356 val = int(m.group(1))
1357 j = find_end_of_inset(document.body, p)
1358 # Revert to old syntax
1359 document.body[p] = "\\begin_inset Argument"
1361 document.warning("Malformed lyx document: Can't find end of Argument inset")
1364 args[val] = document.body[p : j + 1]
1366 realparend = realparend - len(document.body[p : j + 1])
1367 # Remove arg inset at this position
1368 del document.body[p : j + 1]
1371 # Now sort the arg insets
1373 for f in sorted(args):
1376 # Insert the sorted arg insets at paragraph begin
1377 document.body[realparbeg : realparbeg] = subst
1379 i = realparbeg + 1 + len(subst)
1382 def revert_Argument_to_TeX_brace(document, line, n, nmax, environment):
1384 Reverts an InsetArgument to TeX-code
1386 revert_Argument_to_TeX_brace(document, LineOfBeginLayout, StartArgument, EndArgument, isEnvironment)
1387 LineOfBeginLayout is the line of the \begin_layout statement
1388 StartArgument is the number of the first argument that needs to be converted
1389 EndArgument is the number of the last argument that needs to be converted or the last defined one
1390 isEnvironment must be true, if the layout id for a LaTeX environment
1393 while lineArg != -1 and n < nmax + 1:
1394 lineArg = find_token(document.body, "\\begin_inset Argument " + str(n), line)
1396 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", lineArg)
1397 # we have to assure that no other inset is in the Argument
1398 beginInset = find_token(document.body, "\\begin_inset", beginPlain)
1399 endInset = find_token(document.body, "\\end_inset", beginPlain)
1402 while beginInset < endInset and beginInset != -1:
1403 beginInset = find_token(document.body, "\\begin_inset", k)
1404 endInset = find_token(document.body, "\\end_inset", l)
1407 if environment == False:
1408 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}{")
1409 del(document.body[lineArg : beginPlain + 1])
1411 document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}")
1412 document.body[lineArg : beginPlain + 1] = put_cmd_in_ert("{")
1416 def revert_IEEEtran(document):
1418 Reverts InsetArgument of
1421 Biography without photo
1424 if document.textclass == "IEEEtran":
1430 i = find_token(document.body, "\\begin_layout Page headings", i)
1432 revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1435 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1437 revert_Argument_to_TeX_brace(document, j, 1, 1, True)
1440 k = find_token(document.body, "\\begin_layout Biography", k)
1441 kA = find_token(document.body, "\\begin_layout Biography without photo", k)
1442 if k == kA and k != -1:
1446 # start with the second argument, therefore 2
1447 revert_Argument_to_TeX_brace(document, k, 2, 2, True)
1449 if i == -1 and j == -1 and k == -1:
1453 def convert_TeX_brace_to_Argument(document, line, n, nmax, inset, environment):
1455 Converts TeX code for mandatory arguments to an InsetArgument
1456 The conversion of TeX code for optional arguments must be done with another routine
1457 !!! Be careful if the braces are different in your case as expected here:
1458 - "}{" separates mandatory arguments of commands
1459 - "}" + "{" separates mandatory arguments of commands
1460 - "}" + " " + "{" separates mandatory arguments of commands
1461 - { and } surround a mandatory argument of an environment
1463 convert_TeX_brace_to_Argument(document, LineOfBeginLayout/Inset, StartArgument, EndArgument, isInset, isEnvironment)
1464 LineOfBeginLayout/Inset is the line of the \begin_layout or \begin_inset statement
1465 StartArgument is the number of the first ERT that needs to be converted
1466 EndArgument is the number of the last ERT that needs to be converted
1467 isInset must be true, if braces inside an InsetLayout needs to be converted
1468 isEnvironment must be true, if the layout is for a LaTeX environment
1470 Todo: this routine can currently handle only one mandatory argument of environments
1475 while lineERT != -1 and n < nmax + 1:
1476 lineERT = find_token(document.body, "\\begin_inset ERT", lineERT)
1477 if environment == False and lineERT != -1:
1478 bracePair = find_token(document.body, "}{", lineERT)
1479 # assure that the "}{" is in this ERT
1480 if bracePair == lineERT + 5:
1481 end = find_token(document.body, "\\end_inset", bracePair)
1482 document.body[lineERT : end + 1] = ["\\end_layout", "", "\\end_inset"]
1484 # in the case that n > 1 we have optional arguments before
1485 # therefore detect them if any
1487 # first check if there is an argument
1488 lineArg = find_token(document.body, "\\begin_inset Argument", line)
1489 if lineArg < lineERT and lineArg != -1:
1490 # we have an argument, so now search backwards for its end
1491 # we must now assure that we don't find other insets like e.g. a newline
1492 endInsetArg = lineERT
1493 endLayoutArg = endInsetArg
1494 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
1495 endInsetArg = endInsetArg - 1
1496 endLayoutArg = endInsetArg
1497 endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
1498 endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
1499 line = endInsetArg + 1
1501 document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1503 document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1505 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1509 # now check the case that we have "}" + "{" in two ERTs
1511 endBrace = find_token(document.body, "}", lineERT)
1512 if endBrace == lineERT + 5:
1513 beginBrace = find_token(document.body, "{", endBrace)
1514 # assure that the ERTs are consecutive (11 or 12 depending if there is a space between the ERTs or not)
1515 if beginBrace == endBrace + 11 or beginBrace == endBrace + 12:
1516 end = find_token(document.body, "\\end_inset", beginBrace)
1517 document.body[lineERT : end + 1] = ["\\end_layout", "", "\\end_inset"]
1519 # in the case that n > 1 we have optional arguments before
1520 # therefore detect them if any
1522 # first check if there is an argument
1523 lineArg = find_token(document.body, "\\begin_inset Argument", line)
1524 if lineArg < lineERT and lineArg != -1:
1525 # we have an argument, so now search backwards for its end
1526 # we must now assure that we don't find other insets like e.g. a newline
1527 endInsetArg = lineERT
1528 endLayoutArg = endInsetArg
1529 while endInsetArg != endLayoutArg + 2 and endInsetArg != -1:
1530 endInsetArg = endInsetArg - 1
1531 endLayoutArg = endInsetArg
1532 endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg)
1533 endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg)
1534 line = endInsetArg + 1
1536 document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1538 document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1540 document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1543 # set the line where the next argument will be inserted
1544 if beginBrace == endBrace + 11:
1549 lineERT = lineERT + 1
1550 if environment == True and lineERT != -1:
1551 opening = find_token(document.body, "{", lineERT)
1552 if opening == lineERT + 5: # assure that the "{" is in this ERT
1553 end = find_token(document.body, "\\end_inset", opening)
1554 document.body[lineERT : end + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"]
1556 lineERT2 = find_token(document.body, "\\begin_inset ERT", lineERT)
1557 closing = find_token(document.body, "}", lineERT2)
1558 if closing == lineERT2 + 5: # assure that the "}" is in this ERT
1559 end2 = find_token(document.body, "\\end_inset", closing)
1560 document.body[lineERT2 : end2 + 1] = ["\\end_layout", "", "\\end_inset"]
1562 lineERT = lineERT + 1
1565 def convert_IEEEtran(document):
1570 Biography without photo
1573 if document.textclass == "IEEEtran":
1579 i = find_token(document.body, "\\begin_layout Page headings", i)
1581 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1584 j = find_token(document.body, "\\begin_layout Biography without photo", j)
1586 convert_TeX_brace_to_Argument(document, j, 1, 1, False, True)
1589 # assure that we don't handle Biography Biography without photo
1590 k = find_token(document.body, "\\begin_layout Biography", k)
1591 kA = find_token(document.body, "\\begin_layout Biography without photo", k - 1)
1592 if k == kA and k != -1:
1596 # the argument we want to convert is the second one
1597 convert_TeX_brace_to_Argument(document, k, 2, 2, False, True)
1599 if i == -1 and j == -1 and k == -1:
1603 def revert_AASTeX(document):
1604 " Reverts InsetArgument of Altaffilation to TeX-code "
1605 if document.textclass == "aastex":
1609 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1611 revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1617 def convert_AASTeX(document):
1618 " Converts ERT of Altaffilation to InsetArgument "
1619 if document.textclass == "aastex":
1623 i = find_token(document.body, "\\begin_layout Altaffilation", i)
1625 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1631 def revert_AGUTeX(document):
1632 " Reverts InsetArgument of Author affiliation to TeX-code "
1633 if document.textclass == "agutex":
1637 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1639 revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1645 def convert_AGUTeX(document):
1646 " Converts ERT of Author affiliation to InsetArgument "
1647 if document.textclass == "agutex":
1651 i = find_token(document.body, "\\begin_layout Author affiliation", i)
1653 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1659 def revert_IJMP(document):
1660 " Reverts InsetArgument of MarkBoth to TeX-code "
1661 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1665 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1667 revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1673 def convert_IJMP(document):
1674 " Converts ERT of MarkBoth to InsetArgument "
1675 if document.textclass == "ijmpc" or document.textclass == "ijmpd":
1679 i = find_token(document.body, "\\begin_layout MarkBoth", i)
1681 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1687 def revert_SIGPLAN(document):
1688 " Reverts InsetArgument of MarkBoth to TeX-code "
1689 if document.textclass == "sigplanconf":
1694 i = find_token(document.body, "\\begin_layout Conference", i)
1696 revert_Argument_to_TeX_brace(document, i, 1, 1, False)
1699 j = find_token(document.body, "\\begin_layout Author", j)
1701 revert_Argument_to_TeX_brace(document, j, 1, 2, False)
1703 if i == -1 and j == -1:
1707 def convert_SIGPLAN(document):
1708 " Converts ERT of MarkBoth to InsetArgument "
1709 if document.textclass == "sigplanconf":
1714 i = find_token(document.body, "\\begin_layout Conference", i)
1716 convert_TeX_brace_to_Argument(document, i, 1, 1, False, False)
1719 j = find_token(document.body, "\\begin_layout Author", j)
1721 convert_TeX_brace_to_Argument(document, j, 1, 2, False, False)
1723 if i == -1 and j == -1:
1727 def revert_SIGGRAPH(document):
1728 " Reverts InsetArgument of Flex CRcat to TeX-code "
1729 if document.textclass == "acmsiggraph":
1733 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1735 revert_Argument_to_TeX_brace(document, i, 1, 3, False)
1741 def convert_SIGGRAPH(document):
1742 " Converts ERT of Flex CRcat to InsetArgument "
1743 if document.textclass == "acmsiggraph":
1747 i = find_token(document.body, "\\begin_inset Flex CRcat", i)
1749 convert_TeX_brace_to_Argument(document, i, 1, 3, True, False)
1755 def revert_EuropeCV(document):
1756 " Reverts InsetArgument of Flex CRcat to TeX-code "
1757 if document.textclass == "europecv":
1764 i = find_token(document.body, "\\begin_layout Item", i)
1766 revert_Argument_to_TeX_brace(document, i, 2, 2, False)
1769 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1771 revert_Argument_to_TeX_brace(document, j, 2, 2, False)
1774 k = find_token(document.body, "\\begin_layout Language", k)
1776 revert_Argument_to_TeX_brace(document, k, 2, 6, False)
1779 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1781 revert_Argument_to_TeX_brace(document, m, 2, 6, False)
1783 if i == -1 and j == -1 and k == -1 and m == -1:
1787 def convert_EuropeCV(document):
1788 " Converts ERT of Flex CRcat to InsetArgument "
1789 if document.textclass == "europecv":
1796 i = find_token(document.body, "\\begin_layout Item", i)
1798 convert_TeX_brace_to_Argument(document, i, 2, 2, False, False)
1801 j = find_token(document.body, "\\begin_layout BulletedItem", j)
1803 convert_TeX_brace_to_Argument(document, j, 2, 2, False, False)
1806 k = find_token(document.body, "\\begin_layout Language", k)
1808 convert_TeX_brace_to_Argument(document, k, 2, 6, False, False)
1811 m = find_token(document.body, "\\begin_layout LastLanguage", m)
1813 convert_TeX_brace_to_Argument(document, m, 2, 6, False, False)
1815 if i == -1 and j == -1 and k == -1 and m == -1:
1819 def revert_literate(document):
1820 " Revert Literate document to old format "
1821 if del_token(document.header, "noweb", 0):
1822 document.textclass = "literate-" + document.textclass
1825 i = find_token(document.body, "\\begin_layout Chunk", i)
1828 document.body[i] = "\\begin_layout Scrap"
1832 def convert_literate(document):
1833 " Convert Literate document to new format"
1834 i = find_token(document.header, "\\textclass", 0)
1835 if (i != -1) and "literate-" in document.header[i]:
1836 document.textclass = document.header[i].replace("\\textclass literate-", "")
1837 j = find_token(document.header, "\\begin_modules", 0)
1839 document.header.insert(j + 1, "noweb")
1841 document.header.insert(i + 1, "\\end_modules")
1842 document.header.insert(i + 1, "noweb")
1843 document.header.insert(i + 1, "\\begin_modules")
1846 i = find_token(document.body, "\\begin_layout Scrap", i)
1849 document.body[i] = "\\begin_layout Chunk"
1853 def revert_itemargs(document):
1854 " Reverts \\item arguments to TeX-code "
1857 i = find_token(document.body, "\\begin_inset Argument item:", i)
1860 j = find_end_of_inset(document.body, i)
1861 # Find containing paragraph layout
1862 parent = get_containing_layout(document.body, i)
1864 document.warning("Malformed lyx document: Can't find parent paragraph layout")
1868 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
1869 endPlain = find_end_of_layout(document.body, beginPlain)
1870 content = document.body[beginPlain + 1 : endPlain]
1871 del document.body[i:j+1]
1872 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
1873 document.body[parbeg : parbeg] = subst
1877 def revert_garamondx_newtxmath(document):
1878 " Revert native garamond newtxmath definition to LaTeX "
1880 i = find_token(document.header, "\\font_math", 0)
1883 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1884 val = get_value(document.header, "\\font_math", i)
1885 if val == "garamondx-ntxm":
1886 add_to_preamble(document, "\\usepackage[garamondx]{newtxmath}")
1887 document.header[i] = "\\font_math auto"
1890 def revert_garamondx(document):
1891 " Revert native garamond font definition to LaTeX "
1893 if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
1894 i = find_token(document.header, "\\font_roman garamondx", 0)
1897 j = find_token(document.header, "\\font_osf true", 0)
1900 preamble = "\\usepackage"
1902 preamble += "[osfI]"
1903 preamble += "{garamondx}"
1904 add_to_preamble(document, [preamble])
1905 document.header[i] = "\\font_roman default"
1908 def convert_beamerargs(document):
1909 " Converts beamer arguments to new layout "
1911 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
1912 if document.textclass not in beamer_classes:
1915 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
1916 list_layouts = ["Itemize", "Enumerate", "Description"]
1917 rx = re.compile(r'^\\begin_inset Argument (\d+)$')
1921 i = find_token(document.body, "\\begin_inset Argument", i)
1924 # Find containing paragraph layout
1925 parent = get_containing_layout(document.body, i)
1927 document.warning("Malformed lyx document: Can't find parent paragraph layout")
1932 layoutname = parent[0]
1933 for p in range(parbeg, parend):
1934 if layoutname in shifted_layouts:
1935 m = rx.match(document.body[p])
1937 argnr = int(m.group(1))
1939 document.body[p] = "\\begin_inset Argument %d" % argnr
1940 if layoutname == "AgainFrame":
1941 m = rx.match(document.body[p])
1943 document.body[p] = "\\begin_inset Argument 3"
1944 if document.body[p + 4] == "\\begin_inset ERT":
1945 if document.body[p + 9].startswith("<"):
1946 # This is an overlay specification
1948 document.body[p + 9] = document.body[p + 9][1:]
1949 if document.body[p + 9].endswith(">"):
1951 document.body[p + 9] = document.body[p + 9][:-1]
1953 document.body[p] = "\\begin_inset Argument 2"
1954 if layoutname in list_layouts:
1955 m = rx.match(document.body[p])
1957 if m.group(1) == "1":
1958 if document.body[p + 4] == "\\begin_inset ERT":
1959 if document.body[p + 9].startswith("<"):
1960 # This is an overlay specification
1962 document.body[p + 9] = document.body[p + 9][1:]
1963 if document.body[p + 9].endswith(">"):
1965 document.body[p + 9] = document.body[p + 9][:-1]
1966 elif layoutname != "Itemize":
1968 document.body[p] = "\\begin_inset Argument 2"
1972 def convert_againframe_args(document):
1973 " Converts beamer AgainFrame to new layout "
1975 # FIXME: This currently only works if the arguments are in one single ERT
1977 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
1978 if document.textclass not in beamer_classes:
1983 i = find_token(document.body, "\\begin_layout AgainFrame", i)
1986 parent = get_containing_layout(document.body, i)
1988 document.warning("Wrong parent layout!")
1992 if document.body[parbeg] == "\\begin_inset ERT":
1993 ertcont = parbeg + 5
1994 if document.body[ertcont].startswith("[<"):
1995 # This is a default overlay specification
1997 document.body[ertcont] = document.body[ertcont][2:]
1998 if document.body[ertcont].endswith(">]"):
2000 document.body[ertcont] = document.body[ertcont][:-2]
2001 elif document.body[ertcont].endswith("]"):
2003 tok = document.body[ertcont].find('>][')
2005 subst = [document.body[ertcont][:tok],
2006 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2007 'status collapsed', '', '\\begin_layout Plain Layout',
2008 document.body[ertcont][tok + 3:-1]]
2009 document.body[ertcont : ertcont + 1] = subst
2010 # Convert to ArgInset
2011 document.body[parbeg] = "\\begin_inset Argument 2"
2014 elif document.body[ertcont].startswith("<"):
2015 # This is an overlay specification
2017 document.body[ertcont] = document.body[ertcont][1:]
2018 if document.body[ertcont].endswith(">"):
2020 document.body[ertcont] = document.body[ertcont][:-1]
2021 # Convert to ArgInset
2022 document.body[parbeg] = "\\begin_inset Argument 1"
2023 elif document.body[ertcont].endswith(">]"):
2025 tok = document.body[ertcont].find('>[<')
2027 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2028 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2029 'status collapsed', '', '\\begin_layout Plain Layout',
2030 document.body[ertcont][tok + 3:-2]]
2031 # Convert to ArgInset
2032 document.body[parbeg] = "\\begin_inset Argument 1"
2033 elif document.body[ertcont].endswith("]"):
2035 tok = document.body[ertcont].find('>[<')
2038 tokk = document.body[ertcont].find('>][')
2040 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2041 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2042 'status collapsed', '', '\\begin_layout Plain Layout',
2043 document.body[ertcont][tok + 3:tokk],
2044 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2045 'status collapsed', '', '\\begin_layout Plain Layout',
2046 document.body[ertcont][tokk + 3:-1]]
2048 tokk = document.body[ertcont].find('>[')
2050 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tokk],
2051 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3',
2052 'status collapsed', '', '\\begin_layout Plain Layout',
2053 document.body[ertcont][tokk + 2:-1]]
2054 # Convert to ArgInset
2055 document.body[parbeg] = "\\begin_inset Argument 1"
2058 elif document.body[ertcont].startswith("["):
2059 # This is an ERT option
2061 document.body[ertcont] = document.body[ertcont][1:]
2062 if document.body[ertcont].endswith("]"):
2064 document.body[ertcont] = document.body[ertcont][:-1]
2065 # Convert to ArgInset
2066 document.body[parbeg] = "\\begin_inset Argument 3"
2072 def convert_corollary_args(document):
2073 " Converts beamer corrolary-style ERT arguments native InsetArgs "
2075 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2076 if document.textclass not in beamer_classes:
2079 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2080 for lay in corollary_layouts:
2083 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2086 parent = get_containing_layout(document.body, i)
2088 document.warning("Wrong parent layout!")
2092 if document.body[parbeg] == "\\begin_inset ERT":
2093 ertcont = parbeg + 5
2094 if document.body[ertcont].startswith("<"):
2095 # This is an overlay specification
2097 document.body[ertcont] = document.body[ertcont][1:]
2098 if document.body[ertcont].endswith(">"):
2100 document.body[ertcont] = document.body[ertcont][:-1]
2101 elif document.body[ertcont].endswith("]"):
2103 tok = document.body[ertcont].find('>[')
2105 subst = [document.body[ertcont][:tok],
2106 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2107 'status collapsed', '', '\\begin_layout Plain Layout',
2108 document.body[ertcont][tok + 2:-1]]
2109 document.body[ertcont : ertcont + 1] = subst
2110 # Convert to ArgInset
2111 document.body[parbeg] = "\\begin_inset Argument 1"
2114 elif document.body[ertcont].startswith("["):
2115 # This is an ERT option
2117 document.body[ertcont] = document.body[ertcont][1:]
2118 if document.body[ertcont].endswith("]"):
2120 document.body[ertcont] = document.body[ertcont][:-1]
2121 # Convert to ArgInset
2122 document.body[parbeg] = "\\begin_inset Argument 2"
2129 def convert_quote_args(document):
2130 " Converts beamer quote style ERT args to native InsetArgs "
2132 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2133 if document.textclass not in beamer_classes:
2136 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2137 for lay in quote_layouts:
2140 i = find_token(document.body, "\\begin_layout " + lay, i)
2143 parent = get_containing_layout(document.body, i)
2145 document.warning("Wrong parent layout!")
2149 if document.body[parbeg] == "\\begin_inset ERT":
2150 if document.body[i + 6].startswith("<"):
2151 # This is an overlay specification
2153 document.body[i + 6] = document.body[i + 6][1:]
2154 if document.body[i + 6].endswith(">"):
2156 document.body[i + 6] = document.body[i + 6][:-1]
2157 # Convert to ArgInset
2158 document.body[i + 1] = "\\begin_inset Argument 1"
2162 def revert_beamerargs(document):
2163 " Reverts beamer arguments to old layout "
2165 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2166 if document.textclass not in beamer_classes:
2170 list_layouts = ["Itemize", "Enumerate", "Description"]
2171 headings = ["Part", "Section", "Section*", "Subsection", "Subsection*",
2172 "Subsubsection", "Subsubsection*", "FrameSubtitle", "NoteItem"]
2173 quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"]
2174 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2175 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2178 i = find_token(document.body, "\\begin_inset Argument", i)
2181 # Find containing paragraph layout
2182 parent = get_containing_layout(document.body, i)
2184 document.warning("Malformed lyx document: Can't find parent paragraph layout")
2189 realparbeg = parent[3]
2190 layoutname = parent[0]
2192 for p in range(parbeg, parend):
2196 if layoutname in headings:
2197 m = rx.match(document.body[p])
2201 # Find containing paragraph layout
2202 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2203 endPlain = find_end_of_layout(document.body, beginPlain)
2204 endInset = find_end_of_inset(document.body, p)
2205 argcontent = document.body[beginPlain + 1 : endPlain]
2207 realparend = realparend - len(document.body[p : endInset + 1])
2209 del document.body[p : endInset + 1]
2210 if layoutname == "FrameSubtitle":
2211 pre = put_cmd_in_ert("\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2212 elif layoutname == "NoteItem":
2213 pre = put_cmd_in_ert("\\note<") + argcontent + put_cmd_in_ert(">[item]")
2214 elif layoutname.endswith('*'):
2215 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower()[:-1] + "<") + argcontent + put_cmd_in_ert(">*")
2217 pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">")
2218 secarg = find_token(document.body, "\\begin_inset Argument 2", parbeg, parend)
2220 # Find containing paragraph layout
2221 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", secarg)
2222 endPlain = find_end_of_layout(document.body, beginPlain)
2223 endInset = find_end_of_inset(document.body, secarg)
2224 argcontent = document.body[beginPlain + 1 : endPlain]
2226 realparend = realparend - len(document.body[secarg : endInset + 1])
2227 del document.body[secarg : endInset + 1]
2228 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2229 pre += put_cmd_in_ert("{")
2230 document.body[parbeg] = "\\begin_layout Standard"
2231 document.body[realparbeg : realparbeg] = pre
2232 pe = find_end_of_layout(document.body, parbeg)
2233 post = put_cmd_in_ert("}")
2234 document.body[pe : pe] = post
2235 realparend += len(pre) + len(post)
2236 if layoutname == "AgainFrame":
2237 m = rx.match(document.body[p])
2241 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2242 endPlain = find_end_of_layout(document.body, beginPlain)
2243 endInset = find_end_of_inset(document.body, p)
2244 content = document.body[beginPlain + 1 : endPlain]
2246 realparend = realparend - len(document.body[p : endInset + 1])
2248 del document.body[p : endInset + 1]
2249 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2250 document.body[realparbeg : realparbeg] = subst
2251 if layoutname == "Overprint":
2252 m = rx.match(document.body[p])
2256 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2257 endPlain = find_end_of_layout(document.body, beginPlain)
2258 endInset = find_end_of_inset(document.body, p)
2259 content = document.body[beginPlain + 1 : endPlain]
2261 realparend = realparend - len(document.body[p : endInset + 1])
2263 del document.body[p : endInset + 1]
2264 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2265 document.body[realparbeg : realparbeg] = subst
2266 if layoutname == "OverlayArea":
2267 m = rx.match(document.body[p])
2271 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2272 endPlain = find_end_of_layout(document.body, beginPlain)
2273 endInset = find_end_of_inset(document.body, p)
2274 content = document.body[beginPlain + 1 : endPlain]
2276 realparend = realparend - len(document.body[p : endInset + 1])
2278 del document.body[p : endInset + 1]
2279 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2280 document.body[realparbeg : realparbeg] = subst
2281 if layoutname in list_layouts:
2282 m = rx.match(document.body[p])
2286 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2287 endPlain = find_end_of_layout(document.body, beginPlain)
2288 endInset = find_end_of_inset(document.body, p)
2289 content = document.body[beginPlain + 1 : endPlain]
2291 realparend = realparend - len(document.body[p : endInset + 1])
2293 del document.body[p : endInset + 1]
2294 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2295 document.body[realparbeg : realparbeg] = subst
2296 elif argnr == "item:1":
2297 j = find_end_of_inset(document.body, i)
2298 # Find containing paragraph layout
2299 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2300 endPlain = find_end_of_layout(document.body, beginPlain)
2301 content = document.body[beginPlain + 1 : endPlain]
2302 del document.body[i:j+1]
2303 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2304 document.body[realparbeg : realparbeg] = subst
2305 elif argnr == "item:2":
2306 j = find_end_of_inset(document.body, i)
2307 # Find containing paragraph layout
2308 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2309 endPlain = find_end_of_layout(document.body, beginPlain)
2310 content = document.body[beginPlain + 1 : endPlain]
2311 del document.body[i:j+1]
2312 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2313 document.body[realparbeg : realparbeg] = subst
2314 if layoutname in quote_layouts:
2315 m = rx.match(document.body[p])
2319 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2320 endPlain = find_end_of_layout(document.body, beginPlain)
2321 endInset = find_end_of_inset(document.body, p)
2322 content = document.body[beginPlain + 1 : endPlain]
2324 realparend = realparend - len(document.body[p : endInset + 1])
2326 del document.body[p : endInset + 1]
2327 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2328 document.body[realparbeg : realparbeg] = subst
2329 if layoutname in corollary_layouts:
2330 m = rx.match(document.body[p])
2334 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2335 endPlain = find_end_of_layout(document.body, beginPlain)
2336 endInset = find_end_of_inset(document.body, p)
2337 content = document.body[beginPlain + 1 : endPlain]
2339 realparend = realparend - len(document.body[p : endInset + 1])
2341 del document.body[p : endInset + 1]
2342 subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2343 document.body[realparbeg : realparbeg] = subst
2348 def revert_beamerargs2(document):
2349 " Reverts beamer arguments to old layout, step 2 "
2351 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2352 if document.textclass not in beamer_classes:
2356 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"]
2357 corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"]
2358 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2361 i = find_token(document.body, "\\begin_inset Argument", i)
2364 # Find containing paragraph layout
2365 parent = get_containing_layout(document.body, i)
2367 document.warning("Malformed lyx document: Can't find parent paragraph layout")
2372 realparbeg = parent[3]
2373 layoutname = parent[0]
2375 for p in range(parbeg, parend):
2379 if layoutname in shifted_layouts:
2380 m = rx.match(document.body[p])
2384 document.body[p] = "\\begin_inset Argument 1"
2385 if layoutname in corollary_layouts:
2386 m = rx.match(document.body[p])
2390 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2391 endPlain = find_end_of_layout(document.body, beginPlain)
2392 endInset = find_end_of_inset(document.body, p)
2393 content = document.body[beginPlain + 1 : endPlain]
2395 realparend = realparend - len(document.body[p : endInset + 1])
2397 del document.body[p : endInset + 1]
2398 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2399 document.body[realparbeg : realparbeg] = subst
2400 if layoutname == "OverlayArea":
2401 m = rx.match(document.body[p])
2405 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2406 endPlain = find_end_of_layout(document.body, beginPlain)
2407 endInset = find_end_of_inset(document.body, p)
2408 content = document.body[beginPlain + 1 : endPlain]
2410 realparend = realparend - len(document.body[p : endInset + 1])
2412 del document.body[p : endInset + 1]
2413 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2414 document.body[realparbeg : realparbeg] = subst
2415 if layoutname == "AgainFrame":
2416 m = rx.match(document.body[p])
2420 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2421 endPlain = find_end_of_layout(document.body, beginPlain)
2422 endInset = find_end_of_inset(document.body, p)
2423 content = document.body[beginPlain + 1 : endPlain]
2425 realparend = realparend - len(document.body[p : endInset + 1])
2427 del document.body[p : endInset + 1]
2428 subst = put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]")
2429 document.body[realparbeg : realparbeg] = subst
2433 def revert_beamerargs3(document):
2434 " Reverts beamer arguments to old layout, step 3 "
2436 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2437 if document.textclass not in beamer_classes:
2440 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2443 i = find_token(document.body, "\\begin_inset Argument", i)
2446 # Find containing paragraph layout
2447 parent = get_containing_layout(document.body, i)
2449 document.warning("Malformed lyx document: Can't find parent paragraph layout")
2454 realparbeg = parent[3]
2455 layoutname = parent[0]
2457 for p in range(parbeg, parend):
2461 if layoutname == "AgainFrame":
2462 m = rx.match(document.body[p])
2466 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2467 endPlain = find_end_of_layout(document.body, beginPlain)
2468 endInset = find_end_of_inset(document.body, p)
2469 content = document.body[beginPlain + 1 : endPlain]
2471 realparend = realparend - len(document.body[p : endInset + 1])
2473 del document.body[p : endInset + 1]
2474 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2475 document.body[realparbeg : realparbeg] = subst
2479 def revert_beamerflex(document):
2480 " Reverts beamer Flex insets "
2482 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2483 if document.textclass not in beamer_classes:
2486 new_flexes = {"Emphasize" : "\\emph", "Only" : "\\only", "Uncover" : "\\uncover",
2487 "Visible" : "\\visible", "Invisible" : "\\invisible",
2488 "Alternative" : "\\alt", "Beamer_Note" : "\\note"}
2489 old_flexes = {"Alert" : "\\alert", "Structure" : "\\structure"}
2490 rx = re.compile(r'^\\begin_inset Flex (.+)$')
2494 i = find_token(document.body, "\\begin_inset Flex", i)
2497 m = rx.match(document.body[i])
2499 flextype = m.group(1)
2500 z = find_end_of_inset(document.body, i)
2502 document.warning("Can't find end of Flex " + flextype + " inset.")
2505 if flextype in new_flexes:
2506 pre = put_cmd_in_ert(new_flexes[flextype])
2507 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2509 argend = find_end_of_inset(document.body, arg)
2511 document.warning("Can't find end of Argument!")
2514 # Find containing paragraph layout
2515 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2516 endPlain = find_end_of_layout(document.body, beginPlain)
2517 argcontent = document.body[beginPlain + 1 : endPlain]
2519 z = z - len(document.body[arg : argend + 1])
2521 del document.body[arg : argend + 1]
2522 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2523 arg = find_token(document.body, "\\begin_inset Argument 2", i, z)
2525 argend = find_end_of_inset(document.body, arg)
2527 document.warning("Can't find end of Argument!")
2530 # Find containing paragraph layout
2531 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2532 endPlain = find_end_of_layout(document.body, beginPlain)
2533 argcontent = document.body[beginPlain + 1 : endPlain]
2535 z = z - len(document.body[arg : argend + 1])
2537 del document.body[arg : argend + 1]
2538 pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]")
2539 pre += put_cmd_in_ert("{")
2540 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2541 endPlain = find_end_of_layout(document.body, beginPlain)
2543 z = z - len(document.body[i : beginPlain + 1])
2545 document.body[i : beginPlain + 1] = pre
2546 post = put_cmd_in_ert("}")
2547 document.body[z - 2 : z + 1] = post
2548 elif flextype in old_flexes:
2549 pre = put_cmd_in_ert(old_flexes[flextype])
2550 arg = find_token(document.body, "\\begin_inset Argument 1", i, z)
2554 argend = find_end_of_inset(document.body, arg)
2556 document.warning("Can't find end of Argument!")
2559 # Find containing paragraph layout
2560 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg)
2561 endPlain = find_end_of_layout(document.body, beginPlain)
2562 argcontent = document.body[beginPlain + 1 : endPlain]
2564 z = z - len(document.body[arg : argend + 1])
2566 del document.body[arg : argend + 1]
2567 pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">")
2568 pre += put_cmd_in_ert("{")
2569 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
2570 endPlain = find_end_of_layout(document.body, beginPlain)
2572 z = z - len(document.body[i : beginPlain + 1])
2574 document.body[i : beginPlain + 1] = pre
2575 post = put_cmd_in_ert("}")
2576 document.body[z - 2 : z + 1] = post
2581 def revert_beamerblocks(document):
2582 " Reverts beamer block arguments to ERT "
2584 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2585 if document.textclass not in beamer_classes:
2588 blocks = ["Block", "ExampleBlock", "AlertBlock"]
2590 rx = re.compile(r'^\\begin_inset Argument (\S+)$')
2593 i = find_token(document.body, "\\begin_inset Argument", i)
2596 # Find containing paragraph layout
2597 parent = get_containing_layout(document.body, i)
2599 document.warning("Malformed lyx document: Can't find parent paragraph layout")
2604 realparbeg = parent[3]
2605 layoutname = parent[0]
2607 for p in range(parbeg, parend):
2611 if layoutname in blocks:
2612 m = rx.match(document.body[p])
2616 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2617 endPlain = find_end_of_layout(document.body, beginPlain)
2618 endInset = find_end_of_inset(document.body, p)
2619 content = document.body[beginPlain + 1 : endPlain]
2621 realparend = realparend - len(document.body[p : endInset + 1])
2623 del document.body[p : endInset + 1]
2624 subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2625 document.body[realparbeg : realparbeg] = subst
2627 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p)
2628 endPlain = find_end_of_layout(document.body, beginPlain)
2629 endInset = find_end_of_inset(document.body, p)
2630 content = document.body[beginPlain + 1 : endPlain]
2632 realparend = realparend - len(document.body[p : endInset + 1])
2634 del document.body[p : endInset + 1]
2635 subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}")
2636 document.body[realparbeg : realparbeg] = subst
2641 def convert_beamerblocks(document):
2642 " Converts beamer block ERT args to native InsetArgs "
2644 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2645 if document.textclass not in beamer_classes:
2648 blocks = ["Block", "ExampleBlock", "AlertBlock"]
2652 i = find_token_exact(document.body, "\\begin_layout " + lay, i)
2655 parent = get_containing_layout(document.body, i)
2656 if parent == False or parent[1] != i:
2657 document.warning("Wrong parent layout!")
2663 if document.body[parbeg] == "\\begin_inset ERT":
2664 ertcont = parbeg + 5
2666 if document.body[ertcont].startswith("<"):
2667 # This is an overlay specification
2669 document.body[ertcont] = document.body[ertcont][1:]
2670 if document.body[ertcont].endswith(">"):
2672 document.body[ertcont] = document.body[ertcont][:-1]
2673 # Convert to ArgInset
2674 document.body[parbeg] = "\\begin_inset Argument 1"
2675 elif document.body[ertcont].endswith("}"):
2677 tok = document.body[ertcont].find('>{')
2679 document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok],
2680 '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2',
2681 'status collapsed', '', '\\begin_layout Plain Layout',
2682 document.body[ertcont][tok + 2:-1]]
2683 # Convert to ArgInset
2684 document.body[parbeg] = "\\begin_inset Argument 1"
2685 elif document.body[ertcont].startswith("{"):
2686 # This is the block title
2687 if document.body[ertcont].endswith("}"):
2688 # strip off the braces
2689 document.body[ertcont] = document.body[ertcont][1:-1]
2690 # Convert to ArgInset
2691 document.body[parbeg] = "\\begin_inset Argument 2"
2692 elif count_pars_in_inset(document.body, ertcont) > 1:
2693 # Multipar ERT. Skip this.
2696 convert_TeX_brace_to_Argument(document, i, 2, 2, False, True)
2699 j = find_end_of_layout(document.body, i)
2701 document.warning("end of layout not found!")
2702 k = find_token(document.body, "\\begin_inset Argument", i, j)
2704 document.warning("InsetArgument not found!")
2706 l = find_end_of_inset(document.body, k)
2707 m = find_token(document.body, "\\begin_inset ERT", l, j)
2715 def convert_overprint(document):
2716 " Convert old beamer overprint layouts to ERT "
2718 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2719 if document.textclass not in beamer_classes:
2724 i = find_token(document.body, "\\begin_layout Overprint", i)
2727 # Find end of sequence
2728 j = find_end_of_sequence(document.body, i)
2730 document.warning("Malformed lyx document. Cannot find end of Overprint sequence!")
2734 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
2735 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"]
2736 endseq = endseq + len(esubst) - len(document.body[j : j])
2737 document.body[j : j] = esubst
2738 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
2740 argend = find_end_of_layout(document.body, argbeg)
2742 document.warning("Malformed lyx document. Cannot find end of Overprint argument!")
2745 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
2746 endPlain = find_end_of_layout(document.body, beginPlain)
2747 content = document.body[beginPlain + 1 : endPlain]
2749 endseq = endseq - len(document.body[argbeg : argend + 1])
2751 del document.body[argbeg : argend + 1]
2752 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2754 endseq = endseq - len(document.body[i : i])
2755 document.body[i : i] = subst + ["\\end_layout"]
2756 endseq += len(subst)
2758 for p in range(i, endseq):
2759 if document.body[p] == "\\begin_layout Overprint":
2760 document.body[p] = "\\begin_layout Standard"
2765 def revert_overprint(document):
2766 " Revert old beamer overprint layouts to ERT "
2768 beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
2769 if document.textclass not in beamer_classes:
2774 i = find_token(document.body, "\\begin_layout Overprint", i)
2777 # Find end of sequence
2778 j = find_end_of_sequence(document.body, i)
2780 document.warning("Malformed lyx document. Cannot find end of Overprint sequence!")
2784 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}")
2785 esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}")
2786 endseq = endseq + len(esubst) - len(document.body[j : j])
2787 document.body[j : j] = esubst
2788 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j)
2790 argend = find_end_of_inset(document.body, argbeg)
2792 document.warning("Malformed lyx document. Cannot find end of Overprint argument!")
2795 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
2796 endPlain = find_end_of_layout(document.body, beginPlain)
2797 content = document.body[beginPlain + 1 : endPlain]
2799 endseq = endseq - len(document.body[argbeg : argend])
2801 del document.body[argbeg : argend + 1]
2802 subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
2804 endseq = endseq - len(document.body[i : i])
2805 document.body[i : i] = subst + ["\\end_layout"]
2806 endseq += len(subst)
2812 if document.body[p] == "\\begin_layout Overprint":
2813 q = find_end_of_layout(document.body, p)
2815 document.warning("Malformed lyx document. Cannot find end of Overprint layout!")
2818 subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\onslide")
2819 argbeg = find_token(document.body, "\\begin_inset Argument item:1", p, q)
2821 argend = find_end_of_inset(document.body, argbeg)
2823 document.warning("Malformed lyx document. Cannot find end of Overprint item argument!")
2826 beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg)
2827 endPlain = find_end_of_layout(document.body, beginPlain)
2828 content = document.body[beginPlain + 1 : endPlain]
2830 endseq = endseq - len(document.body[argbeg : argend + 1])
2832 del document.body[argbeg : argend + 1]
2833 subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">")
2834 endseq = endseq - len(document.body[p : p + 1]) + len(subst)
2835 document.body[p : p + 1] = subst
2845 supported_versions = ["2.1.0","2.1"]
2848 [415, [convert_undertilde]],
2850 [417, [convert_japanese_encodings]],
2853 [420, [convert_biblio_style]],
2854 [421, [convert_longtable_captions]],
2855 [422, [convert_use_packages]],
2856 [423, [convert_use_mathtools]],
2857 [424, [convert_cite_engine_type]],
2861 [428, [convert_cell_rotation]],
2862 [429, [convert_table_rotation]],
2863 [430, [convert_listoflistings]],
2864 [431, [convert_use_amssymb]],
2866 [433, [convert_armenian]],
2874 [441, [convert_mdnomath]],
2879 [446, [convert_latexargs]],
2880 [447, [convert_IEEEtran, convert_AASTeX, convert_AGUTeX, convert_IJMP, convert_SIGPLAN, convert_SIGGRAPH, convert_EuropeCV]],
2881 [448, [convert_literate]],
2884 [451, [convert_beamerargs, convert_againframe_args, convert_corollary_args, convert_quote_args]],
2885 [452, [convert_beamerblocks]],
2886 [453, [convert_use_stmaryrd]],
2887 [454, [convert_overprint]]
2891 [453, [revert_overprint]],
2892 [452, [revert_use_stmaryrd]],
2893 [451, [revert_beamerblocks]],
2894 [450, [revert_beamerargs, revert_beamerargs2, revert_beamerargs3, revert_beamerflex]],
2895 [449, [revert_garamondx, revert_garamondx_newtxmath]],
2896 [448, [revert_itemargs]],
2897 [447, [revert_literate]],
2898 [446, [revert_IEEEtran, revert_AASTeX, revert_AGUTeX, revert_IJMP, revert_SIGPLAN, revert_SIGGRAPH, revert_EuropeCV]],
2899 [445, [revert_latexargs]],
2900 [444, [revert_uop]],
2901 [443, [revert_biolinum]],
2903 [441, [revert_newtxmath]],
2904 [440, [revert_mdnomath]],
2905 [439, [revert_mathfonts]],
2906 [438, [revert_minionpro]],
2907 [437, [revert_ipadeco, revert_ipachar]],
2908 [436, [revert_texgyre]],
2909 [435, [revert_mathdesign]],
2910 [434, [revert_txtt]],
2911 [433, [revert_libertine]],
2912 [432, [revert_armenian]],
2913 [431, [revert_languages, revert_ancientgreek]],
2914 [430, [revert_use_amssymb]],
2915 [429, [revert_listoflistings]],
2916 [428, [revert_table_rotation]],
2917 [427, [revert_cell_rotation]],
2918 [426, [revert_tipa]],
2919 [425, [revert_verbatim]],
2920 [424, [revert_cancel]],
2921 [423, [revert_cite_engine_type]],
2922 [422, [revert_use_mathtools]],
2923 [421, [revert_use_packages]],
2924 [420, [revert_longtable_captions]],
2925 [419, [revert_biblio_style]],
2926 [418, [revert_australian]],
2927 [417, [revert_justification]],
2928 [416, [revert_japanese_encodings]],
2929 [415, [revert_negative_space, revert_math_spaces]],
2930 [414, [revert_undertilde]],
2931 [413, [revert_visible_space]]
2935 if __name__ == "__main__":