]> git.lyx.org Git - lyx.git/blobdiff - lib/lyx2lyx/lyx_1_6.py
New routine: get_quoted_value.
[lyx.git] / lib / lyx2lyx / lyx_1_6.py
index bc71d94418cd3686640cb9195888fa2541e3eb31..e1ed5e670f86fa360e249988af11b49aebd39c33 100644 (file)
@@ -22,11 +22,27 @@ import re
 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, get_value
 
 ####################################################################
 # Private helper functions
 
+
+def get_value_string(lines, token, start, end = 0, trim = False, default = ""):
+    """ get_value_string(lines, token, start[[, end], trim, default]) -> string
+
+    Return tokens after token as string, in lines, where
+    token is the first element. When trim is used, the first and last character
+    of the string is trimmed."""
+
+    val = get_value(lines, token, start, end, "")
+    if not val:
+      return default
+    if trim:
+      return val[1:-1]
+    return val
+
+
 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")
@@ -209,7 +225,7 @@ def extract_argument(line):
     return (line[:pos + 1], line[pos + 1:])
 
 
-def latex2ert(line):
+def latex2ert(line, isindex):
     '''Converts LaTeX commands into ERT. line may well be a multi-line
        string when it is returned.'''
     if not line:
@@ -246,6 +262,9 @@ def latex2ert(line):
     # put all remaining braces in ERT
     line = wrap_into_ert(line, '}', '}')
     line = wrap_into_ert(line, '{', '{')
+    if isindex:
+        # active character that is not available in all font encodings
+        line = wrap_into_ert(line, '|', '|')
     retval += line
     return retval
 
@@ -257,10 +276,12 @@ unicode_reps = read_unicodesymbols()
 #end up inside ERT. That routine could be modified so that it returned
 #a list of lines, and we could then skip ERT bits and only deal with
 #the other bits.
-def latex2lyx(data):
+def latex2lyx(data, isindex):
     '''Takes a string, possibly multi-line, and returns the result of
     converting LaTeX constructs into LyX constructs. Returns a list of
-    lines, suitable for insertion into document.body.'''
+    lines, suitable for insertion into document.body.
+    The bool isindex specifies whether we are in an index macro (which
+    has some specific active characters that need to be ERTed).'''
 
     if not data:
         return [""]
@@ -309,19 +330,84 @@ def latex2lyx(data):
             g = m.group(3)
             if s:
                 # this is non-math!
-                s = latex2ert(s)
+                s = latex2ert(s, isindex)
                 subst = s.split('\n')
                 retval += subst
             retval.append("\\begin_inset Formula " + f)
             retval.append("\\end_inset")
             m = mathre.match(g)
         # Handle whatever is left, which is just text
-        g = latex2ert(g)
+        g = latex2ert(g, isindex)
         subst = g.split('\n')
         retval += subst
     return retval
 
 
+def lyxline2latex(document, line, inert):
+    'Convert some LyX stuff into corresponding LaTeX stuff line-wise, as best we can.'
+    if 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.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
+        return ""
+
+    # this needs to be added to the preamble because of cases like
+    # \textmu, \textbackslash, etc.
+    add_to_preamble(document, ['% added by lyx2lyx for converted entries',
+                               '\\@ifundefined{textmu}',
+                               ' {\\usepackage{textcomp}}{}'])
+    # a lossless reversion is not possible
+    # try at least to handle some common insets and settings
+    if inert:
+        line = line.replace(r'\backslash', '\\')
+    else:
+        line = line.replace('&', '\\&{}')
+        line = line.replace('#', '\\#{}')
+        line = line.replace('^', '\\^{}')
+        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].replace('\\\\', '\\') + "{}")
+            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'')
+    return line
+
+
 def lyx2latex(document, lines):
     'Convert some LyX stuff into corresponding LaTeX stuff, as best we can.'
     # clean up multiline stuff
@@ -329,73 +415,15 @@ def lyx2latex(document, lines):
     ert_end = 0
 
     for curline in range(len(lines)):
-      line = lines[curline]
-      if 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.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', r'\\')
-      else:
-          line = line.replace('&', '\\&{}')
-          line = line.replace('#', '\\#{}')
-          line = line.replace('^', '\\^{}')
-          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
+        line = lines[curline]
+        if 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
+        inert = ert_end >= curline
+        content += lyxline2latex(document, lines[curline], inert)
+      
     return content
 
 
@@ -460,6 +488,7 @@ def revert_ltcaption(document):
         j = find_end_of_inset(document.body, i + 1)
         if j == -1:
             document.warning("Malformed LyX document: Could not find end of tabular.")
+            i += 1
             continue
 
         m = i + 1
@@ -559,9 +588,10 @@ def revert_tablines(document):
         i = find_token(document.body, "\\begin_inset Tabular", i)
         if i == -1:
             return
-        j = find_end_of_inset(document.body, i + 1)
+        j = find_end_of_inset(document.body, i)
         if j == -1:
             document.warning("Malformed LyX document: Could not find end of tabular.")
+            i += 1
             continue
 
         m = i + 1
@@ -769,7 +799,6 @@ def revert_flex(document):
         document.body[i] = document.body[i].replace('\\begin_inset Flex', '\\begin_inset CharStyle')
 
 
-#  Discard PDF options for hyperref
 def revert_pdf_options(document):
         "Revert PDF options for hyperref."
         # store the PDF options and delete the entries from the Lyx file
@@ -1076,10 +1105,11 @@ def convert_latexcommand_index(document):
         if i == -1:
             return
         if document.body[i + 1] != "LatexCommand index": # Might also be index_print
-            return
-        j = find_end_of_inset(document.body, i + 2)
+            i += 1
+            continue
+        j = find_end_of_inset(document.body, i + 1)
         if j == -1:
-            document.warning("Unable to find end of index inset at line " + i + "!")
+            document.warning("Unable to find end of index inset at line " + str(i) + "!")
             i += 2
             continue
         m = r1.match(document.body[i + 2])
@@ -1089,7 +1119,7 @@ def convert_latexcommand_index(document):
             linelist = [""]
         else:
             fullcontent = m.group(1)
-            linelist = latex2lyx(fullcontent)
+            linelist = latex2lyx(fullcontent, True)
         #document.warning(fullcontent)
 
         linelist = ["\\begin_inset Index", "status collapsed", "\\begin_layout Standard", ""] + \
@@ -1239,7 +1269,9 @@ def revert_inset_info(document):
                 if arg[len(arg) - 1] == '"':
                     arg = arg[:len(arg) - 1]
                 # \" to straight quote
-                arg = arg.replace(r'\"','"')
+                arg = arg.replace(r'\"', '"')
+                # \ to \backslash
+                arg = arg.replace(r'\\', "\\backslash\n")
             if document.body[k].startswith("type"):
                 type = document.body[k][4:].strip().strip('"')
         # I think there is a newline after \\end_inset, which should be removed.
@@ -1312,13 +1344,13 @@ def convert_url(document):
       j = find_token(document.body, "target", i)
       if j == -1:
         document.warning("Malformed LyX document: Can't find target for url inset")
-        i = j
+        i += 1
         continue
       target = document.body[j][8:-1]
       k = find_token(document.body, "\\end_inset", j)
       if k == -1:
         document.warning("Malformed LyX document: Can't find end of url inset")
-        i = k
+        i = j
         continue
       newstuff = ["\\begin_inset Flex URL",
         "status collapsed", "",
@@ -1328,7 +1360,7 @@ def convert_url(document):
         "\\end_layout",
         ""]
       document.body[i:k] = newstuff
-      i = k
+      i = i + len(newstuff)
 
 def convert_ams_classes(document):
   tc = document.textclass
@@ -2167,7 +2199,7 @@ def convert_subfig(document):
         addedLines -= 1
         subst = ['\\begin_inset Float figure', 'wide false', 'sideways false',
                  'status open', '', '\\begin_layout Plain Layout', '\\begin_inset Caption',
-                 '', '\\begin_layout Plain Layout'] + latex2lyx(caption) + \
+                 '', '\\begin_layout Plain Layout'] + latex2lyx(caption, False) + \
                  [ '\\end_layout', '', '\\end_inset', '',
                  '\\end_layout', '', '\\begin_layout Plain Layout']
         document.body[i : i] = subst
@@ -2219,7 +2251,7 @@ def revert_subfig(document):
             if l == -1:
                 document.warning("Malformed lyx document: Missing '\\end_inset' (embedded float).")
                 i += 1
-                j == -1
+                j = -1
                 continue # escape to the outer loop
             m = find_default_layout(document, k + 1, l)
             # caption?
@@ -2271,14 +2303,15 @@ def revert_subfig(document):
                         continue
                     elif line in document.body[opt:optend]:
                         continue
-                    elif not line.startswith('\\'):
-                        caption += line.strip()
+                    else:
+                        inert = True
+                        caption += lyxline2latex(document, line, inert)
                 if len(label) > 0:
-                    caption += "\\backslash\nlabel{" + label + "}"
-            subst = '\\begin_layout Plain Layout\n\\begin_inset ERT\nstatus collapsed\n\n' \
-                      '\\begin_layout Plain Layout\n\n}' + alignment_end + \
+                    caption += "\n\\backslash\nlabel{" + label + "}"
+            subst = '\\begin_layout PlainLayout\n\\begin_inset ERT\nstatus collapsed\n\n' \
+                      '\\begin_layout PlainLayout\n\n}' + alignment_end + \
                       '\n\\end_layout\n\n\\end_inset\n\n' \
-                      '\\end_layout\n\n\\begin_layout Plain Layout\n'
+                      '\\end_layout\n\n\\begin_layout PlainLayout\n'
             subst = subst.split('\n')
             document.body[l : l+1] = subst
             addedLines = len(subst) - 1
@@ -2289,7 +2322,7 @@ def revert_subfig(document):
             del document.body[k+1:m-1]
             addedLines -= (m - 1 - (k + 1))
             insertion = '\\begin_inset ERT\nstatus collapsed\n\n' \
-                        '\\begin_layout Plain Layout\n\n' + alignment_beg + '\\backslash\n' \
+                        '\\begin_layout PlainLayout\n\n' + alignment_beg + '\n\\backslash\n' \
                         'subfloat'
             if len(shortcap) > 0:
                 insertion = insertion + "[" + shortcap + "]"
@@ -2299,6 +2332,7 @@ def revert_subfig(document):
             insertion = insertion.split('\n')
             document.body[k : k + 1] = insertion
             addedLines += len(insertion) - 1
+            al = find_token(document.body, '\\align ', k - 1, j + addedLines)
             if al != -1:
                 del document.body[al]
                 addedLines -= 1
@@ -2925,7 +2959,7 @@ def convert_plain_layout(document):
 
 
 def revert_plain_layout(document):
-    " Convert 'PlainLayout' to 'Plain Layout'"
+    " Revert 'Plain Layout' to 'PlainLayout'"
     i = 0
     while True:
         i = find_token(document.body, '\\begin_layout Plain Layout', i)
@@ -2937,7 +2971,7 @@ def revert_plain_layout(document):
 
 
 def revert_plainlayout(document):
-    " Convert 'PlainLayout' to 'Plain Layout'"
+    " Revert 'PlainLayout' to 'Standard'"
     i = 0
     while True:
         i = find_token(document.body, '\\begin_layout PlainLayout', i)