]> git.lyx.org Git - lyx.git/blobdiff - lib/lyx2lyx/lyx_2_0.py
Fix multirow reversion.
[lyx.git] / lib / lyx2lyx / lyx_2_0.py
index 1b9b89570da830b85ed32670ba9d6627163abab2..33aba904878127dcc9844d87498e6ff095f8234c 100644 (file)
@@ -40,6 +40,11 @@ def find_end_of_inset(lines, i):
     return find_end_of(lines, i, "\\begin_inset", "\\end_inset")
 
 
+def find_end_of_layout(lines, i):
+    " Find end of layout, where lines[i] is included."
+    return find_end_of(lines, i, "\\begin_layout", "\\end_layout")
+
+
 # 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.
@@ -209,8 +214,7 @@ def lyx2latex(document, lines):
               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]
+          length = latex_length(line[8:])[1]
           line = hspace + "{" + length + "}"
           hspace = ""
       elif line.isspace() or \
@@ -260,7 +264,11 @@ def lyx2latex(document, lines):
 
 
 def latex_length(slen):
-    'Convert lengths to their LaTeX representation.'
+    ''' 
+    Convert lengths to their LaTeX representation. Returns (bool, length),
+    where the bool tells us if it was a percentage, and the length is the
+    LaTeX representation.
+    '''
     i = 0
     percent = False
     # the slen has the form
@@ -306,10 +314,7 @@ def latex_length(slen):
         lastvaluepos = slen.rfind(" ")
         lastvalue = slen[lastvaluepos:]
         slen = slen.replace("  ", lastvalue + " ")
-    if percent ==  False:
-        return "False," + slen
-    else:
-        return "True," + slen
+    return (percent, slen)
 
 
 def revert_flex_inset(document, name, LaTeXname, position):
@@ -982,8 +987,7 @@ def revert_paragraph_indentation(document):
     # 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]
@@ -1000,10 +1004,7 @@ 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]
+    percent, length = latex_length(length)
     if percent == "True":
         add_to_preamble(document, ["% this command was inserted by lyx2lyx"])
         add_to_preamble(document, ["\\setlength{\\parskip}{" + length + "}"])
@@ -1020,28 +1021,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 == "True":
           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):
@@ -1051,26 +1050,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
+          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):
@@ -1080,146 +1081,142 @@ 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)
+            line = document.body[i]
+            if line.find("\\ce{") != -1 or line.find("\\cf{") != 1:
+              mhchem = "on"
+              break
+
     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):
@@ -1302,7 +1299,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] = []
 
@@ -1327,33 +1324,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, "</cell>", 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, '<cell multirow="4"', i)
-      if i == -1:
-          break
-      # remove the multirow tag, set the valignment to top
-      # and remove the top line
-      document.body[i] = document.body[i].replace(' multirow="4" ', ' ')
-      document.body[i] = document.body[i].replace('valignment="middle"', 'valignment="top"')
-      document.body[i] = document.body[i].replace(' topline="true" ', ' ')
-      i = i + 1
+      cend = find_token(document.body, "</cell>", 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, '<cell multirow="4"', cend)
+          if k == -1:
+              break
+          # remove the multirow tag, set the valignment to top
+          # and remove the top line
+          # FIXME Are we sure these always have space around them?
+          document.body[k] = document.body[k].replace(' multirow="4" ', ' ')
+          document.body[k] = document.body[k].replace('valignment="middle"', 'valignment="top"')
+          document.body[k] = document.body[k].replace(' topline="true" ', ' ')
+          k += 1
+      # this will always be ok
+      i = cend
+
     if multirow == True:
-        add_to_preamble(document, ["% this command was inserted by lyx2lyx"])
-        add_to_preamble(document, ["\\usepackage{multirow}"])
+        add_to_preamble(document, 
+          ["% lyx2lyx multirow additions ", "\\usepackage{multirow}"])
 
 
 def convert_math_output(document):
@@ -1870,8 +1888,7 @@ def revert_makebox(document):
       length = document.body[l][7:]
       # remove trailing '"'
       length = length[:-1]
-      # latex_length returns "bool,length"
-      length = latex_length(length).split(",")[1]
+      length = latex_length(length)[1]
       subst = "\\makebox[" + length + "][" \
         + align + "]{"
       document.body[i:y + 1] = put_cmd_in_ert(subst)