X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=lib%2Flyx2lyx%2Flyx_2_0.py;h=1a7a266193ebb3ee2835154bd0a02a6f9c05b836;hb=2778d96bd280a51165455165f422485a78c4e7e8;hp=c4439e2f1b3bfc16f4d1d0e7fb415e4244d86424;hpb=dcc164407aa50c99c7d3045fc254c6761c69c22f;p=lyx.git diff --git a/lib/lyx2lyx/lyx_2_0.py b/lib/lyx2lyx/lyx_2_0.py index c4439e2f1b..1a7a266193 100644 --- a/lib/lyx2lyx/lyx_2_0.py +++ b/lib/lyx2lyx/lyx_2_0.py @@ -23,85 +23,24 @@ import re, string import unicodedata import sys, os -from parser_tools import find_token, find_end_of, find_tokens, get_value, get_value_string +from parser_tools import find_token, find_end_of, find_tokens, \ + find_end_of_inset, find_end_of_layout, get_value, get_value_string + +from lyx2lyx_tools import add_to_preamble, insert_to_preamble, \ + put_cmd_in_ert, lyx2latex, latex_length, revert_flex_inset, \ + revert_font_attrs, revert_layout_command, hex2ratio #################################################################### # Private helper functions def remove_option(document, m, option): + ''' removes option from line m. returns whether we did anything ''' l = document.body[m].find(option) - if l != -1: - val = document.body[m][l:].split('"')[1] - document.body[m] = document.body[m][:l - 1] + document.body[m][l+len(option + '="' + val + '"'):] - return l - -def find_end_of_inset(lines, i): - " Find end of inset, where lines[i] is included." - return find_end_of(lines, i, "\\begin_inset", "\\end_inset") - - -# Note that text can be either a list of lines or a single line. -def add_to_preamble(document, text): - """ Add text to the preamble if it is not already there. - Only the first line is checked!""" - - if not type(text) is list: - # split on \n just in case - # it'll give us the one element list we want - # if there's no \n, too - text = text.split('\n') - - if find_token(document.preamble, text[0], 0) != -1: - return - - document.preamble.extend(text) - - -def insert_to_preamble(index, document, text): - """ Insert text to the preamble at a given line""" - - document.preamble.insert(index, text) - - -def read_unicodesymbols(): - " Read the unicodesymbols list of unicode characters and corresponding commands." - pathname = os.path.abspath(os.path.dirname(sys.argv[0])) - fp = open(os.path.join(pathname.strip('lyx2lyx'), 'unicodesymbols')) - spec_chars = [] - # Two backslashes, followed by some non-word character, and then a character - # in brackets. The idea is to check for constructs like: \"{u}, which is how - # they are written in the unicodesymbols file; but they can also be written - # as: \"u or even \" u. - r = re.compile(r'\\\\(\W)\{(\w)\}') - for line in fp.readlines(): - if line[0] != '#' and line.strip() != "": - line=line.replace(' "',' ') # remove all quotation marks with spaces before - line=line.replace('" ',' ') # remove all quotation marks with spaces after - line=line.replace(r'\"','"') # replace \" by " (for characters with diaeresis) - try: - [ucs4,command,dead] = line.split(None,2) - if command[0:1] != "\\": - continue - spec_chars.append([command, unichr(eval(ucs4))]) - except: - continue - m = r.match(command) - if m != None: - command = "\\\\" - # If the character is a double-quote, then we need to escape it, too, - # since it is done that way in the LyX file. - if m.group(1) == "\"": - command += "\\" - commandbl = command - command += m.group(1) + m.group(2) - commandbl += m.group(1) + ' ' + m.group(2) - spec_chars.append([command, unichr(eval(ucs4))]) - spec_chars.append([commandbl, unichr(eval(ucs4))]) - fp.close() - return spec_chars - - -unicode_reps = read_unicodesymbols() + if l == -1: + return False + val = document.body[m][l:].split('"')[1] + document.body[m] = document.body[m][:l - 1] + document.body[m][l+len(option + '="' + val + '"'):] + return True # DO NOT USE THIS ROUTINE ANY MORE. Better yet, replace the uses that @@ -115,303 +54,6 @@ def old_put_cmd_in_ert(string): return string -# This routine wraps some content in an ERT inset. -# -# NOTE: The function accepts either a single string or a LIST of strings as -# argument. But it returns a LIST of strings, split on \n, so that it does -# not have embedded newlines. -# -# This is how lyx2lyx represents a LyX document: as a list of strings, -# each representing a line of a LyX file. Embedded newlines confuse -# lyx2lyx very much. -# -# A call to this routine will often go something like this: -# i = find_token('\\begin_inset FunkyInset', ...) -# ... -# j = find_end_of_inset(document.body, i) -# content = ...extract content from insets -# # that could be as simple as: -# # content = lyx2latex(document[i:j + 1]) -# ert = put_cmd_in_ert(content) -# document.body[i:j] = ert -# Now, before we continue, we need to reset i appropriately. Normally, -# this would be: -# i += len(ert) -# That puts us right after the ERT we just inserted. -# -def put_cmd_in_ert(arg): - ret = ["\\begin_inset ERT", "status collapsed", "\\begin_layout Plain Layout", ""] - # Despite the warnings just given, it will be faster for us to work - # with a single string internally. That way, we only go through the - # unicode_reps loop once. - if type(arg) is list: - s = "\n".join(arg) - else: - s = arg - for rep in unicode_reps: - s = s.replace(rep[1], rep[0].replace('\\\\', '\\')) - s = s.replace('\\', "\\backslash\n") - ret += s.splitlines() - ret += ["\\end_layout", "\\end_inset"] - return ret - - -def lyx2latex(document, lines): - 'Convert some LyX stuff into corresponding LaTeX stuff, as best we can.' - # clean up multiline stuff - content = "" - ert_end = 0 - note_end = 0 - hspace = "" - - for curline in range(len(lines)): - line = lines[curline] - if line.startswith("\\begin_inset Note Note"): - # We want to skip LyX notes, so remember where the inset ends - note_end = find_end_of_inset(lines, curline + 1) - continue - elif note_end >= curline: - # Skip LyX notes - continue - elif line.startswith("\\begin_inset ERT"): - # We don't want to replace things inside ERT, so figure out - # where the end of the inset is. - ert_end = find_end_of_inset(lines, curline + 1) - continue - elif line.startswith("\\begin_inset Formula"): - line = line[20:] - elif line.startswith("\\begin_inset Quotes"): - # For now, we do a very basic reversion. Someone who understands - # quotes is welcome to fix it up. - qtype = line[20:].strip() - # lang = qtype[0] - side = qtype[1] - dbls = qtype[2] - if side == "l": - if dbls == "d": - line = "``" - else: - line = "`" - else: - if dbls == "d": - line = "''" - else: - line = "'" - elif line.startswith("\\begin_inset space"): - line = line[18:].strip() - if line.startswith("\\hspace"): - # Account for both \hspace and \hspace* - hspace = line[:-2] - continue - elif line == "\\space{}": - line = "\\ " - elif line == "\\thinspace{}": - line = "\\," - elif hspace != "": - # The LyX length is in line[8:], after the \length keyword - # latex_length returns "bool,length" - length = latex_length(line[8:]).split(",")[1] - line = hspace + "{" + length + "}" - hspace = "" - elif line.isspace() or \ - line.startswith("\\begin_layout") or \ - line.startswith("\\end_layout") or \ - line.startswith("\\begin_inset") or \ - line.startswith("\\end_inset") or \ - line.startswith("\\lang") or \ - line.strip() == "status collapsed" or \ - line.strip() == "status open": - #skip all that stuff - continue - - # this needs to be added to the preamble because of cases like - # \textmu, \textbackslash, etc. - add_to_preamble(document, ['% added by lyx2lyx for converted index entries', - '\\@ifundefined{textmu}', - ' {\\usepackage{textcomp}}{}']) - # a lossless reversion is not possible - # try at least to handle some common insets and settings - if ert_end >= curline: - line = line.replace(r'\backslash', '\\') - else: - # No need to add "{}" after single-nonletter macros - line = line.replace('&', '\\&') - line = line.replace('#', '\\#') - line = line.replace('^', '\\textasciicircum{}') - line = line.replace('%', '\\%') - line = line.replace('_', '\\_') - line = line.replace('$', '\\$') - - # Do the LyX text --> LaTeX conversion - for rep in unicode_reps: - line = line.replace(rep[1], rep[0] + "{}") - line = line.replace(r'\backslash', r'\textbackslash{}') - line = line.replace(r'\series bold', r'\bfseries{}').replace(r'\series default', r'\mdseries{}') - line = line.replace(r'\shape italic', r'\itshape{}').replace(r'\shape smallcaps', r'\scshape{}') - line = line.replace(r'\shape slanted', r'\slshape{}').replace(r'\shape default', r'\upshape{}') - line = line.replace(r'\emph on', r'\em{}').replace(r'\emph default', r'\em{}') - line = line.replace(r'\noun on', r'\scshape{}').replace(r'\noun default', r'\upshape{}') - line = line.replace(r'\bar under', r'\underbar{').replace(r'\bar default', r'}') - line = line.replace(r'\family sans', r'\sffamily{}').replace(r'\family default', r'\normalfont{}') - line = line.replace(r'\family typewriter', r'\ttfamily{}').replace(r'\family roman', r'\rmfamily{}') - line = line.replace(r'\InsetSpace ', r'').replace(r'\SpecialChar ', r'') - content += line - return content - - -def latex_length(string): - 'Convert lengths to their LaTeX representation.' - i = 0 - percent = False - # the string has the form - # ValueUnit+ValueUnit-ValueUnit or - # ValueUnit+-ValueUnit - # the + and - (glue lengths) are optional - # the + always precedes the - - - # Convert relative lengths to LaTeX units - units = {"text%":"\\textwidth", "col%":"\\columnwidth", - "page%":"\\paperwidth", "line%":"\\linewidth", - "theight%":"\\textheight", "pheight%":"\\paperheight"} - for unit in units.keys(): - i = string.find(unit) - if i == -1: - percent = True - minus = string.rfind("-", 1, i) - plus = string.rfind("+", 0, i) - latex_unit = units[unit] - if plus == -1 and minus == -1: - value = string[:i] - value = str(float(value)/100) - end = string[i + len(unit):] - string = value + latex_unit + end - if plus > minus: - value = string[plus + 1:i] - value = str(float(value)/100) - begin = string[:plus + 1] - end = string[i+len(unit):] - string = begin + value + latex_unit + end - if plus < minus: - value = string[minus + 1:i] - value = str(float(value)/100) - begin = string[:minus + 1] - string = begin + value + latex_unit - - # replace + and -, but only if the - is not the first character - string = string[0] + string[1:].replace("+", " plus ").replace("-", " minus ") - # handle the case where "+-1mm" was used, because LaTeX only understands - # "plus 1mm minus 1mm" - if string.find("plus minus"): - lastvaluepos = string.rfind(" ") - lastvalue = string[lastvaluepos:] - string = string.replace(" ", lastvalue + " ") - if percent == False: - return "False," + string - else: - return "True," + string - - -def revert_flex_inset(document, name, LaTeXname, position): - " Convert flex insets to TeX code " - i = position - while True: - i = find_token(document.body, '\\begin_inset Flex ' + name, i) - if i == -1: - return - z = find_end_of_inset(document.body, i) - if z == -1: - document.warning("Malformed LyX document: Can't find end of Flex " + name + " inset.") - return - # remove the \end_inset - document.body[z - 2:z + 1] = put_cmd_in_ert("}") - # we need to reset character layouts if necessary - j = find_token(document.body, '\\emph on', i, z) - k = find_token(document.body, '\\noun on', i, z) - l = find_token(document.body, '\\series', i, z) - m = find_token(document.body, '\\family', i, z) - n = find_token(document.body, '\\shape', i, z) - o = find_token(document.body, '\\color', i, z) - p = find_token(document.body, '\\size', i, z) - q = find_token(document.body, '\\bar under', i, z) - r = find_token(document.body, '\\uuline on', i, z) - s = find_token(document.body, '\\uwave on', i, z) - t = find_token(document.body, '\\strikeout on', i, z) - if j != -1: - document.body.insert(z - 2, "\\emph default") - if k != -1: - document.body.insert(z - 2, "\\noun default") - if l != -1: - document.body.insert(z - 2, "\\series default") - if m != -1: - document.body.insert(z - 2, "\\family default") - if n != -1: - document.body.insert(z - 2, "\\shape default") - if o != -1: - document.body.insert(z - 2, "\\color inherit") - if p != -1: - document.body.insert(z - 2, "\\size default") - if q != -1: - document.body.insert(z - 2, "\\bar default") - if r != -1: - document.body.insert(z - 2, "\\uuline default") - if s != -1: - document.body.insert(z - 2, "\\uwave default") - if t != -1: - document.body.insert(z - 2, "\\strikeout default") - document.body[i:i + 4] = put_cmd_in_ert(LaTeXname + "{") - i += 1 - - -def revert_font_attrs(document, name, LaTeXname): - " Reverts font changes to TeX code " - i = 0 - changed = False - while True: - i = find_token(document.body, name + ' on', i) - if i == -1: - return changed - j = find_token(document.body, name + ' default', i) - k = find_token(document.body, name + ' on', i + 1) - # if there is no default set, the style ends with the layout - # assure hereby that we found the correct layout end - if j != -1 and (j < k or k == -1): - document.body[j:j + 1] = put_cmd_in_ert("}") - else: - j = find_token(document.body, '\\end_layout', i) - document.body[j:j] = put_cmd_in_ert("}") - document.body[i:i + 1] = put_cmd_in_ert(LaTeXname + "{") - changed = True - i += 1 - - -def revert_layout_command(document, name, LaTeXname, position): - " Reverts a command from a layout to TeX code " - i = position - while True: - i = find_token(document.body, '\\begin_layout ' + name, i) - if i == -1: - return - k = -1 - # find the next layout - j = i + 1 - while k == -1: - j = find_token(document.body, '\\begin_layout', j) - l = len(document.body) - # if nothing was found it was the last layout of the document - if j == -1: - document.body[l - 4:l - 4] = put_cmd_in_ert("}") - k = 0 - # exclude plain layout because this can be TeX code or another inset - elif document.body[j] != '\\begin_layout Plain Layout': - document.body[j - 2:j - 2] = put_cmd_in_ert("}") - k = 0 - else: - j += 1 - document.body[i] = '\\begin_layout Standard' - document.body[i + 1:i + 1] = put_cmd_in_ert(LaTeXname + "{") - i += 1 - - ############################################################################### ### ### Conversion and reversion routines @@ -649,13 +291,6 @@ def revert_outputformat(document): del document.header[i] -def hex2ratio(s): - val = string.atoi(s, 16) - if val != 0: - val += 1 - return str(val / 256.0) - - def revert_backgroundcolor(document): " Reverts background color to preamble code " i = find_token(document.header, "\\backgroundcolor", 0) @@ -974,15 +609,14 @@ def revert_branch_filename(document): def revert_paragraph_indentation(document): " Revert custom paragraph indentation to preamble code " - i = find_token(document.header, "\\paragraph_indentation", i) + i = find_token(document.header, "\\paragraph_indentation", 0) if i == -1: return length = get_value(document.header, "\\paragraph_indentation", i) # we need only remove the line if indentation is default if length != "default": # handle percent lengths - # latex_length returns "bool,length" - length = latex_length(length).split(",")[1] + length = latex_length(length)[1] add_to_preamble(document, ["% this command was inserted by lyx2lyx"]) add_to_preamble(document, ["\\setlength{\\parindent}{" + length + "}"]) del document.header[i] @@ -990,7 +624,7 @@ def revert_paragraph_indentation(document): def revert_percent_skip_lengths(document): " Revert relative lengths for paragraph skip separation to preamble code " - i = find_token(document.header, "\\defskip", i) + i = find_token(document.header, "\\defskip", 0) if i == -1: return length = get_value(document.header, "\\defskip", i) @@ -999,11 +633,8 @@ def revert_percent_skip_lengths(document): if length in ('smallskip', 'medskip', 'bigskip'): return # handle percent lengths - length = latex_length(length) - # latex_length returns "bool,length" - percent = length.split(",")[0] - length = length.split(",")[1] - if percent == "True": + percent, length = latex_length(length) + if percent: add_to_preamble(document, ["% this command was inserted by lyx2lyx"]) add_to_preamble(document, ["\\setlength{\\parskip}{" + length + "}"]) # set defskip to medskip as default @@ -1019,28 +650,26 @@ def revert_percent_vspace_lengths(document): break # only revert if a custom length was set and if # it used a percent length - line = document.body[i] r = re.compile(r'\\begin_inset VSpace (.*)$') - m = r.match(line) + m = r.match(document.body[i]) length = m.group(1) - if length not in ('defskip', 'smallskip', 'medskip', 'bigskip', 'vfill'): - # check if the space has a star (protected space) - protected = (document.body[i].rfind("*") != -1) + if length in ('defskip', 'smallskip', 'medskip', 'bigskip', 'vfill'): + i += 1 + continue + # check if the space has a star (protected space) + protected = (document.body[i].rfind("*") != -1) + if protected: + length = length.rstrip('*') + # handle percent lengths + percent, length = latex_length(length) + # revert the VSpace inset to ERT + if percent: if protected: - length = length.rstrip('*') - # handle percent lengths - length = latex_length(length) - # latex_length returns "bool,length" - percent = length.split(",")[0] - length = length.split(",")[1] - # revert the VSpace inset to ERT - if percent == "True": - if protected: - subst = [old_put_cmd_in_ert("\\vspace*{" + length + "}")] - else: - subst = [old_put_cmd_in_ert("\\vspace{" + length + "}")] - document.body[i:i + 2] = subst - i = i + 1 + subst = put_cmd_in_ert("\\vspace*{" + length + "}") + else: + subst = put_cmd_in_ert("\\vspace{" + length + "}") + document.body[i:i + 2] = subst + i += 1 def revert_percent_hspace_lengths(document): @@ -1050,26 +679,28 @@ def revert_percent_hspace_lengths(document): i = find_token(document.body, "\\begin_inset space \\hspace", i) if i == -1: break - protected = (document.body[i].find("\\hspace*{}") != -1) - # only revert if a custom length was set and if - # it used a percent length - length = get_value(document.body, '\\length', i + 1) + j = find_end_of_inset(document.body, i) + if j == -1: + document.warning("Can't find end of inset at line " + str(i)) + i += 1 + continue + # only revert if a custom length was set... + length = get_value(document.body, '\\length', i + 1, j) if length == '': document.warning("Malformed lyx document: Missing '\\length' in Space inset.") - return - # handle percent lengths - length = latex_length(length) - # latex_length returns "bool,length" - percent = length.split(",")[0] - length = length.split(",")[1] + i = j + continue + protected = "" + if document.body[i].find("\\hspace*{}") != -1: + protected = "*" + # ...and if it used a percent length + percent, length = latex_length(length) # revert the HSpace inset to ERT - if percent == "True": - if protected: - subst = [old_put_cmd_in_ert("\\hspace*{" + length + "}")] - else: - subst = [old_put_cmd_in_ert("\\hspace{" + length + "}")] - document.body[i:i + 3] = subst - i = i + 2 + if percent: + subst = put_cmd_in_ert("\\hspace" + protected + "{" + length + "}") + document.body[i:j + 1] = subst + # if we did a substitution, this will still be ok + i = j def revert_hspace_glue_lengths(document): @@ -1079,146 +710,145 @@ def revert_hspace_glue_lengths(document): i = find_token(document.body, "\\begin_inset space \\hspace", i) if i == -1: break - protected = (document.body[i].find("\\hspace*{}") != -1) - length = get_value(document.body, '\\length', i + 1) + j = find_end_of_inset(document.body, i) + if j == -1: + document.warning("Can't find end of inset at line " + str(i)) + i += 1 + continue + length = get_value(document.body, '\\length', i + 1, j) if length == '': document.warning("Malformed lyx document: Missing '\\length' in Space inset.") - return + i = j + continue + protected = "" + if document.body[i].find("\\hspace*{}") != -1: + protected = "*" # only revert if the length contains a plus or minus at pos != 0 - glue = re.compile(r'.+[\+-]') - if glue.search(length): + if length.find('-',1) != -1 or length.find('+',1) != -1: # handle percent lengths - # latex_length returns "bool,length" - length = latex_length(length).split(",")[1] + length = latex_length(length)[1] # revert the HSpace inset to ERT - if protected: - subst = [old_put_cmd_in_ert("\\hspace*{" + length + "}")] - else: - subst = [old_put_cmd_in_ert("\\hspace{" + length + "}")] - document.body[i:i + 3] = subst - i = i + 2 + subst = put_cmd_in_ert("\\hspace" + protected + "{" + length + "}") + document.body[i:j+1] = subst + i = j + def convert_author_id(document): " Add the author_id to the \\author definition and make sure 0 is not used" i = 0 - j = 1 + anum = 1 + re_author = re.compile(r'(\\author) (\".*\")\s*(.*)$') + while True: i = find_token(document.header, "\\author", i) if i == -1: break - - r = re.compile(r'(\\author) (\".*\")\s?(.*)$') - m = r.match(document.header[i]) - if m != None: + m = re_author.match(document.header[i]) + if m: name = m.group(2) - - email = '' - if m.lastindex == 3: - email = m.group(3) - document.header[i] = "\\author %i %s %s" % (j, name, email) - j = j + 1 - i = i + 1 + email = m.group(3) + document.header[i] = "\\author %i %s %s" % (anum, name, email) + # FIXME Should this really be incremented if we didn't match? + anum += 1 + i += 1 - k = 0 + i = 0 while True: - k = find_token(document.body, "\\change_", k) - if k == -1: + i = find_token(document.body, "\\change_", i) + if i == -1: break - - change = document.body[k].split(' '); + change = document.body[i].split(' '); if len(change) == 3: type = change[0] author_id = int(change[1]) time = change[2] - document.body[k] = "%s %i %s" % (type, author_id + 1, time) - k = k + 1 + document.body[i] = "%s %i %s" % (type, author_id + 1, time) + i += 1 + def revert_author_id(document): " Remove the author_id from the \\author definition " i = 0 - j = 0 + anum = 0 + rx = re.compile(r'(\\author)\s+(\d+)\s+(\".*\")\s*(.*)$') idmap = dict() + while True: i = find_token(document.header, "\\author", i) if i == -1: break - - r = re.compile(r'(\\author) (\d+) (\".*\")\s?(.*)$') - m = r.match(document.header[i]) - if m != None: + m = rx.match(document.header[i]) + if m: author_id = int(m.group(2)) - idmap[author_id] = j + idmap[author_id] = anum name = m.group(3) - - email = '' - if m.lastindex == 4: - email = m.group(4) + email = m.group(4) document.header[i] = "\\author %s %s" % (name, email) - i = i + 1 - j = j + 1 + i += 1 + # FIXME Should this be incremented if we didn't match? + anum += 1 - k = 0 + i = 0 while True: - k = find_token(document.body, "\\change_", k) - if k == -1: + i = find_token(document.body, "\\change_", i) + if i == -1: break - - change = document.body[k].split(' '); + change = document.body[i].split(' '); if len(change) == 3: type = change[0] author_id = int(change[1]) time = change[2] - document.body[k] = "%s %i %s" % (type, idmap[author_id], time) - k = k + 1 + document.body[i] = "%s %i %s" % (type, idmap[author_id], time) + i += 1 def revert_suppress_date(document): " Revert suppressing of default document date to preamble code " - i = 0 - while True: - i = find_token(document.header, "\\suppress_date", i) - if i == -1: - break - # remove the preamble line and write to the preamble - # when suppress_date was true - date = get_value(document.header, "\\suppress_date", i) - if date == "true": - add_to_preamble(document, ["% this command was inserted by lyx2lyx"]) - add_to_preamble(document, ["\\date{}"]) - del document.header[i] - i = i + 1 + i = find_token(document.header, "\\suppress_date", 0) + if i == -1: + return + # remove the preamble line and write to the preamble + # when suppress_date was true + date = get_value(document.header, "\\suppress_date", i) + if date == "true": + add_to_preamble(document, ["% this command was inserted by lyx2lyx"]) + add_to_preamble(document, ["\\date{}"]) + del document.header[i] def revert_mhchem(document): "Revert mhchem loading to preamble code" - i = 0 - j = 0 - k = 0 + mhchem = "off" - i = find_token(document.header, "\\use_mhchem 1", 0) - if i != -1: + i = find_token(document.header, "\\use_mhchem", 0) + if i == -1: + document.warning("Malformed LyX document: Could not find mhchem setting.") mhchem = "auto" else: - i = find_token(document.header, "\\use_mhchem 2", 0) - if i != -1: + val = get_value(document.header, "\\use_mhchem", i) + if val == "1": + mhchem = "auto" + elif val == "2": mhchem = "on" + del document.header[i] + if mhchem == "auto": - j = find_token(document.body, "\\cf{", 0) - if j != -1: - mhchem = "on" - else: - j = find_token(document.body, "\\ce{", 0) - if j != -1: - mhchem = "on" + i = 0 + while True: + i = find_token(document.body, "\\begin_inset Formula", i) + if i == -1: + break + line = document.body[i] + if line.find("\\ce{") != -1 or line.find("\\cf{") != 1: + mhchem = "on" + break + i += 1 + if mhchem == "on": - add_to_preamble(document, ["% this command was inserted by lyx2lyx"]) - add_to_preamble(document, ["\\PassOptionsToPackage{version=3}{mhchem}"]) - add_to_preamble(document, ["\\usepackage{mhchem}"]) - k = find_token(document.header, "\\use_mhchem", 0) - if k == -1: - document.warning("Malformed LyX document: Could not find mhchem setting.") - return - del document.header[k] + pre = ["% lyx2lyx mhchem commands", + "\\PassOptionsToPackage{version=3}{mhchem}", + "\\usepackage{mhchem}"] + add_to_preamble(document, pre) def revert_fontenc(document): @@ -1301,7 +931,7 @@ def revert_includeonly(document): return j = find_end_of(document.header, i, "\\begin_includeonly", "\\end_includeonly") if j == -1: - # this should not happen + document.warning("Unable to find end of includeonly section!!") break document.header[i : j + 1] = [] @@ -1326,33 +956,54 @@ def revert_multirow(document): multirow = True # remove the multirow tag, set the valignment to top # and remove the bottom line + # FIXME Are we sure these always have space around them? document.body[i] = document.body[i].replace(' multirow="3" ', ' ') document.body[i] = document.body[i].replace('valignment="middle"', 'valignment="top"') document.body[i] = document.body[i].replace(' bottomline="true" ', ' ') # write ERT to create the multirow cell # use 2 rows and 2cm as default with because the multirow span # and the column width is only hardly accessible - subst = [old_put_cmd_in_ert("\\multirow{2}{2cm}{")] - document.body[i + 4:i + 4] = subst - i = find_token(document.body, "", i) - if i == -1: - document.warning("Malformed LyX document: Could not find end of tabular cell.") - break - subst = [old_put_cmd_in_ert("}")] - document.body[i - 3:i - 3] = subst - # cell type 4 is multirow part cell - i = find_token(document.body, '", i) + if cend == -1: + document.warning("Malformed LyX document: Could not find end of tabular cell.") + i += 1 + continue + blay = find_token(document.body, "\\begin_layout", i, cend) + if blay == -1: + document.warning("Can't find layout for cell!") + i = j + continue + bend = find_end_of_layout(document.body, blay) + if blay == -1: + document.warning("Can't find end of layout for cell!") + i = cend + continue + + # do the later one first, so as not to mess up the numbering + # we are wrapping the whole cell in this ert + # so before the end of the layout... + document.body[bend:bend] = put_cmd_in_ert("}") + # ...and after the beginning + document.body[blay+1:blay+1] = put_cmd_in_ert("\\multirow{2}{2cm}{") + + while True: + # cell type 4 is multirow part cell + k = find_token(document.body, '