]> git.lyx.org Git - lyx.git/blob - lib/lyx2lyx/lyx_2_0.py
* new per-document default output format. File format change.
[lyx.git] / lib / lyx2lyx / lyx_2_0.py
1 # This file is part of lyx2lyx
2 # -*- coding: utf-8 -*-
3 # Copyright (C) 2008 José Matos  <jamatos@lyx.org>
4 #
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 """ Convert files to the file format generated by lyx 2.0"""
20
21 import re
22
23 from parser_tools import find_token, find_end_of, find_tokens, get_value, get_value_string
24
25 ####################################################################
26 # Private helper functions
27
28 def find_end_of_inset(lines, i):
29     " Find end of inset, where lines[i] is included."
30     return find_end_of(lines, i, "\\begin_inset", "\\end_inset")
31
32
33 def add_to_preamble(document, text):
34     """ Add text to the preamble if it is not already there.
35     Only the first line is checked!"""
36
37     if find_token(document.preamble, text[0], 0) != -1:
38         return
39
40     document.preamble.extend(text)
41
42
43 def insert_to_preamble(index, document, text):
44     """ Insert text to the preamble at a given line"""
45
46     document.preamble.insert(index, text)
47
48
49 ####################################################################
50
51
52 def revert_swiss(document):
53     " Set language german-ch to ngerman "
54     i = 0
55     if document.language == "german-ch":
56         document.language = "ngerman"
57         i = find_token(document.header, "\\language", 0)
58         if i != -1:
59             document.header[i] = "\\language ngerman"
60     j = 0
61     while True:
62         j = find_token(document.body, "\\lang german-ch", j)
63         if j == -1:
64             return
65         document.body[j] = document.body[j].replace("\\lang german-ch", "\\lang ngerman")
66         j = j + 1
67
68
69 def revert_tabularvalign(document):
70    " Revert the tabular valign option "
71    i = 0
72    while True:
73        i = find_token(document.body, "\\begin_inset Tabular", i)
74        if i == -1:
75            return
76        j = find_end_of_inset(document.body, i)
77        if j == -1:
78            document.warning("Malformed LyX document: Could not find end of tabular.")
79            i = j
80            continue
81
82        k = find_token(document.body, "<features tabularvalignment=", i)
83        if k == -1:
84            i = j
85            continue
86
87        # which valignment is specified?
88        tabularvalignment_re = re.compile(r'<features tabularvalignment="(top|bottom)">')
89        m = tabularvalignment_re.match(document.body[k])
90        if not m:
91            i = j
92            continue
93
94        tabularvalignment = m.group(1)
95
96        subst = ['\\end_layout', '\\end_inset']
97        document.body[j+1:j+1] = subst # just inserts those lines
98        subst = ['\\begin_inset Box Frameless',
99            'position "' + tabularvalignment[0] +'"',
100            'hor_pos "c"',
101            'has_inner_box 1',
102            'inner_pos "c"',
103            'use_parbox 0',
104            'width "0col%"',
105            'special "none"',
106            'height "1in"',
107            'height_special "totalheight"',
108            'status open',
109            '',
110            '\\begin_layout Plain Layout']
111        document.body[i:i] = subst # this just inserts the array at i
112        i += len(subst) + 2 # adjust i to save a few cycles
113
114
115 def revert_phantom(document):
116     " Reverts phantom to ERT "
117     i = 0
118     j = 0
119     while True:
120       i = find_token(document.body, "\\begin_inset Phantom Phantom", i)
121       if i == -1:
122           return
123       substi = document.body[i].replace('\\begin_inset Phantom Phantom', \
124                 '\\begin_inset ERT\nstatus collapsed\n\n' \
125                 '\\begin_layout Plain Layout\n\n\n\\backslash\n' \
126                 'phantom{\n\\end_layout\n\n\\end_inset\n')
127       substi = substi.split('\n')
128       document.body[i : i+4] = substi
129       i += len(substi)
130       j = find_token(document.body, "\\end_layout", i)
131       if j == -1:
132           document.warning("Malformed LyX document: Could not find end of Phantom inset.")
133           return
134       substj = document.body[j].replace('\\end_layout', \
135                 '\\size default\n\n\\begin_inset ERT\nstatus collapsed\n\n' \
136                 '\\begin_layout Plain Layout\n\n' \
137                 '}\n\\end_layout\n\n\\end_inset\n')
138       substj = substj.split('\n')
139       document.body[j : j+4] = substj
140       i += len(substj)
141
142
143 def revert_hphantom(document):
144     " Reverts hphantom to ERT "
145     i = 0
146     j = 0
147     while True:
148       i = find_token(document.body, "\\begin_inset Phantom HPhantom", i)
149       if i == -1:
150           return
151       substi = document.body[i].replace('\\begin_inset Phantom HPhantom', \
152                 '\\begin_inset ERT\nstatus collapsed\n\n' \
153                 '\\begin_layout Plain Layout\n\n\n\\backslash\n' \
154                 'hphantom{\n\\end_layout\n\n\\end_inset\n')
155       substi = substi.split('\n')
156       document.body[i : i+4] = substi
157       i += len(substi)
158       j = find_token(document.body, "\\end_layout", i)
159       if j == -1:
160           document.warning("Malformed LyX document: Could not find end of HPhantom inset.")
161           return
162       substj = document.body[j].replace('\\end_layout', \
163                 '\\size default\n\n\\begin_inset ERT\nstatus collapsed\n\n' \
164                 '\\begin_layout Plain Layout\n\n' \
165                 '}\n\\end_layout\n\n\\end_inset\n')
166       substj = substj.split('\n')
167       document.body[j : j+4] = substj
168       i += len(substj)
169
170
171 def revert_vphantom(document):
172     " Reverts vphantom to ERT "
173     i = 0
174     j = 0
175     while True:
176       i = find_token(document.body, "\\begin_inset Phantom VPhantom", i)
177       if i == -1:
178           return
179       substi = document.body[i].replace('\\begin_inset Phantom VPhantom', \
180                 '\\begin_inset ERT\nstatus collapsed\n\n' \
181                 '\\begin_layout Plain Layout\n\n\n\\backslash\n' \
182                 'vphantom{\n\\end_layout\n\n\\end_inset\n')
183       substi = substi.split('\n')
184       document.body[i : i+4] = substi
185       i += len(substi)
186       j = find_token(document.body, "\\end_layout", i)
187       if j == -1:
188           document.warning("Malformed LyX document: Could not find end of VPhantom inset.")
189           return
190       substj = document.body[j].replace('\\end_layout', \
191                 '\\size default\n\n\\begin_inset ERT\nstatus collapsed\n\n' \
192                 '\\begin_layout Plain Layout\n\n' \
193                 '}\n\\end_layout\n\n\\end_inset\n')
194       substj = substj.split('\n')
195       document.body[j : j+4] = substj
196       i += len(substj)
197
198
199 def revert_xetex(document):
200     " Reverts documents that use XeTeX "
201     i = find_token(document.header, '\\use_xetex', 0)
202     if i == -1:
203         document.warning("Malformed LyX document: Missing \\use_xetex.")
204         return
205     if get_value(document.header, "\\use_xetex", i) == 'false':
206         del document.header[i]
207         return
208     del document.header[i]
209     # 1.) set doc encoding to utf8-plain
210     i = find_token(document.header, "\\inputencoding", 0)
211     if i == -1:
212         document.warning("Malformed LyX document: Missing \\inputencoding.")
213     document.header[i] = "\\inputencoding utf8-plain"
214     # 2.) check font settings
215     l = find_token(document.header, "\\font_roman", 0)
216     if l == -1:
217         document.warning("Malformed LyX document: Missing \\font_roman.")
218     line = document.header[l]
219     l = re.compile(r'\\font_roman (.*)$')
220     m = l.match(line)
221     roman = m.group(1)
222     l = find_token(document.header, "\\font_sans", 0)
223     if l == -1:
224         document.warning("Malformed LyX document: Missing \\font_sans.")
225     line = document.header[l]
226     l = re.compile(r'\\font_sans (.*)$')
227     m = l.match(line)
228     sans = m.group(1)
229     l = find_token(document.header, "\\font_typewriter", 0)
230     if l == -1:
231         document.warning("Malformed LyX document: Missing \\font_typewriter.")
232     line = document.header[l]
233     l = re.compile(r'\\font_typewriter (.*)$')
234     m = l.match(line)
235     typewriter = m.group(1)
236     osf = get_value(document.header, '\\font_osf', 0) == "true"
237     sf_scale = float(get_value(document.header, '\\font_sf_scale', 0))
238     tt_scale = float(get_value(document.header, '\\font_tt_scale', 0))
239     # 3.) set preamble stuff
240     pretext = '%% This document must be processed with xelatex!\n'
241     pretext += '\\usepackage{fontspec}\n'
242     if roman != "default":
243         pretext += '\\setmainfont[Mapping=tex-text]{' + roman + '}\n'
244     if sans != "default":
245         pretext += '\\setsansfont['
246         if sf_scale != 100:
247             pretext += 'Scale=' + str(sf_scale / 100) + ','
248         pretext += 'Mapping=tex-text]{' + sans + '}\n'
249     if typewriter != "default":
250         pretext += '\\setmonofont'
251         if tt_scale != 100:
252             pretext += '[Scale=' + str(tt_scale / 100) + ']'
253         pretext += '{' + typewriter + '}\n'
254     if osf:
255         pretext += '\\defaultfontfeatures{Numbers=OldStyle}\n'
256     pretext += '\usepackage{xunicode}\n'
257     pretext += '\usepackage{xltxtra}\n'
258     insert_to_preamble(0, document, pretext)
259     # 4.) reset font settings
260     i = find_token(document.header, "\\font_roman", 0)
261     if i == -1:
262         document.warning("Malformed LyX document: Missing \\font_roman.")
263     document.header[i] = "\\font_roman default"
264     i = find_token(document.header, "\\font_sans", 0)
265     if i == -1:
266         document.warning("Malformed LyX document: Missing \\font_sans.")
267     document.header[i] = "\\font_sans default"
268     i = find_token(document.header, "\\font_typewriter", 0)
269     if i == -1:
270         document.warning("Malformed LyX document: Missing \\font_typewriter.")
271     document.header[i] = "\\font_typewriter default"
272     i = find_token(document.header, "\\font_osf", 0)
273     if i == -1:
274         document.warning("Malformed LyX document: Missing \\font_osf.")
275     document.header[i] = "\\font_osf false"
276     i = find_token(document.header, "\\font_sc", 0)
277     if i == -1:
278         document.warning("Malformed LyX document: Missing \\font_sc.")
279     document.header[i] = "\\font_sc false"
280     i = find_token(document.header, "\\font_sf_scale", 0)
281     if i == -1:
282         document.warning("Malformed LyX document: Missing \\font_sf_scale.")
283     document.header[i] = "\\font_sf_scale 100"
284     i = find_token(document.header, "\\font_tt_scale", 0)
285     if i == -1:
286         document.warning("Malformed LyX document: Missing \\font_tt_scale.")
287     document.header[i] = "\\font_tt_scale 100"
288
289
290 def revert_outputformat(document):
291     " Remove default output format param "
292     i = find_token(document.header, '\\default_output_format', 0)
293     if i == -1:
294         document.warning("Malformed LyX document: Missing \\default_output_format.")
295         return
296     del document.header[i]
297
298
299 ##
300 # Conversion hub
301 #
302
303 supported_versions = ["2.0.0","2.0"]
304 convert = [[346, []],
305            [347, []],
306            [348, []],
307            [349, []],
308            [350, []]
309           ]
310
311 revert =  [[349, [revert_outputformat]],
312            [348, [revert_xetex]],
313            [347, [revert_phantom, revert_hphantom, revert_vphantom]],
314            [346, [revert_tabularvalign]],
315            [345, [revert_swiss]]
316           ]
317
318
319 if __name__ == "__main__":
320     pass