#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
""" Convert files to the file format generated by lyx 1.6"""
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")
# DO NOT do this:
# document.body[i] = wrap_insert_ert(...)
# wrap_into_ert may returns a multiline string, which should NOT appear
-# in document.body. Insetad, do something like this:
+# in document.body. Instead, do something like this:
# subst = wrap_inset_ert(...)
# subst = subst.split('\n')
# document.body[i:i+1] = subst
+ dst + '\n\\end_layout\n\\end_inset\n')
def put_cmd_in_ert(string):
+ for rep in unicode_reps:
+ string = string.replace(rep[1], rep[0].replace('\\\\', '\\'))
string = string.replace('\\', "\\backslash\n")
string = "\\begin_inset ERT\nstatus collapsed\n\\begin_layout Standard\n" \
+ string + "\n\\end_layout\n\\end_inset"
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)
+
# Convert a LyX length into a LaTeX length
def convert_len(len):
units = {"text%":"\\backslash\ntextwidth", "col%":"\\backslash\ncolumnwidth",
"theight%":"\\backslash\ntextheight", "pheight%":"\\backslash\npageheight"}
# Convert LyX units to LaTeX units
- for unit in units.keys():
+ for unit in list(units.keys()):
if len.find(unit) != -1:
len = '%f' % (len2value(len) / 100)
len = len.strip('0') + units[unit]
return l
+# FIXME: Use the version in unicode_symbols.py which has some bug fixes
def read_unicodesymbols():
" Read the unicodesymbols list of unicode characters and corresponding commands."
pathname = os.path.abspath(os.path.dirname(sys.argv[0]))
# 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.
+ # as: \"u or even \" u.
r = re.compile(r'\\\\(\W)\{(\w)\}')
for line in fp.readlines():
if line[0] != '#' and line.strip() != "":
# 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
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:
retval = ""
## FIXME Escaped \ ??
- labelre = re.compile(r'(.*?)\\(\\(?:[a-zA-Z]+|.))(.*)')
+ # This regex looks for a LaTeX command---i.e., something of the form
+ # "\alPhaStuFF", or "\X", where X is any character---where the command
+ # may also be preceded by an additional backslash, which is how it would
+ # appear (e.g.) in an InsetIndex.
+ labelre = re.compile(r'(.*?)\\?(\\(?:[a-zA-Z]+|.))(.*)')
m = labelre.match(line)
while m != None:
break
cmd += arg
end = rest
+ # If we wanted to put labels into an InsetLabel, for example, then we
+ # would just need to test here for cmd == "label" and then take some
+ # appropriate action, i.e., to use arg to get the content and then
+ # wrap it appropriately.
cmd = put_cmd_in_ert(cmd)
retval += "\n" + cmd + "\n"
line = end
m = labelre.match(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
-def latex2lyx(data):
- '''Takes a string, possibly multi-line, and returns the result of
+unicode_reps = read_unicodesymbols()
+
+#Bug 5022....
+#Might should do latex2ert first, then deal with stuff that DOESN'T
+#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, 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 [""]
retval = []
# Convert LaTeX to Unicode
- reps = read_unicodesymbols()
# Commands of this sort need to be checked to make sure they are
# followed by a non-alpha character, lest we replace too much.
hardone = re.compile(r'^\\\\[a-zA-Z]+$')
-
- for rep in reps:
+
+ for rep in unicode_reps:
if hardone.match(rep[0]):
pos = 0
while True:
else:
data = data.replace(rep[0], rep[1])
- # Generic, \" -> ":
+ # Generic
+ # \" -> ":
data = wrap_into_ert(data, r'\"', '"')
+ # \\ -> \:
+ data = data.replace('\\\\', '\\')
# Math:
mathre = re.compile('^(.*?)(\$.*?\$)(.*)')
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
+ content = ""
+ 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
+ inert = ert_end >= curline
+ content += lyxline2latex(document, lines[curline], inert)
+
+ return content
+
+
####################################################################
def convert_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
nrows = int(document.body[i+1].split('"')[3])
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
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
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
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
i = find_token(document.body, "\\begin_inset CharStyle", i)
if i == -1:
return
- document.body[i] = document.body[i].replace("CharStyle CharStyle:", "CharStyle")
+ document.body[i] = document.body[i].replace("CharStyle CharStyle:", "CharStyle ")
i += 1
document.body[i] = document.body[i].replace('\\begin_inset CharStyle', '\\begin_inset Flex')
def revert_flex(document):
- "Convert Flex to CharStyle"
+ "Revert Flex to CharStyle"
i = 0
while True:
i = find_token(document.body, "\\begin_inset Flex", i)
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
setupstart = ""
setupend = ""
# write the preamble
- add_to_preamble(document,
- ['% Commands inserted by lyx2lyx for PDF properties',
- '\\usepackage[unicode=true'
+ # babel must be loaded before hyperref and hyperref the first part
+ # of the preamble, like in LyX 1.6
+ insert_to_preamble(0, document,
+ '% Commands inserted by lyx2lyx for PDF properties\n'
+ + '\\usepackage{babel}\n'
+ + '\\usepackage[unicode=true'
+ bookmarks
+ breaklinks
+ pdfborder
+ colorlinks
+ pagemode
+ ']\n'
- ' {hyperref}\n'
+ + ' {hyperref}\n'
+ setupstart
+ title
+ author
+ subject
+ keywords
+ otheroptions
- + setupend])
+ + setupend)
def remove_inzip_options(document):
if j == -1:
# should not happen
document.warning("Malformed LyX document: Could not find end of graphics inset.")
+ i += 1
+ continue
# If there's a inzip param, just remove that
k = find_token(document.body, "\tinzipName", i + 1, j)
if k != -1:
m = r.match(nextline)
if not m:
document.warning("Malformed LyX document: Missing LatexCommand in " + document.body[i] + ".")
+ i += 1
continue
cmdName = m.group(1)
insertion = ["\\begin_inset LatexCommand " + cmdName]
if i == -1:
return
if document.body[i + 1] != "LatexCommand index": # Might also be index_print
- return
+ 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 " + str(i) + "!")
+ i += 2
+ continue
m = r1.match(document.body[i + 2])
if m == None:
document.warning("Unable to match: " + document.body[i+2])
- i += 1
- continue
- fullcontent = m.group(1)
+ # this can happen with empty index insets!
+ linelist = [""]
+ else:
+ fullcontent = m.group(1)
+ linelist = latex2lyx(fullcontent, True)
#document.warning(fullcontent)
- document.body[i:i + 3] = ["\\begin_inset Index",
- "status collapsed",
- "\\begin_layout Standard"]
- i += 3
- # We are now on the blank line preceding "\end_inset"
- # We will write the content here, into the inset.
-
- linelist = latex2lyx(fullcontent)
- document.body[i+1:i+1] = linelist
- i += len(linelist)
-
- document.body.insert(i + 1, "\\end_layout")
- i += 1
+
+ linelist = ["\\begin_inset Index", "status collapsed", "\\begin_layout Standard", ""] + \
+ linelist + ["\\end_layout"]
+ document.body[i : j] = linelist
+ i += len(linelist) - (j - i)
def revert_latexcommand_index(document):
if j == -1:
return
- # clean up multiline stuff
- content = ""
- ert_end = 0
- reps = read_unicodesymbols()
-
- for curline in range(i + 3, j - 2): # can skip last couple lines
- line = document.body[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(document.body, 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 Standard") or \
- line.startswith("\\begin_layout Plain Layout") or \
- line.startswith("\\end_layout") or \
- line.startswith("\\end_inset") or \
- line.startswith("\\lang") or \
- line.startswith("status collapsed") or \
- line.startswith("status open"):
- #skip all that stuff
- continue
-
- # a lossless reversion is not possible
- # try at least to handle some common insets and settings
- # do not replace inside ERTs
- if ert_end >= curline:
- line = line.replace(r'\backslash', r'\\')
- else:
- # Do the LyX text --> LaTeX conversion
- for rep in 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;
-
- # end of curline loop
+ content = lyx2latex(document, document.body[i:j])
# escape quotes
content = content.replace('"', r'\"')
document.body[i:j] = ["\\begin_inset CommandInset index", "LatexCommand index",
if j == -1:
# should not happen
document.warning("Malformed LyX document: Could not find end of Info inset.")
+ i += 1
+ continue
type = 'unknown'
arg = ''
for k in range(i, j+1):
if document.body[k].startswith("arg"):
- arg = document.body[k][3:].strip().strip('"')
+ arg = document.body[k][3:].strip()
+ # remove embracing quotation marks
+ if arg[0] == '"':
+ arg = arg[1:]
+ if arg[len(arg) - 1] == '"':
+ arg = arg[:len(arg) - 1]
+ # \" to straight quote
+ 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.
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", "",
"\\end_layout",
""]
document.body[i:k] = newstuff
- i = k
+ i = i + len(newstuff)
def convert_ams_classes(document):
tc = document.textclass
return
m = r.match(document.body[i])
if m == None:
- document.warning("Weirdly formed \\begin_layout at line %d of body!" % i)
+ # This is an empty layout
+ # document.warning("Weirdly formed \\begin_layout at line %d of body!" % i)
i += 1
continue
m = m.group(1)
if i == -1:
return
nextline = i + 1
- if r0.match(document.body[nextline]):
- previewline = document.body[nextline]
- nextline += 1
- else:
- previewline = ""
m = r1.match(document.body[nextline])
if m == None:
document.warning("Malformed LyX document: No LatexCommand line for `" +
continue
cmd = m.group(1)
nextline += 1
+ if r0.match(document.body[nextline]):
+ previewline = document.body[nextline]
+ nextline += 1
+ else:
+ previewline = ""
m = r2.match(document.body[nextline])
if m == None:
document.warning("Malformed LyX document: No filename line for `" + \
j = j + 1
+def convert_macro_global(document):
+ "Remove TeX code command \global when it is in front of a macro"
+ # math macros are nowadays already defined \global, so that an additional
+ # \global would make the document uncompilable, see
+ # http://www.lyx.org/trac/ticket/5371
+ # We're looking for something like this:
+ # \begin_inset ERT
+ # status collapsed
+ #
+ # \begin_layout Plain Layout
+ #
+ #
+ # \backslash
+ # global
+ # \end_layout
+ #
+ # \end_inset
+ #
+ #
+ # \begin_inset FormulaMacro
+ # \renewcommand{\foo}{123}
+ # \end_inset
+ i = 0
+ while True:
+ i = find_token(document.body, "\\begin_inset FormulaMacro", i)
+ if i == -1:
+ return
+ # if i <= 13, then there isn't enough room for the ERT
+ if i <= 12:
+ i += 1
+ continue
+ if document.body[i-6] == "global":
+ del document.body[i-13 : i]
+ i = i - 12
+ else:
+ i += 1
+
+
def revert_macro_optional_params(document):
"Convert macro definitions with optional parameters into ERTs"
# Stub to convert macro definitions with one or more optional parameters
'position "t"',
'hor_pos "c"',
'has_inner_box 0',
- 'inner_pos "t"',
+ 'inner_pos "t"',
'use_parbox 0',
'width "100col%"',
'special "none"',
return
newmodlist = []
for mod in modlist:
- if modulemap.has_key(mod):
+ if mod in modulemap:
newmodlist.append(modulemap[mod])
else:
document.warning("Can't find module %s in the module map!" % mod)
return
newmodlist = []
for mod in modlist:
- if modulemap.has_key(mod):
+ if mod in modulemap:
newmodlist.append(modulemap[mod])
else:
document.warning("Can't find module %s in the module map!" % mod)
if j == -1:
# should not happen
document.warning("Malformed LyX document: Could not find end of Box inset.")
+ i += 1
+ continue
k = find_token(document.body, "status", i + 1, j)
if k == -1:
document.warning("Malformed LyX document: Missing `status' tag in Box inset.")
- return
+ i = j
+ continue
status = document.body[k]
l = find_default_layout(document, i + 1, j)
if l == -1:
document.warning("Malformed LyX document: Missing `\\begin_layout' in Box inset.")
- return
+ i = j
+ continue
m = find_token(document.body, "\\end_layout", i + 1, j)
if m == -1:
document.warning("Malformed LyX document: Missing `\\end_layout' in Box inset.")
- return
+ i = j
+ continue
ibox = find_token(document.body, "has_inner_box 1", i + 1, k)
pbox = find_token(document.body, "use_parbox 1", i + 1, k)
if ibox == -1 and pbox == -1:
def revert_slash(document):
'Revert \\SpecialChar \\slash{} to ERT'
- r = re.compile(r'\\SpecialChar \\slash{}')
i = 0
while i < len(document.body):
- m = r.match(document.body[i])
+ m = re.match(r'(.*)\\SpecialChar \\slash{}(.*)', document.body[i])
if m:
- subst = ['\\begin_inset ERT',
- 'status collapsed', '',
- '\\begin_layout Standard',
- '', '', '\\backslash',
- 'slash{}',
- '\\end_layout', '',
- '\\end_inset', '']
- document.body[i: i+1] = subst
- i = i + len(subst)
+ before = m.group(1)
+ after = m.group(2)
+ subst = [before,
+ '\\begin_inset ERT',
+ 'status collapsed', '',
+ '\\begin_layout Standard',
+ '', '', '\\backslash',
+ 'slash{}',
+ '\\end_layout', '',
+ '\\end_inset', '',
+ after]
+ document.body[i: i+1] = subst
+ i = i + len(subst)
else:
- i = i + 1
+ i = i + 1
def revert_nobreakdash(document):
'Revert \\SpecialChar \\nobreakdash- to ERT'
i = 0
while i < len(document.body):
- line = document.body[i]
- r = re.compile(r'\\SpecialChar \\nobreakdash-')
- m = r.match(line)
+ m = re.match(r'(.*)\\SpecialChar \\nobreakdash-(.*)', document.body[i])
if m:
- subst = ['\\begin_inset ERT',
+ before = m.group(1)
+ after = m.group(2)
+ subst = [before,
+ '\\begin_inset ERT',
'status collapsed', '',
'\\begin_layout Standard', '', '',
'\\backslash',
'nobreakdash-',
'\\end_layout', '',
- '\\end_inset', '']
- document.body[i:i+1] = subst
+ '\\end_inset', '',
+ after]
+ document.body[i: i+1] = subst
i = i + len(subst)
j = find_token(document.header, "\\use_amsmath", 0)
if j == -1:
document.warning("Malformed LyX document: Missing '\\use_amsmath'.")
- return
+ i += 1
+ continue
document.header[j] = "\\use_amsmath 2"
else:
i = i + 1
#Returns number of lines added/removed
def revert_nocite_key(body, start, end):
- 'key "..." -> \nocite{...}'
+ 'key "..." -> \nocite{...}'
r = re.compile(r'^key "(.*)"')
i = start
j = end
l = find_default_layout(document, i + 1, j)
if l == -1:
document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
- return
+ i = j
+ continue
subst = ['\\begin_layout Standard',
'\\begin_inset ERT',
'status collapsed', '',
- '\\begin_layout Standard', '', '',
+ '\\begin_layout Standard', '', '',
'\\backslash', '',
'end{sideways' + floattype + '}',
'\\end_layout', '', '\\end_inset']
document.body[j : j+1] = subst
addedLines = len(subst) - 1
del document.body[i+1 : l]
- addedLines -= (l-1) - (i+1)
+ addedLines -= (l-1) - (i+1)
subst = ['\\begin_inset ERT', 'status collapsed', '',
- '\\begin_layout Standard', '', '', '\\backslash',
- 'begin{sideways' + floattype + '}',
+ '\\begin_layout Standard', '', '', '\\backslash',
+ 'begin{sideways' + floattype + '}',
'\\end_layout', '', '\\end_inset', '',
'\\end_layout', '']
document.body[i : i+1] = subst
l = find_default_layout(document, i + 1, j)
if l == -1:
document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
- return
- subst = ['\\begin_layout Standard', '\\begin_inset ERT',
- 'status collapsed', '',
+ i = j
+ continue
+ subst = ['\\begin_layout Standard', '\\begin_inset ERT',
+ 'status collapsed', '',
'\\begin_layout Standard', '', '', '\\backslash',
- 'end{sideways' + floattype + '*}',
+ 'end{sideways' + floattype + '*}',
'\\end_layout', '', '\\end_inset']
document.body[j : j+1] = subst
addedLines = len(subst) - 1
" Convert subfigures to subfloats. "
i = 0
while 1:
+ addedLines = 0
i = find_token(document.body, '\\begin_inset Graphics', i)
if i == -1:
return
continue
l = find_token(document.body, '\tsubcaptionText', i, endInset)
if l == -1:
- document.warning("Malformed lyx document: Can't find subcaptionText!")
- i = endInset
- continue
- caption = document.body[l][16:].strip('"')
- del document.body[l]
+ caption = ""
+ else:
+ caption = document.body[l][16:].strip('"')
+ del document.body[l]
+ addedLines -= 1
del document.body[k]
- addedLines = -2
- subst = ['\\begin_inset Float figure', 'wide false', 'sideways false',
- 'status open', '', '\\begin_layout Plain Layout', '\\begin_inset Caption',
- '', '\\begin_layout Plain Layout'] + latex2lyx(caption) + \
- [ '\\end_layout', '', '\\end_inset', '',
+ 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, False) + \
+ [ '\\end_layout', '', '\\end_inset', '',
'\\end_layout', '', '\\begin_layout Plain Layout']
document.body[i : i] = subst
addedLines += len(subst)
k = find_token(document.body, '\\begin_inset Float ', i + 1, j)
if k == -1:
break
+ # is the subfloat aligned?
+ al = find_token(document.body, '\\align ', k - 1, j)
+ alignment_beg = ""
+ alignment_end = ""
+ if al != -1:
+ if get_value(document.body, '\\align', al) == "center":
+ alignment_beg = "\\backslash\nbegin{centering}"
+ alignment_end = "\\backslash\npar\\backslash\nend{centering}"
+ elif get_value(document.body, '\\align', al) == "left":
+ alignment_beg = "\\backslash\nbegin{raggedright}"
+ alignment_end = "\\backslash\npar\\backslash\nend{raggedright}"
+ elif get_value(document.body, '\\align', al) == "right":
+ alignment_beg = "\\backslash\nbegin{raggedleft}"
+ alignment_end = "\\backslash\npar\\backslash\nend{raggedleft}"
l = find_end_of_inset(document.body, k)
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?
if opt != -1:
optend = find_end_of_inset(document.body, opt)
if optend == -1:
- document.warning("Malformed lyx document: Missing '\\end_inset' (OptArg).")
+ document.warning("Malformed LyX document: Missing '\\end_inset' (OptArg).")
return
optc = find_default_layout(document, opt, optend)
if optc == -1:
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}\n\\end_layout\n\n\\end_inset\n\n' \
- '\\end_layout\n\n\\begin_layout Plain Layout\n'
+ 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 PlainLayout\n'
subst = subst.split('\n')
document.body[l : l+1] = subst
addedLines = len(subst) - 1
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\\backslash\n' \
+ '\\begin_layout PlainLayout\n\n' + alignment_beg + '\n\\backslash\n' \
'subfloat'
if len(shortcap) > 0:
insertion = insertion + "[" + shortcap + "]"
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
add_to_preamble(document, ['\\usepackage{subfig}\n'])
i += addedLines + 1
document.warning("Malformed LyX document: Couldn't find placement parameter of wrap float.")
i += 1
continue
- r = re.compile("placement (o|i|l|r)")
+ r = re.compile("placement (o|i|l|r|O|I|L|R)")
m = r.match(document.body[j])
if m == None:
document.warning("Malformed LyX document: Placement option isn't O|I|R|L!")
- document.body[j] = "placement " + m.group(1).lower()
+ else:
+ document.body[j] = "placement " + m.group(1).lower()
i = j
j = find_end_of_inset(document.body, i)
if j == -1:
document.warning("Malformed LyX document: Could not find end of space inset.")
+ i += 1
continue
document.body[i] = document.body[i].replace('\\begin_inset Space', '\\InsetSpace')
del document.body[j]
j = find_end_of_inset(document.body, i)
if j == -1:
document.warning("Malformed LyX document: Could not find end of space inset.")
+ i += 1
continue
del document.body[j]
subst = document.body[i].replace('\\begin_inset Space \\hspace*{\\fill}', \
j = find_end_of_inset(document.body, i)
if j == -1:
document.warning("Malformed LyX document: Could not find end of space inset.")
+ i += 1
continue
del document.body[j]
subst = document.body[i].replace('\\begin_inset Space \\leftarrowfill{}', \
j = find_end_of_inset(document.body, i)
if j == -1:
document.warning("Malformed LyX document: Could not find end of space inset.")
+ i += 1
continue
del document.body[j]
subst = document.body[i].replace('\\begin_inset Space \\rightarrowfill{}', \
j = find_end_of_inset(document.body, i)
if j == -1:
document.warning("Malformed LyX document: Could not find end of space inset.")
+ i += 1
continue
del document.body[j]
subst = document.body[i].replace('\\begin_inset Space \\upbracefill{}', \
j = find_end_of_inset(document.body, i)
if j == -1:
document.warning("Malformed LyX document: Could not find end of space inset.")
+ i += 1
continue
del document.body[j]
subst = document.body[i].replace('\\begin_inset Space \\downbracefill{}', \
j = find_end_of_inset(document.body, i)
if j == -1:
document.warning("Malformed LyX document: Could not find end of Newpage inset.")
+ i += 1
continue
del document.body[j]
document.body[i] = document.body[i].replace('\\begin_inset Newpage newpage', '\\newpage')
j = find_end_of_inset(document.body, i)
if j == -1:
document.warning("Malformed LyX document: Could not find end of Newline inset.")
+ i += 1
continue
del document.body[j]
document.body[i] = document.body[i].replace('\\begin_inset Newline newline', '\\newline')
def convert_paper_sizes(document):
' exchange size options legalpaper and executivepaper to correct order '
- # routine is needed to fix http://bugzilla.lyx.org/show_bug.cgi?id=4868
+ # routine is needed to fix http://www.lyx.org/trac/ticket/4868
i = 0
j = 0
i = find_token(document.header, "\\papersize executivepaper", 0)
def convert_plain_layout(document):
- " Convert 'PlainLayout' to 'Plain Layout'"
+ " Convert 'PlainLayout' to 'Plain Layout'"
i = 0
while True:
i = find_token(document.body, '\\begin_layout PlainLayout', i)
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)
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)
j = j + 1
+def revert_removed_modules(document):
+ i = 0
+ while True:
+ i = find_token(document.header, "\\begin_remove_modules", i)
+ if i == -1:
+ return
+ j = find_end_of(document.header, i, "\\begin_remove_modules", "\\end_remove_modules")
+ if j == -1:
+ # this should not happen
+ break
+ document.header[i : j + 1] = []
+
+
+def add_plain_layout(document):
+ i = 0
+ while True:
+ i = find_token(document.body, "\\begin_layout", i)
+ if i == -1:
+ return
+ if len(document.body[i].split()) == 1:
+ document.body[i] = "\\begin_layout Plain Layout"
+ i += 1
+
+
+def revert_tabulators(document):
+ "Revert tabulators to 4 spaces"
+ i = 0
+ while True:
+ i = find_token(document.body, "\t", i)
+ if i == -1:
+ return
+ document.body[i] = document.body[i].replace("\t", " ")
+ i += 1
+
+
+def revert_tabsize(document):
+ "Revert the tabsize parameter of listings"
+ i = 0
+ j = 0
+ while True:
+ # either it is the only parameter
+ i = find_token(document.body, 'lstparams "tabsize=4"', i)
+ if i != -1:
+ del document.body[i]
+ # or the last one
+ j = find_token(document.body, "lstparams", j)
+ if j == -1:
+ return
+ pos = document.body[j].find(",tabsize=")
+ document.body[j] = document.body[j][:pos] + '"'
+ i += 1
+ j += 1
+
+
+def revert_mongolian(document):
+ "Set language Mongolian to English"
+ i = 0
+ if document.language == "mongolian":
+ document.language = "english"
+ i = find_token(document.header, "\\language", 0)
+ if i != -1:
+ document.header[i] = "\\language english"
+ j = 0
+ while True:
+ j = find_token(document.body, "\\lang mongolian", j)
+ if j == -1:
+ return
+ document.body[j] = document.body[j].replace("\\lang mongolian", "\\lang english")
+ j = j + 1
+
+
+def revert_default_options(document):
+ ' Remove param use_default_options '
+ i = find_token(document.header, "\\use_default_options", 0)
+ if i != -1:
+ del document.header[i]
+
+
+def convert_default_options(document):
+ ' Add param use_default_options and set it to false '
+ i = find_token(document.header, "\\textclass", 0)
+ if i == -1:
+ document.warning("Malformed LyX document: Missing `\\textclass'.")
+ return
+ document.header.insert(i, '\\use_default_options false')
+
+
+def revert_backref_options(document):
+ ' Revert option pdf_backref=page to pagebackref '
+ i = find_token(document.header, "\\pdf_backref page", 0)
+ if i != -1:
+ document.header[i] = "\\pdf_pagebackref true"
+
+
+def convert_backref_options(document):
+ ' We have changed the option pagebackref to backref=true '
+ i = find_token(document.header, "\\pdf_pagebackref true", 0)
+ if i != -1:
+ document.header[i] = "\\pdf_backref page"
+ j = find_token(document.header, "\\pdf_pagebackref false", 0)
+ if j != -1:
+ del document.header[j]
+ # backref=true was not a valid option, we meant backref=section
+ k = find_token(document.header, "\\pdf_backref true", 0)
+ if k != -1 and i != -1:
+ del document.header[k]
+ elif k != -1 and j != -1:
+ document.header[k] = "\\pdf_backref section"
+
+
+def convert_charstyle_element(document):
+ "Convert CharStyle to Element for docbook backend"
+ if document.backend != "docbook":
+ return
+ i = 0
+ while True:
+ i = find_token(document.body, "\\begin_inset Flex CharStyle:", i)
+ if i == -1:
+ return
+ document.body[i] = document.body[i].replace('\\begin_inset Flex CharStyle:',
+ '\\begin_inset Flex Element:')
+
+def revert_charstyle_element(document):
+ "Convert Element to CharStyle for docbook backend"
+ if document.backend != "docbook":
+ return
+ i = 0
+ while True:
+ i = find_token(document.body, "\\begin_inset Flex Element:", i)
+ if i == -1:
+ return
+ document.body[i] = document.body[i].replace('\\begin_inset Flex Element:',
+ '\\begin_inset Flex CharStyle:')
+
##
# Conversion hub
#
[295, [convert_htmlurl, convert_url]],
[296, [convert_include]],
[297, [convert_usorbian]],
- [298, []],
+ [298, [convert_macro_global]],
[299, []],
[300, []],
[301, []],
[336, []],
[337, [convert_display_enum]],
[338, []],
+ [339, []],
+ [340, [add_plain_layout]],
+ [341, []],
+ [342, []],
+ [343, [convert_default_options]],
+ [344, [convert_backref_options]],
+ [345, [convert_charstyle_element]]
]
-revert = [[337, [revert_polytonicgreek]],
+revert = [[344, [revert_charstyle_element]],
+ [343, [revert_backref_options]],
+ [342, [revert_default_options]],
+ [341, [revert_mongolian]],
+ [340, [revert_tabulators, revert_tabsize]],
+ [339, []],
+ [338, [revert_removed_modules]],
+ [337, [revert_polytonicgreek]],
[336, [revert_display_enum]],
[335, [remove_fontsCJK]],
[334, [revert_InsetSpace]],