# -*- coding: utf-8 -*- # This file is part of lyx2lyx # -*- coding: utf-8 -*- # Copyright (C) 2011 The LyX team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA """ Convert files to the file format generated by lyx 2.1""" import re, string import unicodedata import sys, os # Uncomment only what you need to import, please. from parser_tools import count_pars_in_inset, del_token, find_token, find_token_exact, \ find_token_backwards, find_end_of, find_end_of_inset, find_end_of_layout, \ find_end_of_sequence, find_re, get_option_value, get_containing_layout, \ get_value, get_quoted_value, set_option_value #from parser_tools import find_token, find_end_of, find_tokens, \ #find_end_of_inset, find_end_of_layout, \ #is_in_inset, del_token, check_token from lyx2lyx_tools import add_to_preamble, put_cmd_in_ert, get_ert #from lyx2lyx_tools import insert_to_preamble, \ # lyx2latex, latex_length, revert_flex_inset, \ # revert_font_attrs, hex2ratio, str2bool #################################################################### # Private helper functions #def remove_option(lines, m, option): #''' removes option from line m. returns whether we did anything ''' #l = lines[m].find(option) #if l == -1: #return False #val = lines[m][l:].split('"')[1] #lines[m] = lines[m][:l - 1] + lines[m][l+len(option + '="' + val + '"'):] #return True ############################################################################### ### ### Conversion and reversion routines ### ############################################################################### def revert_visible_space(document): "Revert InsetSpace visible into its ERT counterpart" i = 0 while True: i = find_token(document.body, "\\begin_inset space \\textvisiblespace{}", i) if i == -1: return end = find_end_of_inset(document.body, i) subst = put_cmd_in_ert("\\textvisiblespace{}") document.body[i:end + 1] = subst def convert_undertilde(document): " Load undertilde automatically " i = find_token(document.header, "\\use_mathdots" , 0) if i == -1: i = find_token(document.header, "\\use_mhchem" , 0) if i == -1: i = find_token(document.header, "\\use_esint" , 0) if i == -1: document.warning("Malformed LyX document: Can't find \\use_mathdots.") return; j = find_token(document.preamble, "\\usepackage{undertilde}", 0) if j == -1: document.header.insert(i + 1, "\\use_undertilde 0") else: document.header.insert(i + 1, "\\use_undertilde 2") del document.preamble[j] def revert_undertilde(document): " Load undertilde if used in the document " undertilde = find_token(document.header, "\\use_undertilde" , 0) if undertilde == -1: document.warning("No \\use_undertilde line. Assuming auto.") else: val = get_value(document.header, "\\use_undertilde", undertilde) del document.header[undertilde] try: usetilde = int(val) except: document.warning("Invalid \\use_undertilde value: " + val + ". Assuming auto.") # probably usedots has not been changed, but be safe. usetilde = 1 if usetilde == 0: # do not load case return if usetilde == 2: # force load case add_to_preamble(document, ["\\usepackage{undertilde}"]) return # so we are in the auto case. we want to load undertilde if \utilde is used. i = 0 while True: i = find_token(document.body, '\\begin_inset Formula', i) if i == -1: return j = find_end_of_inset(document.body, i) if j == -1: document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i)) i += 1 continue code = "\n".join(document.body[i:j]) if code.find("\\utilde") != -1: add_to_preamble(document, ["\\@ifundefined{utilde}{\\usepackage{undertilde}}"]) return i = j def revert_negative_space(document): "Revert InsetSpace negmedspace and negthickspace into its TeX-code counterpart" i = 0 j = 0 reverted = False while True: i = find_token(document.body, "\\begin_inset space \\negmedspace{}", i) if i == -1: j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j) if j == -1: # load amsmath in the preamble if not already loaded if we are at the end of checking if reverted == True: i = find_token(document.header, "\\use_amsmath 2", 0) if i == -1: add_to_preamble(document, ["\\@ifundefined{negthickspace}{\\usepackage{amsmath}}"]) return if i == -1: return end = find_end_of_inset(document.body, i) subst = put_cmd_in_ert("\\negmedspace{}") document.body[i:end + 1] = subst j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j) if j == -1: return end = find_end_of_inset(document.body, j) subst = put_cmd_in_ert("\\negthickspace{}") document.body[j:end + 1] = subst reverted = True def revert_math_spaces(document): "Revert formulas with protected custom space and protected hfills to TeX-code" i = 0 while True: i = find_token(document.body, "\\begin_inset Formula", i) if i == -1: return j = document.body[i].find("\\hspace*") if j != -1: end = find_end_of_inset(document.body, i) subst = put_cmd_in_ert(document.body[i][21:]) document.body[i:end + 1] = subst i = i + 1 def convert_japanese_encodings(document): " Rename the japanese encodings to names understood by platex " jap_enc_dict = { "EUC-JP-pLaTeX": "euc", "JIS-pLaTeX": "jis", "SJIS-pLaTeX": "sjis" } i = find_token(document.header, "\\inputencoding" , 0) if i == -1: return val = get_value(document.header, "\\inputencoding", i) if val in jap_enc_dict.keys(): document.header[i] = "\\inputencoding %s" % jap_enc_dict[val] def revert_japanese_encodings(document): " Revert the japanese encodings name changes " jap_enc_dict = { "euc": "EUC-JP-pLaTeX", "jis": "JIS-pLaTeX", "sjis": "SJIS-pLaTeX" } i = find_token(document.header, "\\inputencoding" , 0) if i == -1: return val = get_value(document.header, "\\inputencoding", i) if val in jap_enc_dict.keys(): document.header[i] = "\\inputencoding %s" % jap_enc_dict[val] def revert_justification(document): " Revert the \\justification buffer param" if not del_token(document.header, '\\justification', 0): document.warning("Malformed LyX document: Missing \\justification.") def revert_australian(document): "Set English language variants Australian and Newzealand to English" if document.language == "australian" or document.language == "newzealand": document.language = "english" i = find_token(document.header, "\\language", 0) if i != -1: document.header[i] = "\\language english" j = 0 while True: j = find_token(document.body, "\\lang australian", j) if j == -1: j = find_token(document.body, "\\lang newzealand", 0) if j == -1: return else: document.body[j] = document.body[j].replace("\\lang newzealand", "\\lang english") else: document.body[j] = document.body[j].replace("\\lang australian", "\\lang english") j += 1 def convert_biblio_style(document): "Add a sensible default for \\biblio_style based on the citation engine." i = find_token(document.header, "\\cite_engine", 0) if i != -1: engine = get_value(document.header, "\\cite_engine", i).split("_")[0] style = {"basic": "plain", "natbib": "plainnat", "jurabib": "jurabib"} document.header.insert(i + 1, "\\biblio_style " + style[engine]) def revert_biblio_style(document): "BibTeX insets with default option use the style defined by \\biblio_style." i = find_token(document.header, "\\biblio_style" , 0) if i == -1: document.warning("No \\biblio_style line. Nothing to do.") return default_style = get_value(document.header, "\\biblio_style", i) del document.header[i] # We are looking for bibtex insets having the default option i = 0 while True: i = find_token(document.body, "\\begin_inset CommandInset bibtex", i) if i == -1: return j = find_end_of_inset(document.body, i) if j == -1: document.warning("Malformed LyX document: Can't find end of bibtex inset at line " + str(i)) i += 1 return k = find_token(document.body, "options", i, j) if k != -1: options = get_quoted_value(document.body, "options", k) if "default" in options.split(","): document.body[k] = 'options "%s"' \ % options.replace("default", default_style) i = j def handle_longtable_captions(document, forward): begin_table = 0 while True: begin_table = find_token(document.body, '') if end_table == -1: document.warning("Malformed LyX document: Could not find end of table.") begin_table += 1 continue fline = find_token(document.body, "') if end_row == -1: document.warning("Can't find end of row " + str(row + 1)) break if forward: if (get_option_value(document.body[begin_row], 'caption') == 'true' and get_option_value(document.body[begin_row], 'endfirsthead') != 'true' and get_option_value(document.body[begin_row], 'endhead') != 'true' and get_option_value(document.body[begin_row], 'endfoot') != 'true' and get_option_value(document.body[begin_row], 'endlastfoot') != 'true'): document.body[begin_row] = set_option_value(document.body[begin_row], 'caption', 'true", endfirsthead="true') elif get_option_value(document.body[begin_row], 'caption') == 'true': if get_option_value(document.body[begin_row], 'endfirsthead') == 'true': document.body[begin_row] = set_option_value(document.body[begin_row], 'endfirsthead', 'false') if get_option_value(document.body[begin_row], 'endhead') == 'true': document.body[begin_row] = set_option_value(document.body[begin_row], 'endhead', 'false') if get_option_value(document.body[begin_row], 'endfoot') == 'true': document.body[begin_row] = set_option_value(document.body[begin_row], 'endfoot', 'false') if get_option_value(document.body[begin_row], 'endlastfoot') == 'true': document.body[begin_row] = set_option_value(document.body[begin_row], 'endlastfoot', 'false') begin_row = end_row # since there could be a tabular inside this one, we # cannot jump to end. begin_table += 1 def convert_longtable_captions(document): "Add a firsthead flag to caption rows" handle_longtable_captions(document, True) def revert_longtable_captions(document): "remove head/foot flag from caption rows" handle_longtable_captions(document, False) def convert_use_packages(document): "use_xxx yyy => use_package xxx yyy" packages = ["amsmath", "esint", "mathdots", "mhchem", "undertilde"] for p in packages: i = find_token(document.header, "\\use_%s" % p, 0) if i != -1: value = get_value(document.header, "\\use_%s" % p, i) document.header[i] = "\\use_package %s %s" % (p, value) def revert_use_packages(document): "use_package xxx yyy => use_xxx yyy" packages = ["amsmath", "esint", "mathdots", "mhchem", "undertilde"] # the order is arbitrary for the use_package version, and not all packages need to be given. # Ensure a complete list and correct order (important for older LyX versions and especially lyx2lyx) j = 0 for p in packages: regexp = re.compile(r'(\\use_package\s+%s)' % p) i = find_re(document.header, regexp, j) if i != -1: value = get_value(document.header, "\\use_package %s" % p, i).split()[1] del document.header[i] j = i document.header.insert(j, "\\use_%s %s" % (p, value)) j = j + 1 def convert_use_mathtools(document): "insert use_package mathtools" i = find_token(document.header, "\\use_package", 0) if i == -1: document.warning("Malformed LyX document: Can't find \\use_package.") return; j = find_token(document.preamble, "\\usepackage{mathtools}", 0) if j == -1: document.header.insert(i + 1, "\\use_package mathtools 0") else: document.header.insert(i + 1, "\\use_package mathtools 2") del document.preamble[j] def revert_use_mathtools(document): "remove use_package mathtools" regexp = re.compile(r'(\\use_package\s+mathtools)') i = find_re(document.header, regexp, 0) value = "1" # default is auto if i != -1: value = get_value(document.header, "\\use_package" , i).split()[1] del document.header[i] if value == "2": # on add_to_preamble(document, ["\\usepackage{mathtools}"]) elif value == "1": # auto commands = ["mathclap", "mathllap", "mathrlap", \ "lgathered", "rgathered", "vcentcolon", "dblcolon", \ "coloneqq", "Coloneqq", "coloneq", "Coloneq", "eqqcolon", \ "Eqqcolon", "eqcolon", "Eqcolon", "colonapprox", \ "Colonapprox", "colonsim", "Colonsim"] i = 0 while True: i = find_token(document.body, '\\begin_inset Formula', i) if i == -1: return j = find_end_of_inset(document.body, i) if j == -1: document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i)) i += 1 continue code = "\n".join(document.body[i:j]) for c in commands: if code.find("\\%s" % c) != -1: add_to_preamble(document, ["\\usepackage{mathtools}"]) return i = j def convert_use_stmaryrd(document): "insert use_package stmaryrd" i = find_token(document.header, "\\use_package", 0) if i == -1: document.warning("Malformed LyX document: Can't find \\use_package.") return; j = find_token(document.preamble, "\\usepackage{stmaryrd}", 0) if j == -1: document.header.insert(i + 1, "\\use_package stmaryrd 0") else: document.header.insert(i + 1, "\\use_package stmaryrd 2") del document.preamble[j] def revert_use_stmaryrd(document): "remove use_package stmaryrd" regexp = re.compile(r'(\\use_package\s+stmaryrd)') i = find_re(document.header, regexp, 0) value = "1" # default is auto if i != -1: value = get_value(document.header, "\\use_package" , i).split()[1] del document.header[i] if value == "2": # on add_to_preamble(document, ["\\usepackage{stmaryrd}"]) elif value == "1": # auto commands = ["shortleftarrow", "shortrightarrow", "shortuparrow", \ "shortdownarrow", "Yup", "Ydown", "Yleft", "Yright", \ "varcurlyvee", "varcurlywedge", "minuso", "baro", \ "sslash", "bbslash", "moo", "varotimes", "varoast", \ "varobar", "varodot", "varoslash", "varobslash", \ "varocircle", "varoplus", "varominus", "boxast", \ "boxbar", "boxslash", "boxbslash", "boxcircle", \ "boxbox", "boxempty", "merge", "vartimes", \ "fatsemi", "sswarrow", "ssearrow", "curlywedgeuparrow", \ "curlywedgedownarrow", "fatslash", "fatbslash", "lbag", \ "rbag", "varbigcirc", "leftrightarroweq", \ "curlyveedownarrow", "curlyveeuparrow", "nnwarrow", \ "nnearrow", "leftslice", "rightslice", "varolessthan", \ "varogreaterthan", "varovee", "varowedge", "talloblong", \ "interleave", "obar", "obslash", "olessthan", \ "ogreaterthan", "ovee", "owedge", "oblong", "inplus", \ "niplus", "nplus", "subsetplus", "supsetplus", \ "subsetpluseq", "supsetpluseq", "Lbag", "Rbag", \ "llbracket", "rrbracket", "llparenthesis", \ "rrparenthesis", "binampersand", "bindnasrepma", \ "trianglelefteqslant", "trianglerighteqslant", \ "ntrianglelefteqslant", "ntrianglerighteqslant", \ "llfloor", "rrfloor", "llceil", "rrceil", "arrownot", \ "Arrownot", "Mapstochar", "mapsfromchar", "Mapsfromchar", \ "leftrightarrowtriangle", "leftarrowtriangle", \ "rightarrowtriangle", \ "bigcurlyvee", "bigcurlywedge", "bigsqcap", "bigbox", \ "bigparallel", "biginterleave", "bignplus", \ "varcopyright", "longarrownot", "Longarrownot", \ "Mapsto", "mapsfrom", "Mapsfrom" "Longmapsto", \ "longmapsfrom", "Longmapsfrom"] # commands provided by stmaryrd.sty but LyX uses other packages: # boxdot lightning, bigtriangledown, bigtriangleup i = 0 while True: i = find_token(document.body, '\\begin_inset Formula', i) if i == -1: return j = find_end_of_inset(document.body, i) if j == -1: document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i)) i += 1 continue code = "\n".join(document.body[i:j]) for c in commands: if code.find("\\%s" % c) != -1: add_to_preamble(document, ["\\usepackage{stmaryrd}"]) return i = j def convert_use_stackrel(document): "insert use_package stackrel" i = find_token(document.header, "\\use_package", 0) if i == -1: document.warning("Malformed LyX document: Can't find \\use_package.") return; j = find_token(document.preamble, "\\usepackage{stackrel}", 0) if j == -1: document.header.insert(i + 1, "\\use_package stackrel 0") else: document.header.insert(i + 1, "\\use_package stackrel 2") del document.preamble[j] def revert_use_stackrel(document): "remove use_package stackrel" regexp = re.compile(r'(\\use_package\s+stackrel)') i = find_re(document.header, regexp, 0) value = "1" # default is auto if i != -1: value = get_value(document.header, "\\use_package" , i).split()[1] del document.header[i] if value == "2": # on add_to_preamble(document, ["\\usepackage{stackrel}"]) elif value == "1": # auto regcmd = re.compile(r'.*\\stackrel\s*\[') i = 0 while True: i = find_token(document.body, '\\begin_inset Formula', i) if i == -1: return j = find_end_of_inset(document.body, i) if j == -1: document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i)) i += 1 continue code = "\n".join(document.body[i:j]) if regcmd.match(code): add_to_preamble(document, ["\\usepackage{stackrel}"]) return i = j def convert_cite_engine_type(document): "Determine the \\cite_engine_type from the citation engine." i = find_token(document.header, "\\cite_engine", 0) if i == -1: return engine = get_value(document.header, "\\cite_engine", i) if "_" in engine: engine, type = engine.split("_") else: type = {"basic": "numerical", "jurabib": "authoryear"}[engine] document.header[i] = "\\cite_engine " + engine document.header.insert(i + 1, "\\cite_engine_type " + type) def revert_cite_engine_type(document): "Natbib had the type appended with an underscore." engine_type = "numerical" i = find_token(document.header, "\\cite_engine_type" , 0) if i == -1: document.warning("No \\cite_engine_type line. Assuming numerical.") else: engine_type = get_value(document.header, "\\cite_engine_type", i) del document.header[i] # We are looking for the natbib citation engine i = find_token(document.header, "\\cite_engine natbib", 0) if i == -1: return document.header[i] = "\\cite_engine natbib_" + engine_type def revert_cancel(document): "add cancel to the preamble if necessary" commands = ["cancelto", "cancel", "bcancel", "xcancel"] i = 0 while True: i = find_token(document.body, '\\begin_inset Formula', i) if i == -1: return j = find_end_of_inset(document.body, i) if j == -1: document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i)) i += 1 continue code = "\n".join(document.body[i:j]) for c in commands: if code.find("\\%s" % c) != -1: add_to_preamble(document, ["\\usepackage{cancel}"]) return i = j def revert_verbatim(document): " Revert verbatim einvironments completely to TeX-code. " i = 0 consecutive = False subst_end = ['\end_layout', '', '\\begin_layout Plain Layout', '\end_layout', '', '\\begin_layout Plain Layout', '', '', '\\backslash', '', 'end{verbatim}', '\\end_layout', '', '\\end_inset', '', '', '\\end_layout'] subst_begin = ['\\begin_layout Standard', '\\noindent', '\\begin_inset ERT', 'status collapsed', '', '\\begin_layout Plain Layout', '', '', '\\backslash', 'begin{verbatim}', '\\end_layout', '', '\\begin_layout Plain Layout', ''] while 1: i = find_token(document.body, "\\begin_layout Verbatim", i) if i == -1: return j = find_end_of_layout(document.body, i) if j == -1: document.warning("Malformed lyx document: Can't find end of Verbatim layout") i += 1 continue # delete all line breaks insets (there are no other insets) l = i while 1: n = find_token(document.body, "\\begin_inset Newline newline", l) if n == -1: n = find_token(document.body, "\\begin_inset Newline linebreak", l) if n == -1: break m = find_end_of_inset(document.body, n) del(document.body[m:m+1]) document.body[n:n+1] = ['\end_layout', '', '\\begin_layout Plain Layout'] l += 1 j += 1 # consecutive verbatim environments need to be connected k = find_token(document.body, "\\begin_layout Verbatim", j) if k == j + 2 and consecutive == False: consecutive = True document.body[j:j+1] = ['\end_layout', '', '\\begin_layout Plain Layout'] document.body[i:i+1] = subst_begin continue if k == j + 2 and consecutive == True: document.body[j:j+1] = ['\end_layout', '', '\\begin_layout Plain Layout'] del(document.body[i:i+1]) continue if k != j + 2 and consecutive == True: document.body[j:j+1] = subst_end # the next paragraph must not be indented document.body[j+19:j+19] = ['\\noindent'] del(document.body[i:i+1]) consecutive = False continue else: document.body[j:j+1] = subst_end # the next paragraph must not be indented document.body[j+19:j+19] = ['\\noindent'] document.body[i:i+1] = subst_begin def revert_tipa(document): " Revert native TIPA insets to mathed or ERT. " i = 0 while 1: i = find_token(document.body, "\\begin_inset IPA", i) if i == -1: return j = find_end_of_inset(document.body, i) if j == -1: document.warning("Malformed lyx document: Can't find end of IPA inset") i += 1 continue Multipar = False n = find_token(document.body, "\\begin_layout", i, j) if n == -1: document.warning("Malformed lyx document: IPA inset has no embedded layout") i += 1 continue m = find_end_of_layout(document.body, n) if m == -1: document.warning("Malformed lyx document: Can't find end of embedded layout") i += 1 continue content = document.body[n+1:m] p = find_token(document.body, "\\begin_layout", m, j) if p != -1 or len(content) > 1: Multipar = True content = document.body[i+1:j] if Multipar: # IPA insets with multiple pars need to be wrapped by \begin{IPA}...\end{IPA} 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}") add_to_preamble(document, ["\\usepackage{tipa,tipx}"]) else: # single-par IPA insets can be reverted to mathed document.body[i:j+1] = ["\\begin_inset Formula $\\text{\\textipa{" + content[0] + "}}$", "\\end_inset"] i = j def revert_cell_rotation(document): "Revert cell rotations to TeX-code" load_rotating = False i = 0 try: while True: # first, let's find out if we need to do anything i = find_token(document.body, '', j) k = document.body[i].find('"', j + 8) value = document.body[i][j + 8 : k] if value == "0": rgx = re.compile(r' rotate="[^"]+?"') # remove rotate option document.body[i] = rgx.sub('', document.body[i]) elif value == "90": rgx = re.compile(r'rotate="[^"]+?"') document.body[i] = rgx.sub('rotate="true"', document.body[i]) else: rgx = re.compile(r' rotate="[^"]+?"') load_rotating = True # remove rotate option document.body[i] = rgx.sub('', document.body[i]) # write ERT document.body[end_table + 3 : end_table + 3] = \ put_cmd_in_ert("\\end{turn}") document.body[i - 2 : i - 2] = \ put_cmd_in_ert("\\begin{turn}{" + value + "}") i += 1 finally: if load_rotating: add_to_preamble(document, ["\\@ifundefined{turnbox}{\usepackage{rotating}}{}"]) def convert_table_rotation(document): 'Convert table rotation statements from "true" to "90"' i = 0 while True: # first, let's find out if we need to do anything i = find_token(document.body, ' 0: # We know for now that this must be the initials module with the Initial layout # If we get more such modules, we need some automating. if parent[0] == "Initial": # Layout has 1 opt and 1 req arg. # Count the actual arguments actualargs = 0 for p in range(parbeg, parend): if document.body[p] == "\\begin_inset Argument": actualargs += 1 if actualargs == 1: allowed_opts = 0 first_req = 2 # Collect all arguments in this paragraph argnr = 0 for p in range(parbeg, parend): if document.body[p] == "\\begin_inset Argument": argnr += 1 if allowed_opts != -1: # We have less arguments than opt + required. # required must take precedence. if argnr > allowed_opts and argnr < first_req: argnr = first_req document.body[p] = "\\begin_inset Argument %d" % argnr i = i + 1 def revert_latexargs(document): " Revert InsetArgument to old syntax " i = 0 rx = re.compile(r'^\\begin_inset Argument (\d+)$') args = dict() while True: # Search for Argument insets i = find_token(document.body, "\\begin_inset Argument", i) if i == -1: return m = rx.match(document.body[i]) if not m: # No ID: inset already reverted i = i + 1 continue # Find containing paragraph layout parent = get_containing_layout(document.body, i) if parent == False: document.warning("Malformed lyx document: Can't find parent paragraph layout") i = i + 1 continue parbeg = parent[1] parend = parent[2] realparbeg = parent[3] # Collect all arguments in this paragraph realparend = parend for p in range(parbeg, parend): m = rx.match(document.body[p]) if m: val = int(m.group(1)) j = find_end_of_inset(document.body, p) # Revert to old syntax document.body[p] = "\\begin_inset Argument" if j == -1: document.warning("Malformed lyx document: Can't find end of Argument inset") continue if val > 0: args[val] = document.body[p : j + 1] # Adjust range end realparend = realparend - len(document.body[p : j + 1]) # Remove arg inset at this position del document.body[p : j + 1] if p >= realparend: break # Now sort the arg insets subst = [""] for f in sorted(args): subst += args[f] del args[f] # Insert the sorted arg insets at paragraph begin document.body[realparbeg : realparbeg] = subst i = realparbeg + 1 + len(subst) def revert_Argument_to_TeX_brace(document, line, n, nmax, environment): ''' Reverts an InsetArgument to TeX-code usage: revert_Argument_to_TeX_brace(document, LineOfBeginLayout, StartArgument, EndArgument, isEnvironment) LineOfBeginLayout is the line of the \begin_layout statement StartArgument is the number of the first argument that needs to be converted EndArgument is the number of the last argument that needs to be converted or the last defined one isEnvironment must be true, if the layout id for a LaTeX environment ''' lineArg = 0 while lineArg != -1 and n < nmax + 1: lineArg = find_token(document.body, "\\begin_inset Argument " + str(n), line) if lineArg != -1: beginPlain = find_token(document.body, "\\begin_layout Plain Layout", lineArg) # we have to assure that no other inset is in the Argument beginInset = find_token(document.body, "\\begin_inset", beginPlain) endInset = find_token(document.body, "\\end_inset", beginPlain) k = beginPlain + 1 l = k while beginInset < endInset and beginInset != -1: beginInset = find_token(document.body, "\\begin_inset", k) endInset = find_token(document.body, "\\end_inset", l) k = beginInset + 1 l = endInset + 1 if environment == False: document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}{") del(document.body[lineArg : beginPlain + 1]) else: document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}") document.body[lineArg : beginPlain + 1] = put_cmd_in_ert("{") n = n + 1 def convert_TeX_brace_to_Argument(document, line, n, nmax, inset, environment): ''' Converts TeX code for mandatory arguments to an InsetArgument The conversion of TeX code for optional arguments must be done with another routine !!! Be careful if the braces are different in your case as expected here: - "}{" separates mandatory arguments of commands - "}" + "{" separates mandatory arguments of commands - "}" + " " + "{" separates mandatory arguments of commands - { and } surround a mandatory argument of an environment usage: convert_TeX_brace_to_Argument(document, LineOfBeginLayout/Inset, StartArgument, EndArgument, isInset, isEnvironment) LineOfBeginLayout/Inset is the line of the \begin_layout or \begin_inset statement StartArgument is the number of the first ERT that needs to be converted EndArgument is the number of the last ERT that needs to be converted isInset must be true, if braces inside an InsetLayout needs to be converted isEnvironment must be true, if the layout is for a LaTeX environment Todo: this routine can currently handle only one mandatory argument of environments ''' lineERT = line endn = line loop = 1 while lineERT != -1 and n < nmax + 1: lineERT = find_token(document.body, "\\begin_inset ERT", lineERT) if environment == False and lineERT != -1: bracePair = find_token(document.body, "}{", lineERT) # assure that the "}{" is in this ERT if bracePair == lineERT + 5: end = find_token(document.body, "\\end_inset", bracePair) document.body[lineERT : end + 1] = ["\\end_layout", "", "\\end_inset"] if loop == 1: # in the case that n > 1 we have optional arguments before # therefore detect them if any if n > 1: # first check if there is an argument lineArg = find_token(document.body, "\\begin_inset Argument", line) if lineArg < lineERT and lineArg != -1: # we have an argument, so now search backwards for its end # we must now assure that we don't find other insets like e.g. a newline endInsetArg = lineERT endLayoutArg = endInsetArg while endInsetArg != endLayoutArg + 2 and endInsetArg != -1: endInsetArg = endInsetArg - 1 endLayoutArg = endInsetArg endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg) endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg) line = endInsetArg + 1 if inset == False: document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"] else: document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"] else: document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"] n = n + 1 endn = end loop = loop + 1 # now check the case that we have "}" + "{" in two ERTs else: endBrace = find_token(document.body, "}", lineERT) if endBrace == lineERT + 5: beginBrace = find_token(document.body, "{", endBrace) # assure that the ERTs are consecutive (11 or 12 depending if there is a space between the ERTs or not) if beginBrace == endBrace + 11 or beginBrace == endBrace + 12: end = find_token(document.body, "\\end_inset", beginBrace) document.body[lineERT : end + 1] = ["\\end_layout", "", "\\end_inset"] if loop == 1: # in the case that n > 1 we have optional arguments before # therefore detect them if any if n > 1: # first check if there is an argument lineArg = find_token(document.body, "\\begin_inset Argument", line) if lineArg < lineERT and lineArg != -1: # we have an argument, so now search backwards for its end # we must now assure that we don't find other insets like e.g. a newline endInsetArg = lineERT endLayoutArg = endInsetArg while endInsetArg != endLayoutArg + 2 and endInsetArg != -1: endInsetArg = endInsetArg - 1 endLayoutArg = endInsetArg endInsetArg = find_token_backwards(document.body, "\\end_inset", endInsetArg) endLayoutArg = find_token_backwards(document.body, "\\end_layout", endLayoutArg) line = endInsetArg + 1 if inset == False: document.body[line + 1 : line + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"] else: document.body[line + 4 : line + 4] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"] else: document.body[endn : endn] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"] n = n + 1 loop = loop + 1 # set the line where the next argument will be inserted if beginBrace == endBrace + 11: endn = end - 11 else: endn = end - 12 else: lineERT = lineERT + 1 if environment == True and lineERT != -1: opening = find_token(document.body, "{", lineERT) if opening == lineERT + 5: # assure that the "{" is in this ERT end = find_token(document.body, "\\end_inset", opening) document.body[lineERT : end + 1] = ["\\begin_inset Argument " + str(n), "status open", "", "\\begin_layout Plain Layout"] n = n + 1 lineERT2 = find_token(document.body, "\\begin_inset ERT", lineERT) closing = find_token(document.body, "}", lineERT2) if closing == lineERT2 + 5: # assure that the "}" is in this ERT end2 = find_token(document.body, "\\end_inset", closing) document.body[lineERT2 : end2 + 1] = ["\\end_layout", "", "\\end_inset"] else: lineERT = lineERT + 1 def revert_IEEEtran(document): ''' Reverts InsetArgument of Page headings Biography Biography without photo to TeX-code ''' if document.textclass == "IEEEtran": i = 0 j = 0 k = 0 while True: if i != -1: i = find_token(document.body, "\\begin_layout Page headings", i) if i != -1: revert_Argument_to_TeX_brace(document, i, 1, 1, False) i = i + 1 if j != -1: j = find_token(document.body, "\\begin_layout Biography without photo", j) if j != -1: revert_Argument_to_TeX_brace(document, j, 1, 1, True) j = j + 1 if k != -1: k = find_token(document.body, "\\begin_layout Biography", k) kA = find_token(document.body, "\\begin_layout Biography without photo", k) if k == kA and k != -1: k = k + 1 continue if k != -1: # start with the second argument, therefore 2 revert_Argument_to_TeX_brace(document, k, 2, 2, True) k = k + 1 if i == -1 and j == -1 and k == -1: return def convert_IEEEtran(document): ''' Converts ERT of Page headings Biography Biography without photo to InsetArgument ''' if document.textclass == "IEEEtran": i = 0 j = 0 k = 0 while True: if i != -1: i = find_token(document.body, "\\begin_layout Page headings", i) if i != -1: convert_TeX_brace_to_Argument(document, i, 1, 1, False, False) i = i + 1 if j != -1: j = find_token(document.body, "\\begin_layout Biography without photo", j) if j != -1: convert_TeX_brace_to_Argument(document, j, 1, 1, False, True) j = j + 1 if k != -1: # assure that we don't handle Biography Biography without photo k = find_token(document.body, "\\begin_layout Biography", k) kA = find_token(document.body, "\\begin_layout Biography without photo", k - 1) if k == kA and k != -1: k = k + 1 continue if k != -1: # the argument we want to convert is the second one convert_TeX_brace_to_Argument(document, k, 2, 2, False, True) k = k + 1 if i == -1 and j == -1 and k == -1: return def revert_AASTeX(document): " Reverts InsetArgument of Altaffilation to TeX-code " if document.textclass == "aastex": i = 0 while True: if i != -1: i = find_token(document.body, "\\begin_layout Altaffilation", i) if i != -1: revert_Argument_to_TeX_brace(document, i, 1, 1, False) i = i + 1 if i == -1: return def convert_AASTeX(document): " Converts ERT of Altaffilation to InsetArgument " if document.textclass == "aastex": i = 0 while True: if i != -1: i = find_token(document.body, "\\begin_layout Altaffilation", i) if i != -1: convert_TeX_brace_to_Argument(document, i, 1, 1, False, False) i = i + 1 if i == -1: return def revert_AGUTeX(document): " Reverts InsetArgument of Author affiliation to TeX-code " if document.textclass == "agutex": i = 0 while True: if i != -1: i = find_token(document.body, "\\begin_layout Author affiliation", i) if i != -1: revert_Argument_to_TeX_brace(document, i, 1, 1, False) i = i + 1 if i == -1: return def convert_AGUTeX(document): " Converts ERT of Author affiliation to InsetArgument " if document.textclass == "agutex": i = 0 while True: if i != -1: i = find_token(document.body, "\\begin_layout Author affiliation", i) if i != -1: convert_TeX_brace_to_Argument(document, i, 1, 1, False, False) i = i + 1 if i == -1: return def revert_IJMP(document): " Reverts InsetArgument of MarkBoth to TeX-code " if document.textclass == "ijmpc" or document.textclass == "ijmpd": i = 0 while True: if i != -1: i = find_token(document.body, "\\begin_layout MarkBoth", i) if i != -1: revert_Argument_to_TeX_brace(document, i, 1, 1, False) i = i + 1 if i == -1: return def convert_IJMP(document): " Converts ERT of MarkBoth to InsetArgument " if document.textclass == "ijmpc" or document.textclass == "ijmpd": i = 0 while True: if i != -1: i = find_token(document.body, "\\begin_layout MarkBoth", i) if i != -1: convert_TeX_brace_to_Argument(document, i, 1, 1, False, False) i = i + 1 if i == -1: return def revert_SIGPLAN(document): " Reverts InsetArguments of SIGPLAN to TeX-code " if document.textclass == "sigplanconf": i = 0 j = 0 while True: if i != -1: i = find_token(document.body, "\\begin_layout Conference", i) if i != -1: revert_Argument_to_TeX_brace(document, i, 1, 1, False) i = i + 1 if j != -1: j = find_token(document.body, "\\begin_layout Author", j) if j != -1: revert_Argument_to_TeX_brace(document, j, 1, 2, False) j = j + 1 if i == -1 and j == -1: return def convert_SIGPLAN(document): " Converts ERT of SIGPLAN to InsetArgument " if document.textclass == "sigplanconf": i = 0 j = 0 while True: if i != -1: i = find_token(document.body, "\\begin_layout Conference", i) if i != -1: convert_TeX_brace_to_Argument(document, i, 1, 1, False, False) i = i + 1 if j != -1: j = find_token(document.body, "\\begin_layout Author", j) if j != -1: convert_TeX_brace_to_Argument(document, j, 1, 2, False, False) j = j + 1 if i == -1 and j == -1: return def revert_SIGGRAPH(document): " Reverts InsetArgument of Flex CRcat to TeX-code " if document.textclass == "acmsiggraph": i = 0 while True: if i != -1: i = find_token(document.body, "\\begin_inset Flex CRcat", i) if i != -1: revert_Argument_to_TeX_brace(document, i, 1, 3, False) i = i + 1 if i == -1: return def convert_SIGGRAPH(document): " Converts ERT of Flex CRcat to InsetArgument " if document.textclass == "acmsiggraph": i = 0 while True: if i != -1: i = find_token(document.body, "\\begin_inset Flex CRcat", i) if i != -1: convert_TeX_brace_to_Argument(document, i, 1, 3, True, False) i = i + 1 if i == -1: return def revert_EuropeCV(document): " Reverts InsetArguments of europeCV to TeX-code " if document.textclass == "europecv": i = 0 j = 0 k = 0 m = 0 while True: if i != -1: i = find_token(document.body, "\\begin_layout Item", i) if i != -1: revert_Argument_to_TeX_brace(document, i, 2, 2, False) i = i + 1 if j != -1: j = find_token(document.body, "\\begin_layout BulletedItem", j) if j != -1: revert_Argument_to_TeX_brace(document, j, 2, 2, False) j = j + 1 if k != -1: k = find_token(document.body, "\\begin_layout Language", k) if k != -1: revert_Argument_to_TeX_brace(document, k, 2, 6, False) k = k + 1 if m != -1: m = find_token(document.body, "\\begin_layout LastLanguage", m) if m != -1: revert_Argument_to_TeX_brace(document, m, 2, 6, False) m = m + 1 if i == -1 and j == -1 and k == -1 and m == -1: return def convert_EuropeCV(document): " Converts ERT of europeCV to InsetArgument " if document.textclass == "europecv": i = 0 j = 0 k = 0 m = 0 while True: if i != -1: i = find_token(document.body, "\\begin_layout Item", i) if i != -1: convert_TeX_brace_to_Argument(document, i, 2, 2, False, False) i = i + 1 if j != -1: j = find_token(document.body, "\\begin_layout BulletedItem", j) if j != -1: convert_TeX_brace_to_Argument(document, j, 2, 2, False, False) j = j + 1 if k != -1: k = find_token(document.body, "\\begin_layout Language", k) if k != -1: convert_TeX_brace_to_Argument(document, k, 2, 6, False, False) k = k + 1 if m != -1: m = find_token(document.body, "\\begin_layout LastLanguage", m) if m != -1: convert_TeX_brace_to_Argument(document, m, 2, 6, False, False) m = m + 1 if i == -1 and j == -1 and k == -1 and m == -1: return def revert_ModernCV(document): " Reverts InsetArguments of modernCV to TeX-code " if document.textclass == "moderncv": i = 0 j = 0 k = 0 m = 0 o = 0 while True: if i != -1: i = find_token(document.body, "\\begin_layout DoubleItem", i) if i != -1: revert_Argument_to_TeX_brace(document, i, 1, 3, False) i = i + 1 if j != -1: j = find_token(document.body, "\\begin_layout Entry", j) if j != -1: revert_Argument_to_TeX_brace(document, j, 1, 5, False) j = j + 1 if k != -1: k = find_token(document.body, "\\begin_layout Item", k) if k != -1: revert_Argument_to_TeX_brace(document, k, 1, 1, False) k = k + 1 if m != -1: m = find_token(document.body, "\\begin_layout ItemWithComment", m) if m != -1: revert_Argument_to_TeX_brace(document, m, 1, 2, False) document.body[m] = document.body[m].replace("\\begin_layout ItemWithComment", "\\begin_layout Language") m = m + 1 if o != -1: o = find_token(document.body, "\\begin_layout DoubleItem", o) if o != -1: revert_Argument_to_TeX_brace(document, o, 1, 3, False) document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout Computer") o = o + 1 if i == -1 and j == -1 and k == -1 and m == -1 and o == -1: return def convert_ModernCV(document): " Converts ERT of modernCV to InsetArgument " if document.textclass == "moderncv": i = 0 j = 0 k = 0 m = 0 o = 0 while True: if i != -1: i = find_token(document.body, "\\begin_layout DoubleItem", i) if i != -1: convert_TeX_brace_to_Argument(document, i, 1, 1, False, False) document.body[o] = document.body[o].replace("\\begin_layout DoubleItem", "\\begin_layout DoubleListItem") i = i + 1 if j != -1: j = find_token(document.body, "\\begin_layout Entry", j) if j != -1: convert_TeX_brace_to_Argument(document, j, 1, 5, False, False) j = j + 1 if k != -1: k = find_token(document.body, "\\begin_layout Item", k) if k != -1: convert_TeX_brace_to_Argument(document, k, 1, 1, False, False) k = k + 1 if m != -1: m = find_token(document.body, "\\begin_layout Language", m) if m != -1: convert_TeX_brace_to_Argument(document, m, 1, 2, False, False) m = m + 1 if i == -1 and j == -1 and k == -1 and m == -1: return def revert_Initials(document): " Reverts InsetArgument of Initial to TeX-code " i = 0 while True: if i != -1: i = find_token(document.body, "\\begin_layout Initial", i) if i != -1: # first arg (optional) and second arg (first mandatory) are supported in LyX 2.0.x revert_Argument_to_TeX_brace(document, i, 3, 3, False) i = i + 1 if i == -1: return def convert_Initials(document): " Converts ERT of Initial to InsetArgument " i = 0 while True: if i != -1: i = find_token(document.body, "\\begin_layout Initial", i) if i != -1: convert_TeX_brace_to_Argument(document, i, 3, 3, False, False) i = i + 1 if i == -1: return def revert_literate(document): " Revert Literate document to old format " if del_token(document.header, "noweb", 0): document.textclass = "literate-" + document.textclass i = 0 while True: i = find_token(document.body, "\\begin_layout Chunk", i) if i == -1: break document.body[i] = "\\begin_layout Scrap" i = i + 1 def convert_literate(document): " Convert Literate document to new format" i = find_token(document.header, "\\textclass", 0) if (i != -1) and "literate-" in document.header[i]: document.textclass = document.header[i].replace("\\textclass literate-", "") j = find_token(document.header, "\\begin_modules", 0) if (j != -1): document.header.insert(j + 1, "noweb") else: document.header.insert(i + 1, "\\end_modules") document.header.insert(i + 1, "noweb") document.header.insert(i + 1, "\\begin_modules") i = 0 while True: i = find_token(document.body, "\\begin_layout Scrap", i) if i == -1: break document.body[i] = "\\begin_layout Chunk" i = i + 1 def revert_itemargs(document): " Reverts \\item arguments to TeX-code " i = 0 while True: i = find_token(document.body, "\\begin_inset Argument item:", i) if i == -1: return j = find_end_of_inset(document.body, i) # Find containing paragraph layout parent = get_containing_layout(document.body, i) if parent == False: document.warning("Malformed lyx document: Can't find parent paragraph layout") i = i + 1 continue parbeg = parent[3] beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i) endPlain = find_end_of_layout(document.body, beginPlain) content = document.body[beginPlain + 1 : endPlain] del document.body[i:j+1] subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]") document.body[parbeg : parbeg] = subst i = i + 1 def revert_garamondx_newtxmath(document): " Revert native garamond newtxmath definition to LaTeX " i = find_token(document.header, "\\font_math", 0) if i == -1: return if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: val = get_value(document.header, "\\font_math", i) if val == "garamondx-ntxm": add_to_preamble(document, "\\usepackage[garamondx]{newtxmath}") document.header[i] = "\\font_math auto" def revert_garamondx(document): " Revert native garamond font definition to LaTeX " if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1: i = find_token(document.header, "\\font_roman garamondx", 0) if i != -1: osf = False j = find_token(document.header, "\\font_osf true", 0) if j != -1: osf = True preamble = "\\usepackage" if osf: preamble += "[osfI]" preamble += "{garamondx}" add_to_preamble(document, [preamble]) document.header[i] = "\\font_roman default" def convert_beamerargs(document): " Converts beamer arguments to new layout " beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"] if document.textclass not in beamer_classes: return shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"] list_layouts = ["Itemize", "Enumerate", "Description"] rx = re.compile(r'^\\begin_inset Argument (\d+)$') i = 0 while True: i = find_token(document.body, "\\begin_inset Argument", i) if i == -1: return # Find containing paragraph layout parent = get_containing_layout(document.body, i) if parent == False: document.warning("Malformed lyx document: Can't find parent paragraph layout") i = i + 1 continue parbeg = parent[1] parend = parent[2] layoutname = parent[0] for p in range(parbeg, parend): if layoutname in shifted_layouts: m = rx.match(document.body[p]) if m: argnr = int(m.group(1)) argnr += 1 document.body[p] = "\\begin_inset Argument %d" % argnr if layoutname == "AgainFrame": m = rx.match(document.body[p]) if m: document.body[p] = "\\begin_inset Argument 3" if document.body[p + 4] == "\\begin_inset ERT": if document.body[p + 9].startswith("<"): # This is an overlay specification # strip off the < document.body[p + 9] = document.body[p + 9][1:] if document.body[p + 9].endswith(">"): # strip off the > document.body[p + 9] = document.body[p + 9][:-1] # Shift this one document.body[p] = "\\begin_inset Argument 2" if layoutname in list_layouts: m = rx.match(document.body[p]) if m: if m.group(1) == "1": if document.body[p + 4] == "\\begin_inset ERT": if document.body[p + 9].startswith("<"): # This is an overlay specification # strip off the < document.body[p + 9] = document.body[p + 9][1:] if document.body[p + 9].endswith(">"): # strip off the > document.body[p + 9] = document.body[p + 9][:-1] elif layoutname != "Itemize": # Shift this one document.body[p] = "\\begin_inset Argument 2" i = i + 1 def convert_againframe_args(document): " Converts beamer AgainFrame to new layout " # FIXME: This currently only works if the arguments are in one single ERT beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"] if document.textclass not in beamer_classes: return i = 0 while True: i = find_token(document.body, "\\begin_layout AgainFrame", i) if i == -1: break parent = get_containing_layout(document.body, i) if parent[1] != i: document.warning("Wrong parent layout!") j = parent[2] parbeg = parent[3] if i != -1: if document.body[parbeg] == "\\begin_inset ERT": ertcont = parbeg + 5 if document.body[ertcont].startswith("[<"): # This is a default overlay specification # strip off the [< document.body[ertcont] = document.body[ertcont][2:] if document.body[ertcont].endswith(">]"): # strip off the >] document.body[ertcont] = document.body[ertcont][:-2] elif document.body[ertcont].endswith("]"): # divide the args tok = document.body[ertcont].find('>][') if tok != -1: subst = [document.body[ertcont][:tok], '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3', 'status collapsed', '', '\\begin_layout Plain Layout', document.body[ertcont][tok + 3:-1]] document.body[ertcont : ertcont + 1] = subst # Convert to ArgInset document.body[parbeg] = "\\begin_inset Argument 2" i = j continue elif document.body[ertcont].startswith("<"): # This is an overlay specification # strip off the < document.body[ertcont] = document.body[ertcont][1:] if document.body[ertcont].endswith(">"): # strip off the > document.body[ertcont] = document.body[ertcont][:-1] # Convert to ArgInset document.body[parbeg] = "\\begin_inset Argument 1" elif document.body[ertcont].endswith(">]"): # divide the args tok = document.body[ertcont].find('>[<') if tok != -1: document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok], '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2', 'status collapsed', '', '\\begin_layout Plain Layout', document.body[ertcont][tok + 3:-2]] # Convert to ArgInset document.body[parbeg] = "\\begin_inset Argument 1" elif document.body[ertcont].endswith("]"): # divide the args tok = document.body[ertcont].find('>[<') if tok != -1: # divide the args tokk = document.body[ertcont].find('>][') if tokk != -1: document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok], '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2', 'status collapsed', '', '\\begin_layout Plain Layout', document.body[ertcont][tok + 3:tokk], '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3', 'status collapsed', '', '\\begin_layout Plain Layout', document.body[ertcont][tokk + 3:-1]] else: tokk = document.body[ertcont].find('>[') if tokk != -1: document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tokk], '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 3', 'status collapsed', '', '\\begin_layout Plain Layout', document.body[ertcont][tokk + 2:-1]] # Convert to ArgInset document.body[parbeg] = "\\begin_inset Argument 1" i = j continue elif document.body[ertcont].startswith("["): # This is an ERT option # strip off the [ document.body[ertcont] = document.body[ertcont][1:] if document.body[ertcont].endswith("]"): # strip off the ] document.body[ertcont] = document.body[ertcont][:-1] # Convert to ArgInset document.body[parbeg] = "\\begin_inset Argument 3" i = j continue i = j def convert_corollary_args(document): " Converts beamer corrolary-style ERT arguments native InsetArgs " beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"] if document.textclass not in beamer_classes: return corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"] for lay in corollary_layouts: i = 0 while True: i = find_token_exact(document.body, "\\begin_layout " + lay, i) if i == -1: break parent = get_containing_layout(document.body, i) if parent[1] != i: document.warning("Wrong parent layout!") j = parent[2] parbeg = parent[3] if i != -1: if document.body[parbeg] == "\\begin_inset ERT": ertcont = parbeg + 5 if document.body[ertcont].startswith("<"): # This is an overlay specification # strip off the < document.body[ertcont] = document.body[ertcont][1:] if document.body[ertcont].endswith(">"): # strip off the > document.body[ertcont] = document.body[ertcont][:-1] elif document.body[ertcont].endswith("]"): # divide the args tok = document.body[ertcont].find('>[') if tok != -1: subst = [document.body[ertcont][:tok], '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2', 'status collapsed', '', '\\begin_layout Plain Layout', document.body[ertcont][tok + 2:-1]] document.body[ertcont : ertcont + 1] = subst # Convert to ArgInset document.body[parbeg] = "\\begin_inset Argument 1" i = j continue elif document.body[ertcont].startswith("["): # This is an ERT option # strip off the [ document.body[ertcont] = document.body[ertcont][1:] if document.body[ertcont].endswith("]"): # strip off the ] document.body[ertcont] = document.body[ertcont][:-1] # Convert to ArgInset document.body[parbeg] = "\\begin_inset Argument 2" i = j continue i = j def convert_quote_args(document): " Converts beamer quote style ERT args to native InsetArgs " beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"] if document.textclass not in beamer_classes: return quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"] for lay in quote_layouts: i = 0 while True: i = find_token(document.body, "\\begin_layout " + lay, i) if i == -1: break parent = get_containing_layout(document.body, i) if parent[1] != i: document.warning("Wrong parent layout!") j = parent[2] parbeg = parent[3] if i != -1: if document.body[parbeg] == "\\begin_inset ERT": if document.body[i + 6].startswith("<"): # This is an overlay specification # strip off the < document.body[i + 6] = document.body[i + 6][1:] if document.body[i + 6].endswith(">"): # strip off the > document.body[i + 6] = document.body[i + 6][:-1] # Convert to ArgInset document.body[i + 1] = "\\begin_inset Argument 1" i = j def revert_beamerargs(document): " Reverts beamer arguments to old layout " beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"] if document.textclass not in beamer_classes: return i = 0 list_layouts = ["Itemize", "Enumerate", "Description"] headings = ["Part", "Section", "Section*", "Subsection", "Subsection*", "Subsubsection", "Subsubsection*", "FrameSubtitle", "NoteItem"] quote_layouts = ["Uncover", "Only", "Quotation", "Quote", "Verse"] corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"] rx = re.compile(r'^\\begin_inset Argument (\S+)$') while True: i = find_token(document.body, "\\begin_inset Argument", i) if i == -1: return # Find containing paragraph layout parent = get_containing_layout(document.body, i) if parent == False: document.warning("Malformed lyx document: Can't find parent paragraph layout") i = i + 1 continue parbeg = parent[1] parend = parent[2] realparbeg = parent[3] layoutname = parent[0] realparend = parend for p in range(parbeg, parend): if p >= realparend: i = realparend break if layoutname in headings: m = rx.match(document.body[p]) if m: argnr = m.group(1) if argnr == "1": # Find containing paragraph layout beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p) endPlain = find_end_of_layout(document.body, beginPlain) endInset = find_end_of_inset(document.body, p) argcontent = document.body[beginPlain + 1 : endPlain] # Adjust range end realparend = realparend - len(document.body[p : endInset + 1]) # Remove arg inset del document.body[p : endInset + 1] if layoutname == "FrameSubtitle": pre = put_cmd_in_ert("\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">") elif layoutname == "NoteItem": pre = put_cmd_in_ert("\\note<") + argcontent + put_cmd_in_ert(">[item]") elif layoutname.endswith('*'): pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower()[:-1] + "<") + argcontent + put_cmd_in_ert(">*") else: pre = put_cmd_in_ert("\\lyxframeend\\" + layoutname.lower() + "<") + argcontent + put_cmd_in_ert(">") secarg = find_token(document.body, "\\begin_inset Argument 2", parbeg, parend) if secarg != -1: # Find containing paragraph layout beginPlain = find_token(document.body, "\\begin_layout Plain Layout", secarg) endPlain = find_end_of_layout(document.body, beginPlain) endInset = find_end_of_inset(document.body, secarg) argcontent = document.body[beginPlain + 1 : endPlain] # Adjust range end realparend = realparend - len(document.body[secarg : endInset + 1]) del document.body[secarg : endInset + 1] pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]") pre += put_cmd_in_ert("{") document.body[parbeg] = "\\begin_layout Standard" document.body[realparbeg : realparbeg] = pre pe = find_end_of_layout(document.body, parbeg) post = put_cmd_in_ert("}") document.body[pe : pe] = post realparend += len(pre) + len(post) if layoutname == "AgainFrame": m = rx.match(document.body[p]) if m: argnr = m.group(1) if argnr == "3": beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p) endPlain = find_end_of_layout(document.body, beginPlain) endInset = find_end_of_inset(document.body, p) content = document.body[beginPlain + 1 : endPlain] # Adjust range end realparend = realparend - len(document.body[p : endInset + 1]) # Remove arg inset del document.body[p : endInset + 1] subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]") document.body[realparbeg : realparbeg] = subst if layoutname == "Overprint": m = rx.match(document.body[p]) if m: argnr = m.group(1) if argnr == "1": beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p) endPlain = find_end_of_layout(document.body, beginPlain) endInset = find_end_of_inset(document.body, p) content = document.body[beginPlain + 1 : endPlain] # Adjust range end realparend = realparend - len(document.body[p : endInset + 1]) # Remove arg inset del document.body[p : endInset + 1] subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]") document.body[realparbeg : realparbeg] = subst if layoutname == "OverlayArea": m = rx.match(document.body[p]) if m: argnr = m.group(1) if argnr == "2": beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p) endPlain = find_end_of_layout(document.body, beginPlain) endInset = find_end_of_inset(document.body, p) content = document.body[beginPlain + 1 : endPlain] # Adjust range end realparend = realparend - len(document.body[p : endInset + 1]) # Remove arg inset del document.body[p : endInset + 1] subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}") document.body[realparbeg : realparbeg] = subst if layoutname in list_layouts: m = rx.match(document.body[p]) if m: argnr = m.group(1) if argnr == "1": beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p) endPlain = find_end_of_layout(document.body, beginPlain) endInset = find_end_of_inset(document.body, p) content = document.body[beginPlain + 1 : endPlain] subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">") realparend = realparend + len(subst) - len(content) document.body[beginPlain + 1 : endPlain] = subst elif argnr == "item:1": j = find_end_of_inset(document.body, i) # Find containing paragraph layout beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i) endPlain = find_end_of_layout(document.body, beginPlain) content = document.body[beginPlain + 1 : endPlain] del document.body[i:j+1] subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]") document.body[realparbeg : realparbeg] = subst elif argnr == "item:2": j = find_end_of_inset(document.body, i) # Find containing paragraph layout beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i) endPlain = find_end_of_layout(document.body, beginPlain) content = document.body[beginPlain + 1 : endPlain] del document.body[i:j+1] subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">") document.body[realparbeg : realparbeg] = subst if layoutname in quote_layouts: m = rx.match(document.body[p]) if m: argnr = m.group(1) if argnr == "1": beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p) endPlain = find_end_of_layout(document.body, beginPlain) endInset = find_end_of_inset(document.body, p) content = document.body[beginPlain + 1 : endPlain] # Adjust range end realparend = realparend - len(document.body[p : endInset + 1]) # Remove arg inset del document.body[p : endInset + 1] subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">") document.body[realparbeg : realparbeg] = subst if layoutname in corollary_layouts: m = rx.match(document.body[p]) if m: argnr = m.group(1) if argnr == "2": beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p) endPlain = find_end_of_layout(document.body, beginPlain) endInset = find_end_of_inset(document.body, p) content = document.body[beginPlain + 1 : endPlain] # Adjust range end realparend = realparend - len(document.body[p : endInset + 1]) # Remove arg inset del document.body[p : endInset + 1] subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]") document.body[realparbeg : realparbeg] = subst i = realparend def revert_beamerargs2(document): " Reverts beamer arguments to old layout, step 2 " beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"] if document.textclass not in beamer_classes: return i = 0 shifted_layouts = ["Part", "Section", "Subsection", "Subsubsection"] corollary_layouts = ["Corollary", "Definition", "Definitions", "Example", "Examples", "Fact", "Proof", "Theorem"] rx = re.compile(r'^\\begin_inset Argument (\S+)$') while True: i = find_token(document.body, "\\begin_inset Argument", i) if i == -1: return # Find containing paragraph layout parent = get_containing_layout(document.body, i) if parent == False: document.warning("Malformed lyx document: Can't find parent paragraph layout") i = i + 1 continue parbeg = parent[1] parend = parent[2] realparbeg = parent[3] layoutname = parent[0] realparend = parend for p in range(parbeg, parend): if p >= realparend: i = realparend break if layoutname in shifted_layouts: m = rx.match(document.body[p]) if m: argnr = m.group(1) if argnr == "2": document.body[p] = "\\begin_inset Argument 1" if layoutname in corollary_layouts: m = rx.match(document.body[p]) if m: argnr = m.group(1) if argnr == "1": beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p) endPlain = find_end_of_layout(document.body, beginPlain) endInset = find_end_of_inset(document.body, p) content = document.body[beginPlain + 1 : endPlain] # Adjust range end realparend = realparend - len(document.body[p : endInset + 1]) # Remove arg inset del document.body[p : endInset + 1] subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">") document.body[realparbeg : realparbeg] = subst if layoutname == "OverlayArea": m = rx.match(document.body[p]) if m: argnr = m.group(1) if argnr == "1": beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p) endPlain = find_end_of_layout(document.body, beginPlain) endInset = find_end_of_inset(document.body, p) content = document.body[beginPlain + 1 : endPlain] # Adjust range end realparend = realparend - len(document.body[p : endInset + 1]) # Remove arg inset del document.body[p : endInset + 1] subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}") document.body[realparbeg : realparbeg] = subst if layoutname == "AgainFrame": m = rx.match(document.body[p]) if m: argnr = m.group(1) if argnr == "2": beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p) endPlain = find_end_of_layout(document.body, beginPlain) endInset = find_end_of_inset(document.body, p) content = document.body[beginPlain + 1 : endPlain] # Adjust range end realparend = realparend - len(document.body[p : endInset + 1]) # Remove arg inset del document.body[p : endInset + 1] subst = put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]") document.body[realparbeg : realparbeg] = subst i = realparend def revert_beamerargs3(document): " Reverts beamer arguments to old layout, step 3 " beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"] if document.textclass not in beamer_classes: return rx = re.compile(r'^\\begin_inset Argument (\S+)$') i = 0 while True: i = find_token(document.body, "\\begin_inset Argument", i) if i == -1: return # Find containing paragraph layout parent = get_containing_layout(document.body, i) if parent == False: document.warning("Malformed lyx document: Can't find parent paragraph layout") i = i + 1 continue parbeg = parent[1] parend = parent[2] realparbeg = parent[3] layoutname = parent[0] realparend = parend for p in range(parbeg, parend): if p >= realparend: i = realparend break if layoutname == "AgainFrame": m = rx.match(document.body[p]) if m: argnr = m.group(1) if argnr == "1": beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p) endPlain = find_end_of_layout(document.body, beginPlain) endInset = find_end_of_inset(document.body, p) content = document.body[beginPlain + 1 : endPlain] # Adjust range end realparend = realparend - len(document.body[p : endInset + 1]) # Remove arg inset del document.body[p : endInset + 1] subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">") document.body[realparbeg : realparbeg] = subst i = realparend def revert_beamerflex(document): " Reverts beamer Flex insets " beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"] if document.textclass not in beamer_classes: return new_flexes = {"Bold" : "\\textbf", "Emphasize" : "\\emph", "Only" : "\\only", "Uncover" : "\\uncover", "Visible" : "\\visible", "Invisible" : "\\invisible", "Alternative" : "\\alt", "Beamer_Note" : "\\note"} old_flexes = {"Alert" : "\\alert", "Structure" : "\\structure"} rx = re.compile(r'^\\begin_inset Flex (.+)$') i = 0 while True: i = find_token(document.body, "\\begin_inset Flex", i) if i == -1: return m = rx.match(document.body[i]) if m: flextype = m.group(1) z = find_end_of_inset(document.body, i) if z == -1: document.warning("Can't find end of Flex " + flextype + " inset.") i += 1 continue if flextype in new_flexes: pre = put_cmd_in_ert(new_flexes[flextype]) arg = find_token(document.body, "\\begin_inset Argument 1", i, z) if arg != -1: argend = find_end_of_inset(document.body, arg) if argend == -1: document.warning("Can't find end of Argument!") i += 1 continue # Find containing paragraph layout beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg) endPlain = find_end_of_layout(document.body, beginPlain) argcontent = document.body[beginPlain + 1 : endPlain] # Adjust range end z = z - len(document.body[arg : argend + 1]) # Remove arg inset del document.body[arg : argend + 1] pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">") arg = find_token(document.body, "\\begin_inset Argument 2", i, z) if arg != -1: argend = find_end_of_inset(document.body, arg) if argend == -1: document.warning("Can't find end of Argument!") i += 1 continue # Find containing paragraph layout beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg) endPlain = find_end_of_layout(document.body, beginPlain) argcontent = document.body[beginPlain + 1 : endPlain] # Adjust range end z = z - len(document.body[arg : argend + 1]) # Remove arg inset del document.body[arg : argend + 1] if flextype == "Alternative": pre += put_cmd_in_ert("{") + argcontent + put_cmd_in_ert("}") else: pre += put_cmd_in_ert("[") + argcontent + put_cmd_in_ert("]") pre += put_cmd_in_ert("{") beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i) endPlain = find_end_of_layout(document.body, beginPlain) # Adjust range end z = z - len(document.body[i : beginPlain + 1]) z += len(pre) document.body[i : beginPlain + 1] = pre post = put_cmd_in_ert("}") document.body[z - 2 : z + 1] = post elif flextype in old_flexes: pre = put_cmd_in_ert(old_flexes[flextype]) arg = find_token(document.body, "\\begin_inset Argument 1", i, z) if arg == -1: i += 1 continue argend = find_end_of_inset(document.body, arg) if argend == -1: document.warning("Can't find end of Argument!") i += 1 continue # Find containing paragraph layout beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg) endPlain = find_end_of_layout(document.body, beginPlain) argcontent = document.body[beginPlain + 1 : endPlain] # Adjust range end z = z - len(document.body[arg : argend + 1]) # Remove arg inset del document.body[arg : argend + 1] pre += put_cmd_in_ert("<") + argcontent + put_cmd_in_ert(">") pre += put_cmd_in_ert("{") beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i) endPlain = find_end_of_layout(document.body, beginPlain) # Adjust range end z = z - len(document.body[i : beginPlain + 1]) z += len(pre) document.body[i : beginPlain + 1] = pre post = put_cmd_in_ert("}") document.body[z - 2 : z + 1] = post i += 1 def revert_beamerblocks(document): " Reverts beamer block arguments to ERT " beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"] if document.textclass not in beamer_classes: return blocks = ["Block", "ExampleBlock", "AlertBlock"] rx = re.compile(r'^\\begin_inset Argument (\S+)$') i = 0 while True: i = find_token(document.body, "\\begin_inset Argument", i) if i == -1: return # Find containing paragraph layout parent = get_containing_layout(document.body, i) if parent == False: document.warning("Malformed lyx document: Can't find parent paragraph layout") i = i + 1 continue parbeg = parent[1] parend = parent[2] realparbeg = parent[3] layoutname = parent[0] realparend = parend for p in range(parbeg, parend): if p >= realparend: i = realparend break if layoutname in blocks: m = rx.match(document.body[p]) if m: argnr = m.group(1) if argnr == "1": beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p) endPlain = find_end_of_layout(document.body, beginPlain) endInset = find_end_of_inset(document.body, p) content = document.body[beginPlain + 1 : endPlain] # Adjust range end realparend = realparend - len(document.body[p : endInset + 1]) # Remove arg inset del document.body[p : endInset + 1] subst = put_cmd_in_ert("<") + content + put_cmd_in_ert(">") document.body[realparbeg : realparbeg] = subst elif argnr == "2": beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p) endPlain = find_end_of_layout(document.body, beginPlain) endInset = find_end_of_inset(document.body, p) content = document.body[beginPlain + 1 : endPlain] # Adjust range end realparend = realparend - len(document.body[p : endInset + 1]) # Remove arg inset del document.body[p : endInset + 1] subst = put_cmd_in_ert("{") + content + put_cmd_in_ert("}") document.body[realparbeg : realparbeg] = subst i = realparend def convert_beamerblocks(document): " Converts beamer block ERT args to native InsetArgs " beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"] if document.textclass not in beamer_classes: return blocks = ["Block", "ExampleBlock", "AlertBlock"] for lay in blocks: i = 0 while True: i = find_token_exact(document.body, "\\begin_layout " + lay, i) if i == -1: break parent = get_containing_layout(document.body, i) if parent == False or parent[1] != i: document.warning("Wrong parent layout!") i += 1 continue j = parent[2] parbeg = parent[3] if i != -1: if document.body[parbeg] == "\\begin_inset ERT": ertcont = parbeg + 5 while True: if document.body[ertcont].startswith("<"): # This is an overlay specification # strip off the < document.body[ertcont] = document.body[ertcont][1:] if document.body[ertcont].endswith(">"): # strip off the > document.body[ertcont] = document.body[ertcont][:-1] # Convert to ArgInset document.body[parbeg] = "\\begin_inset Argument 1" elif document.body[ertcont].endswith("}"): # divide the args tok = document.body[ertcont].find('>{') if tok != -1: document.body[ertcont : ertcont + 1] = [document.body[ertcont][:tok], '\\end_layout', '', '\\end_inset', '', '', '\\begin_inset Argument 2', 'status collapsed', '', '\\begin_layout Plain Layout', document.body[ertcont][tok + 2:-1]] # Convert to ArgInset document.body[parbeg] = "\\begin_inset Argument 1" elif document.body[ertcont].startswith("{"): # This is the block title if document.body[ertcont].endswith("}"): # strip off the braces document.body[ertcont] = document.body[ertcont][1:-1] # Convert to ArgInset document.body[parbeg] = "\\begin_inset Argument 2" elif count_pars_in_inset(document.body, ertcont) > 1: # Multipar ERT. Skip this. break else: convert_TeX_brace_to_Argument(document, i, 2, 2, False, True) else: break j = find_end_of_layout(document.body, i) if j == -1: document.warning("end of layout not found!") k = find_token(document.body, "\\begin_inset Argument", i, j) if k == -1: document.warning("InsetArgument not found!") break l = find_end_of_inset(document.body, k) m = find_token(document.body, "\\begin_inset ERT", l, j) if m == -1: break ertcont = m + 5 parbeg = m i = j def convert_overprint(document): " Convert old beamer overprint layouts to ERT " beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"] if document.textclass not in beamer_classes: return i = 0 while True: i = find_token(document.body, "\\begin_layout Overprint", i) if i == -1: return # Find end of sequence j = find_end_of_sequence(document.body, i) if j == -1: document.warning("Malformed lyx document. Cannot find end of Overprint sequence!") i = i + 1 continue endseq = j subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}") esubst = list() if document.body[j] == "\\end_deeper": esubst = ["", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"] else: esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") + ["\\end_layout"] endseq = endseq + len(esubst) - len(document.body[j : j]) document.body[j : j] = esubst argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j) if argbeg != -1: argend = find_end_of_layout(document.body, argbeg) if argend == -1: document.warning("Malformed lyx document. Cannot find end of Overprint argument!") i = i + 1 continue beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg) endPlain = find_end_of_layout(document.body, beginPlain) content = document.body[beginPlain + 1 : endPlain] # Adjust range end endseq = endseq - len(document.body[argbeg : argend + 1]) # Remove arg inset del document.body[argbeg : argend + 1] subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]") endseq = endseq - len(document.body[i : i]) document.body[i : i] = subst + ["\\end_layout"] endseq += len(subst) for p in range(i, endseq): if document.body[p] == "\\begin_layout Overprint": document.body[p] = "\\begin_layout Standard" i = endseq def revert_overprint(document): " Revert old beamer overprint layouts to ERT " beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"] if document.textclass not in beamer_classes: return i = 0 while True: i = find_token(document.body, "\\begin_layout Overprint", i) if i == -1: return # Find end of sequence j = find_end_of_sequence(document.body, i) if j == -1: document.warning("Malformed lyx document. Cannot find end of Overprint sequence!") i = i + 1 continue endseq = j subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{overprint}") esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{overprint}") endseq = endseq + len(esubst) - len(document.body[j : j]) if document.body[j] == "\\end_deeper": document.body[j : j] = ["\\end_deeper", ""] + esubst else: document.body[j : j] = esubst r = i while r < j: if document.body[r] == "\\begin_deeper": s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper") if s != -1: document.body[r] = "" document.body[s] = "" r = s continue r = r + 1 argbeg = find_token(document.body, "\\begin_inset Argument 1", i, j) if argbeg != -1: argend = find_end_of_inset(document.body, argbeg) if argend == -1: document.warning("Malformed lyx document. Cannot find end of Overprint argument!") i = i + 1 continue beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg) endPlain = find_end_of_layout(document.body, beginPlain) content = document.body[beginPlain + 1 : endPlain] # Adjust range end endseq = endseq - len(document.body[argbeg : argend]) # Remove arg inset del document.body[argbeg : argend + 1] subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]") endseq = endseq - len(document.body[i : i]) document.body[i : i] = subst + ["\\end_layout"] endseq += len(subst) p = i while True: if p >= endseq: break if document.body[p] == "\\begin_layout Overprint": q = find_end_of_layout(document.body, p) if q == -1: document.warning("Malformed lyx document. Cannot find end of Overprint layout!") p += 1 continue subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\onslide") argbeg = find_token(document.body, "\\begin_inset Argument item:1", p, q) if argbeg != -1: argend = find_end_of_inset(document.body, argbeg) if argend == -1: document.warning("Malformed lyx document. Cannot find end of Overprint item argument!") p += 1 continue beginPlain = find_token(document.body, "\\begin_layout Plain Layout", argbeg) endPlain = find_end_of_layout(document.body, beginPlain) content = document.body[beginPlain + 1 : endPlain] # Adjust range end endseq = endseq - len(document.body[argbeg : argend + 1]) # Remove arg inset del document.body[argbeg : argend + 1] subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">") endseq = endseq - len(document.body[p : p + 1]) + len(subst) document.body[p : p + 1] = subst p = p + 1 i = endseq def revert_frametitle(document): " Reverts beamer frametitle layout to ERT " beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"] if document.textclass not in beamer_classes: return rx = re.compile(r'^\\begin_inset Argument (\S+)$') i = 0 while True: i = find_token(document.body, "\\begin_layout FrameTitle", i) if i == -1: return j = find_end_of_layout(document.body, i) if j == -1: document.warning("Malformed lyx document: Can't find end of FrameTitle layout") i = i + 1 continue endlay = j document.body[j : j] = put_cmd_in_ert("}") + document.body[j : j] endlay += len(put_cmd_in_ert("}")) subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\frametitle") for p in range(i, j): if p >= endlay: break m = rx.match(document.body[p]) if m: argnr = m.group(1) if argnr == "1": beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p) endPlain = find_end_of_layout(document.body, beginPlain) endInset = find_end_of_inset(document.body, p) content = document.body[beginPlain + 1 : endPlain] # Adjust range end endlay = endlay - len(document.body[p : endInset + 1]) # Remove arg inset del document.body[p : endInset + 1] subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">") elif argnr == "2": beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p) endPlain = find_end_of_layout(document.body, beginPlain) endInset = find_end_of_inset(document.body, p) content = document.body[beginPlain + 1 : endPlain] # Adjust range end endlay = endlay - len(document.body[p : endInset + 1]) # Remove arg inset del document.body[p : endInset + 1] subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]") subst += put_cmd_in_ert("{") document.body[i : i + 1] = subst i = endlay def convert_epigraph(document): " Converts memoir epigraph to new syntax " if document.textclass != "memoir": return i = 0 while True: i = find_token(document.body, "\\begin_layout Epigraph", i) if i == -1: return j = find_end_of_layout(document.body, i) if j == -1: document.warning("Malformed lyx document: Can't find end of Epigraph layout") i = i + 1 continue endlay = j subst = list() ert = find_token(document.body, "\\begin_inset ERT", i, j) if ert != -1: endInset = find_end_of_inset(document.body, ert) beginPlain = find_token(document.body, "\\begin_layout Plain Layout", ert) endPlain = find_end_of_layout(document.body, beginPlain) ertcont = beginPlain + 2 if document.body[ertcont] == "}{": # strip off the < # Convert to ArgInset endlay = endlay - 2 * len(document.body[j]) begsubst = ['\\begin_inset Argument post:1', 'status collapsed', '', '\\begin_layout Plain Layout'] endsubst = ['\\end_layout', '', '\\end_inset', '', document.body[j]] document.body[j : j + 1] = endsubst document.body[endInset + 1 : endInset + 1] = begsubst # Adjust range end endlay += len(begsubst) + len(endsubst) endlay = endlay - len(document.body[ert : endInset + 1]) del document.body[ert : endInset + 1] i = endlay def revert_epigraph(document): " Reverts memoir epigraph argument to ERT " if document.textclass != "memoir": return i = 0 while True: i = find_token(document.body, "\\begin_layout Epigraph", i) if i == -1: return j = find_end_of_layout(document.body, i) if j == -1: document.warning("Malformed lyx document: Can't find end of Epigraph layout") i = i + 1 continue endlay = j subst = list() p = find_token(document.body, "\\begin_layout Argument post:1", i, j) if p != -1: beginPlain = find_token(document.body, "\\begin_layout Plain Layout", p) endPlain = find_end_of_layout(document.body, beginPlain) endInset = find_end_of_inset(document.body, p) content = document.body[beginPlain + 1 : endPlain] # Adjust range end endlay = endlay - len(document.body[p : endInset + 1]) # Remove arg inset del document.body[p : endInset + 1] subst += put_cmd_in_ert("}{") + content else: subst += put_cmd_in_ert("}{") document.body[j : j] = subst + document.body[j : j] i = endlay def convert_captioninsets(document): " Converts caption insets to new syntax " i = 0 while True: i = find_token(document.body, "\\begin_inset Caption", i) if i == -1: return document.body[i] = "\\begin_inset Caption Standard" i = i + 1 def revert_captioninsets(document): " Reverts caption insets to old syntax " i = 0 while True: i = find_token(document.body, "\\begin_inset Caption Standard", i) if i == -1: return document.body[i] = "\\begin_inset Caption" i = i + 1 def convert_captionlayouts(document): " Convert caption layouts to caption insets. " caption_dict = { "Captionabove": "Above", "Captionbelow": "Below", "FigCaption" : "FigCaption", "Table_Caption" : "Table", "CenteredCaption" : "Centered", "Bicaption" : "Bicaption", } i = 0 while True: i = find_token(document.body, "\\begin_layout", i) if i == -1: return val = get_value(document.body, "\\begin_layout", i) if val in caption_dict.keys(): j = find_end_of_layout(document.body, i) if j == -1: document.warning("Malformed LyX document: Missing `\\end_layout'.") return document.body[j:j] = ["\\end_layout", "", "\\end_inset", "", ""] document.body[i:i+1] = ["\\begin_layout %s" % document.default_layout, "\\begin_inset Caption %s" % caption_dict[val], "", "\\begin_layout %s" % document.default_layout] i = i + 1 def revert_captionlayouts(document): " Revert caption insets to caption layouts. " caption_dict = { "Above" : "Captionabove", "Below" : "Captionbelow", "FigCaption" : "FigCaption", "Table" : "Table_Caption", "Centered" : "CenteredCaption", "Bicaption" : "Bicaption", } i = 0 rx = re.compile(r'^\\begin_inset Caption (\S+)$') while True: i = find_token(document.body, "\\begin_inset Caption", i) if i == -1: return m = rx.match(document.body[i]) val = "" if m: val = m.group(1) if val not in caption_dict.keys(): i = i + 1 continue # We either need to delete the previous \begin_layout line, or we # need to end the previous layout if this inset is not in the first # position of the paragraph. layout_before = find_token_backwards(document.body, "\\begin_layout", i) if layout_before == -1: document.warning("Malformed LyX document: Missing `\\begin_layout'.") return layout_line = document.body[layout_before] del_layout_before = True l = layout_before + 1 while l < i: if document.body[l] != "": del_layout_before = False break l = l + 1 if del_layout_before: del document.body[layout_before:i] i = layout_before else: document.body[i:i] = ["\\end_layout", ""] i = i + 2 # Find start of layout in the inset and end of inset j = find_token(document.body, "\\begin_layout", i) if j == -1: document.warning("Malformed LyX document: Missing `\\begin_layout'.") return k = find_end_of_inset(document.body, i) if k == -1: document.warning("Malformed LyX document: Missing `\\end_inset'.") return # We either need to delete the following \end_layout line, or we need # to restart the old layout if this inset is not at the paragraph end. layout_after = find_token(document.body, "\\end_layout", k) if layout_after == -1: document.warning("Malformed LyX document: Missing `\\end_layout'.") return del_layout_after = True l = k + 1 while l < layout_after: if document.body[l] != "": del_layout_after = False break l = l + 1 if del_layout_after: del document.body[k+1:layout_after+1] else: document.body[k+1:k+1] = [layout_line, ""] # delete \begin_layout and \end_inset and replace \begin_inset with # "\begin_layout XXX". This works because we can only have one # paragraph in the caption inset: The old \end_layout will be recycled. del document.body[k] if document.body[k] == "": del document.body[k] del document.body[j] if document.body[j] == "": del document.body[j] document.body[i] = "\\begin_layout %s" % caption_dict[val] if document.body[i+1] == "": del document.body[i+1] i = i + 1 def revert_fragileframe(document): " Reverts beamer FragileFrame layout to ERT " beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"] if document.textclass not in beamer_classes: return i = 0 while True: i = find_token(document.body, "\\begin_layout FragileFrame", i) if i == -1: return # Find end of sequence j = find_end_of_sequence(document.body, i) if j == -1: document.warning("Malformed lyx document. Cannot find end of FragileFrame sequence!") i = i + 1 continue endseq = j subst = ["\\begin_layout Standard"] + put_cmd_in_ert("\\begin{frame}") esubst = ["\\end_layout", "", "\\begin_layout Standard"] + put_cmd_in_ert("\\end{frame}") endseq = endseq + len(esubst) - len(document.body[j : j]) if document.body[j] == "\\end_deeper": document.body[j : j] = ["\\end_deeper", ""] + esubst else: document.body[j : j] = esubst for q in range(i, j): if document.body[q] == "\\begin_layout FragileFrame": document.body[q] = "\\begin_layout %s" % document.default_layout r = i while r < j: if document.body[r] == "\\begin_deeper": s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper") if s != -1: document.body[r] = "" document.body[s] = "" r = s continue r = r + 1 for p in range(1, 5): arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, j) if arg != -1: if p == 1: beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg) endPlain = find_end_of_layout(document.body, beginPlain) endInset = find_end_of_inset(document.body, arg) content = document.body[beginPlain + 1 : endPlain] # Adjust range end j = j - len(document.body[arg : endInset + 1]) # Remove arg inset del document.body[arg : endInset + 1] subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">") elif p == 2: beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg) endPlain = find_end_of_layout(document.body, beginPlain) endInset = find_end_of_inset(document.body, arg) content = document.body[beginPlain + 1 : endPlain] # Adjust range end j = j - len(document.body[arg : endInset + 1]) # Remove arg inset del document.body[arg : endInset + 1] subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]") elif p == 3: beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg) endPlain = find_end_of_layout(document.body, beginPlain) endInset = find_end_of_inset(document.body, arg) content = document.body[beginPlain + 1 : endPlain] # Adjust range end j = j - len(document.body[arg : endInset + 1]) # Remove arg inset del document.body[arg : endInset + 1] subst += put_cmd_in_ert("[fragile,") + content + put_cmd_in_ert("]") elif p == 4: beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg) endPlain = find_end_of_layout(document.body, beginPlain) endInset = find_end_of_inset(document.body, arg) content = document.body[beginPlain + 1 : endPlain] # Adjust range end j = j - len(document.body[arg : endInset + 1]) # Remove arg inset del document.body[arg : endInset + 1] subst += put_cmd_in_ert("{") + content + put_cmd_in_ert("}") elif p == 3: subst += put_cmd_in_ert("[fragile]") document.body[i : i + 1] = subst i = j def revert_newframes(document): " Reverts beamer Frame and PlainFrame layouts to old forms " beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"] if document.textclass not in beamer_classes: return frame_dict = { "Frame" : "BeginFrame", "PlainFrame" : "BeginPlainFrame", } rx = re.compile(r'^\\begin_layout (\S+)$') i = 0 while True: i = find_token(document.body, "\\begin_layout", i) if i == -1: return m = rx.match(document.body[i]) val = "" if m: val = m.group(1) if val not in frame_dict.keys(): i = i + 1 continue # Find end of sequence j = find_end_of_sequence(document.body, i) if j == -1: document.warning("Malformed lyx document. Cannot find end of Frame sequence!") i = i + 1 continue endseq = j subst = ["\\begin_layout %s" % frame_dict[val]] esubst = ["\\end_layout", "", "\\begin_layout EndFrame", "", "\\end_layout"] endseq = endseq + len(esubst) - len(document.body[j : j]) if document.body[j] == "\\end_deeper": document.body[j : j] = ["\\end_deeper", ""] + esubst else: document.body[j : j] = esubst for q in range(i, j): if document.body[q] == "\\begin_layout %s" % val: document.body[q] = "\\begin_layout %s" % document.default_layout r = i while r < j: if document.body[r] == "\\begin_deeper": s = find_end_of(document.body, r, "\\begin_deeper", "\\end_deeper") if s != -1: document.body[r] = "" document.body[s] = "" r = s continue r = r + 1 l = find_end_of_layout(document.body, i) for p in range(1, 5): arg = find_token(document.body, "\\begin_inset Argument %d" % p, i, l) if arg != -1: if p == 1: beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg) endPlain = find_end_of_layout(document.body, beginPlain) endInset = find_end_of_inset(document.body, arg) content = document.body[beginPlain + 1 : endPlain] # Adjust range end l = l - len(document.body[arg : endInset + 1]) # Remove arg inset del document.body[arg : endInset + 1] subst += put_cmd_in_ert("<") + content + put_cmd_in_ert(">") elif p == 2: beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg) endPlain = find_end_of_layout(document.body, beginPlain) endInset = find_end_of_inset(document.body, arg) content = document.body[beginPlain + 1 : endPlain] # Adjust range end l = l - len(document.body[arg : endInset + 1]) # Remove arg inset del document.body[arg : endInset + 1] subst += put_cmd_in_ert("[<") + content + put_cmd_in_ert(">]") elif p == 3: beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg) endPlain = find_end_of_layout(document.body, beginPlain) endInset = find_end_of_inset(document.body, arg) content = document.body[beginPlain + 1 : endPlain] # Adjust range end l = l - len(document.body[arg : endInset + 1]) # Remove arg inset del document.body[arg : endInset + 1] subst += put_cmd_in_ert("[") + content + put_cmd_in_ert("]") elif p == 4: beginPlain = find_token(document.body, "\\begin_layout Plain Layout", arg) endPlain = find_end_of_layout(document.body, beginPlain) endInset = find_end_of_inset(document.body, arg) content = document.body[beginPlain + 1 : endPlain] # Adjust range end l = l - len(document.body[arg : endInset + 1]) # Remove arg inset del document.body[arg : endInset + 1] subst += content document.body[i : i + 1] = subst i = j ## # Conversion hub # supported_versions = ["2.1.0","2.1"] convert = [ [414, []], [415, [convert_undertilde]], [416, []], [417, [convert_japanese_encodings]], [418, []], [419, []], [420, [convert_biblio_style]], [421, [convert_longtable_captions]], [422, [convert_use_packages]], [423, [convert_use_mathtools]], [424, [convert_cite_engine_type]], [425, []], [426, []], [427, []], [428, [convert_cell_rotation]], [429, [convert_table_rotation]], [430, [convert_listoflistings]], [431, [convert_use_amssymb]], [432, []], [433, [convert_armenian]], [434, []], [435, []], [436, []], [437, []], [438, []], [439, []], [440, []], [441, [convert_mdnomath]], [442, []], [443, []], [444, []], [445, []], [446, [convert_latexargs]], [447, [convert_IEEEtran, convert_AASTeX, convert_AGUTeX, convert_IJMP, convert_SIGPLAN, convert_SIGGRAPH, convert_EuropeCV, convert_Initials, convert_ModernCV]], [448, [convert_literate]], [449, []], [450, []], [451, [convert_beamerargs, convert_againframe_args, convert_corollary_args, convert_quote_args]], [452, [convert_beamerblocks]], [453, [convert_use_stmaryrd]], [454, [convert_overprint]], [455, []], [456, [convert_epigraph]], [457, [convert_use_stackrel]], [458, [convert_captioninsets, convert_captionlayouts]], [459, []] ] revert = [ [458, [revert_fragileframe, revert_newframes]], [457, [revert_captioninsets, revert_captionlayouts]], [456, [revert_use_stackrel]], [455, [revert_epigraph]], [454, [revert_frametitle]], [453, [revert_overprint]], [452, [revert_use_stmaryrd]], [451, [revert_beamerblocks]], [450, [revert_beamerargs, revert_beamerargs2, revert_beamerargs3, revert_beamerflex]], [449, [revert_garamondx, revert_garamondx_newtxmath]], [448, [revert_itemargs]], [447, [revert_literate]], [446, [revert_IEEEtran, revert_AASTeX, revert_AGUTeX, revert_IJMP, revert_SIGPLAN, revert_SIGGRAPH, revert_EuropeCV, revert_Initials, revert_ModernCV]], [445, [revert_latexargs]], [444, [revert_uop]], [443, [revert_biolinum]], [442, []], [441, [revert_newtxmath]], [440, [revert_mdnomath]], [439, [revert_mathfonts]], [438, [revert_minionpro]], [437, [revert_ipadeco, revert_ipachar]], [436, [revert_texgyre]], [435, [revert_mathdesign]], [434, [revert_txtt]], [433, [revert_libertine]], [432, [revert_armenian]], [431, [revert_languages, revert_ancientgreek]], [430, [revert_use_amssymb]], [429, [revert_listoflistings]], [428, [revert_table_rotation]], [427, [revert_cell_rotation]], [426, [revert_tipa]], [425, [revert_verbatim]], [424, [revert_cancel]], [423, [revert_cite_engine_type]], [422, [revert_use_mathtools]], [421, [revert_use_packages]], [420, [revert_longtable_captions]], [419, [revert_biblio_style]], [418, [revert_australian]], [417, [revert_justification]], [416, [revert_japanese_encodings]], [415, [revert_negative_space, revert_math_spaces]], [414, [revert_undertilde]], [413, [revert_visible_space]] ] if __name__ == "__main__": pass