Fix lyx2lyx math package defaults (bug #9069)

lyx2lyx sets all new math packages to off when converting from old formats.
This is correct if any command which would cause an automatic package loading
exists in the document. However, it is wrong if no command exists: This leads
to problems if later a command is added (bug #9069), which is especially
annoying for templates.
The fix consists of two parts:
1) convert_use_package() considers now the used commands like
   revert_use_package(), and uses them to decide whether to set the package to
   auto or off.
2) convert_undertilde() and revert_undertilde() use a slightly adjusted copy of
   convert_use_package() and revert_use_package(), so that the bug is also
   fixed for undertilde. We cannot use the latter functions directly, because
   of "\usepackage undertilde" vs. "\use_undertilde".
(cherry picked from commit b73a59932e)

Conflicts:
	status.21x
This commit is contained in:
Georg Baum 2014-04-27 18:09:29 +02:00 committed by Richard Heck
parent 493dab6881
commit 41dcd49980

View File

@ -253,6 +253,7 @@ def revert_visible_space(document):
document.body[i:end + 1] = subst
undertilde_commands = ["utilde"]
def convert_undertilde(document):
" Load undertilde automatically "
i = find_token(document.header, "\\use_mathdots" , 0)
@ -264,37 +265,44 @@ def convert_undertilde(document):
document.warning("Malformed LyX document: Can't find \\use_mathdots.")
return;
j = find_token(document.preamble, "\\usepackage{undertilde}", 0)
if j == -1:
document.header.insert(i + 1, "\\use_undertilde 0")
else:
document.header.insert(i + 1, "\\use_undertilde 2")
if j != -1:
# package was loaded in the preamble, convert this to header setting for round trip
document.header.insert(i + 1, "\\use_undertilde 2") # on
del document.preamble[j]
else:
j = 0
while True:
j = find_token(document.body, '\\begin_inset Formula', j)
if j == -1:
break
k = find_end_of_inset(document.body, j)
if k == -1:
document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(j))
j += 1
continue
code = "\n".join(document.body[j:k])
for c in undertilde_commands:
if code.find("\\%s" % c) != -1:
# at least one of the commands was found - need to switch package off
document.header.insert(i + 1, "\\use_undertilde 0") # off
return
j = k
# no command was found - set to auto (bug 9069)
document.header.insert(i + 1, "\\use_undertilde 1") # auto
def revert_undertilde(document):
" Load undertilde if used in the document "
undertilde = find_token(document.header, "\\use_undertilde" , 0)
if undertilde == -1:
document.warning("No \\use_undertilde line. Assuming auto.")
else:
val = get_value(document.header, "\\use_undertilde", undertilde)
del document.header[undertilde]
try:
usetilde = int(val)
except:
document.warning("Invalid \\use_undertilde value: " + val + ". Assuming auto.")
# probably usedots has not been changed, but be safe.
usetilde = 1
if usetilde == 0:
# do not load case
return
if usetilde == 2:
# force load case
regexp = re.compile(r'(\\use_undertilde)')
i = find_re(document.header, regexp, 0)
value = "1" # default is auto
if i != -1:
value = get_value(document.header, "\\use_undertilde" , i).split()[0]
del document.header[i]
if value == "2": # on
add_to_preamble(document, ["\\usepackage{undertilde}"])
return
# so we are in the auto case. we want to load undertilde if \utilde is used.
elif value == "1": # auto
i = 0
while True:
i = find_token(document.body, '\\begin_inset Formula', i)
@ -306,8 +314,9 @@ def revert_undertilde(document):
i += 1
continue
code = "\n".join(document.body[i:j])
if code.find("\\utilde") != -1:
add_to_preamble(document, ["\\@ifundefined{utilde}{\\usepackage{undertilde}}"])
for c in undertilde_commands:
if code.find("\\%s" % c) != -1:
add_to_preamble(document, ["\\usepackage{undertilde}"])
return
i = j
@ -569,17 +578,50 @@ def revert_use_packages(document):
j += 1
def convert_use_package(document, pkg):
def convert_use_package(document, pkg, commands, oldauto):
# oldauto defines how the version we are converting from behaves:
# if it is true, the old version uses the package automatically.
# if it is false, the old version never uses the package.
i = find_token(document.header, "\\use_package", 0)
if i == -1:
document.warning("Malformed LyX document: Can't find \\use_package.")
return;
j = find_token(document.preamble, "\\usepackage{" + pkg + "}", 0)
if j == -1:
document.header.insert(i + 1, "\\use_package " + pkg + " 0")
else:
document.header.insert(i + 1, "\\use_package " + pkg + " 2")
if j != -1:
# package was loaded in the preamble, convert this to header setting for round trip
document.header.insert(i + 1, "\\use_package " + pkg + " 2") # on
del document.preamble[j]
# If oldauto is true we have two options:
# We can either set the package to auto - this is correct for files in
# format 425 to 463, and may create a conflict for older files which use
# any command in commands with a different definition.
# Or we can look whether any command in commands is used, and set it to
# auto if not and to off if yes. This will not create a conflict, but will
# create uncompilable documents for files in format 425 to 463, which use
# any command in commands.
# We choose the first option since its error is less likely.
elif oldauto:
document.header.insert(i + 1, "\\use_package " + pkg + " 1") # auto
else:
j = 0
while True:
j = find_token(document.body, '\\begin_inset Formula', j)
if j == -1:
break
k = find_end_of_inset(document.body, j)
if k == -1:
document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(j))
j += 1
continue
code = "\n".join(document.body[j:k])
for c in commands:
if code.find("\\%s" % c) != -1:
# at least one of the commands was found - need to switch package off
document.header.insert(i + 1, "\\use_package " + pkg + " 0") # off
return
j = k
# no command was found - set to auto (bug 9069)
document.header.insert(i + 1, "\\use_package " + pkg + " 1") # auto
def revert_use_package(document, pkg, commands, oldauto):
@ -613,31 +655,24 @@ def revert_use_package(document, pkg, commands, oldauto):
i = j
def convert_use_mathtools(document):
"insert use_package mathtools"
convert_use_package(document, "mathtools")
def revert_use_mathtools(document):
"remove use_package mathtools"
commands = ["mathclap", "mathllap", "mathrlap", \
mathtools_commands = ["mathclap", "mathllap", "mathrlap", \
"lgathered", "rgathered", "vcentcolon", "dblcolon", \
"coloneqq", "Coloneqq", "coloneq", "Coloneq", "eqqcolon", \
"Eqqcolon", "eqcolon", "Eqcolon", "colonapprox", \
"Colonapprox", "colonsim", "Colonsim"]
revert_use_package(document, "mathtools", commands, False)
def convert_use_mathtools(document):
"insert use_package mathtools"
convert_use_package(document, "mathtools", mathtools_commands, False)
def convert_use_stmaryrd(document):
"insert use_package stmaryrd"
convert_use_package(document, "stmaryrd")
def revert_use_mathtools(document):
"remove use_package mathtools"
revert_use_package(document, "mathtools", mathtools_commands, False)
def revert_use_stmaryrd(document):
"remove use_package stmaryrd"
# commands provided by stmaryrd.sty but LyX uses other packages:
# boxdot lightning, bigtriangledown, bigtriangleup
commands = ["shortleftarrow", "shortrightarrow", "shortuparrow", \
# commands provided by stmaryrd.sty but LyX uses other packages:
# boxdot lightning, bigtriangledown, bigtriangleup
stmaryrd_commands = ["shortleftarrow", "shortrightarrow", "shortuparrow", \
"shortdownarrow", "Yup", "Ydown", "Yleft", "Yright", \
"varcurlyvee", "varcurlywedge", "minuso", "baro", \
"sslash", "bbslash", "moo", "varotimes", "varoast", \
@ -668,19 +703,25 @@ def revert_use_stmaryrd(document):
"varcopyright", "longarrownot", "Longarrownot", \
"Mapsto", "mapsfrom", "Mapsfrom" "Longmapsto", \
"longmapsfrom", "Longmapsfrom"]
revert_use_package(document, "stmaryrd", commands, False)
def convert_use_stmaryrd(document):
"insert use_package stmaryrd"
convert_use_package(document, "stmaryrd", stmaryrd_commands, False)
def revert_use_stmaryrd(document):
"remove use_package stmaryrd"
revert_use_package(document, "stmaryrd", stmaryrd_commands, False)
stackrel_commands = ["stackrel"]
def convert_use_stackrel(document):
"insert use_package stackrel"
convert_use_package(document, "stackrel")
convert_use_package(document, "stackrel", stackrel_commands, False)
def revert_use_stackrel(document):
"remove use_package stackrel"
commands = ["stackrel"]
revert_use_package(document, "stackrel", commands, False)
revert_use_package(document, "stackrel", stackrel_commands, False)
def convert_cite_engine_type(document):
@ -739,11 +780,11 @@ def revert_cite_engine_type_default(document):
document.header[i] = "\\cite_engine_type " + engine_type
cancel_commands = ["cancel", "bcancel", "xcancel", "cancelto"]
# this is the same, as revert_use_cancel() except for the default
def revert_cancel(document):
"add cancel to the preamble if necessary"
commands = ["cancelto", "cancel", "bcancel", "xcancel"]
revert_use_package(document, "cancel", commands, False)
revert_use_package(document, "cancel", cancel_commands, False)
def revert_verbatim(document):
@ -1047,13 +1088,12 @@ def revert_use_amssymb(document):
def convert_use_cancel(document):
"insert use_package cancel"
convert_use_package(document, "cancel")
convert_use_package(document, "cancel", cancel_commands, True)
def revert_use_cancel(document):
"remove use_package cancel"
commands = ["cancel", "bcancel", "xcancel", "cancelto"]
revert_use_package(document, "cancel", commands, True)
revert_use_package(document, "cancel", cancel_commands, True)
def revert_ancientgreek(document):
@ -4465,6 +4505,9 @@ convert = [
[422, [convert_use_packages]],
[423, [convert_use_mathtools]],
[424, [convert_cite_engine_type]],
# No convert_cancel, since cancel will be loaded automatically
# in format 425 without any possibility to switch it off.
# This has been fixed in format 464.
[425, []],
[426, []],
[427, []],