]> git.lyx.org Git - features.git/blob - lib/lyx2lyx/lyx_2_2.py
99236ffa110ac6a9e44fe72848a9496e3671dc3e
[features.git] / lib / lyx2lyx / lyx_2_2.py
1 # -*- coding: utf-8 -*-
2 # This file is part of lyx2lyx
3 # -*- coding: utf-8 -*-
4 # Copyright (C) 2011 The LyX team
5 #
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19
20 """ Convert files to the file format generated by lyx 2.2"""
21
22 import re, string
23 import unicodedata
24 import sys, os
25
26 # Uncomment only what you need to import, please.
27
28 #from parser_tools import find_token, find_end_of, find_tokens, \
29 #  find_token_exact, find_end_of_inset, find_end_of_layout, \
30 #  find_token_backwards, is_in_inset, get_value, get_quoted_value, \
31 #  del_token, check_token, get_option_value
32   
33 #from lyx2lyx_tools import add_to_preamble, insert_to_preamble, \
34 #  put_cmd_in_ert, lyx2latex, latex_length, revert_flex_inset, \
35 #  revert_font_attrs, hex2ratio, str2bool
36
37 from parser_tools import find_token, find_token_backwards, find_re, \
38      find_end_of_inset, find_end_of_layout, find_nonempty_line, \
39      get_containing_layout, get_value, check_token
40
41 ###############################################################################
42 ###
43 ### Conversion and reversion routines
44 ###
45 ###############################################################################
46
47 def convert_separator(document):
48     """
49     Convert layout separators to separator insets and add (LaTeX) paragraph
50     breaks in order to mimic previous LaTeX export.
51     """
52
53     parins = ["\\begin_inset Separator parbreak", "\\end_inset", ""]
54     parlay = ["\\begin_layout Standard", "\\begin_inset Separator parbreak",
55               "\\end_inset", "", "\\end_layout", ""]
56     sty_dict = {
57         "family" : "default",
58         "series" : "default",
59         "shape"  : "default",
60         "size"   : "default",
61         "bar"    : "default",
62         "color"  : "inherit"
63         }
64
65     i = 0
66     while 1:
67         i = find_token(document.body, "\\begin_deeper", i)
68         if i == -1:
69             break
70
71         j = find_token_backwards(document.body, "\\end_layout", i-1)
72         if j != -1:
73             # reset any text style before inserting the inset
74             lay = get_containing_layout(document.body, j-1)
75             if lay != False:
76                 content = "\n".join(document.body[lay[1]:lay[2]])
77                 for val in sty_dict.keys():
78                     if content.find("\\%s" % val) != -1:
79                         document.body[j:j] = ["\\%s %s" % (val, sty_dict[val])]
80                         i = i + 1
81                         j = j + 1
82             document.body[j:j] = parins
83             i = i + len(parins) + 1
84         else:
85             i = i + 1
86
87     i = 0
88     while 1:
89         i = find_token(document.body, "\\align", i)
90         if i == -1:
91             break
92
93         lay = get_containing_layout(document.body, i)
94         if lay != False and lay[0] == "Plain Layout":
95             i = i + 1
96             continue
97
98         j = find_token_backwards(document.body, "\\end_layout", i-1)
99         if j != -1:
100             lay = get_containing_layout(document.body, j-1)
101             if lay != False and lay[0] == "Standard" \
102                and find_token(document.body, "\\align", lay[1], lay[2]) == -1 \
103                and find_token(document.body, "\\begin_inset VSpace", lay[1], lay[2]) == -1:
104                 # reset any text style before inserting the inset
105                 content = "\n".join(document.body[lay[1]:lay[2]])
106                 for val in sty_dict.keys():
107                     if content.find("\\%s" % val) != -1:
108                         document.body[j:j] = ["\\%s %s" % (val, sty_dict[val])]
109                         i = i + 1
110                         j = j + 1
111                 document.body[j:j] = parins
112                 i = i + len(parins) + 1
113             else:
114                 i = i + 1
115         else:
116             i = i + 1
117
118     regexp = re.compile(r'^\\begin_layout (?:(-*)|(\s*))(Separator|EndOfSlide)(?:(-*)|(\s*))$', re.IGNORECASE)
119
120     i = 0
121     while 1:
122         i = find_re(document.body, regexp, i)
123         if i == -1:
124             return
125
126         j = find_end_of_layout(document.body, i)
127         if j == -1:
128             document.warning("Malformed LyX document: Missing `\\end_layout'.")
129             return
130
131         lay = get_containing_layout(document.body, j-1)
132         if lay != False:
133             lines = document.body[lay[3]:lay[2]]
134         else:
135             lines = []
136
137         document.body[i:j+1] = parlay
138         if len(lines) > 0:
139             document.body[i+1:i+1] = lines
140
141         i = i + len(parlay) + len(lines) + 1
142
143
144 def revert_separator(document):
145     " Revert separator insets to layout separators "
146
147     parsep = ["\\begin_layout --Separator--", "", "\\end_layout", ""]
148     comert = ["\\begin_inset ERT", "status collapsed", "",
149               "\\begin_layout Plain Layout", "%", "\\end_layout",
150               "", "\\end_inset", ""]
151     empert = ["\\begin_inset ERT", "status collapsed", "",
152               "\\begin_layout Plain Layout", " ", "\\end_layout",
153               "", "\\end_inset", ""]
154
155     i = 0
156     while 1:
157         i = find_token(document.body, "\\begin_inset Separator", i)
158         if i == -1:
159             return
160
161         lay = get_containing_layout(document.body, i)
162         if lay == False:
163             document.warning("Malformed LyX document: Can't convert separator inset at line " + str(i))
164             i = i + 1
165             continue
166
167         layoutname = lay[0]
168         beg = lay[1]
169         end = lay[2]
170         kind = get_value(document.body, "\\begin_inset Separator", i, i+1, "plain").split()[1]
171         before = document.body[beg+1:i]
172         something_before = len(before) > 0 and len("".join(before)) > 0
173         j = find_end_of_inset(document.body, i)
174         after = document.body[j+1:end]
175         something_after = len(after) > 0 and len("".join(after)) > 0
176         if kind == "plain":
177             beg = beg + len(before) + 1
178         elif something_before:
179             document.body[i:i] = ["\\end_layout", ""]
180             i = i + 2
181             j = j + 2
182             beg = i
183             end = end + 2
184
185         if kind == "plain":
186             if something_after:
187                 document.body[beg:j+1] = empert
188                 i = i + len(empert)
189             else:
190                 document.body[beg:j+1] = comert
191                 i = i + len(comert)
192         else:
193             if something_after:
194                 if layoutname == "Standard":
195                     if not something_before:
196                         document.body[beg:j+1] = parsep
197                         i = i + len(parsep)
198                         document.body[i:i] = ["", "\\begin_layout Standard"]
199                         i = i + 2
200                     else:
201                         document.body[beg:j+1] = ["\\begin_layout Standard"]
202                         i = i + 1
203                 else:
204                     document.body[beg:j+1] = ["\\begin_deeper"]
205                     i = i + 1
206                     end = end + 1 - (j + 1 - beg)
207                     if not something_before:
208                         document.body[i:i] = parsep
209                         i = i + len(parsep)
210                         end = end + len(parsep)
211                     document.body[i:i] = ["\\begin_layout Standard"]
212                     document.body[end+2:end+2] = ["", "\\end_deeper", ""]
213                     i = i + 4
214             else:
215                 next_par_is_aligned = False
216                 k = find_nonempty_line(document.body, end+1)
217                 if k != -1 and check_token(document.body[k], "\\begin_layout"):
218                     lay = get_containing_layout(document.body, k)
219                     next_par_is_aligned = lay != False and \
220                             find_token(document.body, "\\align", lay[1], lay[2]) != -1
221                 if k != -1 and not next_par_is_aligned \
222                         and not check_token(document.body[k], "\\end_deeper") \
223                         and not check_token(document.body[k], "\\begin_deeper"):
224                     if layoutname == "Standard":
225                         document.body[beg:j+1] = ["\\begin_layout --Separator--"]
226                         i = i + 1
227                     else:
228                         document.body[beg:j+1] = ["\\begin_deeper", "\\begin_layout --Separator--"]
229                         end = end + 2 - (j + 1 - beg)
230                         document.body[end+1:end+1] = ["", "\\end_deeper", ""]
231                         i = i + 3
232                 else:
233                     del document.body[i:end+1]
234
235         i = i + 1
236
237
238 ##
239 # Conversion hub
240 #
241
242 supported_versions = ["2.2.0","2.2"]
243 convert = [
244            [475, [convert_separator]],
245           ]
246
247 revert =  [
248            [474, [revert_separator]]
249           ]
250
251
252 if __name__ == "__main__":
253     pass