lyx_mirror/lib/lyx2lyx/lyx_2_0.py
Uwe Stöhr d5099c8605 - introduce option to suppress the LaTeX package mhchem, fileformat change
The fileformat change is also needed because of our mistake that we load mhchem since LyX 1.6.4 automatically so that files created with LyX 1.6.4 won't compile under LyX 1.6.3. Now at least all files created or opened with LyX 1.7 can be reverted to the fileformat of LyX 1.6.x and can therefore be read by all LyX 1.6.x versions.

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@31941 a592a061-630c-0410-9148-cb99ea01b6c8
2009-11-11 01:48:07 +00:00

1136 lines
40 KiB
Python

# This file is part of lyx2lyx
# -*- coding: utf-8 -*-
# Copyright (C) 2008 José Matos <jamatos@lyx.org>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# 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.
""" Convert files to the file format generated by lyx 2.0"""
import re, string
import unicodedata
import sys, os
from parser_tools import find_token, find_end_of, find_tokens, get_value, get_value_string
####################################################################
# Private helper functions
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")
def add_to_preamble(document, text):
""" Add text to the preamble if it is not already there.
Only the first line is checked!"""
if find_token(document.preamble, text[0], 0) != -1:
return
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)
def read_unicodesymbols():
" Read the unicodesymbols list of unicode characters and corresponding commands."
pathname = os.path.abspath(os.path.dirname(sys.argv[0]))
fp = open(os.path.join(pathname.strip('lyx2lyx'), 'unicodesymbols'))
spec_chars = []
# 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 or even \" u.
r = re.compile(r'\\\\(\W)\{(\w)\}')
for line in fp.readlines():
if line[0] != '#' and line.strip() != "":
line=line.replace(' "',' ') # remove all quotation marks with spaces before
line=line.replace('" ',' ') # remove all quotation marks with spaces after
line=line.replace(r'\"','"') # replace \" by " (for characters with diaeresis)
try:
[ucs4,command,dead] = line.split(None,2)
if command[0:1] != "\\":
continue
spec_chars.append([command, unichr(eval(ucs4))])
except:
continue
m = r.match(command)
if m != None:
command = "\\\\"
# If the character is a double-quote, then we need to escape it, too,
# 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
unicode_reps = read_unicodesymbols()
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 Plain Layout\n" \
+ string + "\n\\end_layout\n\\end_inset"
return string
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
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
return content
def latex_length(string):
'Convert lengths to their LaTeX representation.'
i = 0
percent = False
# the string has the form
# ValueUnit+ValueUnit-ValueUnit or
# ValueUnit+-ValueUnit
# the + and - (glue lengths) are optional
# the + always precedes the -
# Convert relative lengths to LaTeX units
units = {"text%":"\\textwidth", "col%":"\\columnwidth",
"page%":"\\pagewidth", "line%":"\\linewidth",
"theight%":"\\textheight", "pheight%":"\\pageheight"}
for unit in units.keys():
i = string.find(unit)
if i != -1:
percent = True
minus = string.rfind("-", 1, i)
plus = string.rfind("+", 0, i)
latex_unit = units[unit]
if plus == -1 and minus == -1:
value = string[:i]
value = str(float(value)/100)
end = string[i + len(unit):]
string = value + latex_unit + end
if plus > minus:
value = string[plus+1:i]
value = str(float(value)/100)
begin = string[:plus+1]
end = string[i+len(unit):]
string = begin + value + latex_unit + end
if plus < minus:
value = string[minus+1:i]
value = str(float(value)/100)
begin = string[:minus+1]
string = begin + value + latex_unit
# replace + and -, but only if the - is not the first character
string = string[0] + string[1:].replace("+", " plus ").replace("-", " minus ")
# handle the case where "+-1mm" was used, because LaTeX only understands
# "plus 1mm minus 1mm"
if string.find("plus minus"):
lastvaluepos = string.rfind(" ")
lastvalue = string[lastvaluepos:]
string = string.replace(" ", lastvalue + " ")
if percent == False:
return "False," + string
else:
return "True," + string
####################################################################
def revert_swiss(document):
" Set language german-ch to ngerman "
i = 0
if document.language == "german-ch":
document.language = "ngerman"
i = find_token(document.header, "\\language", 0)
if i != -1:
document.header[i] = "\\language ngerman"
j = 0
while True:
j = find_token(document.body, "\\lang german-ch", j)
if j == -1:
return
document.body[j] = document.body[j].replace("\\lang german-ch", "\\lang ngerman")
j = j + 1
def revert_tabularvalign(document):
" Revert the tabular valign option "
i = 0
while True:
i = find_token(document.body, "\\begin_inset Tabular", i)
if i == -1:
return
j = find_end_of_inset(document.body, i)
if j == -1:
document.warning("Malformed LyX document: Could not find end of tabular.")
i = j
continue
# don't set a box for longtables, only delete tabularvalignment
# the alignment is 2 lines below \\begin_inset Tabular
p = document.body[i+2].find("islongtable")
if p > -1:
q = document.body[i+2].find("tabularvalignment")
if q > -1:
document.body[i+2] = document.body[i+2][:q-1]
document.body[i+2] = document.body[i+2] + '>'
i = i + 1
# when no longtable
if p == -1:
tabularvalignment = 'c'
# which valignment is specified?
m = document.body[i+2].find('tabularvalignment="top"')
if m > -1:
tabularvalignment = 't'
m = document.body[i+2].find('tabularvalignment="bottom"')
if m > -1:
tabularvalignment = 'b'
# delete tabularvalignment
q = document.body[i+2].find("tabularvalignment")
if q > -1:
document.body[i+2] = document.body[i+2][:q-1]
document.body[i+2] = document.body[i+2] + '>'
# don't add a box when centered
if tabularvalignment == 'c':
i = j
continue
subst = ['\\end_layout', '\\end_inset']
document.body[j+1:j+1] = subst # just inserts those lines
subst = ['\\begin_inset Box Frameless',
'position "' + tabularvalignment +'"',
'hor_pos "c"',
'has_inner_box 1',
'inner_pos "c"',
'use_parbox 0',
# we don't know the width, assume 50%
'width "50col%"',
'special "none"',
'height "1in"',
'height_special "totalheight"',
'status open',
'',
'\\begin_layout Plain Layout']
document.body[i:i] = subst # this just inserts the array at i
i += len(subst) + 2 # adjust i to save a few cycles
def revert_phantom(document):
" Reverts phantom to ERT "
i = 0
j = 0
while True:
i = find_token(document.body, "\\begin_inset Phantom Phantom", i)
if i == -1:
return
substi = document.body[i].replace('\\begin_inset Phantom Phantom', \
'\\begin_inset ERT\nstatus collapsed\n\n' \
'\\begin_layout Plain Layout\n\n\n\\backslash\n' \
'phantom{\n\\end_layout\n\n\\end_inset\n')
substi = substi.split('\n')
document.body[i : i+4] = substi
i += len(substi)
j = find_token(document.body, "\\end_layout", i)
if j == -1:
document.warning("Malformed LyX document: Could not find end of Phantom inset.")
return
substj = document.body[j].replace('\\end_layout', \
'\\size default\n\n\\begin_inset ERT\nstatus collapsed\n\n' \
'\\begin_layout Plain Layout\n\n' \
'}\n\\end_layout\n\n\\end_inset\n')
substj = substj.split('\n')
document.body[j : j+4] = substj
i += len(substj)
def revert_hphantom(document):
" Reverts hphantom to ERT "
i = 0
j = 0
while True:
i = find_token(document.body, "\\begin_inset Phantom HPhantom", i)
if i == -1:
return
substi = document.body[i].replace('\\begin_inset Phantom HPhantom', \
'\\begin_inset ERT\nstatus collapsed\n\n' \
'\\begin_layout Plain Layout\n\n\n\\backslash\n' \
'hphantom{\n\\end_layout\n\n\\end_inset\n')
substi = substi.split('\n')
document.body[i : i+4] = substi
i += len(substi)
j = find_token(document.body, "\\end_layout", i)
if j == -1:
document.warning("Malformed LyX document: Could not find end of HPhantom inset.")
return
substj = document.body[j].replace('\\end_layout', \
'\\size default\n\n\\begin_inset ERT\nstatus collapsed\n\n' \
'\\begin_layout Plain Layout\n\n' \
'}\n\\end_layout\n\n\\end_inset\n')
substj = substj.split('\n')
document.body[j : j+4] = substj
i += len(substj)
def revert_vphantom(document):
" Reverts vphantom to ERT "
i = 0
j = 0
while True:
i = find_token(document.body, "\\begin_inset Phantom VPhantom", i)
if i == -1:
return
substi = document.body[i].replace('\\begin_inset Phantom VPhantom', \
'\\begin_inset ERT\nstatus collapsed\n\n' \
'\\begin_layout Plain Layout\n\n\n\\backslash\n' \
'vphantom{\n\\end_layout\n\n\\end_inset\n')
substi = substi.split('\n')
document.body[i : i+4] = substi
i += len(substi)
j = find_token(document.body, "\\end_layout", i)
if j == -1:
document.warning("Malformed LyX document: Could not find end of VPhantom inset.")
return
substj = document.body[j].replace('\\end_layout', \
'\\size default\n\n\\begin_inset ERT\nstatus collapsed\n\n' \
'\\begin_layout Plain Layout\n\n' \
'}\n\\end_layout\n\n\\end_inset\n')
substj = substj.split('\n')
document.body[j : j+4] = substj
i += len(substj)
def revert_xetex(document):
" Reverts documents that use XeTeX "
i = find_token(document.header, '\\use_xetex', 0)
if i == -1:
document.warning("Malformed LyX document: Missing \\use_xetex.")
return
if get_value(document.header, "\\use_xetex", i) == 'false':
del document.header[i]
return
del document.header[i]
# 1.) set doc encoding to utf8-plain
i = find_token(document.header, "\\inputencoding", 0)
if i == -1:
document.warning("Malformed LyX document: Missing \\inputencoding.")
document.header[i] = "\\inputencoding utf8-plain"
# 2.) check font settings
l = find_token(document.header, "\\font_roman", 0)
if l == -1:
document.warning("Malformed LyX document: Missing \\font_roman.")
line = document.header[l]
l = re.compile(r'\\font_roman (.*)$')
m = l.match(line)
roman = m.group(1)
l = find_token(document.header, "\\font_sans", 0)
if l == -1:
document.warning("Malformed LyX document: Missing \\font_sans.")
line = document.header[l]
l = re.compile(r'\\font_sans (.*)$')
m = l.match(line)
sans = m.group(1)
l = find_token(document.header, "\\font_typewriter", 0)
if l == -1:
document.warning("Malformed LyX document: Missing \\font_typewriter.")
line = document.header[l]
l = re.compile(r'\\font_typewriter (.*)$')
m = l.match(line)
typewriter = m.group(1)
osf = get_value(document.header, '\\font_osf', 0) == "true"
sf_scale = float(get_value(document.header, '\\font_sf_scale', 0))
tt_scale = float(get_value(document.header, '\\font_tt_scale', 0))
# 3.) set preamble stuff
pretext = '%% This document must be processed with xelatex!\n'
pretext += '\\usepackage{fontspec}\n'
if roman != "default":
pretext += '\\setmainfont[Mapping=tex-text]{' + roman + '}\n'
if sans != "default":
pretext += '\\setsansfont['
if sf_scale != 100:
pretext += 'Scale=' + str(sf_scale / 100) + ','
pretext += 'Mapping=tex-text]{' + sans + '}\n'
if typewriter != "default":
pretext += '\\setmonofont'
if tt_scale != 100:
pretext += '[Scale=' + str(tt_scale / 100) + ']'
pretext += '{' + typewriter + '}\n'
if osf:
pretext += '\\defaultfontfeatures{Numbers=OldStyle}\n'
pretext += '\usepackage{xunicode}\n'
pretext += '\usepackage{xltxtra}\n'
insert_to_preamble(0, document, pretext)
# 4.) reset font settings
i = find_token(document.header, "\\font_roman", 0)
if i == -1:
document.warning("Malformed LyX document: Missing \\font_roman.")
document.header[i] = "\\font_roman default"
i = find_token(document.header, "\\font_sans", 0)
if i == -1:
document.warning("Malformed LyX document: Missing \\font_sans.")
document.header[i] = "\\font_sans default"
i = find_token(document.header, "\\font_typewriter", 0)
if i == -1:
document.warning("Malformed LyX document: Missing \\font_typewriter.")
document.header[i] = "\\font_typewriter default"
i = find_token(document.header, "\\font_osf", 0)
if i == -1:
document.warning("Malformed LyX document: Missing \\font_osf.")
document.header[i] = "\\font_osf false"
i = find_token(document.header, "\\font_sc", 0)
if i == -1:
document.warning("Malformed LyX document: Missing \\font_sc.")
document.header[i] = "\\font_sc false"
i = find_token(document.header, "\\font_sf_scale", 0)
if i == -1:
document.warning("Malformed LyX document: Missing \\font_sf_scale.")
document.header[i] = "\\font_sf_scale 100"
i = find_token(document.header, "\\font_tt_scale", 0)
if i == -1:
document.warning("Malformed LyX document: Missing \\font_tt_scale.")
document.header[i] = "\\font_tt_scale 100"
def revert_outputformat(document):
" Remove default output format param "
i = find_token(document.header, '\\default_output_format', 0)
if i == -1:
document.warning("Malformed LyX document: Missing \\default_output_format.")
return
del document.header[i]
def revert_backgroundcolor(document):
" Reverts background color to preamble code "
i = 0
colorcode = ""
while True:
i = find_token(document.header, "\\backgroundcolor", i)
if i == -1:
return
colorcode = get_value(document.header, '\\backgroundcolor', 0)
del document.header[i]
# don't clutter the preamble if backgroundcolor is not set
if colorcode == "#ffffff":
continue
# the color code is in the form #rrggbb where every character denotes a hex number
# convert the string to an int
red = string.atoi(colorcode[1:3],16)
# we want the output "0.5" for the value "127" therefore add here
if red != 0:
red = red + 1
redout = float(red) / 256
green = string.atoi(colorcode[3:5],16)
if green != 0:
green = green + 1
greenout = float(green) / 256
blue = string.atoi(colorcode[5:7],16)
if blue != 0:
blue = blue + 1
blueout = float(blue) / 256
# write the preamble
insert_to_preamble(0, document,
'% Commands inserted by lyx2lyx to set the background color\n'
+ '\\@ifundefined{definecolor}{\\usepackage{color}}{}\n'
+ '\\definecolor{page_backgroundcolor}{rgb}{'
+ str(redout) + ', ' + str(greenout)
+ ', ' + str(blueout) + '}\n'
+ '\\pagecolor{page_backgroundcolor}\n')
def revert_splitindex(document):
" Reverts splitindex-aware documents "
i = find_token(document.header, '\\use_indices', 0)
if i == -1:
document.warning("Malformed LyX document: Missing \\use_indices.")
return
indices = get_value(document.header, "\\use_indices", i)
preamble = ""
if indices == "true":
preamble += "\\usepackage{splitidx}\n"
del document.header[i]
i = 0
while True:
i = find_token(document.header, "\\index", i)
if i == -1:
break
k = find_token(document.header, "\\end_index", i)
if k == -1:
document.warning("Malformed LyX document: Missing \\end_index.")
return
line = document.header[i]
l = re.compile(r'\\index (.*)$')
m = l.match(line)
iname = m.group(1)
ishortcut = get_value(document.header, '\\shortcut', i, k)
if ishortcut != "" and indices == "true":
preamble += "\\newindex[" + iname + "]{" + ishortcut + "}\n"
del document.header[i:k+1]
i = 0
if preamble != "":
insert_to_preamble(0, document, preamble)
i = 0
while True:
i = find_token(document.body, "\\begin_inset Index", i)
if i == -1:
break
line = document.body[i]
l = re.compile(r'\\begin_inset Index (.*)$')
m = l.match(line)
itype = m.group(1)
if itype == "idx" or indices == "false":
document.body[i] = "\\begin_inset Index"
else:
k = find_end_of_inset(document.body, i)
if k == -1:
return
content = lyx2latex(document, document.body[i:k])
# escape quotes
content = content.replace('"', r'\"')
subst = [put_cmd_in_ert("\\sindex[" + itype + "]{" + content + "}")]
document.body[i:k+1] = subst
i = i + 1
i = 0
while True:
i = find_token(document.body, "\\begin_inset CommandInset index_print", i)
if i == -1:
return
k = find_end_of_inset(document.body, i)
ptype = get_value(document.body, 'type', i, k).strip('"')
if ptype == "idx":
j = find_token(document.body, "type", i, k)
del document.body[j]
elif indices == "false":
del document.body[i:k+1]
else:
subst = [put_cmd_in_ert("\\printindex[" + ptype + "]{}")]
document.body[i:k+1] = subst
i = i + 1
def convert_splitindex(document):
" Converts index and printindex insets to splitindex-aware format "
i = 0
while True:
i = find_token(document.body, "\\begin_inset Index", i)
if i == -1:
break
document.body[i] = document.body[i].replace("\\begin_inset Index",
"\\begin_inset Index idx")
i = i + 1
i = 0
while True:
i = find_token(document.body, "\\begin_inset CommandInset index_print", i)
if i == -1:
return
if document.body[i + 1].find('LatexCommand printindex') == -1:
document.warning("Malformed LyX document: Incomplete printindex inset.")
return
subst = ["LatexCommand printindex",
"type \"idx\""]
document.body[i + 1:i + 2] = subst
i = i + 1
def revert_subindex(document):
" Reverts \\printsubindex CommandInset types "
i = find_token(document.header, '\\use_indices', 0)
if i == -1:
document.warning("Malformed LyX document: Missing \\use_indices.")
return
indices = get_value(document.header, "\\use_indices", i)
i = 0
while True:
i = find_token(document.body, "\\begin_inset CommandInset index_print", i)
if i == -1:
return
k = find_end_of_inset(document.body, i)
ctype = get_value(document.body, 'LatexCommand', i, k)
if ctype != "printsubindex":
i = i + 1
continue
ptype = get_value(document.body, 'type', i, k).strip('"')
if indices == "false":
del document.body[i:k+1]
else:
subst = [put_cmd_in_ert("\\printsubindex[" + ptype + "]{}")]
document.body[i:k+1] = subst
i = i + 1
def revert_printindexall(document):
" Reverts \\print[sub]index* CommandInset types "
i = find_token(document.header, '\\use_indices', 0)
if i == -1:
document.warning("Malformed LyX document: Missing \\use_indices.")
return
indices = get_value(document.header, "\\use_indices", i)
i = 0
while True:
i = find_token(document.body, "\\begin_inset CommandInset index_print", i)
if i == -1:
return
k = find_end_of_inset(document.body, i)
ctype = get_value(document.body, 'LatexCommand', i, k)
if ctype != "printindex*" and ctype != "printsubindex*":
i = i + 1
continue
if indices == "false":
del document.body[i:k+1]
else:
subst = [put_cmd_in_ert("\\" + ctype + "{}")]
document.body[i:k+1] = subst
i = i + 1
def revert_strikeout(document):
" Reverts \\strikeout character style "
while True:
i = find_token(document.body, '\\strikeout', 0)
if i == -1:
return
del document.body[i]
def revert_uulinewave(document):
" Reverts \\uuline, and \\uwave character styles "
while True:
i = find_token(document.body, '\\uuline', 0)
if i == -1:
break
del document.body[i]
while True:
i = find_token(document.body, '\\uwave', 0)
if i == -1:
return
del document.body[i]
def revert_ulinelatex(document):
" Reverts \\uline character style "
i = find_token(document.body, '\\bar under', 0)
if i == -1:
return
insert_to_preamble(0, document,
'% Commands inserted by lyx2lyx for proper underlining\n'
+ '\\PassOptionsToPackage{normalem}{ulem}\n'
+ '\\usepackage{ulem}\n'
+ '\\let\\cite@rig\\cite\n'
+ '\\newcommand{\\b@xcite}[2][\\%]{\\def\\def@pt{\\%}\\def\\pas@pt{#1}\n'
+ ' \\mbox{\\ifx\\def@pt\\pas@pt\\cite@rig{#2}\\else\\cite@rig[#1]{#2}\\fi}}\n'
+ '\\renewcommand{\\underbar}[1]{{\\let\\cite\\b@xcite\\uline{#1}}}\n')
def revert_custom_processors(document):
" Remove bibtex_command and index_command params "
i = find_token(document.header, '\\bibtex_command', 0)
if i == -1:
document.warning("Malformed LyX document: Missing \\bibtex_command.")
return
del document.header[i]
i = find_token(document.header, '\\index_command', 0)
if i == -1:
document.warning("Malformed LyX document: Missing \\index_command.")
return
del document.header[i]
def convert_nomencl_width(document):
" Add set_width param to nomencl_print "
i = 0
while True:
i = find_token(document.body, "\\begin_inset CommandInset nomencl_print", i)
if i == -1:
break
document.body.insert(i + 2, "set_width \"none\"")
i = i + 1
def revert_nomencl_width(document):
" Remove set_width param from nomencl_print "
i = 0
while True:
i = find_token(document.body, "\\begin_inset CommandInset nomencl_print", i)
if i == -1:
break
j = find_end_of_inset(document.body, i)
l = find_token(document.body, "set_width", i, j)
if l == -1:
document.warning("Can't find set_width option for nomencl_print!")
i = j
continue
del document.body[l]
i = i + 1
def revert_nomencl_cwidth(document):
" Remove width param from nomencl_print "
i = 0
while True:
i = find_token(document.body, "\\begin_inset CommandInset nomencl_print", i)
if i == -1:
break
j = find_end_of_inset(document.body, i)
l = find_token(document.body, "width", i, j)
if l == -1:
document.warning("Can't find width option for nomencl_print!")
i = j
continue
width = get_value(document.body, "width", i, j).strip('"')
del document.body[l]
add_to_preamble(document, ["\\setlength{\\nomlabelwidth}{" + width + "}"])
i = i + 1
def revert_applemac(document):
" Revert applemac encoding to auto "
i = 0
if document.encoding == "applemac":
document.encoding = "auto"
i = find_token(document.header, "\\encoding", 0)
if i != -1:
document.header[i] = "\\encoding auto"
def revert_longtable_align(document):
" Remove longtable alignment setting "
i = 0
j = 0
while True:
i = find_token(document.body, "\\begin_inset Tabular", i)
if i == -1:
break
# the alignment is 2 lines below \\begin_inset Tabular
j = document.body[i+2].find("longtabularalignment")
if j == -1:
break
document.body[i+2] = document.body[i+2][:j-1]
document.body[i+2] = document.body[i+2] + '>'
i = i + 1
def revert_branch_filename(document):
" Remove \\filename_suffix parameter from branches "
i = 0
while True:
i = find_token(document.header, "\\filename_suffix", i)
if i == -1:
return
del document.header[i]
def revert_paragraph_indentation(document):
" Revert custom paragraph indentation to preamble code "
i = 0
while True:
i = find_token(document.header, "\\paragraph_indentation", i)
if i == -1:
break
# only remove the preamble line if default
# otherwise also write the value to the preamble
length = get_value(document.header, "\\paragraph_indentation", i)
if length == "default":
del document.header[i]
break
else:
# handle percent lengths
# latex_length returns "bool,length"
length = latex_length(length).split(",")[1]
add_to_preamble(document, ["% this command was inserted by lyx2lyx"])
add_to_preamble(document, ["\\setlength{\\parindent}{" + length + "}"])
del document.header[i]
i = i + 1
def revert_percent_skip_lengths(document):
" Revert relative lengths for paragraph skip separation to preamble code "
i = 0
while True:
i = find_token(document.header, "\\defskip", i)
if i == -1:
break
length = get_value(document.header, "\\defskip", i)
# only revert when a custom length was set and when
# it used a percent length
if length not in ('smallskip', 'medskip', 'bigskip'):
# handle percent lengths
length = latex_length(length)
# latex_length returns "bool,length"
percent = length.split(",")[0]
length = length.split(",")[1]
if percent == "True":
add_to_preamble(document, ["% this command was inserted by lyx2lyx"])
add_to_preamble(document, ["\\setlength{\\parskip}{" + length + "}"])
# set defskip to medskip as default
document.header[i] = "\\defskip medskip"
i = i + 1
def revert_percent_vspace_lengths(document):
" Revert relative VSpace lengths to ERT "
i = 0
while True:
i = find_token(document.body, "\\begin_inset VSpace", i)
if i == -1:
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)
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 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 = [put_cmd_in_ert("\\vspace*{" + length + "}")]
else:
subst = [put_cmd_in_ert("\\vspace{" + length + "}")]
document.body[i:i+2] = subst
i = i + 1
def revert_percent_hspace_lengths(document):
" Revert relative HSpace lengths to ERT "
i = 0
while True:
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)
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]
# revert the HSpace inset to ERT
if percent == "True":
if protected:
subst = [put_cmd_in_ert("\\hspace*{" + length + "}")]
else:
subst = [put_cmd_in_ert("\\hspace{" + length + "}")]
document.body[i:i+3] = subst
i = i + 2
def revert_hspace_glue_lengths(document):
" Revert HSpace glue lengths to ERT "
i = 0
while True:
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)
if length == '':
document.warning("Malformed lyx document: Missing '\\length' in Space inset.")
return
# only revert if the length contains a plus or minus at pos != 0
glue = re.compile(r'.+[\+-]')
if glue.search(length):
# handle percent lengths
# latex_length returns "bool,length"
length = latex_length(length).split(",")[1]
# revert the HSpace inset to ERT
if protected:
subst = [put_cmd_in_ert("\\hspace*{" + length + "}")]
else:
subst = [put_cmd_in_ert("\\hspace{" + length + "}")]
document.body[i:i+3] = subst
i = i + 2
def convert_author_id(document):
" Add the author_id to the \\author definition and make sure 0 is not used"
i = 0
j = 1
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:
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
k = 0
while True:
k = find_token(document.body, "\\change_", k)
if k == -1:
break
change = document.body[k].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
def revert_author_id(document):
" Remove the author_id from the \\author definition "
i = 0
j = 0
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:
author_id = int(m.group(2))
idmap[author_id] = j
name = m.group(3)
email = ''
if m.lastindex == 4:
email = m.group(4)
document.header[i] = "\\author %s %s" % (name, email)
i = i + 1
j = j + 1
k = 0
while True:
k = find_token(document.body, "\\change_", k)
if k == -1:
break
change = document.body[k].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
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
def revert_mhchem(document):
"Revert mhchem loading to preamble code"
i = 0
j = 0
k = 0
i = find_token(document.header, "\\use_mhchem 1", 0)
if i != -1:
mhchem = "auto"
else:
i = find_token(document.header, "\\use_mhchem 2", 0)
if i != -1:
mhchem = "on"
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"
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]
##
# Conversion hub
#
supported_versions = ["2.0.0","2.0"]
convert = [[346, []],
[347, []],
[348, []],
[349, []],
[350, []],
[351, []],
[352, [convert_splitindex]],
[353, []],
[354, []],
[355, []],
[356, []],
[357, []],
[358, []],
[359, [convert_nomencl_width]],
[360, []],
[361, []],
[362, []],
[363, []],
[364, []],
[365, []],
[366, []],
[367, []],
[368, []],
[369, [convert_author_id]],
[370, []],
[371, []]
]
revert = [[370, [revert_mhchem]],
[369, [revert_suppress_date]],
[368, [revert_author_id]],
[367, [revert_hspace_glue_lengths]],
[366, [revert_percent_vspace_lengths, revert_percent_hspace_lengths]],
[365, [revert_percent_skip_lengths]],
[364, [revert_paragraph_indentation]],
[363, [revert_branch_filename]],
[362, [revert_longtable_align]],
[361, [revert_applemac]],
[360, []],
[359, [revert_nomencl_cwidth]],
[358, [revert_nomencl_width]],
[357, [revert_custom_processors]],
[356, [revert_ulinelatex]],
[355, [revert_uulinewave]],
[354, [revert_strikeout]],
[353, [revert_printindexall]],
[352, [revert_subindex]],
[351, [revert_splitindex]],
[350, [revert_backgroundcolor]],
[349, [revert_outputformat]],
[348, [revert_xetex]],
[347, [revert_phantom, revert_hphantom, revert_vphantom]],
[346, [revert_tabularvalign]],
[345, [revert_swiss]]
]
if __name__ == "__main__":
pass