mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-12-01 05:25:55 +00:00
52295693d6
Please linter where it makes sense: * Avoid bare exceptions; * Use formatted strings instead of string interpolation
2853 lines
97 KiB
Python
2853 lines
97 KiB
Python
# This file is part of lyx2lyx
|
|
# Copyright (C) 2015 The LyX team
|
|
#
|
|
# 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.2"""
|
|
|
|
import os
|
|
import re
|
|
|
|
# Uncomment only what you need to import, please.
|
|
from lyx2lyx_tools import (
|
|
add_to_preamble,
|
|
convert_info_insets,
|
|
get_ert,
|
|
length_in_bp,
|
|
lyx2latex,
|
|
lyx2verbatim,
|
|
put_cmd_in_ert,
|
|
revert_language,
|
|
)
|
|
from parser_tools import (
|
|
check_token,
|
|
del_complete_lines,
|
|
find_end_of_inset,
|
|
find_end_of_layout,
|
|
find_nonempty_line,
|
|
find_re,
|
|
find_substring,
|
|
find_token,
|
|
find_token_backwards,
|
|
get_containing_inset,
|
|
get_containing_layout,
|
|
get_quoted_value,
|
|
get_value,
|
|
is_in_inset,
|
|
set_bool_value,
|
|
)
|
|
|
|
####################################################################
|
|
# Private helper functions
|
|
|
|
|
|
def revert_Argument_to_TeX_brace(document, line, endline, n, nmax, environment, opt, nolastopt):
|
|
r"""
|
|
Reverts an InsetArgument to TeX-code
|
|
usage:
|
|
revert_Argument_to_TeX_brace(document, LineOfBegin, LineOfEnd, StartArgument, EndArgument, isEnvironment, isOpt, notLastOpt)
|
|
LineOfBegin is the line of the \begin_layout or \begin_inset statement
|
|
LineOfEnd is the line of the \end_layout or \end_inset statement, if "0" is given, the end of the file is used instead
|
|
StartArgument is the number of the first argument that needs to be converted
|
|
EndArgument is the number of the last argument that needs to be converted or the last defined one
|
|
isEnvironment must be true, if the layout is for a LaTeX environment
|
|
isOpt must be true, if the argument is an optional one
|
|
notLastOpt must be true if the argument is mandatory and followed by optional ones
|
|
"""
|
|
lineArg = 0
|
|
wasOpt = False
|
|
while lineArg != -1 and n < nmax + 1:
|
|
lineArg = find_token(document.body, "\\begin_inset Argument " + str(n), line)
|
|
if lineArg > endline and endline != 0:
|
|
return wasOpt
|
|
if lineArg != -1:
|
|
beginPlain = find_token(document.body, "\\begin_layout Plain Layout", lineArg)
|
|
# we have to assure that no other inset is in the Argument
|
|
beginInset = find_token(document.body, "\\begin_inset", beginPlain)
|
|
endInset = find_token(document.body, "\\end_inset", beginPlain)
|
|
k = beginPlain + 1
|
|
l = k
|
|
while beginInset < endInset and beginInset != -1:
|
|
beginInset = find_token(document.body, "\\begin_inset", k)
|
|
endInset = find_token(document.body, "\\end_inset", l)
|
|
k = beginInset + 1
|
|
l = endInset + 1
|
|
if environment == False:
|
|
if opt == False:
|
|
document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}")
|
|
document.body[lineArg : beginPlain + 1] = put_cmd_in_ert("{")
|
|
wasOpt = False
|
|
else:
|
|
document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("]")
|
|
document.body[lineArg : beginPlain + 1] = put_cmd_in_ert("[")
|
|
wasOpt = True
|
|
else:
|
|
if opt == False:
|
|
document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("}")
|
|
document.body[lineArg : beginPlain + 1] = put_cmd_in_ert("{")
|
|
wasOpt = False
|
|
else:
|
|
document.body[endInset - 2 : endInset + 1] = put_cmd_in_ert("]")
|
|
document.body[lineArg : beginPlain + 1] = put_cmd_in_ert("[")
|
|
wasOpt = True
|
|
n += 1
|
|
return wasOpt
|
|
|
|
|
|
###############################################################################
|
|
###
|
|
### Conversion and reversion routines
|
|
###
|
|
###############################################################################
|
|
|
|
|
|
def convert_longtable_label_internal(document, forward):
|
|
"""
|
|
Convert reference to "LongTableNoNumber" into "Unnumbered" if forward is True
|
|
else revert it.
|
|
"""
|
|
old_reference = "\\begin_inset Caption LongTableNoNumber"
|
|
new_reference = "\\begin_inset Caption Unnumbered"
|
|
|
|
# if the purpose is to revert swap the strings roles
|
|
if not forward:
|
|
old_reference, new_reference = new_reference, old_reference
|
|
|
|
i = 0
|
|
while True:
|
|
i = find_token(document.body, old_reference, i)
|
|
|
|
if i == -1:
|
|
return
|
|
|
|
document.body[i] = new_reference
|
|
|
|
|
|
def convert_longtable_label(document):
|
|
convert_longtable_label_internal(document, True)
|
|
|
|
|
|
def revert_longtable_label(document):
|
|
convert_longtable_label_internal(document, False)
|
|
|
|
|
|
def convert_separator(document):
|
|
"""
|
|
Convert layout separators to separator insets and add (LaTeX) paragraph
|
|
breaks in order to mimic previous LaTeX export.
|
|
"""
|
|
|
|
parins = ["\\begin_inset Separator parbreak", "\\end_inset", ""]
|
|
parlay = [
|
|
"\\begin_layout Standard",
|
|
"\\begin_inset Separator parbreak",
|
|
"\\end_inset",
|
|
"",
|
|
"\\end_layout",
|
|
"",
|
|
]
|
|
sty_dict = {
|
|
"family": "default",
|
|
"series": "default",
|
|
"shape": "default",
|
|
"size": "default",
|
|
"bar": "default",
|
|
"color": "inherit",
|
|
}
|
|
|
|
i = 0
|
|
while True:
|
|
i = find_token(document.body, "\\begin_deeper", i)
|
|
if i == -1:
|
|
break
|
|
|
|
j = find_token_backwards(document.body, "\\end_layout", i - 1)
|
|
if j != -1:
|
|
# reset any text style before inserting the inset
|
|
lay = get_containing_layout(document.body, j - 1)
|
|
if lay != False:
|
|
content = "\n".join(document.body[lay[1] : lay[2]])
|
|
for val in list(sty_dict.keys()):
|
|
if content.find("\\%s" % val) != -1:
|
|
document.body[j:j] = [f"\\{val} {sty_dict[val]}"]
|
|
i = i + 1
|
|
j = j + 1
|
|
document.body[j:j] = parins
|
|
i = i + len(parins) + 1
|
|
else:
|
|
i = i + 1
|
|
|
|
i = 0
|
|
while True:
|
|
i = find_token(document.body, "\\align", i)
|
|
if i == -1:
|
|
break
|
|
|
|
lay = get_containing_layout(document.body, i)
|
|
if lay != False and lay[0] == "Plain Layout":
|
|
i = i + 1
|
|
continue
|
|
|
|
j = find_token_backwards(document.body, "\\end_layout", i - 1)
|
|
if j != -1:
|
|
# Very old LyX files do not have Plain Layout in insets (but Standard).
|
|
# So we additionally check here if there is no inset boundary
|
|
# between the previous layout and this one.
|
|
n = find_token(document.body, "\\end_inset", j, lay[1])
|
|
if n != -1:
|
|
i = i + 1
|
|
continue
|
|
lay = get_containing_layout(document.body, j - 1)
|
|
if (
|
|
lay != False
|
|
and lay[0] == "Standard"
|
|
and find_token(document.body, "\\align", lay[1], lay[2]) == -1
|
|
and find_token(document.body, "\\begin_inset VSpace", lay[1], lay[2]) == -1
|
|
):
|
|
# reset any text style before inserting the inset
|
|
content = "\n".join(document.body[lay[1] : lay[2]])
|
|
for val in list(sty_dict.keys()):
|
|
if content.find("\\%s" % val) != -1:
|
|
document.body[j:j] = [f"\\{val} {sty_dict[val]}"]
|
|
i = i + 1
|
|
j = j + 1
|
|
document.body[j:j] = parins
|
|
i = i + len(parins) + 1
|
|
else:
|
|
i = i + 1
|
|
else:
|
|
i = i + 1
|
|
|
|
regexp = re.compile(
|
|
r"^\\begin_layout (?:(-*)|(\s*))(Separator|EndOfSlide)(?:(-*)|(\s*))$",
|
|
re.IGNORECASE,
|
|
)
|
|
|
|
i = 0
|
|
while True:
|
|
i = find_re(document.body, regexp, i)
|
|
if i == -1:
|
|
return
|
|
|
|
j = find_end_of_layout(document.body, i)
|
|
if j == -1:
|
|
document.warning("Malformed LyX document: Missing `\\end_layout'.")
|
|
return
|
|
|
|
lay = get_containing_layout(document.body, j - 1)
|
|
if lay != False:
|
|
lines = document.body[lay[3] : lay[2]]
|
|
else:
|
|
lines = []
|
|
|
|
document.body[i : j + 1] = parlay
|
|
if len(lines) > 0:
|
|
document.body[i + 1 : i + 1] = lines
|
|
|
|
i = i + len(parlay) + len(lines) + 1
|
|
|
|
|
|
def revert_separator(document):
|
|
"Revert separator insets to layout separators"
|
|
|
|
beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
|
|
if document.textclass in beamer_classes:
|
|
beglaysep = "\\begin_layout Separator"
|
|
else:
|
|
beglaysep = "\\begin_layout --Separator--"
|
|
|
|
parsep = [beglaysep, "", "\\end_layout", ""]
|
|
comert = [
|
|
"\\begin_inset ERT",
|
|
"status collapsed",
|
|
"",
|
|
"\\begin_layout Plain Layout",
|
|
"%",
|
|
"\\end_layout",
|
|
"",
|
|
"\\end_inset",
|
|
"",
|
|
]
|
|
empert = [
|
|
"\\begin_inset ERT",
|
|
"status collapsed",
|
|
"",
|
|
"\\begin_layout Plain Layout",
|
|
" ",
|
|
"\\end_layout",
|
|
"",
|
|
"\\end_inset",
|
|
"",
|
|
]
|
|
|
|
i = 0
|
|
while True:
|
|
i = find_token(document.body, "\\begin_inset Separator", i)
|
|
if i == -1:
|
|
return
|
|
|
|
lay = get_containing_layout(document.body, i)
|
|
if lay == False:
|
|
document.warning(
|
|
"Malformed LyX document: Can't convert separator inset at line " + str(i)
|
|
)
|
|
i = i + 1
|
|
continue
|
|
|
|
layoutname = lay[0]
|
|
beg = lay[1]
|
|
end = lay[2]
|
|
kind = get_value(document.body, "\\begin_inset Separator", i, i + 1, "plain").split()[1]
|
|
before = document.body[beg + 1 : i]
|
|
something_before = len(before) > 0 and len("".join(before)) > 0
|
|
j = find_end_of_inset(document.body, i)
|
|
after = document.body[j + 1 : end]
|
|
something_after = len(after) > 0 and len("".join(after)) > 0
|
|
if kind == "plain":
|
|
beg = beg + len(before) + 1
|
|
elif something_before:
|
|
document.body[i:i] = ["\\end_layout", ""]
|
|
i = i + 2
|
|
j = j + 2
|
|
beg = i
|
|
end = end + 2
|
|
|
|
if kind == "plain":
|
|
if something_after:
|
|
document.body[beg : j + 1] = empert
|
|
i = i + len(empert)
|
|
else:
|
|
document.body[beg : j + 1] = comert
|
|
i = i + len(comert)
|
|
else:
|
|
if something_after:
|
|
if layoutname == "Standard":
|
|
if not something_before:
|
|
document.body[beg : j + 1] = parsep
|
|
i = i + len(parsep)
|
|
document.body[i:i] = ["", "\\begin_layout Standard"]
|
|
i = i + 2
|
|
else:
|
|
document.body[beg : j + 1] = ["\\begin_layout Standard"]
|
|
i = i + 1
|
|
else:
|
|
document.body[beg : j + 1] = ["\\begin_deeper"]
|
|
i = i + 1
|
|
end = end + 1 - (j + 1 - beg)
|
|
if not something_before:
|
|
document.body[i:i] = parsep
|
|
i = i + len(parsep)
|
|
end = end + len(parsep)
|
|
document.body[i:i] = ["\\begin_layout Standard"]
|
|
document.body[end + 2 : end + 2] = ["", "\\end_deeper", ""]
|
|
i = i + 4
|
|
else:
|
|
next_par_is_aligned = False
|
|
k = find_nonempty_line(document.body, end + 1)
|
|
if k != -1 and check_token(document.body[k], "\\begin_layout"):
|
|
lay = get_containing_layout(document.body, k)
|
|
next_par_is_aligned = (
|
|
lay != False
|
|
and find_token(document.body, "\\align", lay[1], lay[2]) != -1
|
|
)
|
|
if (
|
|
k != -1
|
|
and not next_par_is_aligned
|
|
and not check_token(document.body[k], "\\end_deeper")
|
|
and not check_token(document.body[k], "\\begin_deeper")
|
|
):
|
|
if layoutname == "Standard":
|
|
document.body[beg : j + 1] = [beglaysep]
|
|
i = i + 1
|
|
else:
|
|
document.body[beg : j + 1] = ["\\begin_deeper", beglaysep]
|
|
end = end + 2 - (j + 1 - beg)
|
|
document.body[end + 1 : end + 1] = ["", "\\end_deeper", ""]
|
|
i = i + 3
|
|
else:
|
|
if something_before:
|
|
del document.body[i : end + 1]
|
|
else:
|
|
del document.body[i : end - 1]
|
|
|
|
i = i + 1
|
|
|
|
|
|
def convert_parbreak(document):
|
|
"""
|
|
Convert parbreak separators not specifically used to separate
|
|
environments to latexpar separators.
|
|
"""
|
|
parbreakinset = "\\begin_inset Separator parbreak"
|
|
i = 0
|
|
while True:
|
|
i = find_token(document.body, parbreakinset, i)
|
|
if i == -1:
|
|
return
|
|
lay = get_containing_layout(document.body, i)
|
|
if lay == False:
|
|
document.warning(
|
|
"Malformed LyX document: " "Can't convert separator inset at line %d" % i
|
|
)
|
|
i += 1
|
|
continue
|
|
if lay[0] == "Standard":
|
|
# Convert only if not alone in the paragraph
|
|
k1 = find_nonempty_line(document.body, lay[1] + 1, i + 1)
|
|
k2 = find_nonempty_line(document.body, i + 1, lay[2])
|
|
if (k1 < i) or (k2 > i + 1) or not check_token(document.body[i], parbreakinset):
|
|
document.body[i] = document.body[i].replace("parbreak", "latexpar")
|
|
else:
|
|
document.body[i] = document.body[i].replace("parbreak", "latexpar")
|
|
i += 1
|
|
|
|
|
|
def revert_parbreak(document):
|
|
"""
|
|
Revert latexpar separators to parbreak separators.
|
|
"""
|
|
i = 0
|
|
while True:
|
|
i = find_token(document.body, "\\begin_inset Separator latexpar", i)
|
|
if i == -1:
|
|
return
|
|
document.body[i] = document.body[i].replace("latexpar", "parbreak")
|
|
i += 1
|
|
|
|
|
|
def revert_smash(document):
|
|
"Set amsmath to on if smash commands are used"
|
|
|
|
commands = ["smash[t]", "smash[b]", "notag"]
|
|
i = find_token(document.header, "\\use_package amsmath", 0)
|
|
if i == -1:
|
|
document.warning("Malformed LyX document: Can't find \\use_package amsmath.")
|
|
return
|
|
value = get_value(document.header, "\\use_package amsmath", i).split()[1]
|
|
if value != "1":
|
|
# nothing to do if package is not auto but on or off
|
|
return
|
|
j = 0
|
|
while True:
|
|
j = find_token(document.body, "\\begin_inset Formula", j)
|
|
if j == -1:
|
|
return
|
|
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:
|
|
# set amsmath to on, since it is loaded by the newer format
|
|
document.header[i] = "\\use_package amsmath 2"
|
|
return
|
|
j = k
|
|
|
|
|
|
def revert_swissgerman(document):
|
|
"Set language german-ch-old to german"
|
|
i = 0
|
|
if document.language == "german-ch-old":
|
|
document.language = "german"
|
|
i = find_token(document.header, "\\language", 0)
|
|
if i != -1:
|
|
document.header[i] = "\\language german"
|
|
j = 0
|
|
while True:
|
|
j = find_token(document.body, "\\lang german-ch-old", j)
|
|
if j == -1:
|
|
return
|
|
document.body[j] = document.body[j].replace("\\lang german-ch-old", "\\lang german")
|
|
j = j + 1
|
|
|
|
|
|
def revert_use_package(document, pkg, commands, oldauto, supported):
|
|
# oldauto defines how the version we are reverting to behaves:
|
|
# if it is true, the old version uses the package automatically.
|
|
# if it is false, the old version never uses the package.
|
|
# If "supported" is true, the target version also supports this
|
|
# package natively.
|
|
regexp = re.compile(r"(\\use_package\s+%s)" % pkg)
|
|
p = find_re(document.header, regexp, 0)
|
|
value = "1" # default is auto
|
|
if p != -1:
|
|
value = get_value(document.header, "\\use_package", p).split()[1]
|
|
if not supported:
|
|
del document.header[p]
|
|
if value == "2" and not supported: # on
|
|
add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
|
|
elif value == "1" and not oldauto: # auto
|
|
i = 0
|
|
while True:
|
|
i = find_token(document.body, "\\begin_inset Formula", i)
|
|
if i == -1:
|
|
return
|
|
j = find_end_of_inset(document.body, i)
|
|
if j == -1:
|
|
document.warning(
|
|
"Malformed LyX document: Can't find end of Formula inset at line " + str(i)
|
|
)
|
|
i += 1
|
|
continue
|
|
code = "\n".join(document.body[i:j])
|
|
for c in commands:
|
|
if code.find("\\%s" % c) != -1:
|
|
if supported:
|
|
document.header[p] = "\\use_package " + pkg + " 2"
|
|
else:
|
|
add_to_preamble(document, ["\\usepackage{" + pkg + "}"])
|
|
return
|
|
i = j
|
|
|
|
|
|
mathtools_commands = [
|
|
"xhookrightarrow",
|
|
"xhookleftarrow",
|
|
"xRightarrow",
|
|
"xrightharpoondown",
|
|
"xrightharpoonup",
|
|
"xrightleftharpoons",
|
|
"xLeftarrow",
|
|
"xleftharpoondown",
|
|
"xleftharpoonup",
|
|
"xleftrightarrow",
|
|
"xLeftrightarrow",
|
|
"xleftrightharpoons",
|
|
"xmapsto",
|
|
]
|
|
|
|
|
|
def revert_xarrow(document):
|
|
"remove use_package mathtools"
|
|
revert_use_package(document, "mathtools", mathtools_commands, False, True)
|
|
|
|
|
|
def revert_beamer_lemma(document):
|
|
"Reverts beamer lemma layout to ERT"
|
|
|
|
beamer_classes = ["beamer", "article-beamer", "scrarticle-beamer"]
|
|
if document.textclass not in beamer_classes:
|
|
return
|
|
|
|
consecutive = False
|
|
i = 0
|
|
while True:
|
|
i = find_token(document.body, "\\begin_layout Lemma", i)
|
|
if i == -1:
|
|
return
|
|
j = find_end_of_layout(document.body, i)
|
|
if j == -1:
|
|
document.warning("Malformed LyX document: Can't find end of Lemma layout")
|
|
i += 1
|
|
continue
|
|
arg1 = find_token(document.body, "\\begin_inset Argument 1", i, j)
|
|
endarg1 = find_end_of_inset(document.body, arg1)
|
|
arg2 = find_token(document.body, "\\begin_inset Argument 2", i, j)
|
|
endarg2 = find_end_of_inset(document.body, arg2)
|
|
subst1 = []
|
|
subst2 = []
|
|
if arg1 != -1:
|
|
beginPlain1 = find_token(
|
|
document.body, "\\begin_layout Plain Layout", arg1, endarg1
|
|
)
|
|
if beginPlain1 == -1:
|
|
document.warning("Malformed LyX document: Can't find arg1 plain Layout")
|
|
i += 1
|
|
continue
|
|
endPlain1 = find_end_of_inset(document.body, beginPlain1)
|
|
content1 = document.body[beginPlain1 + 1 : endPlain1 - 2]
|
|
subst1 = put_cmd_in_ert("<") + content1 + put_cmd_in_ert(">")
|
|
if arg2 != -1:
|
|
beginPlain2 = find_token(
|
|
document.body, "\\begin_layout Plain Layout", arg2, endarg2
|
|
)
|
|
if beginPlain2 == -1:
|
|
document.warning("Malformed LyX document: Can't find arg2 plain Layout")
|
|
i += 1
|
|
continue
|
|
endPlain2 = find_end_of_inset(document.body, beginPlain2)
|
|
content2 = document.body[beginPlain2 + 1 : endPlain2 - 2]
|
|
subst2 = put_cmd_in_ert("[") + content2 + put_cmd_in_ert("]")
|
|
|
|
# remove Arg insets
|
|
if arg1 < arg2:
|
|
del document.body[arg2 : endarg2 + 1]
|
|
if arg1 != -1:
|
|
del document.body[arg1 : endarg1 + 1]
|
|
if arg2 < arg1:
|
|
del document.body[arg1 : endarg1 + 1]
|
|
if arg2 != -1:
|
|
del document.body[arg2 : endarg2 + 1]
|
|
|
|
# index of end layout has probably changed
|
|
j = find_end_of_layout(document.body, i)
|
|
if j == -1:
|
|
document.warning("Malformed LyX document: Can't find end of Lemma layout")
|
|
i += 1
|
|
continue
|
|
|
|
begcmd = []
|
|
|
|
# if this is not a consecutive env, add start command
|
|
if not consecutive:
|
|
begcmd = put_cmd_in_ert("\\begin{lemma}")
|
|
|
|
# has this a consecutive lemma?
|
|
consecutive = document.body[j + 2] == "\\begin_layout Lemma"
|
|
|
|
# if this is not followed by a consecutive env, add end command
|
|
if not consecutive:
|
|
document.body[j : j + 1] = put_cmd_in_ert("\\end{lemma}") + ["\\end_layout"]
|
|
|
|
document.body[i : i + 1] = ["\\begin_layout Standard", ""] + begcmd + subst1 + subst2
|
|
|
|
i = j
|
|
|
|
|
|
def revert_question_env(document):
|
|
"""
|
|
Reverts question and question* environments of
|
|
theorems-ams-extended-bytype module to ERT
|
|
"""
|
|
|
|
# Do we use theorems-ams-extended-bytype module?
|
|
if "theorems-ams-extended-bytype" not in document.get_module_list():
|
|
return
|
|
|
|
consecutive = False
|
|
i = 0
|
|
while True:
|
|
i = find_token(document.body, "\\begin_layout Question", i)
|
|
if i == -1:
|
|
return
|
|
|
|
starred = document.body[i] == "\\begin_layout Question*"
|
|
|
|
j = find_end_of_layout(document.body, i)
|
|
if j == -1:
|
|
document.warning("Malformed LyX document: Can't find end of Question layout")
|
|
i += 1
|
|
continue
|
|
|
|
# if this is not a consecutive env, add start command
|
|
begcmd = []
|
|
if not consecutive:
|
|
if starred:
|
|
begcmd = put_cmd_in_ert("\\begin{question*}")
|
|
else:
|
|
begcmd = put_cmd_in_ert("\\begin{question}")
|
|
|
|
# has this a consecutive theorem of same type?
|
|
consecutive = False
|
|
if starred:
|
|
consecutive = document.body[j + 2] == "\\begin_layout Question*"
|
|
else:
|
|
consecutive = document.body[j + 2] == "\\begin_layout Question"
|
|
|
|
# if this is not followed by a consecutive env, add end command
|
|
if not consecutive:
|
|
if starred:
|
|
document.body[j : j + 1] = put_cmd_in_ert("\\end{question*}") + ["\\end_layout"]
|
|
else:
|
|
document.body[j : j + 1] = put_cmd_in_ert("\\end{question}") + ["\\end_layout"]
|
|
|
|
document.body[i : i + 1] = ["\\begin_layout Standard", ""] + begcmd
|
|
|
|
add_to_preamble(document, "\\providecommand{\\questionname}{Question}")
|
|
|
|
if starred:
|
|
add_to_preamble(
|
|
document,
|
|
"\\theoremstyle{plain}\n" "\\newtheorem*{question*}{\\protect\\questionname}",
|
|
)
|
|
else:
|
|
add_to_preamble(
|
|
document,
|
|
"\\theoremstyle{plain}\n" "\\newtheorem{question}{\\protect\\questionname}",
|
|
)
|
|
|
|
i = j
|
|
|
|
|
|
def convert_dashes(document):
|
|
"convert -- and --- to \\twohyphens and \\threehyphens"
|
|
|
|
if document.backend != "latex":
|
|
return
|
|
|
|
i = 0
|
|
while True:
|
|
i = find_substring(document.body, "--", i + 1)
|
|
if i == -1:
|
|
break
|
|
line = document.body[i]
|
|
# skip label width string (bug 10243):
|
|
if line.startswith("\\labelwidthstring"):
|
|
continue
|
|
# Do not touch hyphens in some insets:
|
|
try:
|
|
value, start, end = get_containing_inset(document.body, i)
|
|
except TypeError:
|
|
# False means no (or malformed) containing inset
|
|
value, start, end = "no inset", -1, -1
|
|
# We must not replace anything in insets that store LaTeX contents in .lyx files
|
|
# (math and command insets without overridden read() and write() methods.
|
|
# Filtering out IPA and ERT makes Text::readParToken() more simple,
|
|
# Flex Code is logical markup, typically rendered as typewriter
|
|
if value.split()[0] in [
|
|
"CommandInset",
|
|
"ERT",
|
|
"External",
|
|
"Formula",
|
|
"FormulaMacro",
|
|
"Graphics",
|
|
"IPA",
|
|
"listings",
|
|
] or value in ["Flex Code", "Flex URL"]:
|
|
i = end
|
|
continue
|
|
try:
|
|
layout, start, end, j = get_containing_layout(document.body, i)
|
|
except TypeError: # no (or malformed) containing layout
|
|
document.warning("Malformed LyX document: " "Can't find layout at line %d" % i)
|
|
continue
|
|
if layout == "LyX-Code":
|
|
i = end
|
|
continue
|
|
# We can have an arbitrary number of consecutive hyphens.
|
|
# Replace as LaTeX does: First try emdash, then endash
|
|
line = line.replace("---", "\\threehyphens\n")
|
|
line = line.replace("--", "\\twohyphens\n")
|
|
document.body[i : i + 1] = line.split("\n")
|
|
|
|
# remove ligature breaks between dashes
|
|
i = 0
|
|
while True:
|
|
i = find_substring(document.body, r"-\SpecialChar \textcompwordmark{}", i + 1)
|
|
if i == -1:
|
|
break
|
|
if document.body[i + 1].startswith("-"):
|
|
document.body[i] = document.body[i].replace(
|
|
r"\SpecialChar \textcompwordmark{}", document.body.pop(i + 1)
|
|
)
|
|
|
|
|
|
def revert_dashes(document):
|
|
"""
|
|
Remove preamble code from 2.3->2.2 conversion.
|
|
Prevent ligatures of existing --- and --.
|
|
Revert \\twohyphens and \\threehyphens to -- and ---.
|
|
"""
|
|
del_complete_lines(
|
|
document.preamble,
|
|
[
|
|
"% Added by lyx2lyx",
|
|
r"\renewcommand{\textendash}{--}",
|
|
r"\renewcommand{\textemdash}{---}",
|
|
],
|
|
)
|
|
|
|
# Insert ligature breaks to prevent ligation of hyphens to dashes:
|
|
i = 0
|
|
while True:
|
|
i = find_substring(document.body, "--", i + 1)
|
|
if i == -1:
|
|
break
|
|
line = document.body[i]
|
|
# skip label width string (bug 10243):
|
|
if line.startswith("\\labelwidthstring"):
|
|
continue
|
|
# do not touch hyphens in some insets (cf. convert_dashes):
|
|
try:
|
|
value, start, end = get_containing_inset(document.body, i)
|
|
except TypeError:
|
|
# False means no (or malformed) containing inset
|
|
value, start, end = "no inset", -1, -1
|
|
if (
|
|
value.split()[0]
|
|
in [
|
|
"CommandInset",
|
|
"ERT",
|
|
"External",
|
|
"Formula",
|
|
"FormulaMacro",
|
|
"Graphics",
|
|
"IPA",
|
|
"listings",
|
|
]
|
|
or value == "Flex URL"
|
|
):
|
|
i = end
|
|
continue
|
|
line = line.replace("--", "-\\SpecialChar \\textcompwordmark{}\n-")
|
|
document.body[i : i + 1] = line.split("\n")
|
|
|
|
# Revert \twohyphens and \threehyphens:
|
|
i = 1
|
|
while i < len(document.body):
|
|
line = document.body[i]
|
|
if not line.endswith("hyphens"):
|
|
i += 1
|
|
elif line.endswith("\\twohyphens") or line.endswith("\\threehyphens"):
|
|
line = line.replace("\\twohyphens", "--")
|
|
line = line.replace("\\threehyphens", "---")
|
|
document.body[i] = line + document.body.pop(i + 1)
|
|
else:
|
|
i += 1
|
|
|
|
|
|
# order is important for the last three!
|
|
phrases = ["LyX", "LaTeX2e", "LaTeX", "TeX"]
|
|
|
|
|
|
def is_part_of_converted_phrase(line, j, phrase):
|
|
"is phrase part of an already converted phrase?"
|
|
for p in phrases:
|
|
converted = "\\SpecialCharNoPassThru \\" + p
|
|
pos = j + len(phrase) - len(converted)
|
|
if pos >= 0:
|
|
if line[pos : pos + len(converted)] == converted:
|
|
return True
|
|
return False
|
|
|
|
|
|
def convert_phrases(document):
|
|
"convert special phrases from plain text to \\SpecialCharNoPassThru"
|
|
|
|
if document.backend != "latex":
|
|
return
|
|
|
|
i = 0
|
|
while i < len(document.body):
|
|
if document.body[i] and document.body[i][0] == "\\":
|
|
words = document.body[i].split()
|
|
if (
|
|
len(words) > 1
|
|
and words[0] == "\\begin_inset"
|
|
and words[1] in ["CommandInset", "External", "Formula", "Graphics", "listings"]
|
|
):
|
|
# must not replace anything in insets that store LaTeX contents in .lyx files
|
|
# (math and command insets without overridden read() and write() methods)
|
|
j = find_end_of_inset(document.body, i)
|
|
if j == -1:
|
|
document.warning(
|
|
"Malformed LyX document: Can't find end of inset at line %d" % (i)
|
|
)
|
|
i += 1
|
|
else:
|
|
i = j
|
|
else:
|
|
i += 1
|
|
continue
|
|
for phrase in phrases:
|
|
j = document.body[i].find(phrase)
|
|
if j == -1:
|
|
continue
|
|
if not is_part_of_converted_phrase(document.body[i], j, phrase):
|
|
front = document.body[i][:j]
|
|
back = document.body[i][j + len(phrase) :]
|
|
if len(back) > 0:
|
|
document.body.insert(i + 1, back)
|
|
# We cannot use SpecialChar since we do not know whether we are outside passThru
|
|
document.body[i] = front + "\\SpecialCharNoPassThru \\" + phrase
|
|
i += 1
|
|
|
|
|
|
def revert_phrases(document):
|
|
"revert special phrases to plain text"
|
|
|
|
i = 0
|
|
while i < len(document.body):
|
|
words = document.body[i].split()
|
|
if (
|
|
len(words) > 1
|
|
and words[0] == "\\begin_inset"
|
|
and words[1] in ["CommandInset", "External", "Formula", "Graphics", "listings"]
|
|
):
|
|
# see convert_phrases
|
|
j = find_end_of_inset(document.body, i)
|
|
if j == -1:
|
|
document.warning(
|
|
"Malformed LyX document: Can't find end of Formula inset at line " + str(i)
|
|
)
|
|
i += 1
|
|
else:
|
|
i = j
|
|
continue
|
|
replaced = False
|
|
for phrase in phrases:
|
|
# we can replace SpecialChar since LyX ensures that it cannot be inserted into passThru parts
|
|
if document.body[i].find("\\SpecialChar \\" + phrase) >= 0:
|
|
document.body[i] = document.body[i].replace("\\SpecialChar \\" + phrase, phrase)
|
|
replaced = True
|
|
if document.body[i].find("\\SpecialCharNoPassThru \\" + phrase) >= 0:
|
|
document.body[i] = document.body[i].replace(
|
|
"\\SpecialCharNoPassThru \\" + phrase, phrase
|
|
)
|
|
replaced = True
|
|
if (
|
|
replaced
|
|
and i + 1 < len(document.body)
|
|
and (
|
|
document.body[i + 1].find("\\") != 0
|
|
or document.body[i + 1].find("\\SpecialChar") == 0
|
|
)
|
|
and len(document.body[i]) + len(document.body[i + 1]) <= 80
|
|
):
|
|
document.body[i] = document.body[i] + document.body[i + 1]
|
|
document.body[i + 1 : i + 2] = []
|
|
i -= 1
|
|
i += 1
|
|
|
|
|
|
def convert_specialchar_internal(document, forward):
|
|
specialchars = {
|
|
"\\-": "softhyphen",
|
|
"\\textcompwordmark{}": "ligaturebreak",
|
|
"\\@.": "endofsentence",
|
|
"\\ldots{}": "ldots",
|
|
"\\menuseparator": "menuseparator",
|
|
"\\slash{}": "breakableslash",
|
|
"\\nobreakdash-": "nobreakdash",
|
|
"\\LyX": "LyX",
|
|
"\\TeX": "TeX",
|
|
"\\LaTeX2e": "LaTeX2e",
|
|
"\\LaTeX": "LaTeX", # must be after LaTeX2e
|
|
}
|
|
|
|
i = 0
|
|
while i < len(document.body):
|
|
if document.body[i] and document.body[i][0] == "\\":
|
|
words = document.body[i].split()
|
|
if (
|
|
len(words) > 1
|
|
and words[0] == "\\begin_inset"
|
|
and words[1] in ["CommandInset", "External", "Formula", "Graphics", "listings"]
|
|
):
|
|
# see convert_phrases
|
|
j = find_end_of_inset(document.body, i)
|
|
if j == -1:
|
|
document.warning(
|
|
"Malformed LyX document: Can't find end of %s inset at line %d"
|
|
% (words[1], i)
|
|
)
|
|
i += 1
|
|
else:
|
|
i = j
|
|
continue
|
|
# else...
|
|
if "\\SpecialChar" not in document.body[i]:
|
|
i += 1
|
|
continue
|
|
for key, value in specialchars.items():
|
|
if forward:
|
|
document.body[i] = document.body[i].replace(
|
|
"\\SpecialChar " + key, "\\SpecialChar " + value
|
|
)
|
|
document.body[i] = document.body[i].replace(
|
|
"\\SpecialCharNoPassThru " + key, "\\SpecialCharNoPassThru " + value
|
|
)
|
|
else:
|
|
document.body[i] = document.body[i].replace(
|
|
"\\SpecialChar " + value, "\\SpecialChar " + key
|
|
)
|
|
document.body[i] = document.body[i].replace(
|
|
"\\SpecialCharNoPassThru " + value, "\\SpecialCharNoPassThru " + key
|
|
)
|
|
i += 1
|
|
|
|
|
|
def convert_specialchar(document):
|
|
"convert special characters to new syntax"
|
|
convert_specialchar_internal(document, True)
|
|
|
|
|
|
def revert_specialchar(document):
|
|
"convert special characters to old syntax"
|
|
convert_specialchar_internal(document, False)
|
|
|
|
|
|
def revert_georgian(document):
|
|
"Set the document language to English but assure Georgian output"
|
|
|
|
revert_language(document, "georgian", "georgian", "")
|
|
|
|
|
|
def revert_sigplan_doi(document):
|
|
"Reverts sigplanconf DOI layout to ERT"
|
|
|
|
if document.textclass != "sigplanconf":
|
|
return
|
|
|
|
i = 0
|
|
while True:
|
|
i = find_token(document.body, "\\begin_layout DOI", i)
|
|
if i == -1:
|
|
return
|
|
j = find_end_of_layout(document.body, i)
|
|
if j == -1:
|
|
document.warning("Malformed LyX document: Can't find end of DOI layout")
|
|
i += 1
|
|
continue
|
|
|
|
content = lyx2latex(document, document.body[i : j + 1])
|
|
add_to_preamble(document, ["\\doi{" + content + "}"])
|
|
del document.body[i : j + 1]
|
|
# no need to reset i
|
|
|
|
|
|
def revert_ex_itemargs(document):
|
|
"Reverts \\item arguments of the example environments (Linguistics module) to TeX-code"
|
|
|
|
if "linguistics" not in document.get_module_list():
|
|
return
|
|
|
|
i = 0
|
|
example_layouts = ["Numbered Examples (consecutive)", "Subexample"]
|
|
while True:
|
|
i = find_token(document.body, "\\begin_inset Argument item:", i)
|
|
if i == -1:
|
|
return
|
|
j = find_end_of_inset(document.body, i)
|
|
# Find containing paragraph layout
|
|
parent = get_containing_layout(document.body, i)
|
|
if parent == False:
|
|
document.warning("Malformed LyX document: Can't find parent paragraph layout")
|
|
i += 1
|
|
continue
|
|
parbeg = parent[3]
|
|
layoutname = parent[0]
|
|
if layoutname in example_layouts:
|
|
beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
|
|
endPlain = find_end_of_layout(document.body, beginPlain)
|
|
content = document.body[beginPlain + 1 : endPlain]
|
|
del document.body[i : j + 1]
|
|
subst = put_cmd_in_ert("[") + content + put_cmd_in_ert("]")
|
|
document.body[parbeg:parbeg] = subst
|
|
i += 1
|
|
|
|
|
|
def revert_forest(document):
|
|
"Reverts the forest environment (Linguistics module) to TeX-code"
|
|
|
|
if "linguistics" not in document.get_module_list():
|
|
return
|
|
|
|
i = 0
|
|
while True:
|
|
i = find_token(document.body, "\\begin_inset Flex Structure Tree", i)
|
|
if i == -1:
|
|
return
|
|
j = find_end_of_inset(document.body, i)
|
|
if j == -1:
|
|
document.warning("Malformed LyX document: Can't find end of Structure Tree inset")
|
|
i += 1
|
|
continue
|
|
|
|
beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
|
|
endPlain = find_end_of_layout(document.body, beginPlain)
|
|
content = lyx2latex(document, document.body[beginPlain:endPlain])
|
|
|
|
add_to_preamble(document, ["\\usepackage{forest}"])
|
|
|
|
document.body[i : j + 1] = put_cmd_in_ert("\\begin{forest}" + content + "\\end{forest}")
|
|
# no need to reset i
|
|
|
|
|
|
def revert_glossgroup(document):
|
|
"Reverts the GroupGlossedWords inset (Linguistics module) to TeX-code"
|
|
|
|
if "linguistics" not in document.get_module_list():
|
|
return
|
|
|
|
i = 0
|
|
while True:
|
|
i = find_token(document.body, "\\begin_inset Flex GroupGlossedWords", i)
|
|
if i == -1:
|
|
return
|
|
j = find_end_of_inset(document.body, i)
|
|
if j == -1:
|
|
document.warning(
|
|
"Malformed LyX document: Can't find end of GroupGlossedWords inset"
|
|
)
|
|
i += 1
|
|
continue
|
|
|
|
beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
|
|
endPlain = find_end_of_layout(document.body, beginPlain)
|
|
content = lyx2verbatim(document, document.body[beginPlain:endPlain])
|
|
|
|
document.body[i : j + 1] = ["{", "", content, "", "}"]
|
|
# no need to reset i
|
|
|
|
|
|
def revert_newgloss(document):
|
|
"Reverts the new Glosse insets (Linguistics module) to the old format"
|
|
|
|
if "linguistics" not in document.get_module_list():
|
|
return
|
|
|
|
glosses = ("\\begin_inset Flex Glosse", "\\begin_inset Flex Tri-Glosse")
|
|
for glosse in glosses:
|
|
i = 0
|
|
while True:
|
|
i = find_token(document.body, glosse, i)
|
|
if i == -1:
|
|
break
|
|
j = find_end_of_inset(document.body, i)
|
|
if j == -1:
|
|
document.warning("Malformed LyX document: Can't find end of Glosse inset")
|
|
i += 1
|
|
continue
|
|
|
|
arg = find_token(document.body, "\\begin_inset Argument 1", i, j)
|
|
endarg = find_end_of_inset(document.body, arg)
|
|
argcontent = ""
|
|
if arg != -1:
|
|
argbeginPlain = find_token(
|
|
document.body, "\\begin_layout Plain Layout", arg, endarg
|
|
)
|
|
if argbeginPlain == -1:
|
|
document.warning("Malformed LyX document: Can't find arg plain Layout")
|
|
i += 1
|
|
continue
|
|
argendPlain = find_end_of_inset(document.body, argbeginPlain)
|
|
argcontent = lyx2verbatim(
|
|
document, document.body[argbeginPlain : argendPlain - 2]
|
|
)
|
|
|
|
document.body[j:j] = [
|
|
"",
|
|
"\\begin_layout Plain Layout",
|
|
"\\backslash",
|
|
"glt ",
|
|
argcontent,
|
|
"\\end_layout",
|
|
]
|
|
|
|
# remove Arg insets and paragraph, if it only contains this inset
|
|
if (
|
|
document.body[arg - 1] == "\\begin_layout Plain Layout"
|
|
and find_end_of_layout(document.body, arg - 1) == endarg + 3
|
|
):
|
|
del document.body[arg - 1 : endarg + 4]
|
|
else:
|
|
del document.body[arg : endarg + 1]
|
|
|
|
beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
|
|
endPlain = find_end_of_layout(document.body, beginPlain)
|
|
content = lyx2verbatim(document, document.body[beginPlain:endPlain])
|
|
|
|
document.body[beginPlain + 1 : endPlain] = [content]
|
|
i = beginPlain + 1
|
|
|
|
# Dissolve ERT insets
|
|
for glosse in glosses:
|
|
i = 0
|
|
while True:
|
|
i = find_token(document.body, glosse, i)
|
|
if i == -1:
|
|
break
|
|
j = find_end_of_inset(document.body, i)
|
|
if j == -1:
|
|
document.warning("Malformed LyX document: Can't find end of Glosse inset")
|
|
i += 1
|
|
continue
|
|
while True:
|
|
ert = find_token(document.body, "\\begin_inset ERT", i, j)
|
|
if ert == -1:
|
|
break
|
|
ertend = find_end_of_inset(document.body, ert)
|
|
if ertend == -1:
|
|
document.warning("Malformed LyX document: Can't find end of ERT inset")
|
|
ert += 1
|
|
continue
|
|
ertcontent = get_ert(document.body, ert, True)
|
|
document.body[ert : ertend + 1] = [ertcontent]
|
|
i += 1
|
|
|
|
|
|
def convert_newgloss(document):
|
|
"Converts Glosse insets (Linguistics module) to the new format"
|
|
|
|
if "linguistics" not in document.get_module_list():
|
|
return
|
|
|
|
glosses = ("\\begin_inset Flex Glosse", "\\begin_inset Flex Tri-Glosse")
|
|
for glosse in glosses:
|
|
i = 0
|
|
while True:
|
|
i = find_token(document.body, glosse, i)
|
|
if i == -1:
|
|
break
|
|
j = find_end_of_inset(document.body, i)
|
|
if j == -1:
|
|
document.warning("Malformed LyX document: Can't find end of Glosse inset")
|
|
i += 1
|
|
continue
|
|
|
|
k = i
|
|
while True:
|
|
argcontent = []
|
|
beginPlain = find_token(document.body, "\\begin_layout Plain Layout", k, j)
|
|
if beginPlain == -1:
|
|
break
|
|
endPlain = find_end_of_layout(document.body, beginPlain)
|
|
if endPlain == -1:
|
|
document.warning("Malformed LyX document: Can't find end of Glosse layout")
|
|
i += 1
|
|
continue
|
|
|
|
glt = find_token(document.body, "\\backslash", beginPlain, endPlain)
|
|
if glt != -1 and document.body[glt + 1].startswith("glt"):
|
|
document.body[glt + 1] = document.body[glt + 1].lstrip("glt").lstrip()
|
|
argcontent = document.body[glt + 1 : endPlain]
|
|
document.body[beginPlain + 1 : endPlain] = (
|
|
[
|
|
"\\begin_inset Argument 1",
|
|
"status open",
|
|
"",
|
|
"\\begin_layout Plain Layout",
|
|
"\\begin_inset ERT",
|
|
"status open",
|
|
"",
|
|
"\\begin_layout Plain Layout",
|
|
"",
|
|
]
|
|
+ argcontent
|
|
+ [
|
|
"\\end_layout",
|
|
"",
|
|
"\\end_inset",
|
|
"",
|
|
"\\end_layout",
|
|
"",
|
|
"\\end_inset",
|
|
]
|
|
)
|
|
else:
|
|
content = document.body[beginPlain + 1 : endPlain]
|
|
document.body[beginPlain + 1 : endPlain] = (
|
|
[
|
|
"\\begin_inset ERT",
|
|
"status open",
|
|
"",
|
|
"\\begin_layout Plain Layout",
|
|
]
|
|
+ content
|
|
+ ["\\end_layout", "", "\\end_inset"]
|
|
)
|
|
|
|
endPlain = find_end_of_layout(document.body, beginPlain)
|
|
k = endPlain
|
|
j = find_end_of_inset(document.body, i)
|
|
|
|
i = endPlain + 1
|
|
|
|
|
|
def convert_BoxFeatures(document):
|
|
"adds new box features"
|
|
|
|
i = 0
|
|
while True:
|
|
i = find_token(document.body, "height_special", i)
|
|
if i == -1:
|
|
return
|
|
document.body[i + 1 : i + 1] = [
|
|
'thickness "0.4pt"',
|
|
'separation "3pt"',
|
|
'shadowsize "4pt"',
|
|
]
|
|
i = i + 4
|
|
|
|
|
|
def revert_BoxFeatures(document):
|
|
"outputs new box features as TeX code"
|
|
|
|
i = 0
|
|
defaultSep = "3pt"
|
|
defaultThick = "0.4pt"
|
|
defaultShadow = "4pt"
|
|
while True:
|
|
i = find_token(document.body, "thickness", i)
|
|
if i == -1:
|
|
return
|
|
binset = find_token(document.body, "\\begin_inset Box", i - 11)
|
|
if binset == -1 or binset != i - 11:
|
|
i = i + 1
|
|
continue # then "thickness" is is just a word in the text
|
|
einset = find_end_of_inset(document.body, binset)
|
|
if einset == -1:
|
|
document.warning("Malformed LyX document: Can't find end of box inset!")
|
|
i = i + 1
|
|
continue
|
|
# read out the values
|
|
beg = document.body[i].find('"')
|
|
end = document.body[i].rfind('"')
|
|
thickness = document.body[i][beg + 1 : end]
|
|
beg = document.body[i + 1].find('"')
|
|
end = document.body[i + 1].rfind('"')
|
|
separation = document.body[i + 1][beg + 1 : end]
|
|
beg = document.body[i + 2].find('"')
|
|
end = document.body[i + 2].rfind('"')
|
|
shadowsize = document.body[i + 2][beg + 1 : end]
|
|
# output ERT
|
|
# first output the closing brace
|
|
if shadowsize != defaultShadow or separation != defaultSep or thickness != defaultThick:
|
|
document.body[einset + 1 : einset + 1] = put_cmd_in_ert("}")
|
|
# delete the specification
|
|
del document.body[i : i + 3]
|
|
# we have now the problem that if there is already \(f)colorbox in ERT around the inset
|
|
# the ERT from this routine must be around it
|
|
regexp = re.compile(r"^.*colorbox{.*$")
|
|
pos = find_re(document.body, regexp, binset - 4)
|
|
if pos != -1 and pos == binset - 4:
|
|
pos = i - 11 - 10
|
|
else:
|
|
pos = i - 11
|
|
# now output the lengths
|
|
if shadowsize != defaultShadow or separation != defaultSep or thickness != defaultThick:
|
|
document.body[pos:pos] = put_cmd_in_ert("{")
|
|
if thickness != defaultThick:
|
|
document.body[pos + 5 : pos + 6] = ["{\\backslash fboxrule " + thickness]
|
|
if separation != defaultSep and thickness == defaultThick:
|
|
document.body[pos + 5 : pos + 6] = ["{\\backslash fboxsep " + separation]
|
|
if separation != defaultSep and thickness != defaultThick:
|
|
document.body[pos + 5 : pos + 6] = [
|
|
"{\\backslash fboxrule " + thickness + "\\backslash fboxsep " + separation
|
|
]
|
|
if (
|
|
shadowsize != defaultShadow
|
|
and separation == defaultSep
|
|
and thickness == defaultThick
|
|
):
|
|
document.body[pos + 5 : pos + 6] = ["{\\backslash shadowsize " + shadowsize]
|
|
if (
|
|
shadowsize != defaultShadow
|
|
and separation != defaultSep
|
|
and thickness == defaultThick
|
|
):
|
|
document.body[pos + 5 : pos + 6] = [
|
|
"{\\backslash fboxsep " + separation + "\\backslash shadowsize " + shadowsize
|
|
]
|
|
if (
|
|
shadowsize != defaultShadow
|
|
and separation == defaultSep
|
|
and thickness != defaultThick
|
|
):
|
|
document.body[pos + 5 : pos + 6] = [
|
|
"{\\backslash fboxrule " + thickness + "\\backslash shadowsize " + shadowsize
|
|
]
|
|
if (
|
|
shadowsize != defaultShadow
|
|
and separation != defaultSep
|
|
and thickness != defaultThick
|
|
):
|
|
document.body[pos + 5 : pos + 6] = [
|
|
"{\\backslash fboxrule "
|
|
+ thickness
|
|
+ "\\backslash fboxsep "
|
|
+ separation
|
|
+ "\\backslash shadowsize "
|
|
+ shadowsize
|
|
]
|
|
|
|
|
|
def convert_origin(document):
|
|
"Insert the origin tag"
|
|
|
|
i = find_token(document.header, "\\textclass ", 0)
|
|
if i == -1:
|
|
document.warning("Malformed LyX document: No \\textclass!!")
|
|
return
|
|
if document.dir == "":
|
|
origin = "stdin"
|
|
else:
|
|
relpath = ""
|
|
if document.systemlyxdir and document.systemlyxdir != "":
|
|
try:
|
|
if os.path.isabs(document.dir):
|
|
absdir = os.path.normpath(document.dir)
|
|
else:
|
|
absdir = os.path.normpath(os.path.abspath(document.dir))
|
|
if os.path.isabs(document.systemlyxdir):
|
|
abssys = os.path.normpath(document.systemlyxdir)
|
|
else:
|
|
abssys = os.path.normpath(os.path.abspath(document.systemlyxdir))
|
|
relpath = os.path.relpath(absdir, abssys)
|
|
if relpath.find("..") == 0:
|
|
relpath = ""
|
|
except:
|
|
relpath = ""
|
|
if relpath == "":
|
|
origin = document.dir.replace("\\", "/") + "/"
|
|
else:
|
|
origin = os.path.join("/systemlyxdir", relpath).replace("\\", "/") + "/"
|
|
document.header[i:i] = ["\\origin " + origin]
|
|
|
|
|
|
def revert_origin(document):
|
|
"Remove the origin tag"
|
|
|
|
i = find_token(document.header, "\\origin ", 0)
|
|
if i == -1:
|
|
document.warning("Malformed LyX document: No \\origin!!")
|
|
return
|
|
del document.header[i]
|
|
|
|
|
|
color_names = [
|
|
"brown",
|
|
"darkgray",
|
|
"gray",
|
|
"lightgray",
|
|
"lime",
|
|
"olive",
|
|
"orange",
|
|
"pink",
|
|
"purple",
|
|
"teal",
|
|
"violet",
|
|
]
|
|
|
|
|
|
def revert_textcolor(document):
|
|
"revert new \\textcolor colors to TeX code"
|
|
|
|
i = 0
|
|
j = 0
|
|
xcolor = False
|
|
while True:
|
|
i = find_token(document.body, "\\color ", i)
|
|
if i == -1:
|
|
return
|
|
else:
|
|
for color in list(color_names):
|
|
if document.body[i] == "\\color " + color:
|
|
# register that xcolor must be loaded in the preamble
|
|
if xcolor == False:
|
|
xcolor = True
|
|
add_to_preamble(
|
|
document,
|
|
["\\@ifundefined{rangeHsb}{\\usepackage{xcolor}}{}"],
|
|
)
|
|
# find the next \\color and/or the next \\end_layout
|
|
j = find_token(document.body, "\\color", i + 1)
|
|
k = find_token(document.body, "\\end_layout", i + 1)
|
|
if j == -1 and k != -1:
|
|
j = k + 1
|
|
# output TeX code
|
|
# first output the closing brace
|
|
if k < j:
|
|
document.body[k:k] = put_cmd_in_ert("}")
|
|
else:
|
|
document.body[j:j] = put_cmd_in_ert("}")
|
|
# now output the \textcolor command
|
|
document.body[i : i + 1] = put_cmd_in_ert("\\textcolor{" + color + "}{")
|
|
i = i + 1
|
|
|
|
|
|
def convert_colorbox(document):
|
|
"Add color settings for boxes."
|
|
i = 1
|
|
while True:
|
|
i = find_token(document.body, "shadowsize", i)
|
|
if i == -1:
|
|
return
|
|
# check whether this is really a LyX Box setting
|
|
start, end = is_in_inset(document.body, i, "\\begin_inset Box")
|
|
if end == -1 or find_token(document.body, "\\begin_layout", start, i) != -1:
|
|
i += 1
|
|
continue
|
|
document.body[i + 1 : i + 1] = ['framecolor "black"', 'backgroundcolor "none"']
|
|
i += 3
|
|
|
|
|
|
def revert_colorbox(document):
|
|
"""Change box color settings to LaTeX code."""
|
|
|
|
i = 0
|
|
while True:
|
|
i = find_token(document.body, "\\begin_inset Box", i)
|
|
if i == -1:
|
|
return
|
|
|
|
j = find_end_of_inset(document.body, i)
|
|
k = find_token(document.body, "\\begin_layout", i, j)
|
|
if k == -1:
|
|
document.warning("Malformed LyX document: no layout in Box inset!")
|
|
i += 1
|
|
continue
|
|
# Get and delete colour settings:
|
|
framecolor = get_quoted_value(document.body, "framecolor", i, k, delete=True)
|
|
backcolor = get_quoted_value(document.body, "backgroundcolor", i, k + 1, delete=True)
|
|
if not framecolor or not backcolor:
|
|
document.warning("Malformed LyX document: color options not found in Box inset!")
|
|
i += 1
|
|
continue
|
|
if framecolor == "black" and backcolor == "none": # default values
|
|
i += 1
|
|
continue
|
|
|
|
# Emulate non-default colours with LaTeX code:
|
|
einset = find_end_of_inset(document.body, i)
|
|
if einset == -1:
|
|
document.warning("Malformed LyX document: Can't find end of box inset!")
|
|
i += 1
|
|
continue
|
|
add_to_preamble(document, ["\\@ifundefined{rangeHsb}{\\usepackage{xcolor}}{}"])
|
|
# insert the closing brace first (keeps indices 'i' and 'einset' valid)
|
|
document.body[einset + 1 : einset + 1] = put_cmd_in_ert("}")
|
|
# now insert the (f)color box command
|
|
if "Box Boxed" in document.body[i]: # framed box, use \fcolorbox
|
|
# change the box type (frame added by \fcolorbox)
|
|
document.body[i] = "\\begin_inset Box Frameless"
|
|
# ensure an inner box:
|
|
try:
|
|
if not set_bool_value(document.body, "has_inner_box", True, i + 3, i + 4):
|
|
set_bool_value(document.body, "use_makebox", True, i + 6, i + 7)
|
|
except ValueError:
|
|
document.warning(
|
|
"Malformed LyX document: 'has_inner_box' or "
|
|
"'use_makebox' option not found in box inset!"
|
|
)
|
|
ertinset = put_cmd_in_ert(f"\\fcolorbox{{{framecolor}}}{{{backcolor}}}{{")
|
|
else:
|
|
ertinset = put_cmd_in_ert("\\colorbox{%s}{" % backcolor)
|
|
document.body[i:i] = ertinset + [""]
|
|
i += 13
|
|
|
|
|
|
def revert_mathmulticol(document):
|
|
"Convert formulas to ERT if they contain multicolumns"
|
|
|
|
i = 0
|
|
while True:
|
|
i = find_token(document.body, "\\begin_inset Formula", i)
|
|
if i == -1:
|
|
return
|
|
j = find_end_of_inset(document.body, i)
|
|
if j == -1:
|
|
document.warning(
|
|
"Malformed LyX document: Can't find end of Formula inset at line " + str(i)
|
|
)
|
|
i += 1
|
|
continue
|
|
lines = document.body[i:j]
|
|
lines[0] = lines[0].replace("\\begin_inset Formula", "").lstrip()
|
|
code = "\n".join(lines)
|
|
converted = False
|
|
k = 0
|
|
n = 0
|
|
while n >= 0:
|
|
n = code.find("\\multicolumn", k)
|
|
# no need to convert degenerated multicolumn cells,
|
|
# they work in old LyX versions as "math ERT"
|
|
if n != -1 and code.find("\\multicolumn{1}", k) != n:
|
|
ert = put_cmd_in_ert(code)
|
|
document.body[i : j + 1] = ert
|
|
converted = True
|
|
break
|
|
else:
|
|
k = n + 12
|
|
if converted:
|
|
i = find_end_of_inset(document.body, i)
|
|
else:
|
|
i = j
|
|
|
|
|
|
def revert_jss(document):
|
|
"Reverts JSS In_Preamble commands to ERT in preamble"
|
|
|
|
if document.textclass != "jss":
|
|
return
|
|
|
|
# at first revert the inset layouts because
|
|
# they can be part of the In_Preamble layouts
|
|
il_dict = {
|
|
"Pkg": "pkg",
|
|
"Proglang": "proglang",
|
|
"Code": "code",
|
|
"E-mail": "email",
|
|
"URL": "url",
|
|
}
|
|
for iltype in il_dict.keys():
|
|
i = 0
|
|
while True:
|
|
i = find_token(document.body, "\\begin_inset Flex " + iltype, i)
|
|
if i == -1:
|
|
break
|
|
|
|
if document.body[i] != "\\begin_inset Flex " + iltype:
|
|
# Not an exact match!
|
|
i += 1
|
|
continue
|
|
|
|
end = find_end_of_inset(document.body, i)
|
|
if end == -1:
|
|
document.warning("Malformed LyX document: No end of Flex " + iltype + " found!")
|
|
i += 1
|
|
continue
|
|
document.body[end - 2 : end + 1] = put_cmd_in_ert("}")
|
|
document.body[i : i + 4] = put_cmd_in_ert("\\%s{" % il_dict[iltype])
|
|
i += 1
|
|
|
|
# now revert the In_Preamble layouts
|
|
ipl_dict = {
|
|
"Title": "title",
|
|
"Author": "author",
|
|
"Plain Author": "Plainauthor",
|
|
"Plain Title": "Plaintitle",
|
|
"Short Title": "Shorttitle",
|
|
"Abstract": "Abstract",
|
|
"Keywords": "Keywords",
|
|
"Plain Keywords": "Plainkeywords",
|
|
"Address": "Address",
|
|
}
|
|
for ipltype in ipl_dict.keys():
|
|
i = 0
|
|
while True:
|
|
i = find_token(document.body, "\\begin_layout " + ipltype, i)
|
|
if i == -1:
|
|
break
|
|
|
|
end = find_end_of_layout(document.body, i)
|
|
if end == -1:
|
|
document.warning(
|
|
"Malformed LyX document: Can't find end of " + ipltype + " layout"
|
|
)
|
|
i += 1
|
|
continue
|
|
|
|
content = lyx2latex(document, document.body[i : end + 1])
|
|
add_to_preamble(document, ["\\" + ipl_dict[ipltype] + "{" + content + "}"])
|
|
del document.body[i : end + 1]
|
|
i += 1
|
|
|
|
# Now code chunks
|
|
i = 0
|
|
while True:
|
|
# \CodeChunk
|
|
i = find_token(document.body, "\\begin_inset Flex Code Chunk", i)
|
|
if i == -1:
|
|
break
|
|
|
|
end = find_end_of_inset(document.body, i)
|
|
if end == -1:
|
|
document.warning("Malformed LyX document: No end of Flex Code Chunk found!")
|
|
i += 1
|
|
continue
|
|
|
|
document.body[end : end + 1] = [
|
|
"\\end_layout",
|
|
"",
|
|
"\\begin_layout Standard",
|
|
] + put_cmd_in_ert("\\end{CodeChunk}")
|
|
document.body[i : i + 2] = put_cmd_in_ert("\\begin{CodeChunk}")
|
|
i += 1
|
|
|
|
# finally handle the code layouts
|
|
codes_dict = {
|
|
"Code Input": "CodeInput",
|
|
"Code Output": "CodeOutput",
|
|
"Code": "Code",
|
|
}
|
|
for ctype in codes_dict.keys():
|
|
i = 0
|
|
while True:
|
|
i = find_token(document.body, "\\begin_layout " + ctype, i)
|
|
if i == -1:
|
|
break
|
|
if document.body[i] != "\\begin_layout " + ctype:
|
|
# Not an exact match!
|
|
i += 1
|
|
continue
|
|
end = find_end_of_layout(document.body, i)
|
|
if end == -1:
|
|
document.warning(
|
|
"Malformed LyX document: No end of " + ctype + " layout found!"
|
|
)
|
|
i += 1
|
|
continue
|
|
seq_end = end
|
|
# Handle subsequent layouts
|
|
while True:
|
|
j = find_token(document.body, "\\begin_layout ", seq_end)
|
|
if j == -1 or document.body[j] != "\\begin_layout " + ctype:
|
|
break
|
|
this_end = find_end_of_layout(document.body, j)
|
|
if this_end == -1:
|
|
document.warning(
|
|
"Malformed LyX document: No end of " + ctype + " layout found!"
|
|
)
|
|
j += 1
|
|
continue
|
|
seq_end = this_end
|
|
document.body[seq_end + 1 : seq_end + 1] = [
|
|
"\\end_inset",
|
|
"\\end_layout",
|
|
"",
|
|
"\\begin_layout Standard",
|
|
] + put_cmd_in_ert("\\end{%s}" % codes_dict[ctype])
|
|
if seq_end != end:
|
|
k = i + 1
|
|
while k < seq_end:
|
|
document.body[k] = document.body[k].replace(
|
|
"\\begin_layout " + ctype, "\\begin_layout Plain Layout"
|
|
)
|
|
k += 1
|
|
document.body[i : i + 1] = (
|
|
["\\end_layout", "", "\\begin_layout Standard"]
|
|
+ put_cmd_in_ert("\\begin{%s}" % codes_dict[ctype])
|
|
+ [
|
|
"\\end_layout",
|
|
"",
|
|
"\\begin_layout Standard",
|
|
"",
|
|
"\\begin_inset ERT",
|
|
"status open",
|
|
"",
|
|
"\\begin_layout Plain Layout",
|
|
]
|
|
)
|
|
i += 1
|
|
|
|
|
|
def convert_subref(document):
|
|
"converts sub: ref prefixes to subref:"
|
|
|
|
# 1) label insets
|
|
rx = re.compile(r"^name \"sub:(.+)$")
|
|
i = 0
|
|
while True:
|
|
i = find_token(document.body, "\\begin_inset CommandInset label", i)
|
|
if i == -1:
|
|
break
|
|
j = find_end_of_inset(document.body, i)
|
|
if j == -1:
|
|
document.warning(
|
|
"Malformed LyX document: Can't find end of Label inset at line " + str(i)
|
|
)
|
|
i += 1
|
|
continue
|
|
|
|
for p in range(i, j):
|
|
m = rx.match(document.body[p])
|
|
if m:
|
|
label = m.group(1)
|
|
document.body[p] = 'name "subsec:' + label
|
|
i += 1
|
|
|
|
# 2) xref insets
|
|
rx = re.compile(r"^reference \"sub:(.+)$")
|
|
i = 0
|
|
while True:
|
|
i = find_token(document.body, "\\begin_inset CommandInset ref", i)
|
|
if i == -1:
|
|
return
|
|
j = find_end_of_inset(document.body, i)
|
|
if j == -1:
|
|
document.warning(
|
|
"Malformed LyX document: Can't find end of Ref inset at line " + str(i)
|
|
)
|
|
i += 1
|
|
continue
|
|
|
|
for p in range(i, j):
|
|
m = rx.match(document.body[p])
|
|
if m:
|
|
label = m.group(1)
|
|
document.body[p] = 'reference "subsec:' + label
|
|
break
|
|
i += 1
|
|
|
|
|
|
def revert_subref(document):
|
|
"reverts subref: ref prefixes to sub:"
|
|
|
|
# 1) label insets
|
|
rx = re.compile(r"^name \"subsec:(.+)$")
|
|
i = 0
|
|
while True:
|
|
i = find_token(document.body, "\\begin_inset CommandInset label", i)
|
|
if i == -1:
|
|
break
|
|
j = find_end_of_inset(document.body, i)
|
|
if j == -1:
|
|
document.warning(
|
|
"Malformed LyX document: Can't find end of Label inset at line " + str(i)
|
|
)
|
|
i += 1
|
|
continue
|
|
|
|
for p in range(i, j):
|
|
m = rx.match(document.body[p])
|
|
if m:
|
|
label = m.group(1)
|
|
document.body[p] = 'name "sub:' + label
|
|
break
|
|
i += 1
|
|
|
|
# 2) xref insets
|
|
rx = re.compile(r"^reference \"subsec:(.+)$")
|
|
i = 0
|
|
while True:
|
|
i = find_token(document.body, "\\begin_inset CommandInset ref", i)
|
|
if i == -1:
|
|
return
|
|
j = find_end_of_inset(document.body, i)
|
|
if j == -1:
|
|
document.warning(
|
|
"Malformed LyX document: Can't find end of Ref inset at line " + str(i)
|
|
)
|
|
i += 1
|
|
continue
|
|
|
|
for p in range(i, j):
|
|
m = rx.match(document.body[p])
|
|
if m:
|
|
label = m.group(1)
|
|
document.body[p] = 'reference "sub:' + label
|
|
break
|
|
i += 1
|
|
|
|
|
|
def convert_nounzip(document):
|
|
"remove the noUnzip parameter of graphics insets"
|
|
|
|
rx = re.compile(r"\s*noUnzip\s*$")
|
|
i = 0
|
|
while True:
|
|
i = find_token(document.body, "\\begin_inset Graphics", i)
|
|
if i == -1:
|
|
break
|
|
j = find_end_of_inset(document.body, i)
|
|
if j == -1:
|
|
document.warning(
|
|
"Malformed LyX document: Can't find end of graphics inset at line " + str(i)
|
|
)
|
|
i += 1
|
|
continue
|
|
|
|
k = find_re(document.body, rx, i, j)
|
|
if k != -1:
|
|
del document.body[k]
|
|
j = j - 1
|
|
i = j + 1
|
|
|
|
|
|
def convert_revert_external_bbox(document, forward):
|
|
"add units to bounding box of external insets"
|
|
|
|
rx = re.compile(r"^\s*boundingBox\s+\S+\s+\S+\s+\S+\s+\S+\s*$")
|
|
i = 0
|
|
while True:
|
|
i = find_token(document.body, "\\begin_inset External", i)
|
|
if i == -1:
|
|
break
|
|
j = find_end_of_inset(document.body, i)
|
|
if j == -1:
|
|
document.warning(
|
|
"Malformed LyX document: Can't find end of external inset at line " + str(i)
|
|
)
|
|
i += 1
|
|
continue
|
|
k = find_re(document.body, rx, i, j)
|
|
if k == -1:
|
|
i = j + 1
|
|
continue
|
|
tokens = document.body[k].split()
|
|
if forward:
|
|
for t in range(1, 5):
|
|
tokens[t] += "bp"
|
|
else:
|
|
for t in range(1, 5):
|
|
tokens[t] = length_in_bp(document, tokens[t])
|
|
document.body[k] = (
|
|
"\tboundingBox " + tokens[1] + " " + tokens[2] + " " + tokens[3] + " " + tokens[4]
|
|
)
|
|
i = j + 1
|
|
|
|
|
|
def convert_external_bbox(document):
|
|
convert_revert_external_bbox(document, True)
|
|
|
|
|
|
def revert_external_bbox(document):
|
|
convert_revert_external_bbox(document, False)
|
|
|
|
|
|
def revert_tcolorbox_1(document):
|
|
"Reverts the Flex:Subtitle inset of tcolorbox to TeX-code"
|
|
|
|
i = find_token(document.header, "tcolorbox", 0)
|
|
if i == -1:
|
|
return
|
|
|
|
flex = 0
|
|
|
|
while True:
|
|
flex = find_token(document.body, "\\begin_inset Flex Subtitle", flex)
|
|
if flex == -1:
|
|
return
|
|
|
|
flexEnd = find_end_of_inset(document.body, flex)
|
|
if flexEnd == -1:
|
|
document.warning("Malformed LyX document! No end of Flex Subtitle found.")
|
|
flex += 1
|
|
continue
|
|
|
|
wasOpt = revert_Argument_to_TeX_brace(document, flex, flexEnd, 1, 1, False, True, False)
|
|
flexEnd = find_end_of_inset(document.body, flex)
|
|
if flexEnd == -1:
|
|
document.warning("Malformed LyX document! No end of Flex Subtitle found.")
|
|
flex += 1
|
|
continue
|
|
revert_Argument_to_TeX_brace(document, flex, flexEnd, 2, 2, False, False, False)
|
|
flexEnd = find_end_of_inset(document.body, flex)
|
|
if flexEnd == -1:
|
|
document.warning("Malformed LyX document! No end of Flex Subtitle found.")
|
|
flex += 1
|
|
continue
|
|
|
|
bp = find_token(document.body, "\\begin_layout Plain Layout", flex)
|
|
if bp == -1:
|
|
document.warning("Malformed LyX document! No Flex Subtitle layout found.")
|
|
flex += 1
|
|
continue
|
|
|
|
ep = find_end_of_layout(document.body, bp)
|
|
if ep == -1:
|
|
document.warning("Malformed LyX document! No end of layout found.")
|
|
flex += 1
|
|
continue
|
|
|
|
document.body[ep : flexEnd + 1] = put_cmd_in_ert("}")
|
|
if wasOpt == True:
|
|
document.body[flex : bp + 1] = put_cmd_in_ert("\\tcbsubtitle")
|
|
else:
|
|
document.body[flex : bp + 1] = put_cmd_in_ert("\\tcbsubtitle{")
|
|
flex += 1
|
|
|
|
|
|
def revert_tcolorbox_2(document):
|
|
"Reverts the Flex:Raster_Color_Box inset of tcolorbox to TeX-code"
|
|
|
|
i = find_token(document.header, "tcolorbox", 0)
|
|
if i == -1:
|
|
return
|
|
|
|
flex = 0
|
|
while True:
|
|
flex = find_token(document.body, "\\begin_inset Flex Raster Color Box", flex)
|
|
if flex == -1:
|
|
return
|
|
|
|
flexEnd = find_end_of_inset(document.body, flex)
|
|
if flexEnd == -1:
|
|
document.warning("Malformed LyX document! No end of Flex Raster Color Box found.")
|
|
flex += 1
|
|
continue
|
|
|
|
revert_Argument_to_TeX_brace(document, flex, flexEnd, 1, 1, True, True, False)
|
|
|
|
bp = find_token(document.body, "\\begin_layout Plain Layout", flex)
|
|
if bp == -1:
|
|
document.warning(
|
|
"Malformed LyX document! No plain layout in Raster Color Box found."
|
|
)
|
|
flex += 1
|
|
continue
|
|
|
|
ep = find_end_of_layout(document.body, bp)
|
|
if ep == -1:
|
|
document.warning("Malformed LyX document! No end of layout found.")
|
|
flex += 1
|
|
continue
|
|
|
|
flexEnd = find_end_of_inset(document.body, flex)
|
|
if flexEnd == -1:
|
|
document.warning("Malformed LyX document! No end of Flex Raster Color Box found.")
|
|
flex += 1
|
|
continue
|
|
document.body[ep : flexEnd + 1] = put_cmd_in_ert("\\end{tcbraster}")
|
|
document.body[flex : bp + 1] = put_cmd_in_ert("\\begin{tcbraster}")
|
|
flex += 1
|
|
|
|
|
|
def revert_tcolorbox_3(document):
|
|
"Reverts the Flex:Custom_Color_Box_1 inset of tcolorbox to TeX-code"
|
|
|
|
i = find_token(document.header, "tcolorbox", 0)
|
|
if i == -1:
|
|
return
|
|
|
|
flex = 0
|
|
while True:
|
|
flex = find_token(document.body, "\\begin_inset Flex Custom Color Box 1", flex)
|
|
if flex == -1:
|
|
return
|
|
|
|
flexEnd = find_end_of_inset(document.body, flex)
|
|
if flexEnd == -1:
|
|
document.warning("Malformed LyX document! No end of Flex Custom Color Box 1 found.")
|
|
flex += 1
|
|
continue
|
|
|
|
revert_Argument_to_TeX_brace(document, flex, flexEnd, 1, 1, True, True, False)
|
|
flexEnd = find_end_of_inset(document.body, flex)
|
|
if flexEnd == -1:
|
|
document.warning("Malformed LyX document! No end of Flex Subtitle found.")
|
|
flex += 1
|
|
continue
|
|
revert_Argument_to_TeX_brace(document, flex, flexEnd, 2, 2, True, False, False)
|
|
|
|
bp = find_token(document.body, "\\begin_layout Plain Layout", flex)
|
|
if bp == -1:
|
|
document.warning(
|
|
"Malformed LyX document! No plain layout in Custom Color Box 1 found."
|
|
)
|
|
flex += 1
|
|
continue
|
|
|
|
ep = find_end_of_layout(document.body, bp)
|
|
if ep == -1:
|
|
document.warning("Malformed LyX document! No end of layout found.")
|
|
flex += 1
|
|
continue
|
|
|
|
flexEnd = find_end_of_inset(document.body, flex)
|
|
if flexEnd == -1:
|
|
document.warning("Malformed LyX document! No end of Flex Custom Color Box 1 found.")
|
|
flex += 1
|
|
continue
|
|
|
|
document.body[ep : flexEnd + 1] = put_cmd_in_ert("{}\\end{cBoxA}")
|
|
document.body[flex : bp + 1] = put_cmd_in_ert("\\begin{cBoxA}")
|
|
flex += 1
|
|
|
|
|
|
def revert_tcolorbox_4(document):
|
|
"Reverts the Flex:Custom_Color_Box_2 inset of tcolorbox to TeX-code"
|
|
|
|
i = find_token(document.header, "tcolorbox", 0)
|
|
if i == -1:
|
|
return
|
|
|
|
flex = 0
|
|
while True:
|
|
flex = find_token(document.body, "\\begin_inset Flex Custom Color Box 2", flex)
|
|
if flex == -1:
|
|
return
|
|
|
|
flexEnd = find_end_of_inset(document.body, flex)
|
|
if flexEnd == -1:
|
|
document.warning("Malformed LyX document! No end of Flex Custom Color Box 2 found.")
|
|
flex += 1
|
|
continue
|
|
|
|
revert_Argument_to_TeX_brace(document, flex, flexEnd, 1, 1, True, True, False)
|
|
flexEnd = find_end_of_inset(document.body, flex)
|
|
if flexEnd == -1:
|
|
document.warning("Malformed LyX document! No end of Flex Subtitle found.")
|
|
flex += 1
|
|
continue
|
|
revert_Argument_to_TeX_brace(document, flex, flexEnd, 2, 2, True, False, False)
|
|
flexEnd = find_end_of_inset(document.body, flex)
|
|
if flexEnd == -1:
|
|
document.warning("Malformed LyX document! No end of Flex Custom Color Box 2 found.")
|
|
flex += 1
|
|
continue
|
|
|
|
bp = find_token(document.body, "\\begin_layout Plain Layout", flex)
|
|
if bp == -1:
|
|
document.warning(
|
|
"Malformed LyX document! No plain layout in Custom Color Box 2 found."
|
|
)
|
|
flex += 1
|
|
continue
|
|
|
|
ep = find_end_of_layout(document.body, bp)
|
|
if ep == -1:
|
|
document.warning("Malformed LyX document! No end of layout found.")
|
|
flex += 1
|
|
continue
|
|
|
|
document.body[ep : flexEnd + 1] = put_cmd_in_ert("{}\\end{cBoxB}")
|
|
document.body[flex : bp + 1] = put_cmd_in_ert("\\begin{cBoxB}")
|
|
flex += 1
|
|
|
|
|
|
def revert_tcolorbox_5(document):
|
|
"Reverts the Flex:Custom_Color_Box_3 inset of tcolorbox to TeX-code"
|
|
|
|
i = find_token(document.header, "tcolorbox", 0)
|
|
if i == -1:
|
|
return
|
|
|
|
flex = 0
|
|
while True:
|
|
flex = find_token(document.body, "\\begin_inset Flex Custom Color Box 3", flex)
|
|
if flex == -1:
|
|
return
|
|
|
|
flexEnd = find_end_of_inset(document.body, flex)
|
|
if flexEnd == -1:
|
|
document.warning("Malformed LyX document! No end of Flex Custom Color Box 3 found.")
|
|
flex += 1
|
|
continue
|
|
|
|
revert_Argument_to_TeX_brace(document, flex, flexEnd, 1, 1, True, True, False)
|
|
flexEnd = find_end_of_inset(document.body, flex)
|
|
if flexEnd == -1:
|
|
document.warning("Malformed LyX document! No end of Flex Subtitle found.")
|
|
flex += 1
|
|
continue
|
|
revert_Argument_to_TeX_brace(document, flex, flexEnd, 2, 2, True, False, False)
|
|
flexEnd = find_end_of_inset(document.body, flex)
|
|
if flexEnd == -1:
|
|
document.warning("Malformed LyX document! No end of Flex Custom Color Box 3 found.")
|
|
flex += 1
|
|
continue
|
|
|
|
bp = find_token(document.body, "\\begin_layout Plain Layout", flex)
|
|
if bp == -1:
|
|
document.warning(
|
|
"Malformed LyX document! No plain layout in Custom Color Box 3 found."
|
|
)
|
|
flex += 1
|
|
continue
|
|
|
|
ep = find_end_of_layout(document.body, bp)
|
|
if ep == -1:
|
|
document.warning("Malformed LyX document! No end of layout found.")
|
|
flex += 1
|
|
continue
|
|
|
|
document.body[ep : flexEnd + 1] = put_cmd_in_ert("{}\\end{cBoxC}")
|
|
document.body[flex : bp + 1] = put_cmd_in_ert("\\begin{cBoxC}")
|
|
flex += 1
|
|
|
|
|
|
def revert_tcolorbox_6(document):
|
|
"Reverts the Flex:Custom_Color_Box_4 inset of tcolorbox to TeX-code"
|
|
|
|
i = find_token(document.header, "tcolorbox", 0)
|
|
if i == -1:
|
|
return
|
|
|
|
flex = 0
|
|
while True:
|
|
flex = find_token(document.body, "\\begin_inset Flex Custom Color Box 4", flex)
|
|
if flex == -1:
|
|
return
|
|
|
|
flexEnd = find_end_of_inset(document.body, flex)
|
|
if flexEnd == -1:
|
|
document.warning("Malformed LyX document! No end of Flex Custom Color Box 4 found.")
|
|
flex += 1
|
|
continue
|
|
|
|
revert_Argument_to_TeX_brace(document, flex, flexEnd, 1, 1, True, True, False)
|
|
flexEnd = find_end_of_inset(document.body, flex)
|
|
if flexEnd == -1:
|
|
document.warning("Malformed LyX document! No end of Flex Subtitle found.")
|
|
flex += 1
|
|
continue
|
|
revert_Argument_to_TeX_brace(document, flex, flexEnd, 2, 2, True, False, False)
|
|
flexEnd = find_end_of_inset(document.body, flex)
|
|
if flexEnd == -1:
|
|
document.warning("Malformed LyX document! No end of Flex Custom Color Box 4 found.")
|
|
flex += 1
|
|
continue
|
|
|
|
bp = find_token(document.body, "\\begin_layout Plain Layout", flex)
|
|
if bp == -1:
|
|
document.warning(
|
|
"Malformed LyX document! No plain layout in Custom Color Box 4 found."
|
|
)
|
|
flex += 1
|
|
continue
|
|
|
|
ep = find_end_of_layout(document.body, bp)
|
|
if ep == -1:
|
|
document.warning("Malformed LyX document! No end of layout found.")
|
|
flex += 1
|
|
continue
|
|
|
|
document.body[ep : flexEnd + 1] = put_cmd_in_ert("{}\\end{cBoxD}")
|
|
document.body[flex : bp + 1] = put_cmd_in_ert("\\begin{cBoxD}")
|
|
flex += 1
|
|
|
|
|
|
def revert_tcolorbox_7(document):
|
|
"Reverts the Flex:Custom_Color_Box_5 inset of tcolorbox to TeX-code"
|
|
|
|
i = find_token(document.header, "tcolorbox", 0)
|
|
if i == -1:
|
|
return
|
|
|
|
flex = 0
|
|
while True:
|
|
flex = find_token(document.body, "\\begin_inset Flex Custom Color Box 5", flex)
|
|
if flex == -1:
|
|
return
|
|
|
|
flexEnd = find_end_of_inset(document.body, flex)
|
|
if flexEnd == -1:
|
|
document.warning("Malformed LyX document! No end of Flex Custom Color Box 5 found.")
|
|
flex += 1
|
|
continue
|
|
|
|
revert_Argument_to_TeX_brace(document, flex, flexEnd, 1, 1, True, True, False)
|
|
flexEnd = find_end_of_inset(document.body, flex)
|
|
if flexEnd == -1:
|
|
document.warning("Malformed LyX document! No end of Flex Subtitle found.")
|
|
flex += 1
|
|
continue
|
|
revert_Argument_to_TeX_brace(document, flex, flexEnd, 2, 2, True, False, False)
|
|
flexEnd = find_end_of_inset(document.body, flex)
|
|
if flexEnd == -1:
|
|
document.warning("Malformed LyX document! No end of Flex Custom Color Box 5 found.")
|
|
flex += 1
|
|
continue
|
|
|
|
bp = find_token(document.body, "\\begin_layout Plain Layout", flex)
|
|
if bp == -1:
|
|
document.warning(
|
|
"Malformed LyX document! No plain layout in Custom Color Box 5 found."
|
|
)
|
|
flex += 1
|
|
continue
|
|
|
|
ep = find_end_of_layout(document.body, bp)
|
|
if ep == -1:
|
|
document.warning("Malformed LyX document! No end of layout found.")
|
|
flex += 1
|
|
continue
|
|
|
|
document.body[ep : flexEnd + 1] = put_cmd_in_ert("{}\\end{cBoxE}")
|
|
document.body[flex : bp + 1] = put_cmd_in_ert("\\begin{cBoxE}")
|
|
flex += 1
|
|
|
|
|
|
def revert_tcolorbox_8(document):
|
|
"Reverts the layout New Color Box Type of tcolorbox to TeX-code"
|
|
|
|
i = 0
|
|
while True:
|
|
i = find_token(document.body, "\\begin_layout New Color Box Type", i)
|
|
if i == -1:
|
|
return
|
|
|
|
j = find_end_of_layout(document.body, i)
|
|
if j == -1:
|
|
document.warning(
|
|
"Malformed LyX document! No end of New Color Box Type layout found."
|
|
)
|
|
i += 1
|
|
continue
|
|
|
|
wasOpt = revert_Argument_to_TeX_brace(document, i, j, 1, 1, False, True, True)
|
|
j = find_end_of_layout(document.body, i)
|
|
if j == -1:
|
|
document.warning(
|
|
"Malformed LyX document! No end of New Color Box Type layout found."
|
|
)
|
|
i += 1
|
|
continue
|
|
revert_Argument_to_TeX_brace(document, i, j, 2, 2, False, False, True)
|
|
j = find_end_of_layout(document.body, i)
|
|
if j == -1:
|
|
document.warning(
|
|
"Malformed LyX document! No end of New Color Box Type layout found."
|
|
)
|
|
i += 1
|
|
continue
|
|
revert_Argument_to_TeX_brace(document, i, j, 3, 4, False, True, False)
|
|
j = find_end_of_layout(document.body, i)
|
|
if j == -1:
|
|
document.warning(
|
|
"Malformed LyX document! No end of New Color Box Type layout found."
|
|
)
|
|
i += 1
|
|
continue
|
|
document.body[i] = document.body[i].replace(
|
|
"\\begin_layout New Color Box Type", "\\begin_layout Standard"
|
|
)
|
|
document.body[i + 1 : i + 1] = put_cmd_in_ert("\\newtcolorbox")
|
|
k = find_end_of_inset(document.body, j)
|
|
document.body[k + 2 : j + 2] = put_cmd_in_ert("{") + [
|
|
"\\begin_inset ERT",
|
|
"status collapsed",
|
|
"\\begin_layout Plain Layout",
|
|
]
|
|
j = find_token(document.body, "\\begin_layout Standard", j + 1)
|
|
document.body[j - 2 : j - 2] = ["\\end_layout", "\\end_inset"] + put_cmd_in_ert("}")
|
|
i += 1
|
|
|
|
|
|
def revert_moderncv_1(document):
|
|
"Reverts the new inset of moderncv to TeX-code in preamble"
|
|
|
|
if document.textclass != "moderncv":
|
|
return
|
|
i = 0
|
|
j = 0
|
|
lineArg = 0
|
|
while True:
|
|
# at first revert the new styles
|
|
# \moderncvicons
|
|
i = find_token(document.body, "\\begin_layout CVIcons", 0)
|
|
if i == -1:
|
|
return
|
|
j = find_end_of_layout(document.body, i)
|
|
if j == -1:
|
|
document.warning("Malformed LyX document: Can't find end of CVIcons layout")
|
|
i += 1
|
|
continue
|
|
content = lyx2latex(document, document.body[i : j + 1])
|
|
add_to_preamble(document, ["\\moderncvicons{" + content + "}"])
|
|
del document.body[i : j + 1]
|
|
# \hintscolumnwidth
|
|
i = find_token(document.body, "\\begin_layout CVColumnWidth", 0)
|
|
if i == -1:
|
|
return
|
|
j = find_end_of_layout(document.body, i)
|
|
if j == -1:
|
|
document.warning("Malformed LyX document: Can't find end of CVColumnWidth layout")
|
|
i += 1
|
|
continue
|
|
content = lyx2latex(document, document.body[i : j + 1])
|
|
add_to_preamble(document, ["\\setlength{\\hintscolumnwidth}{" + content + "}"])
|
|
del document.body[i : j + 1]
|
|
# now change the new styles to the obsolete ones
|
|
# \name
|
|
i = find_token(document.body, "\\begin_layout Name", 0)
|
|
if i == -1:
|
|
return
|
|
j = find_end_of_layout(document.body, i)
|
|
if j == -1:
|
|
document.warning("Malformed LyX document: Can't find end of Name layout")
|
|
i += 1
|
|
continue
|
|
lineArg = find_token(document.body, "\\begin_inset Argument 1", i)
|
|
if lineArg > j and j != 0:
|
|
return
|
|
if lineArg != -1:
|
|
beginPlain = find_token(document.body, "\\begin_layout Plain Layout", lineArg)
|
|
# we have to assure that no other inset is in the Argument
|
|
beginInset = find_token(document.body, "\\begin_inset", beginPlain)
|
|
endInset = find_token(document.body, "\\end_inset", beginPlain)
|
|
k = beginPlain + 1
|
|
l = k
|
|
while beginInset < endInset and beginInset != -1:
|
|
beginInset = find_token(document.body, "\\begin_inset", k)
|
|
endInset = find_token(document.body, "\\end_inset", l)
|
|
k = beginInset + 1
|
|
l = endInset + 1
|
|
Arg2 = document.body[l + 5 : l + 6]
|
|
# rename the style
|
|
document.body[i : i + 1] = ["\\begin_layout FirstName"]
|
|
# delete the Argument inset
|
|
del document.body[endInset - 2 : endInset + 3]
|
|
del document.body[lineArg : beginPlain + 1]
|
|
document.body[i + 4 : i + 4] = (
|
|
["\\begin_layout FamilyName"] + Arg2 + ["\\end_layout"] + [""]
|
|
)
|
|
|
|
|
|
def revert_moderncv_2(document):
|
|
"Reverts the phone inset of moderncv to the obsoleted mobile or fax"
|
|
|
|
if document.textclass != "moderncv":
|
|
return
|
|
i = 0
|
|
j = 0
|
|
lineArg = 0
|
|
while True:
|
|
# \phone
|
|
i = find_token(document.body, "\\begin_layout Phone", i)
|
|
if i == -1:
|
|
return
|
|
j = find_end_of_layout(document.body, i)
|
|
if j == -1:
|
|
document.warning("Malformed LyX document: Can't find end of Phone layout")
|
|
i += 1
|
|
return
|
|
lineArg = find_token(document.body, "\\begin_inset Argument 1", i)
|
|
if lineArg > j and j != 0:
|
|
i += 1
|
|
continue
|
|
if lineArg != -1:
|
|
beginPlain = find_token(document.body, "\\begin_layout Plain Layout", lineArg)
|
|
# we have to assure that no other inset is in the Argument
|
|
beginInset = find_token(document.body, "\\begin_inset", beginPlain)
|
|
endInset = find_token(document.body, "\\end_inset", beginPlain)
|
|
k = beginPlain + 1
|
|
l = k
|
|
while beginInset < endInset and beginInset != -1:
|
|
beginInset = find_token(document.body, "\\begin_inset", k)
|
|
endInset = find_token(document.body, "\\end_inset", l)
|
|
k = beginInset + 1
|
|
l = endInset + 1
|
|
Arg = document.body[beginPlain + 1 : beginPlain + 2]
|
|
# rename the style
|
|
if Arg[0] == "mobile":
|
|
document.body[i : i + 1] = ["\\begin_layout Mobile"]
|
|
if Arg[0] == "fax":
|
|
document.body[i : i + 1] = ["\\begin_layout Fax"]
|
|
# delete the Argument inset
|
|
del document.body[endInset - 2 : endInset + 1]
|
|
del document.body[lineArg : beginPlain + 3]
|
|
i += 1
|
|
|
|
|
|
def convert_moderncv_phone(document):
|
|
"Convert the Fax and Mobile inset of moderncv to the new phone inset"
|
|
|
|
if document.textclass != "moderncv":
|
|
return
|
|
i = 0
|
|
j = 0
|
|
lineArg = 0
|
|
|
|
phone_dict = {
|
|
"Mobile": "mobile",
|
|
"Fax": "fax",
|
|
}
|
|
|
|
rx = re.compile(r"^\\begin_layout (\S+)$")
|
|
while True:
|
|
# substitute \fax and \mobile by \phone[fax] and \phone[mobile], respectively
|
|
i = find_token(document.body, "\\begin_layout", i)
|
|
if i == -1:
|
|
return
|
|
|
|
m = rx.match(document.body[i])
|
|
val = ""
|
|
if m:
|
|
val = m.group(1)
|
|
if val not in list(phone_dict.keys()):
|
|
i += 1
|
|
continue
|
|
j = find_end_of_layout(document.body, i)
|
|
if j == -1:
|
|
document.warning("Malformed LyX document: Can't find end of Mobile layout")
|
|
i += 1
|
|
return
|
|
|
|
document.body[i : i + 1] = [
|
|
"\\begin_layout Phone",
|
|
"\\begin_inset Argument 1",
|
|
"status open",
|
|
"",
|
|
"\\begin_layout Plain Layout",
|
|
phone_dict[val],
|
|
"\\end_layout",
|
|
"",
|
|
"\\end_inset",
|
|
"",
|
|
]
|
|
|
|
|
|
def convert_moderncv_name(document):
|
|
"Convert the FirstName and LastName layout of moderncv to the general Name layout"
|
|
|
|
if document.textclass != "moderncv":
|
|
return
|
|
|
|
fnb = 0 # Begin of FirstName inset
|
|
fne = 0 # End of FirstName inset
|
|
lnb = 0 # Begin of LastName (FamilyName) inset
|
|
lne = 0 # End of LastName (FamilyName) inset
|
|
nb = 0 # Begin of substituting Name inset
|
|
ne = 0 # End of substituting Name inset
|
|
FirstName = [] # FirstName content
|
|
FamilyName = [] # LastName content
|
|
|
|
while True:
|
|
# locate FirstName
|
|
fnb = find_token(document.body, "\\begin_layout FirstName", fnb)
|
|
if fnb != -1:
|
|
fne = find_end_of_layout(document.body, fnb)
|
|
if fne == -1:
|
|
document.warning("Malformed LyX document: Can't find end of FirstName layout")
|
|
return
|
|
FirstName = document.body[fnb + 1 : fne]
|
|
# locate FamilyName
|
|
lnb = find_token(document.body, "\\begin_layout FamilyName", lnb)
|
|
if lnb != -1:
|
|
lne = find_end_of_layout(document.body, lnb)
|
|
if lne == -1:
|
|
document.warning("Malformed LyX document: Can't find end of FamilyName layout")
|
|
return
|
|
FamilyName = document.body[lnb + 1 : lne]
|
|
# Determine the region for the substituting Name layout
|
|
if fnb == -1 and lnb == -1: # Neither FirstName nor FamilyName exists -> Do nothing
|
|
return
|
|
elif fnb == -1: # Only FamilyName exists -> New Name insets replaces that
|
|
nb = lnb
|
|
ne = lne
|
|
elif lnb == -1: # Only FirstName exists -> New Name insets replaces that
|
|
nb = fnb
|
|
ne = fne
|
|
elif fne > lne: # FirstName position before FamilyName -> New Name insets spans
|
|
nb = lnb # from FamilyName begin
|
|
ne = fne # to FirstName end
|
|
else: # FirstName position before FamilyName -> New Name insets spans
|
|
nb = fnb # from FirstName begin
|
|
ne = lne # to FamilyName end
|
|
|
|
# Insert the substituting layout now. If FirstName exists, use an otpional argument.
|
|
if FirstName == []:
|
|
document.body[nb : ne + 1] = (
|
|
["\\begin_layout Name"] + FamilyName + ["\\end_layout", ""]
|
|
)
|
|
else:
|
|
document.body[nb : ne + 1] = (
|
|
[
|
|
"\\begin_layout Name",
|
|
"\\begin_inset Argument 1",
|
|
"status open",
|
|
"",
|
|
"\\begin_layout Plain Layout",
|
|
]
|
|
+ FirstName
|
|
+ ["\\end_layout", "", "\\end_inset", ""]
|
|
+ FamilyName
|
|
+ ["\\end_layout", ""]
|
|
)
|
|
|
|
|
|
def revert_achemso(document):
|
|
"Reverts the flex inset Latin to TeX code"
|
|
|
|
if document.textclass != "achemso":
|
|
return
|
|
i = 0
|
|
j = 0
|
|
while True:
|
|
i = find_token(document.body, "\\begin_inset Flex Latin", i)
|
|
if i != -1:
|
|
j = find_end_of_inset(document.body, i)
|
|
else:
|
|
return
|
|
if j != -1:
|
|
beginPlain = find_token(document.body, "\\begin_layout Plain Layout", i)
|
|
endPlain = find_end_of_layout(document.body, beginPlain)
|
|
content = lyx2latex(document, document.body[beginPlain:endPlain])
|
|
document.body[i : j + 1] = put_cmd_in_ert("\\latin{" + content + "}")
|
|
else:
|
|
document.warning("Malformed LyX document: Can't find end of flex inset Latin")
|
|
return
|
|
i += 1
|
|
|
|
|
|
fontsettings = [
|
|
"\\font_roman",
|
|
"\\font_sans",
|
|
"\\font_typewriter",
|
|
"\\font_math",
|
|
"\\font_sf_scale",
|
|
"\\font_tt_scale",
|
|
]
|
|
fontdefaults = ["default", "default", "default", "auto", "100", "100"]
|
|
fontquotes = [True, True, True, True, False, False]
|
|
|
|
|
|
def convert_fontsettings(document):
|
|
"Duplicate font settings"
|
|
|
|
i = find_token(document.header, "\\use_non_tex_fonts ", 0)
|
|
if i == -1:
|
|
document.warning("Malformed LyX document: No \\use_non_tex_fonts!")
|
|
use_non_tex_fonts = "false"
|
|
else:
|
|
use_non_tex_fonts = get_value(document.header, "\\use_non_tex_fonts", i)
|
|
j = 0
|
|
for f in fontsettings:
|
|
i = find_token(document.header, f + " ", 0)
|
|
if i == -1:
|
|
document.warning("Malformed LyX document: No " + f + "!")
|
|
# we can fix that
|
|
# note that with i = -1, this will insert at the end
|
|
# of the header
|
|
value = fontdefaults[j]
|
|
else:
|
|
value = document.header[i][len(f) :].strip()
|
|
if fontquotes[j]:
|
|
if use_non_tex_fonts == "true":
|
|
document.header[i : i + 1] = [f + ' "' + fontdefaults[j] + '" "' + value + '"']
|
|
else:
|
|
document.header[i : i + 1] = [f + ' "' + value + '" "' + fontdefaults[j] + '"']
|
|
else:
|
|
if use_non_tex_fonts == "true":
|
|
document.header[i : i + 1] = [f + " " + fontdefaults[j] + " " + value]
|
|
else:
|
|
document.header[i : i + 1] = [f + " " + value + " " + fontdefaults[j]]
|
|
j = j + 1
|
|
|
|
|
|
def revert_fontsettings(document):
|
|
"Merge font settings"
|
|
|
|
i = find_token(document.header, "\\use_non_tex_fonts ", 0)
|
|
if i == -1:
|
|
document.warning("Malformed LyX document: No \\use_non_tex_fonts!")
|
|
use_non_tex_fonts = "false"
|
|
else:
|
|
use_non_tex_fonts = get_value(document.header, "\\use_non_tex_fonts", i)
|
|
j = 0
|
|
for f in fontsettings:
|
|
i = find_token(document.header, f + " ", 0)
|
|
if i == -1:
|
|
document.warning("Malformed LyX document: No " + f + "!")
|
|
j = j + 1
|
|
continue
|
|
line = get_value(document.header, f, i)
|
|
if fontquotes[j]:
|
|
q1 = line.find('"')
|
|
q2 = line.find('"', q1 + 1)
|
|
q3 = line.find('"', q2 + 1)
|
|
q4 = line.find('"', q3 + 1)
|
|
if q1 == -1 or q2 == -1 or q3 == -1 or q4 == -1:
|
|
document.warning("Malformed LyX document: Missing quotes!")
|
|
j = j + 1
|
|
continue
|
|
if use_non_tex_fonts == "true":
|
|
document.header[i : i + 1] = [f + " " + line[q3 + 1 : q4]]
|
|
else:
|
|
document.header[i : i + 1] = [f + " " + line[q1 + 1 : q2]]
|
|
else:
|
|
if use_non_tex_fonts == "true":
|
|
document.header[i : i + 1] = [f + " " + line.split()[1]]
|
|
else:
|
|
document.header[i : i + 1] = [f + " " + line.split()[0]]
|
|
j = j + 1
|
|
|
|
|
|
def revert_solution(document):
|
|
"Reverts the solution environment of the theorem module to TeX code"
|
|
|
|
# Do we use one of the modules that provides Solution?
|
|
have_mod = False
|
|
mods = document.get_module_list()
|
|
for mod in mods:
|
|
if (
|
|
mod == "theorems-std"
|
|
or mod == "theorems-bytype"
|
|
or mod == "theorems-ams"
|
|
or mod == "theorems-ams-bytype"
|
|
):
|
|
have_mod = True
|
|
break
|
|
if not have_mod:
|
|
return
|
|
|
|
consecutive = False
|
|
is_starred = False
|
|
i = 0
|
|
while True:
|
|
i = find_token(document.body, "\\begin_layout Solution", i)
|
|
if i == -1:
|
|
return
|
|
|
|
is_starred = document.body[i].startswith("\\begin_layout Solution*")
|
|
if is_starred == True:
|
|
LaTeXName = "sol*"
|
|
LyXName = "Solution*"
|
|
theoremName = "newtheorem*"
|
|
else:
|
|
LaTeXName = "sol"
|
|
LyXName = "Solution"
|
|
theoremName = "newtheorem"
|
|
|
|
j = find_end_of_layout(document.body, i)
|
|
if j == -1:
|
|
document.warning("Malformed LyX document: Can't find end of " + LyXName + " layout")
|
|
i += 1
|
|
continue
|
|
|
|
# if this is not a consecutive env, add start command
|
|
begcmd = []
|
|
if not consecutive:
|
|
begcmd = put_cmd_in_ert("\\begin{%s}" % (LaTeXName))
|
|
|
|
# has this a consecutive theorem of same type?
|
|
consecutive = document.body[j + 2] == "\\begin_layout " + LyXName
|
|
|
|
# if this is not followed by a consecutive env, add end command
|
|
if not consecutive:
|
|
document.body[j : j + 1] = put_cmd_in_ert("\\end{%s}" % (LaTeXName)) + [
|
|
"\\end_layout"
|
|
]
|
|
|
|
document.body[i : i + 1] = ["\\begin_layout Standard", ""] + begcmd
|
|
|
|
add_to_preamble(document, "\\theoremstyle{definition}")
|
|
if is_starred or mod == "theorems-bytype" or mod == "theorems-ams-bytype":
|
|
add_to_preamble(
|
|
document, f"\\{theoremName}{{{LaTeXName}}}{{\\protect\\solutionname}}"
|
|
)
|
|
else: # mod == "theorems-std" or mod == "theorems-ams" and not is_starred
|
|
add_to_preamble(
|
|
document,
|
|
f"\\{theoremName}{{{LaTeXName}}}[thm]{{\\protect\\solutionname}}",
|
|
)
|
|
|
|
add_to_preamble(document, "\\providecommand{\\solutionname}{Solution}")
|
|
i = j
|
|
|
|
|
|
def revert_verbatim_star(document):
|
|
from lyx_2_1 import revert_verbatim
|
|
|
|
revert_verbatim(document, True)
|
|
|
|
|
|
def convert_save_props(document):
|
|
"Add save_transient_properties parameter."
|
|
i = find_token(document.header, "\\begin_header", 0)
|
|
if i == -1:
|
|
document.warning("Malformed lyx document: Missing '\\begin_header'.")
|
|
return
|
|
document.header.insert(i + 1, "\\save_transient_properties true")
|
|
|
|
|
|
def revert_save_props(document):
|
|
"Remove save_transient_properties parameter."
|
|
i = find_token(document.header, "\\save_transient_properties", 0)
|
|
if i == -1:
|
|
return
|
|
del document.header[i]
|
|
|
|
|
|
def convert_info_tabular_feature(document):
|
|
def f(arg):
|
|
return arg.replace("inset-modify tabular", "tabular-feature")
|
|
|
|
convert_info_insets(document, "shortcut(s)?|icon", f)
|
|
|
|
|
|
def revert_info_tabular_feature(document):
|
|
def f(arg):
|
|
return arg.replace("tabular-feature", "inset-modify tabular")
|
|
|
|
convert_info_insets(document, "shortcut(s)?|icon", f)
|
|
|
|
|
|
##
|
|
# Conversion hub
|
|
#
|
|
|
|
supported_versions = ["2.2.0", "2.2"]
|
|
convert = [
|
|
[475, [convert_separator]],
|
|
# nothing to do for 476: We consider it a bug that older versions
|
|
# did not load amsmath automatically for these commands, and do not
|
|
# want to hardcode amsmath off.
|
|
[476, []],
|
|
[477, []],
|
|
[478, []],
|
|
[479, []],
|
|
[480, []],
|
|
[481, [convert_dashes]],
|
|
[482, [convert_phrases]],
|
|
[483, [convert_specialchar]],
|
|
[484, []],
|
|
[485, []],
|
|
[486, []],
|
|
[487, []],
|
|
[488, [convert_newgloss]],
|
|
[489, [convert_BoxFeatures]],
|
|
[490, [convert_origin]],
|
|
[491, []],
|
|
[492, [convert_colorbox]],
|
|
[493, []],
|
|
[494, []],
|
|
[495, [convert_subref]],
|
|
[496, [convert_nounzip]],
|
|
[497, [convert_external_bbox]],
|
|
[498, []],
|
|
[499, [convert_moderncv_phone, convert_moderncv_name]],
|
|
[500, []],
|
|
[501, [convert_fontsettings]],
|
|
[502, []],
|
|
[503, []],
|
|
[504, [convert_save_props]],
|
|
[505, []],
|
|
[506, [convert_info_tabular_feature]],
|
|
[507, [convert_longtable_label]],
|
|
[508, [convert_parbreak]],
|
|
]
|
|
|
|
revert = [
|
|
[507, [revert_parbreak]],
|
|
[506, [revert_longtable_label]],
|
|
[505, [revert_info_tabular_feature]],
|
|
[504, []],
|
|
[503, [revert_save_props]],
|
|
[502, [revert_verbatim_star]],
|
|
[501, [revert_solution]],
|
|
[500, [revert_fontsettings]],
|
|
[499, [revert_achemso]],
|
|
[498, [revert_moderncv_1, revert_moderncv_2]],
|
|
[
|
|
497,
|
|
[
|
|
revert_tcolorbox_1,
|
|
revert_tcolorbox_2,
|
|
revert_tcolorbox_3,
|
|
revert_tcolorbox_4,
|
|
revert_tcolorbox_5,
|
|
revert_tcolorbox_6,
|
|
revert_tcolorbox_7,
|
|
revert_tcolorbox_8,
|
|
],
|
|
],
|
|
[496, [revert_external_bbox]],
|
|
[495, []], # nothing to do since the noUnzip parameter was optional
|
|
[494, [revert_subref]],
|
|
[493, [revert_jss]],
|
|
[492, [revert_mathmulticol]],
|
|
[491, [revert_colorbox]],
|
|
[490, [revert_textcolor]],
|
|
[489, [revert_origin]],
|
|
[488, [revert_BoxFeatures]],
|
|
[487, [revert_newgloss, revert_glossgroup]],
|
|
[486, [revert_forest]],
|
|
[485, [revert_ex_itemargs]],
|
|
[484, [revert_sigplan_doi]],
|
|
[483, [revert_georgian]],
|
|
[482, [revert_specialchar]],
|
|
[481, [revert_phrases]],
|
|
[480, [revert_dashes]],
|
|
[479, [revert_question_env]],
|
|
[478, [revert_beamer_lemma]],
|
|
[477, [revert_xarrow]],
|
|
[476, [revert_swissgerman]],
|
|
[475, [revert_smash]],
|
|
[474, [revert_separator]],
|
|
]
|
|
|
|
|
|
if __name__ == "__main__":
|
|
pass
|