# 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
+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
##
# Class
#
-class FileInfo:
+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):
if input and input != '-':
self.textclass = "article"
self.header = []
self.body = []
- self.read()
+
def warning(self, message, debug_level= default_debug_level):
if debug_level <= self.debug:
self.err.write(message + "\n")
+
def error(self, message):
self.warning(message)
self.warning("Quiting.")
sys.exit(1)
+
def read(self):
"""Reads a file into the self.header and self.body parts"""
preamble = 0
self.language = "english"
self.initial_version = self.read_version()
+
def write(self):
self.set_version()
self.set_format()
except:
return open(file)
+
def lyxformat(self, format):
result = format_re.match(format)
if result:
self.error(str(format) + ": " + "Format not supported.")
return None
+
def read_version(self):
for line in self.header:
if line[0] != "#":
return result.group(1)
return None
+
def set_version(self):
self.header[0] = "#LyX %s created this file. For more info see http://www.lyx.org/" % version
if self.header[1][0] == '#':
del self.header[1]
+
def read_format(self):
for line in self.header:
result = fileformat.match(line)
self.header[i] = "\\lyxformat %s" % format
+ def set_parameter(self, param, value):
+ i = find_token(self.header, '\\' + param, 0)
+ if i == -1:
+ self.warning(3, 'Parameter not found in the header: %s' % param)
+ return
+ self.header[i] = '\\%s %s' % (param, str(value))
+
+
+ def convert(self):
+ "Convert from old to new 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)
+
+
def chain(self):
""" This is where all the decisions related with the convertion are taken"""
steps.pop()
return mode, steps
+
+
+ def get_toc(self, depth = 4):
+ " Returns the TOC of a lyx document."
+ paragraphs_filter = {'Title' : 0,'Chapter' : 1, 'Section' : 2, 'Subsection' : 3, 'Subsubsection': 4}
+ allowed_insets = ['Quotes']
+
+ sections = []
+ for section in paragraphs_filter.keys():
+ sections.append('\\begin_layout %s' % section)
+
+ toc_par = []
+ i = 0
+ while 1:
+ i = find_tokens(self.body, sections, i)
+ if i == -1:
+ break
+
+ j = find_end_of(self.body, i + 1, '\\begin_layout', '\\end_layout')
+ if j == -1:
+ self.warning('Incomplete file.', 0)
+ break
+
+ section = string.split(self.body[i])[1]
+ if section[-1] == '*':
+ section = section[:-1]
+
+ par = []
+
+ k = i + 1
+ # skip paragraph parameters
+ while not self.body[k] or self.body[k][0] == '\\':
+ k = k +1
+
+ while k < j:
+ if check_token(self.body[k], '\\begin_inset'):
+ inset = string.split(self.body[k])[1]
+ end = find_end_of_inset(self.body, k)
+ if end == -1 or end > j:
+ self.warning('Malformed file.', 0)
+
+ if inset in allowed_insets:
+ par.extend(self.body[k: end+1])
+ k = end + 1
+ else:
+ par.append(self.body[k])
+ k = k + 1
+
+ # trim empty lines in the end.
+ while string.strip(par[-1]) == '' and par:
+ par.pop()
+
+ toc_par.append(Paragraph(section, par))
+
+ i = j + 1
+
+ return toc_par
+
+
+class File(LyX_Base):
+ 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):
+ def set_header(self, **params):
+ # set default values
+ self.header.extend([
+ "#LyX xxxx created this file. For more info see http://www.lyx.org/",
+ "\\lyxformat xxx",
+ "\\begin_document",
+ "\\begin_header",
+ "\\textclass article",
+ "\\language english",
+ "\\inputencoding auto",
+ "\\fontscheme default",
+ "\\graphics default",
+ "\\paperfontsize default",
+ "\\papersize default",
+ "\\paperpackage none",
+ "\\use_geometry false",
+ "\\use_amsmath 1",
+ "\\cite_engine basic",
+ "\\use_bibtopic false",
+ "\\paperorientation portrait",
+ "\\secnumdepth 3",
+ "\\tocdepth 3",
+ "\\paragraph_separation indent",
+ "\\defskip medskip",
+ "\\quotes_language english",
+ "\\quotes_times 2",
+ "\\papercolumns 1",
+ "\\papersides 1",
+ "\\paperpagestyle default",
+ "\\tracking_changes false",
+ "\\end_header"])
+
+ self.format = get_end_format()
+ for param in params:
+ self.set_parameter(param, params[param])
+
+
+ def set_body(self, paragraphs):
+ self.body.extend(['\\begin_body',''])
+
+ for par in paragraphs:
+ self.body.extend(par.asLines())
+
+ self.body.extend(['','\\end_body', '\\end_document'])
+
+
+class Paragraph:
+ def __init__(self, name, body=[], settings = [], child = []):
+ self.name = name
+ self.body = body
+ self.settings = settings
+ self.child = child
+
+ def asLines(self):
+ result = ['','\\begin_layout %s' % self.name]
+ result.extend(self.settings)
+ result.append('')
+ result.extend(self.body)
+ result.append('\\end_layout')
+
+ if not self.child:
+ return result
+
+ result.append('\\begin_deeper')
+ for node in self.child:
+ result.extend(node.asLines())
+ result.append('\\end_deeper')
+
+ return result