]> git.lyx.org Git - lyx.git/blobdiff - lib/lyx2lyx/LyX.py
Whitespace, only whitespace. s/ +$//
[lyx.git] / lib / lyx2lyx / LyX.py
index 6ed2c47d3ab577906856762a8500cb67934cb4bf..e906912e17022c3554576f0833deee9c9ac2cde9 100644 (file)
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
-from parser_tools import get_value, check_token, find_token, find_tokens, find_end_of, find_end_of_inset
+from parser_tools import get_value, check_token, find_token,\
+     find_tokens, find_end_of, find_end_of_inset
 import os.path
 import gzip
 import sys
 import re
 import string
+import time
 
-##
-# file format version
-#
-version = "1.4.0cvs"
+version_lyx2lyx = "1.4.0cvs"
 default_debug_level = 2
+
+# Regular expressions used
 format_re = re.compile(r"(\d)[\.,]?(\d\d)")
 fileformat = re.compile(r"\\lyxformat\s*(\S*)")
 original_version = re.compile(r"\#LyX (\S*)")
 
+##
+# file format information:
+#  file, supported formats, stable release versions
 format_relation = [("0_10",  [210], ["0.10.7","0.10"]),
                    ("0_12",  [215], ["0.12","0.12.1","0.12"]),
                    ("1_0_0", [215], ["1.0.0","1.0"]),
@@ -42,10 +46,11 @@ format_relation = [("0_10",  [210], ["0.10.7","0.10"]),
                    ("1_1_6fix3", [218], ["1.1.6fix3","1.1.6fix4","1.1"]),
                    ("1_2", [220], ["1.2.0","1.2.1","1.2.3","1.2.4","1.2"]),
                    ("1_3", [221], ["1.3.0","1.3.1","1.3.2","1.3.3","1.3.4","1.3.5","1.3"]),
-                   ("1_4", range(223,238), ["1.4.0cvs","1.4"])]
+                   ("1_4", range(223,242), ["1.4.0cvs","1.4"])]
 
 
 def formats_list():
+    " Returns a list with supported file formats."
     formats = []
     for version in format_relation:
         for format in version[1]:
@@ -55,10 +60,12 @@ def formats_list():
 
 
 def get_end_format():
+    " Returns the more recent file format available."
     return format_relation[-1][1][-1]
 
 
 def get_backend(textclass):
+    " For _textclass_ returns its backend."
     if textclass == "linuxdoc" or textclass == "manpage":
         return "linuxdoc"
     if textclass[:7] == "docbook":
@@ -72,6 +79,13 @@ def get_backend(textclass):
 class LyX_Base:
     """This class carries all the information of the LyX file."""
     def __init__(self, end_format = 0, input = "", output = "", error = "", debug = default_debug_level):
+        """Arguments:
+        end_format: final format that the file should be converted. (integer)
+        input: the name of the input source, if empty resort to standard input.
+        output: the name of the output file, if empty use the standard output.
+        error: the name of the error file, if empty use the standard error.
+        debug: debug level, O means no debug, as its value increases be more verbose.
+        """
         if input and input != '-':
             self.input = self.open(input)
         else:
@@ -100,18 +114,20 @@ class LyX_Base:
 
 
     def warning(self, message, debug_level= default_debug_level):
+        " Emits warning to self.error, if the debug_level is less than the self.debug."
         if debug_level <= self.debug:
             self.err.write(message + "\n")
 
 
     def error(self, message):
+        " Emits a warning and exist incondicionally."
         self.warning(message)
         self.warning("Quiting.")
         sys.exit(1)
 
 
     def read(self):
-        """Reads a file into the self.header and self.body parts"""
+        """Reads a file into the self.header and self.body parts, from self.input."""
         preamble = 0
 
         while 1:
@@ -157,6 +173,7 @@ class LyX_Base:
 
 
     def write(self):
+        " Writes the LyX file to self.output."
         self.set_version()
         self.set_format()
 
@@ -180,6 +197,7 @@ class LyX_Base:
 
 
     def lyxformat(self, format):
+        " Returns the file format representation, an integer."
         result = format_re.match(format)
         if result:
             format = int(result.group(1) + result.group(2))
@@ -194,6 +212,8 @@ class LyX_Base:
 
 
     def read_version(self):
+        """ Searchs for clues of the LyX version used to write the file, returns the
+        most likely value, or None otherwise."""
         for line in self.header:
             if line[0] != "#":
                 return None
@@ -205,12 +225,14 @@ class LyX_Base:
 
 
     def set_version(self):
-        self.header[0] = "#LyX %s created this file. For more info see http://www.lyx.org/" % version
+        " Set the header with the version used."
+        self.header[0] = "#LyX %s created this file. For more info see http://www.lyx.org/" % version_lyx2lyx
         if self.header[1][0] == '#':
             del self.header[1]
 
 
     def read_format(self):
+        " Read from the header the fileformat of the present LyX file."
         for line in self.header:
             result = fileformat.match(line)
             if result:
@@ -221,8 +243,9 @@ class LyX_Base:
 
 
     def set_format(self):
+        " Set the file format of the file, in the header."
         if self.format <= 217:
-            format = str(float(format)/100)
+            format = str(float(self.format)/100)
         else:
             format = str(self.format)
         i = find_token(self.header, "\\lyxformat", 0)
@@ -230,6 +253,7 @@ class LyX_Base:
 
 
     def set_parameter(self, param, value):
+        " Set the value of the header parameter."
         i = find_token(self.header, '\\' + param, 0)
         if i == -1:
             self.warning(3, 'Parameter not found in the header: %s' % param)
@@ -238,17 +262,39 @@ class LyX_Base:
 
 
     def convert(self):
-        "Convert from old to new format."
+        "Convert from current (self.format) to self.end_format."
         mode, convertion_chain = self.chain()
         self.warning("convertion chain: " + str(convertion_chain), 3)
 
         for step in convertion_chain:
-            convert_step = getattr(__import__("lyx_" + step), mode)
-            convert_step(self)
+            steps = getattr(__import__("lyx_" + step), mode)
+
+            self.warning("Convertion step: %s - %s" % (step, mode), default_debug_level + 1)
+            if not steps:
+                    self.error("The convertion to an older format (%s) is not implemented." % self.format)
+
+            multi_conv = len(steps) != 1
+            for version, table in steps:
+                if multi_conv and \
+                   (self.format >= version and mode == "convert") or\
+                   (self.format <= version and mode == "revert"):
+                    continue
+
+                for conv in table:
+                    init_t = time.time()
+                    conv(self)
+                    self.warning("%lf: Elapsed time on %s"  % (time.time() - init_t, str(conv)),
+                                 default_debug_level + 1)
+
+                self.format = version
+                if self.end_format == self.format:
+                    return
 
 
     def chain(self):
-        """ This is where all the decisions related with the convertion are taken"""
+        """ This is where all the decisions related with the convertion are taken.
+        It returns a list of modules needed to convert the LyX file from
+        self.format to self.end_format"""
 
         self.start =  self.format
         format = self.format
@@ -309,9 +355,10 @@ class LyX_Base:
 
 
     def get_toc(self, depth = 4):
-        " Returns the TOC of a lyx document."
+        " Returns the TOC of this LyX document."
         paragraphs_filter = {'Title' : 0,'Chapter' : 1, 'Section' : 2, 'Subsection' : 3, 'Subsubsection': 4}
         allowed_insets = ['Quotes']
+        allowed_parameters = '\\paragraph_spacing', '\\noindent', '\\align', '\\labelwidthstring', "\\start_of_appendix"
 
         sections = []
         for section in paragraphs_filter.keys():
@@ -337,7 +384,7 @@ class LyX_Base:
 
             k = i + 1
             # skip paragraph parameters
-            while not self.body[k] or self.body[k][0] == '\\':
+            while not string.strip(self.body[k]) and string.split(self.body[k])[0] in allowed_parameters:
                 k = k +1
 
             while k < j:
@@ -366,12 +413,14 @@ class LyX_Base:
 
 
 class File(LyX_Base):
+    " This class reads existing LyX files."
     def __init__(self, end_format = 0, input = "", output = "", error = "", debug = default_debug_level):
         LyX_Base.__init__(self, end_format, input, output, error, debug)
         self.read()
 
 
 class NewFile(LyX_Base):
+    " This class is to create new LyX files."
     def set_header(self, **params):
         # set default values
         self.header.extend([
@@ -419,13 +468,21 @@ class NewFile(LyX_Base):
 
 
 class Paragraph:
+    # unfinished implementation, it is missing the Text and Insets representation.
+    " This class represents the LyX paragraphs."
     def __init__(self, name, body=[], settings = [], child = []):
+        """ Parameters:
+        name: paragraph name.
+        body: list of lines of body text.
+        child: list of paragraphs that descend from this paragraph.
+        """
         self.name = name
         self.body = body
         self.settings = settings
         self.child = child
 
     def asLines(self):
+        " Converts the paragraph to a list of strings, representing it in the LyX file."
         result = ['','\\begin_layout %s' % self.name]
         result.extend(self.settings)
         result.append('')
@@ -441,3 +498,13 @@ class Paragraph:
         result.append('\\end_deeper')
 
         return result
+
+
+class Inset:
+    " This class represents the LyX insets."
+    pass
+
+
+class Text:
+    " This class represents simple chuncks of text."
+    pass