X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=lib%2Flyx2lyx%2Flyx_1_4.py;h=c043472ff0646f56f18ebb06aae7e394c12777c7;hb=b8227ebda0a2a8127731749d2caaa5dae45ef5d7;hp=c2039f2e48f78158e25f28a00727d13bdc0127d7;hpb=2796b1fe323c827c738dcb885f3940931a5f6299;p=lyx.git diff --git a/lib/lyx2lyx/lyx_1_4.py b/lib/lyx2lyx/lyx_1_4.py index c2039f2e48..c043472ff0 100644 --- a/lib/lyx2lyx/lyx_1_4.py +++ b/lib/lyx2lyx/lyx_1_4.py @@ -23,7 +23,8 @@ from os import access, F_OK import os.path from parser_tools import find_token, find_end_of_inset, get_next_paragraph, \ get_paragraph, get_value, del_token, is_nonempty_line,\ - find_tokens, find_end_of, find_token2, find_re + find_tokens, find_end_of, find_token2, find_re,\ + get_layout from sys import stdin from string import replace, split, find, strip, join @@ -65,8 +66,38 @@ def convert_spaces(file): def revert_spaces(file): + regexp = re.compile(r'(.*)(\\InsetSpace\s+)(\S+)') + i = 0 + while 1: + i = find_re(file.body, regexp, i) + if i == -1: + break + space = regexp.match(file.body[i]).group(3) + prepend = regexp.match(file.body[i]).group(1) + if space == '~': + file.body[i] = regexp.sub(prepend + '\\SpecialChar ~', file.body[i]) + i = i + 1 + else: + file.body[i] = regexp.sub(prepend, file.body[i]) + file.body[i+1:i+1] = '' + if space == "\\space": + space = "\\ " + i = insert_ert(file.body, i+1, 'Collapsed', space, file.format - 1, file.default_layout) + +## +# \InsetSpace \, -> \InsetSpace \thinspace{} +# \InsetSpace \space -> \InsetSpace \space{} +# +def rename_spaces(file): + for i in range(len(file.body)): + file.body[i] = replace(file.body[i],"\\InsetSpace \\space","\\InsetSpace \\space{}") + file.body[i] = replace(file.body[i],"\\InsetSpace \,","\\InsetSpace \\thinspace{}") + + +def revert_space_names(file): for i in range(len(file.body)): - file.body[i] = replace(file.body[i],"\\InsetSpace ~", "\\SpecialChar ~") + file.body[i] = replace(file.body[i],"\\InsetSpace \\space{}","\\InsetSpace \\space") + file.body[i] = replace(file.body[i],"\\InsetSpace \\thinspace{}","\\InsetSpace \\,") ## @@ -99,7 +130,7 @@ def revert_eqref(file): break eqref = lyx_support_escape(regexp.sub("", file.body[i])) file.body[i:i+1] = ["\\begin_inset ERT", "status Collapsed", "", - "\\layout Standard", "", "\\backslash ", + '\\layout %s' % file.default_layout, "", "\\backslash ", "eqref" + eqref] i = i + 7 @@ -221,10 +252,10 @@ def convert_comment(file): if i == -1: return - file.body[i:i+1] = ["\\layout Standard","","", + file.body[i:i+1] = ['\\layout %s' % file.default_layout,"","", "\\begin_inset Comment", "collapsed true","", - "\\layout Standard"] + '\\layout %s' % file.default_layout] i = i + 7 while 1: @@ -273,7 +304,7 @@ def convert_comment(file): file.body[i:i] = ["\\end_inset"] i = i + 1 break - file.body[i:i+1] = ["\\layout Standard"] + file.body[i:i+1] = ['\\layout %s' % file.default_layout] i = i + 1 @@ -506,15 +537,18 @@ def revert_end_document(file): #\newpage # #\lyxline -#\begin_inset VSpace xxx +#\begin_inset ERT +#\begin layout Standard +#\backslash +#vspace{-1\backslash +#parskip} +#\end_layout #\end_inset # -#\end_layout -#\begin_layout Standard +#\begin_inset VSpace xxx +#\end_inset # #0 -#\end_layout -#\begin_layout Standard # #\begin_inset VSpace xxx #\end_inset @@ -528,11 +562,16 @@ def convert_breaks(file): 'labelwidthstring', 'line_bottom', 'line_top', 'noindent', 'pagebreak_bottom', 'pagebreak_top', 'paragraph_spacing', 'start_of_appendix') + font_attributes = ['\\family', '\\series', '\\shape', '\\emph', + '\\numeric', '\\bar', '\\noun', '\\color', '\\lang'] + attribute_values = ['default', 'default', 'default', 'default', + 'default', 'default', 'default', 'none', file.language] i = 0 while 1: i = find_token(file.body, "\\begin_layout", i) if i == -1: return + layout = get_layout(file.body[i], file.default_layout) i = i + 1 # Merge all paragraph parameters into a single line @@ -552,6 +591,28 @@ def convert_breaks(file): if line_top == -1 and line_bot == -1 and pb_bot == -1 and pb_top == -1 and vspace_top == -1 and vspace_bot == -1: continue + # Do we have a nonstandard paragraph? We need to create new paragraphs + # if yes to avoid putting lyxline etc. inside of special environments. + # This is wrong for itemize and enumerate environments, but it is + # impossible to convert these correctly. + # We want to avoid new paragraphs if possible becauase we want to + # inherit font sizes. + nonstandard = 0 + if (not file.is_default_layout(layout) or + find(file.body[i],"\\align") != -1 or + find(file.body[i],"\\labelwidthstring") != -1 or + find(file.body[i],"\\noindent") != -1): + nonstandard = 1 + + # get the font size of the beginning of this paragraph, since we need + # it for the lyxline inset + j = i + 1 + while not is_nonempty_line(file.body[j]): + j = j + 1 + size_top = "" + if find(file.body[j], "\\size") != -1: + size_top = split(file.body[j])[1] + for tag in "\\line_top", "\\line_bottom", "\\pagebreak_top", "\\pagebreak_bottom": file.body[i] = replace(file.body[i], tag, "") @@ -574,11 +635,14 @@ def convert_breaks(file): file.body[i] = strip(file.body[i]) i = i + 1 - # Create an empty paragraph for line and page break that belong - # above the paragraph + # Create an empty paragraph or paragraph fragment for line and + # page break that belong above the paragraph if pb_top !=-1 or line_top != -1 or vspace_top != -1: - paragraph_above = ['','\\begin_layout Standard','',''] + paragraph_above = list() + if nonstandard: + # We need to create an extra paragraph for nonstandard environments + paragraph_above = ['\\begin_layout %s' % file.default_layout, ''] if pb_top != -1: paragraph_above.extend(['\\newpage ','']) @@ -587,12 +651,23 @@ def convert_breaks(file): paragraph_above.extend(['\\begin_inset VSpace ' + vspace_top_value,'\\end_inset','','']) if line_top != -1: - paragraph_above.extend(['\\lyxline ','']) - - paragraph_above.extend(['\\end_layout','']) + if size_top != '': + paragraph_above.extend(['\\size ' + size_top + ' ']) + # We need an additional vertical space of -\parskip. + # We can't use the vspace inset because it does not know \parskip. + paragraph_above.extend(['\\lyxline ', '', '']) + insert_ert(paragraph_above, len(paragraph_above) - 1, 'Collapsed', + '\\vspace{-1\\parskip}\n', file.format + 1, file.default_layout) + paragraph_above.extend(['']) + + if nonstandard: + paragraph_above.extend(['\\end_layout ','']) + # insert new paragraph above the current paragraph + file.body[i-2:i-2] = paragraph_above + else: + # insert new lines at the beginning of the current paragraph + file.body[i:i] = paragraph_above - #inset new paragraph above the current paragraph - file.body[i-2:i-2] = paragraph_above i = i + len(paragraph_above) # Ensure that nested style are converted later. @@ -603,10 +678,34 @@ def convert_breaks(file): if pb_bot !=-1 or line_bot != -1 or vspace_bot != -1: - paragraph_below = ['','\\begin_layout Standard','',''] + # get the font size of the end of this paragraph + size_bot = size_top + j = i + 1 + while j < k: + if find(file.body[j], "\\size") != -1: + size_bot = split(file.body[j])[1] + j = j + 1 + elif find(file.body[j], "\\begin_inset") != -1: + # skip insets + j = find_end_of_inset(file.body, j) + else: + j = j + 1 + + paragraph_below = list() + if nonstandard: + # We need to create an extra paragraph for nonstandard environments + paragraph_below = ['', '\\begin_layout %s' % file.default_layout, ''] + else: + for a in range(len(font_attributes)): + if find_token(file.body, font_attributes[a], i, k) != -1: + paragraph_below.extend([font_attributes[a] + ' ' + attribute_values[a]]) if line_bot != -1: + if nonstandard and size_bot != '': + paragraph_below.extend(['\\size ' + size_bot + ' ']) paragraph_below.extend(['\\lyxline ','']) + if size_bot != '': + paragraph_below.extend(['\\size default ']) if vspace_bot != -1: paragraph_below.extend(['\\begin_inset VSpace ' + vspace_bot_value,'\\end_inset','','']) @@ -614,10 +713,13 @@ def convert_breaks(file): if pb_bot != -1: paragraph_below.extend(['\\newpage ','']) - paragraph_below.extend(['\\end_layout','']) - - #inset new paragraph above the current paragraph - file.body[k + 1: k + 1] = paragraph_below + if nonstandard: + paragraph_below.extend(['\\end_layout ']) + # insert new paragraph below the current paragraph + file.body[k+1:k+1] = paragraph_below + else: + # insert new lines at the end of the current paragraph + file.body[k:k] = paragraph_below ## @@ -855,7 +957,7 @@ def convert_minipage(file): if file.body[i][:6] == "height": height = file.body[i][6:] # test for default value of 221 and convert it accordingly - if height == ' "0pt"': + if height == ' "0pt"' or height == ' "0"': height = ' "1pt"' del file.body[i] else: @@ -893,106 +995,382 @@ def convert_minipage(file): # ------------------------------------------------------------------------------------------- # Convert backslashes and '\n' into valid ERT code, append the converted # text to body[i] and return the (maybe incremented) line index i -def convert_ertbackslash(body, i, ert): +def convert_ertbackslash(body, i, ert, format, default_layout): for c in ert: if c == '\\': body[i] = body[i] + '\\backslash ' i = i + 1 body.insert(i, '') elif c == '\n': - body[i+1:i+1] = ['\\newline ', ''] - i = i + 2 + if format <= 240: + body[i+1:i+1] = ['\\newline ', ''] + i = i + 2 + else: + body[i+1:i+1] = ['\\end_layout', '', '\\begin_layout %s' % default_layout, ''] + i = i + 4 else: body[i] = body[i] + c return i -def convert_vspace(file): +# Converts lines in ERT code to LaTeX +# The surrounding \begin_layout ... \end_layout pair must not be included +def ert2latex(lines, format): + backslash = re.compile(r'\\backslash\s*$') + newline = re.compile(r'\\newline\s*$') + if format <= 224: + begin_layout = re.compile(r'\\layout\s*\S+$') + else: + begin_layout = re.compile(r'\\begin_layout\s*\S+$') + end_layout = re.compile(r'\\end_layout\s*$') + ert = '' + for i in range(len(lines)): + line = backslash.sub('\\\\', lines[i]) + if format <= 240: + if begin_layout.match(line): + line = '\n\n' + else: + line = newline.sub('\n', line) + else: + if begin_layout.match(line): + line = '\n' + if format > 224 and end_layout.match(line): + line = '' + ert = ert + line + return ert + + +# get all paragraph parameters. They can be all on one line or on several lines. +# lines[i] must be the first parameter line +def get_par_params(lines, i): + par_params = ('added_space_bottom', 'added_space_top', 'align', + 'labelwidthstring', 'line_bottom', 'line_top', 'noindent', + 'pagebreak_bottom', 'pagebreak_top', 'paragraph_spacing', + 'start_of_appendix') + # We cannot check for '\\' only because paragraphs may start e.g. + # with '\\backslash' + params = '' + while lines[i][:1] == '\\' and split(lines[i][1:])[0] in par_params: + params = params + ' ' + strip(lines[i]) + i = i + 1 + return strip(params) + + +# convert LyX font size to LaTeX fontsize +def lyxsize2latexsize(lyxsize): + sizes = {"tiny" : "tiny", "scriptsize" : "scriptsize", + "footnotesize" : "footnotesize", "small" : "small", + "normal" : "normalsize", "large" : "large", "larger" : "Large", + "largest" : "LARGE", "huge" : "huge", "giant" : "Huge"} + if lyxsize in sizes: + return '\\' + sizes[lyxsize] + return '' + + +# Change vspace insets, page breaks and lyxlines to paragraph options +# (if possible) or ERT +def revert_breaks(file): # Get default spaceamount i = find_token(file.header, '\\defskip', 0) if i == -1: - defskipamount = 'medskip' + defskipamount = 'medskip' else: - defskipamount = split(file.header[i])[1] + defskipamount = split(file.header[i])[1] + + keys = {"\\begin_inset" : "vspace", "\\lyxline" : "lyxline", + "\\newpage" : "newpage"} + keywords_top = {"vspace" : "\\added_space_top", "lyxline" : "\\line_top", + "newpage" : "\\pagebreak_top"} + keywords_bot = {"vspace" : "\\added_space_bottom", "lyxline" : "\\line_bottom", + "newpage" : "\\pagebreak_bottom"} + tokens = ["\\begin_inset VSpace", "\\lyxline", "\\newpage"] # Convert the insets i = 0 while 1: - i = find_token(file.body, '\\begin_inset VSpace', i) + i = find_tokens(file.body, tokens, i) if i == -1: return - spaceamount = split(file.body[i])[2] - - # Are we at the beginning or end of a paragraph? - paragraph_start = 1 - start = get_paragraph(file.body, i) + 1 - for k in range(start, i): - if is_nonempty_line(file.body[k]): - paragraph_start = 0 - break - paragraph_end = 1 - j = find_end_of_inset(file.body, i) - if j == -1: - file.warning("Malformed LyX file: Missing '\\end_inset'.") - i = i + 1 - continue - end = get_next_paragraph(file.body, i) - for k in range(j + 1, end): - if is_nonempty_line(file.body[k]): - paragraph_end = 0 - break - - # Convert to paragraph formatting if we are at the beginning or end - # of a paragraph and the resulting paragraph would not be empty - if ((paragraph_start and not paragraph_end) or - (paragraph_end and not paragraph_start)): - # The order is important: del and insert invalidate some indices - del file.body[j] - del file.body[i] - if paragraph_start: - file.body.insert(start, '\\added_space_top ' + spaceamount + ' ') - else: - file.body.insert(start, '\\added_space_bottom ' + spaceamount + ' ') - continue - # Convert to ERT - file.body[i:i+1] = ['\\begin_inset ERT', 'status Collapsed', '', - '\\layout Standard', '', '\\backslash '] - i = i + 6 - if spaceamount[-1] == '*': - spaceamount = spaceamount[:-1] - keep = 1 - else: - keep = 0 - - # Replace defskip by the actual value - if spaceamount == 'defskip': - spaceamount = defskipamount - - # LaTeX does not know \\smallskip* etc - if keep: - if spaceamount == 'smallskip': - spaceamount = '\\smallskipamount' - elif spaceamount == 'medskip': - spaceamount = '\\medskipamount' - elif spaceamount == 'bigskip': - spaceamount = '\\bigskipamount' - elif spaceamount == 'vfill': - spaceamount = '\\fill' - - # Finally output the LaTeX code - if (spaceamount == 'smallskip' or spaceamount == 'medskip' or - spaceamount == 'bigskip' or spaceamount == 'vfill'): - file.body.insert(i, spaceamount) - else : - if keep: - file.body.insert(i, 'vspace*{') - else: - file.body.insert(i, 'vspace{') - i = convert_ertbackslash(file.body, i, spaceamount) - file.body[i] = file.body[i] + '}' - i = i + 1 + # Are we at the beginning of a paragraph? + paragraph_start = 1 + this_par = get_paragraph(file.body, i, file.format - 1) + start = this_par + 1 + params = get_par_params(file.body, start) + size = "normal" + # Paragraph parameters may be on one or more lines. + # Find the start of the real paragraph text. + while file.body[start][:1] == '\\' and split(file.body[start])[0] in params: + start = start + 1 + for k in range(start, i): + if find(file.body[k], "\\size") != -1: + # store font size + size = split(file.body[k])[1] + elif is_nonempty_line(file.body[k]): + paragraph_start = 0 + break + # Find the end of the real paragraph text. + next_par = get_next_paragraph(file.body, i, file.format - 1) + if next_par == -1: + file.warning("Malformed LyX file: Missing next paragraph.") + i = i + 1 + continue + + # first line of our insets + inset_start = i + # last line of our insets + inset_end = inset_start + # Are we at the end of a paragraph? + paragraph_end = 1 + # start and end line numbers to delete if we convert this inset + del_lines = list() + # is this inset a lyxline above a paragraph? + top = list() + # raw inset information + lines = list() + # name of this inset + insets = list() + # font size of this inset + sizes = list() + + # Detect subsequent lyxline, vspace and pagebreak insets created by convert_breaks() + n = 0 + k = inset_start + while k < next_par: + if find_tokens(file.body, tokens, k) == k: + # inset to convert + lines.append(split(file.body[k])) + insets.append(keys[lines[n][0]]) + del_lines.append([k, k]) + top.append(0) + sizes.append(size) + n = n + 1 + inset_end = k + elif find(file.body[k], "\\size") != -1: + # store font size + size = split(file.body[k])[1] + elif find_token(file.body, "\\begin_inset ERT", k) == k: + ert_begin = find_token(file.body, "\\layout", k) + 1 + if ert_begin == 0: + file.warning("Malformed LyX file: Missing '\\layout'.") + continue + ert_end = find_end_of_inset(file.body, k) + if ert_end == -1: + file.warning("Malformed LyX file: Missing '\\end_inset'.") + continue + ert = ert2latex(file.body[ert_begin:ert_end], file.format - 1) + if (n > 0 and insets[n - 1] == "lyxline" and + ert == '\\vspace{-1\\parskip}\n'): + # vspace ERT created by convert_breaks() for top lyxline + top[n - 1] = 1 + del_lines[n - 1][1] = ert_end + inset_end = ert_end + k = ert_end + else: + paragraph_end = 0 + break + elif (n > 0 and insets[n - 1] == "vspace" and + find_token(file.body, "\\end_inset", k) == k): + # ignore end of vspace inset + del_lines[n - 1][1] = k + inset_end = k + elif is_nonempty_line(file.body[k]): + paragraph_end = 0 + break + k = k + 1 + + # Determine space amount for vspace insets + spaceamount = list() + arguments = list() + for k in range(n): + if insets[k] == "vspace": + spaceamount.append(lines[k][2]) + arguments.append(' ' + spaceamount[k] + ' ') + else: + spaceamount.append('') + arguments.append(' ') + + # Can we convert to top paragraph parameters? + before = 0 + if ((n == 3 and insets[0] == "newpage" and insets[1] == "vspace" and + insets[2] == "lyxline" and top[2]) or + (n == 2 and + ((insets[0] == "newpage" and insets[1] == "vspace") or + (insets[0] == "newpage" and insets[1] == "lyxline" and top[1]) or + (insets[0] == "vspace" and insets[1] == "lyxline" and top[1]))) or + (n == 1 and insets[0] == "lyxline" and top[0])): + # These insets have been created before a paragraph by + # convert_breaks() + before = 1 + + # Can we convert to bottom paragraph parameters? + after = 0 + if ((n == 3 and insets[0] == "lyxline" and not top[0] and + insets[1] == "vspace" and insets[2] == "newpage") or + (n == 2 and + ((insets[0] == "lyxline" and not top[0] and insets[1] == "vspace") or + (insets[0] == "lyxline" and not top[0] and insets[1] == "newpage") or + (insets[0] == "vspace" and insets[1] == "newpage"))) or + (n == 1 and insets[0] == "lyxline" and not top[0])): + # These insets have been created after a paragraph by + # convert_breaks() + after = 1 + + if paragraph_start and paragraph_end: + # We are in a paragraph of our own. + # We must not delete this paragraph if it has parameters + if params == '': + # First try to merge with the previous paragraph. + # We try the previous paragraph first because we would + # otherwise need ERT for two subsequent vspaces. + prev_par = get_paragraph(file.body, this_par - 1, file.format - 1) + 1 + if prev_par > 0 and not before: + prev_params = get_par_params(file.body, prev_par + 1) + ert = 0 + # determine font size + prev_size = "normal" + k = prev_par + 1 + while file.body[k][:1] == '\\' and split(file.body[k])[0] in prev_params: + k = k + 1 + while k < this_par: + if find(file.body[k], "\\size") != -1: + prev_size = split(file.body[k])[1] + break + elif find(file.body[k], "\\begin_inset") != -1: + # skip insets + k = find_end_of_inset(file.body, k) + elif is_nonempty_line(file.body[k]): + break + k = k + 1 + for k in range(n): + if (keywords_bot[insets[k]] in prev_params or + (insets[k] == "lyxline" and sizes[k] != prev_size)): + ert = 1 + break + if not ert: + for k in range(n): + file.body.insert(prev_par + 1, + keywords_bot[insets[k]] + arguments[k]) + del file.body[this_par+n:next_par-1+n] + i = this_par + n + continue + # Then try next paragraph + if next_par > 0 and not after: + next_params = get_par_params(file.body, next_par + 1) + ert = 0 + while file.body[k][:1] == '\\' and split(file.body[k])[0] in next_params: + k = k + 1 + # determine font size + next_size = "normal" + k = next_par + 1 + while k < this_par: + if find(file.body[k], "\\size") != -1: + next_size = split(file.body[k])[1] + break + elif is_nonempty_line(file.body[k]): + break + k = k + 1 + for k in range(n): + if (keywords_top[insets[k]] in next_params or + (insets[k] == "lyxline" and sizes[k] != next_size)): + ert = 1 + break + if not ert: + for k in range(n): + file.body.insert(next_par + 1, + keywords_top[insets[k]] + arguments[k]) + del file.body[this_par:next_par-1] + i = this_par + continue + elif paragraph_start or paragraph_end: + # Convert to paragraph formatting if we are at the beginning or end + # of a paragraph and the resulting paragraph would not be empty + # The order is important: del and insert invalidate some indices + if paragraph_start: + keywords = keywords_top + else: + keywords = keywords_bot + ert = 0 + for k in range(n): + if keywords[insets[k]] in params: + ert = 1 + break + if not ert: + for k in range(n): + file.body.insert(this_par + 1, + keywords[insets[k]] + arguments[k]) + for j in range(k, n): + del_lines[j][0] = del_lines[j][0] + 1 + del_lines[j][1] = del_lines[j][1] + 1 + del file.body[del_lines[k][0]:del_lines[k][1]+1] + deleted = del_lines[k][1] - del_lines[k][0] + 1 + for j in range(k + 1, n): + del_lines[j][0] = del_lines[j][0] - deleted + del_lines[j][1] = del_lines[j][1] - deleted + i = this_par + continue + + # Convert the first inset to ERT. + # The others are converted in the next loop runs (if they exist) + if insets[0] == "vspace": + file.body[i:i+1] = ['\\begin_inset ERT', 'status Collapsed', '', + '\\layout %s' % file.default_layout, '', '\\backslash '] + i = i + 6 + if spaceamount[0][-1] == '*': + spaceamount[0] = spaceamount[0][:-1] + keep = 1 + else: + keep = 0 + + # Replace defskip by the actual value + if spaceamount[0] == 'defskip': + spaceamount[0] = defskipamount + + # LaTeX does not know \\smallskip* etc + if keep: + if spaceamount[0] == 'smallskip': + spaceamount[0] = '\\smallskipamount' + elif spaceamount[0] == 'medskip': + spaceamount[0] = '\\medskipamount' + elif spaceamount[0] == 'bigskip': + spaceamount[0] = '\\bigskipamount' + elif spaceamount[0] == 'vfill': + spaceamount[0] = '\\fill' + + # Finally output the LaTeX code + if (spaceamount[0] == 'smallskip' or spaceamount[0] == 'medskip' or + spaceamount[0] == 'bigskip' or spaceamount[0] == 'vfill'): + file.body.insert(i, spaceamount[0] + '{}') + else : + if keep: + file.body.insert(i, 'vspace*{') + else: + file.body.insert(i, 'vspace{') + i = convert_ertbackslash(file.body, i, spaceamount[0], file.format - 1, file.default_layout) + file.body[i] = file.body[i] + '}' + i = i + 1 + elif insets[0] == "lyxline": + file.body[i] = '' + latexsize = lyxsize2latexsize(size) + if latexsize == '': + file.warning("Could not convert LyX fontsize '%s' to LaTeX font size." % size) + latexsize = '\\normalsize' + i = insert_ert(file.body, i, 'Collapsed', + '\\lyxline{%s}' % latexsize, + file.format - 1, file.default_layout) + # We use \providecommand so that we don't get an error if native + # lyxlines are used (LyX writes first its own preamble and then + # the user specified one) + add_to_preamble(file, + ['% Commands inserted by lyx2lyx for lyxlines', + '\\providecommand{\\lyxline}[1]{', + ' {#1 \\vspace{1ex} \\hrule width \\columnwidth \\vspace{1ex}}' + '}']) + elif insets[0] == "newpage": + file.body[i] = '' + i = insert_ert(file.body, i, 'Collapsed', '\\newpage{}', + file.format - 1, file.default_layout) # Convert a LyX length into a LaTeX length @@ -1016,9 +1394,9 @@ def convert_len(len, special): # Convert a LyX length into valid ERT code and append it to body[i] # Return the (maybe incremented) line index i -def convert_ertlen(body, i, len, special): +def convert_ertlen(body, i, len, special, format, default_layout): # Convert backslashes and insert the converted length into body - return convert_ertbackslash(body, i, convert_len(len, special)) + return convert_ertbackslash(body, i, convert_len(len, special), format, default_layout) # Return the value of len without the unit in numerical form @@ -1032,11 +1410,18 @@ def len2value(len): # Convert text to ERT and insert it at body[i] # Return the index of the line after the inserted ERT -def insert_ert(body, i, status, text): - body[i:i] = ['\\begin_inset ERT', 'status ' + status, '', - '\\layout Standard', ''] - i = i + 5 - i = convert_ertbackslash(body, i, text) + 1 +def insert_ert(body, i, status, text, format, default_layout): + body[i:i] = ['\\begin_inset ERT', 'status ' + status, ''] + i = i + 3 + if format <= 224: + body[i:i] = ['\\layout %s' % default_layout, ''] + else: + body[i:i] = ['\\begin_layout %s' % default_layout, ''] + i = i + 1 # i points now to the just created empty line + i = convert_ertbackslash(body, i, text, format, default_layout) + 1 + if format > 224: + body[i:i] = ['\\end_layout'] + i = i + 1 body[i:i] = ['', '\\end_inset', ''] i = i + 3 return i @@ -1045,21 +1430,10 @@ def insert_ert(body, i, status, text): # Add text to the preamble if it is not already there. # Only the first line is checked! def add_to_preamble(file, text): - i = find_token(file.header, '\\begin_preamble', 0) - if i == -1: - file.header.extend(['\\begin_preamble'] + text + ['\\end_preamble']) + if find_token(file.preamble, text[0], 0) != -1: return - j = find_token(file.header, '\\end_preamble', i) - if j == -1: - file.warning("Malformed LyX file: Missing '\\end_preamble'.") - file.warning("Adding it now and hoping for the best.") - file.header.append('\\end_preamble') - j = len(file.header) - - if find_token(file.header, text[0], i, j) != -1: - return - file.header[j:j] = text + file.preamble.extend(text) def convert_frameless_box(file): @@ -1112,7 +1486,6 @@ def convert_frameless_box(file): if (params['use_parbox'] != '0' or params['has_inner_box'] != '1' or params['special'] != 'none' or - inner_pos[params['inner_pos']] != pos[params['position']] or params['height_special'] != 'totalheight' or len2value(params['height']) != 1.0): @@ -1186,7 +1559,7 @@ def convert_frameless_box(file): ert = ert + '\\let\\endminipage\\endlyxtolyxminipage%\n' old_i = i - i = insert_ert(file.body, i, 'Collapsed', ert) + i = insert_ert(file.body, i, 'Collapsed', ert, file.format - 1, file.default_layout) j = j + i - old_i - 1 file.body[i:i] = ['\\begin_inset Minipage', @@ -1201,21 +1574,21 @@ def convert_frameless_box(file): # Restore the original minipage environment since we may have # minipages inside this box. # Start a new paragraph because the following may be nonstandard - file.body[i:i] = ['\\layout Standard', '', ''] + file.body[i:i] = ['\\layout %s' % file.default_layout, '', ''] i = i + 2 j = j + 3 ert = '\\let\\minipage\\lyxtolyxrealminipage%\n' ert = ert + '\\let\\endminipage\\lyxtolyxrealendminipage%' old_i = i - i = insert_ert(file.body, i, 'Collapsed', ert) + i = insert_ert(file.body, i, 'Collapsed', ert, file.format - 1, file.default_layout) j = j + i - old_i - 1 # Redefine the minipage end before the inset end. # Start a new paragraph because the previous may be nonstandard - file.body[j:j] = ['\\layout Standard', '', ''] + file.body[j:j] = ['\\layout %s' % file.default_layout, '', ''] j = j + 2 ert = '\\let\\endminipage\\endlyxtolyxminipage' - j = insert_ert(file.body, j, 'Collapsed', ert) + j = insert_ert(file.body, j, 'Collapsed', ert, file.format - 1, file.default_layout) j = j + 1 file.body.insert(j, '') j = j + 1 @@ -1226,7 +1599,7 @@ def convert_frameless_box(file): ert = '}%\n' else: ert = '\\end{lyxtolyxrealminipage}%\n' - j = insert_ert(file.body, j, 'Collapsed', ert) + j = insert_ert(file.body, j, 'Collapsed', ert, file.format - 1, file.default_layout) # We don't need to restore the original minipage after the inset # end because the scope of the redefinition is the original box. @@ -1242,6 +1615,51 @@ def convert_frameless_box(file): 'collapsed ' + params['collapsed']] i = i + 6 + +def remove_branches(file): + i = 0 + while 1: + i = find_token(file.header, "\\branch", i) + if i == -1: + break + file.warning("Removing branch %s." % split(file.header[i])[1]) + j = find_token(file.header, "\\end_branch", i) + if j == -1: + file.warning("Malformed LyX file: Missing '\\end_branch'.") + break + del file.header[i:j+1] + + i = 0 + while 1: + i = find_token(file.body, "\\begin_inset Branch", i) + if i == -1: + return + j = find_end_of_inset(file.body, i) + if j == -1: + file.warning("Malformed LyX file: Missing '\\end_inset'.") + i = i + 1 + continue + del file.body[i] + del file.body[j - 1] + # Seach for a line starting 'collapsed' + # If, however, we find a line starting '\layout' + # (_always_ present) then break with a warning message + collapsed_found = 0 + while 1: + if (file.body[i][:9] == "collapsed"): + del file.body[i] + collapsed_found = 1 + continue + elif (file.body[i][:7] == "\\layout"): + if collapsed_found == 0: + file.warning("Malformed LyX file: Missing 'collapsed'.") + # Delete this new paragraph, since it would not appear in + # .tex output. This avoids also empty paragraphs. + del file.body[i] + break + i = i + 1 + + ## # Convert jurabib # @@ -1425,7 +1843,7 @@ def convert_names(file): "\\begin_inset CharStyle Firstname", "status inlined", "", - "\\begin_layout Standard", + '\\begin_layout %s' % file.default_layout, "", "%s" % firstname, "\end_layout", @@ -1436,7 +1854,7 @@ def convert_names(file): "\\begin_inset CharStyle Surname", "status inlined", "", - "\\begin_layout Standard", + '\\begin_layout %s' % file.default_layout, "", "%s" % surname, "\\end_layout", @@ -1522,21 +1940,19 @@ def revert_cite_engine(file): def convert_paperpackage(file): i = find_token(file.header, "\\paperpackage", 0) if i == -1: - file.warning("Malformed lyx file: Missing '\\paperpackage'.") return packages = {'default':'none','a4':'none', 'a4wide':'a4', 'widemarginsa4':'a4wide'} if len(split(file.header[i])) > 1: paperpackage = split(file.header[i])[1] + file.header[i] = replace(file.header[i], paperpackage, packages[paperpackage]) else: - paperpackage = "default" - file.header[i] = replace(file.header[i], paperpackage, packages[paperpackage]) + file.header[i] = file.header[i] + ' widemarginsa4' def revert_paperpackage(file): i = find_token(file.header, "\\paperpackage", 0) if i == -1: - file.warning("Malformed lyx file: Missing '\\paperpackage'.") return packages = {'none':'a4', 'a4':'a4wide', 'a4wide':'widemarginsa4', @@ -1696,7 +2112,7 @@ def use_x_binary(file): # def normalize_paragraph_params(file): body = file.body - allowed_parameters = '\\paragraph_spacing', '\\noindent', '\\align', '\\labelwidthstring', "\\start_of_appendix" + allowed_parameters = '\\paragraph_spacing', '\\noindent', '\\align', '\\labelwidthstring', "\\start_of_appendix", "\\leftindent" i = 0 while 1: @@ -1765,7 +2181,7 @@ def convert_ert_paragraphs(file): k = find_token(file.body, "\\begin_layout", k, j) if k == -1: break - file.body[k] = "\\begin_layout Standard" + file.body[k] = '\\begin_layout %s' % file.default_layout k = k + 1 # remove all paragraph parameters and font settings @@ -1782,14 +2198,14 @@ def convert_ert_paragraphs(file): k = i first_pagraph = 1 while 1: - k = find_token(file.body, "\\begin_layout Standard", k, j) + k = find_token(file.body, "\\begin_layout", k, j) if k == -1: break if first_pagraph: first_pagraph = 0 k = k + 1 continue - file.body[k:k] = ["\\begin_layout Standard", "", + file.body[k:k] = ['\\begin_layout %s' % file.default_layout, "", "\\end_layout", ""] k = k + 5 j = j + 4 @@ -1800,9 +2216,14 @@ def convert_ert_paragraphs(file): k = find_token(file.body, "\\newline", k, j) if k == -1: break - file.body[k:k+1] = ["\\end_layout", "", "\\begin_layout Standard"] + file.body[k:k+1] = ["\\end_layout", "", '\\begin_layout %s' % file.default_layout] k = k + 4 j = j + 3 + # We need an empty line if file.default_layout == '' + if file.body[k-1] != '': + file.body.insert(k-1, '') + k = k + 1 + j = j + 1 i = i + 1 @@ -1843,9 +2264,14 @@ def revert_ert_paragraphs(file): l = l + 1 if strip(file.body[l]) and split(file.body[l])[0] == "\\newline": file.body[k:l+1] = ["\\end_layout", "", - "\\begin_layout Standard"] + '\\begin_layout %s' % file.default_layout] j = j - l + k + 2 k = k + 3 + # We need an empty line if file.default_layout == '' + if file.body[l+1] != '': + file.body.insert(l+1, '') + k = k + 1 + j = j + 1 else: k = k + 1 i = i + 1 @@ -1857,13 +2283,51 @@ def convert_french(file): if i != -1: file.header[i] = "\\language french" + # Change language in the document body + regexp = re.compile(r'^\\lang\s+frenchb') + i = 0 + while 1: + i = find_re(file.body, regexp, i) + if i == -1: + break + file.body[i] = "\\lang french" + i = i + 1 + + +def remove_paperpackage(file): + i = find_token(file.header, '\\paperpackage', 0) + + if i == -1: + return + + paperpackage = split(file.header[i])[1] + + if paperpackage in ("a4", "a4wide", "widemarginsa4"): + conv = {"a4":"\\usepackage{a4}","a4wide": "\\usepackage{a4wide}", + "widemarginsa4": "\\usepackage[widemargins]{a4}"} + # for compatibility we ensure it is the first entry in preamble + file.preamble[0:0] = [conv[paperpackage]] + + del file.header[i] + + i = find_token(file.header, '\\papersize', 0) + if i != -1: + file.header[i] = "\\papersize default" + + +def remove_quotestimes(file): + i = find_token(file.header, '\\quotes_times', 0) + if i == -1: + return + del file.header[i] + ## # Convertion hub # -convert = [[223, [insert_tracking_changes, add_end_header, remove_color_default, - convert_spaces, convert_bibtex, remove_insetparent]], +convert = [[222, [insert_tracking_changes, add_end_header]], + [223, [remove_color_default, convert_spaces, convert_bibtex, remove_insetparent]], [224, [convert_external, convert_comment]], [225, [add_end_layout, layout2begin_layout, convert_end_document, convert_table_valignment_middle, convert_breaks]], @@ -1884,9 +2348,15 @@ convert = [[223, [insert_tracking_changes, add_end_header, remove_color_default, [239, [normalize_paragraph_params]], [240, [convert_output_changes]], [241, [convert_ert_paragraphs]], - [242, [convert_french]]] - -revert = [[241, []], + [242, [convert_french]], + [243, [remove_paperpackage]], + [244, [rename_spaces]], + [245, [remove_quotestimes]]] + +revert = [[244, []], + [243, [revert_space_names]], + [242, []], + [241, []], [240, [revert_ert_paragraphs]], [239, [revert_output_changes]], [238, []], @@ -1905,10 +2375,11 @@ revert = [[241, []], [226, [revert_box, revert_external_2]], [225, [revert_note]], [224, [rm_end_layout, begin_layout2layout, revert_end_document, - revert_valignment_middle, convert_vspace, convert_frameless_box]], + revert_valignment_middle, revert_breaks, convert_frameless_box, + remove_branches]], [223, [revert_external_2, revert_comment, revert_eqref]], - [221, [rm_end_header, revert_spaces, revert_bibtex, - rm_tracking_changes, rm_body_changes]]] + [222, [revert_spaces, revert_bibtex]], + [221, [rm_end_header, rm_tracking_changes, rm_body_changes]]] if __name__ == "__main__":