tufte layout files:
[lyx.git] / lib / lyx2lyx / lyx_1_6.py
blob562f32946bcef81216f61757e8e2d703b472b5d1
1 # This file is part of lyx2lyx
2 # -*- coding: utf-8 -*-
3 # Copyright (C) 2007-2008 The LyX Team <lyx-devel@lists.lyx.org>
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.
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.
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.
19 """ Convert files to the file format generated by lyx 1.6"""
21 import re
22 import unicodedata
23 import sys, os
25 from parser_tools import find_token, find_end_of, find_tokens, get_value, get_value_string
27 ####################################################################
28 # Private helper functions
30 def find_end_of_inset(lines, i):
31 " Find end of inset, where lines[i] is included."
32 return find_end_of(lines, i, "\\begin_inset", "\\end_inset")
34 # WARNING!
35 # DO NOT do this:
36 # document.body[i] = wrap_insert_ert(...)
37 # wrap_into_ert may returns a multiline string, which should NOT appear
38 # in document.body. Insetad, do something like this:
39 # subst = wrap_inset_ert(...)
40 # subst = subst.split('\n')
41 # document.body[i:i+1] = subst
42 # i+= len(subst) - 1
43 # where the last statement resets the counter to accord with the added
44 # lines.
45 def wrap_into_ert(string, src, dst):
46 '''Within string, replace occurrences of src with dst, wrapped into ERT
47 E.g.: wrap_into_ert('sch\"on', "\\", "\\backslash") is:
48 sch<ERT>\\backslash</ERT>"on'''
49 return string.replace(src, '\n\\begin_inset ERT\nstatus collapsed\n\\begin_layout Standard\n'
50 + dst + '\n\\end_layout\n\\end_inset\n')
52 def put_cmd_in_ert(string):
53 for rep in unicode_reps:
54 string = string.replace(rep[1], rep[0].replace('\\\\', '\\'))
55 string = string.replace('\\', "\\backslash\n")
56 string = "\\begin_inset ERT\nstatus collapsed\n\\begin_layout Standard\n" \
57 + string + "\n\\end_layout\n\\end_inset"
58 return string
60 def add_to_preamble(document, text):
61 """ Add text to the preamble if it is not already there.
62 Only the first line is checked!"""
64 if find_token(document.preamble, text[0], 0) != -1:
65 return
67 document.preamble.extend(text)
69 def insert_to_preamble(index, document, text):
70 """ Insert text to the preamble at a given line"""
72 document.preamble.insert(index, text)
74 # Convert a LyX length into a LaTeX length
75 def convert_len(len):
76 units = {"text%":"\\backslash\ntextwidth", "col%":"\\backslash\ncolumnwidth",
77 "page%":"\\backslash\npagewidth", "line%":"\\backslash\nlinewidth",
78 "theight%":"\\backslash\ntextheight", "pheight%":"\\backslash\npageheight"}
80 # Convert LyX units to LaTeX units
81 for unit in units.keys():
82 if len.find(unit) != -1:
83 len = '%f' % (len2value(len) / 100)
84 len = len.strip('0') + units[unit]
85 break
87 return len
89 # Return the value of len without the unit in numerical form.
90 def len2value(len):
91 result = re.search('([+-]?[0-9.]+)', len)
92 if result:
93 return float(result.group(1))
94 # No number means 1.0
95 return 1.0
97 # Unfortunately, this doesn't really work, since Standard isn't always default.
98 # But it's as good as we can do right now.
99 def find_default_layout(document, start, end):
100 l = find_token(document.body, "\\begin_layout Standard", start, end)
101 if l == -1:
102 l = find_token(document.body, "\\begin_layout PlainLayout", start, end)
103 if l == -1:
104 l = find_token(document.body, "\\begin_layout Plain Layout", start, end)
105 return l
107 def get_option(document, m, option, default):
108 l = document.body[m].find(option)
109 val = default
110 if l != -1:
111 val = document.body[m][l:].split('"')[1]
112 return val
114 def remove_option(document, m, option):
115 l = document.body[m].find(option)
116 if l != -1:
117 val = document.body[m][l:].split('"')[1]
118 document.body[m] = document.body[m][:l-1] + document.body[m][l+len(option + '="' + val + '"'):]
119 return l
121 def set_option(document, m, option, value):
122 l = document.body[m].find(option)
123 if l != -1:
124 oldval = document.body[m][l:].split('"')[1]
125 l = l + len(option + '="')
126 document.body[m] = document.body[m][:l] + value + document.body[m][l+len(oldval):]
127 else:
128 document.body[m] = document.body[m][:-1] + ' ' + option + '="' + value + '">'
129 return l
132 def read_unicodesymbols():
133 " Read the unicodesymbols list of unicode characters and corresponding commands."
134 pathname = os.path.abspath(os.path.dirname(sys.argv[0]))
135 fp = open(os.path.join(pathname.strip('lyx2lyx'), 'unicodesymbols'))
136 spec_chars = []
137 # Two backslashes, followed by some non-word character, and then a character
138 # in brackets. The idea is to check for constructs like: \"{u}, which is how
139 # they are written in the unicodesymbols file; but they can also be written
140 # as: \"u or even \" u.
141 r = re.compile(r'\\\\(\W)\{(\w)\}')
142 for line in fp.readlines():
143 if line[0] != '#' and line.strip() != "":
144 line=line.replace(' "',' ') # remove all quotation marks with spaces before
145 line=line.replace('" ',' ') # remove all quotation marks with spaces after
146 line=line.replace(r'\"','"') # replace \" by " (for characters with diaeresis)
147 try:
148 [ucs4,command,dead] = line.split(None,2)
149 if command[0:1] != "\\":
150 continue
151 spec_chars.append([command, unichr(eval(ucs4))])
152 except:
153 continue
154 m = r.match(command)
155 if m != None:
156 command = "\\\\"
157 # If the character is a double-quote, then we need to escape it, too,
158 # since it is done that way in the LyX file.
159 if m.group(1) == "\"":
160 command += "\\"
161 commandbl = command
162 command += m.group(1) + m.group(2)
163 commandbl += m.group(1) + ' ' + m.group(2)
164 spec_chars.append([command, unichr(eval(ucs4))])
165 spec_chars.append([commandbl, unichr(eval(ucs4))])
166 fp.close()
167 return spec_chars
170 def extract_argument(line):
171 'Extracts a LaTeX argument from the start of line. Returns (arg, rest).'
173 if not line:
174 return (None, "")
176 bracere = re.compile("(\s*)(.*)")
177 n = bracere.match(line)
178 whitespace = n.group(1)
179 stuff = n.group(2)
180 brace = stuff[:1]
181 if brace != "[" and brace != "{":
182 return (None, line)
184 # find closing brace
185 remain = stuff[1:]
186 pos = 0
187 num = 1
188 term = "}"
189 if brace == "[":
190 term = "]"
191 skip = False
192 for c in remain:
193 if skip:
194 skip = False
195 elif c == "\\":
196 skip = True
197 elif c == brace:
198 num += 1
199 elif c == term:
200 num -= 1
201 if c == 0:
202 break
203 pos += 1
204 if num != 0:
205 # We never found the matching brace
206 # So, to be on the safe side, let's just return everything
207 # which will then get wrapped as ERT
208 return (line, "")
209 return (line[:pos + 1], line[pos + 1:])
212 def latex2ert(line, isindex):
213 '''Converts LaTeX commands into ERT. line may well be a multi-line
214 string when it is returned.'''
215 if not line:
216 return line
218 retval = ""
219 ## FIXME Escaped \ ??
220 # This regex looks for a LaTeX command---i.e., something of the form
221 # "\alPhaStuFF", or "\X", where X is any character---where the command
222 # may also be preceded by an additional backslash, which is how it would
223 # appear (e.g.) in an InsetIndex.
224 labelre = re.compile(r'(.*?)\\?(\\(?:[a-zA-Z]+|.))(.*)')
226 m = labelre.match(line)
227 while m != None:
228 retval += m.group(1)
229 cmd = m.group(2)
230 end = m.group(3)
232 while True:
233 (arg, rest) = extract_argument(end)
234 if arg == None:
235 break
236 cmd += arg
237 end = rest
238 # If we wanted to put labels into an InsetLabel, for example, then we
239 # would just need to test here for cmd == "label" and then take some
240 # appropriate action, i.e., to use arg to get the content and then
241 # wrap it appropriately.
242 cmd = put_cmd_in_ert(cmd)
243 retval += "\n" + cmd + "\n"
244 line = end
245 m = labelre.match(line)
246 # put all remaining braces in ERT
247 line = wrap_into_ert(line, '}', '}')
248 line = wrap_into_ert(line, '{', '{')
249 if isindex:
250 # active character that is not available in all font encodings
251 line = wrap_into_ert(line, '|', '|')
252 retval += line
253 return retval
256 unicode_reps = read_unicodesymbols()
258 #Bug 5022....
259 #Might should do latex2ert first, then deal with stuff that DOESN'T
260 #end up inside ERT. That routine could be modified so that it returned
261 #a list of lines, and we could then skip ERT bits and only deal with
262 #the other bits.
263 def latex2lyx(data, isindex):
264 '''Takes a string, possibly multi-line, and returns the result of
265 converting LaTeX constructs into LyX constructs. Returns a list of
266 lines, suitable for insertion into document.body.
267 The bool isindex specifies whether we are in an index macro (which
268 has some specific active characters that need to be ERTed).'''
270 if not data:
271 return [""]
272 retval = []
274 # Convert LaTeX to Unicode
275 # Commands of this sort need to be checked to make sure they are
276 # followed by a non-alpha character, lest we replace too much.
277 hardone = re.compile(r'^\\\\[a-zA-Z]+$')
279 for rep in unicode_reps:
280 if hardone.match(rep[0]):
281 pos = 0
282 while True:
283 pos = data.find(rep[0], pos)
284 if pos == -1:
285 break
286 nextpos = pos + len(rep[0])
287 if nextpos < len(data) and data[nextpos].isalpha():
288 # not the end of that command
289 pos = nextpos
290 continue
291 data = data[:pos] + rep[1] + data[nextpos:]
292 pos = nextpos
293 else:
294 data = data.replace(rep[0], rep[1])
296 # Generic
297 # \" -> ":
298 data = wrap_into_ert(data, r'\"', '"')
299 # \\ -> \:
300 data = data.replace('\\\\', '\\')
302 # Math:
303 mathre = re.compile('^(.*?)(\$.*?\$)(.*)')
304 lines = data.split('\n')
305 for line in lines:
306 #document.warning("LINE: " + line)
307 #document.warning(str(i) + ":" + document.body[i])
308 #document.warning("LAST: " + document.body[-1])
309 g = line
310 m = mathre.match(g)
311 while m != None:
312 s = m.group(1)
313 f = m.group(2).replace('\\\\', '\\')
314 g = m.group(3)
315 if s:
316 # this is non-math!
317 s = latex2ert(s, isindex)
318 subst = s.split('\n')
319 retval += subst
320 retval.append("\\begin_inset Formula " + f)
321 retval.append("\\end_inset")
322 m = mathre.match(g)
323 # Handle whatever is left, which is just text
324 g = latex2ert(g, isindex)
325 subst = g.split('\n')
326 retval += subst
327 return retval
330 def lyxline2latex(document, line, inert):
331 'Convert some LyX stuff into corresponding LaTeX stuff line-wise, as best we can.'
332 if line.startswith("\\begin_inset Formula"):
333 line = line[20:]
334 elif line.startswith("\\begin_inset Quotes"):
335 # For now, we do a very basic reversion. Someone who understands
336 # quotes is welcome to fix it up.
337 qtype = line[20:].strip()
338 # lang = qtype[0]
339 side = qtype[1]
340 dbls = qtype[2]
341 if side == "l":
342 if dbls == "d":
343 line = "``"
344 else:
345 line = "`"
346 else:
347 if dbls == "d":
348 line = "''"
349 else:
350 line = "'"
351 elif line.isspace() or \
352 line.startswith("\\begin_layout") or \
353 line.startswith("\\end_layout") or \
354 line.startswith("\\begin_inset") or \
355 line.startswith("\\end_inset") or \
356 line.startswith("\\lang") or \
357 line.strip() == "status collapsed" or \
358 line.strip() == "status open":
359 #skip all that stuff
360 return ""
362 # this needs to be added to the preamble because of cases like
363 # \textmu, \textbackslash, etc.
364 add_to_preamble(document, ['% added by lyx2lyx for converted entries',
365 '\\@ifundefined{textmu}',
366 ' {\\usepackage{textcomp}}{}'])
367 # a lossless reversion is not possible
368 # try at least to handle some common insets and settings
369 if inert:
370 line = line.replace(r'\backslash', '\\')
371 else:
372 line = line.replace('&', '\\&{}')
373 line = line.replace('#', '\\#{}')
374 line = line.replace('^', '\\^{}')
375 line = line.replace('%', '\\%{}')
376 line = line.replace('_', '\\_{}')
377 line = line.replace('$', '\\${}')
379 # Do the LyX text --> LaTeX conversion
380 for rep in unicode_reps:
381 line = line.replace(rep[1], rep[0].replace('\\\\', '\\') + "{}")
382 line = line.replace(r'\backslash', r'\textbackslash{}')
383 line = line.replace(r'\series bold', r'\bfseries{}').replace(r'\series default', r'\mdseries{}')
384 line = line.replace(r'\shape italic', r'\itshape{}').replace(r'\shape smallcaps', r'\scshape{}')
385 line = line.replace(r'\shape slanted', r'\slshape{}').replace(r'\shape default', r'\upshape{}')
386 line = line.replace(r'\emph on', r'\em{}').replace(r'\emph default', r'\em{}')
387 line = line.replace(r'\noun on', r'\scshape{}').replace(r'\noun default', r'\upshape{}')
388 line = line.replace(r'\bar under', r'\underbar{').replace(r'\bar default', r'}')
389 line = line.replace(r'\family sans', r'\sffamily{}').replace(r'\family default', r'\normalfont{}')
390 line = line.replace(r'\family typewriter', r'\ttfamily{}').replace(r'\family roman', r'\rmfamily{}')
391 line = line.replace(r'\InsetSpace ', r'').replace(r'\SpecialChar ', r'')
392 return line
395 def lyx2latex(document, lines):
396 'Convert some LyX stuff into corresponding LaTeX stuff, as best we can.'
397 # clean up multiline stuff
398 content = ""
399 ert_end = 0
401 for curline in range(len(lines)):
402 line = lines[curline]
403 if line.startswith("\\begin_inset ERT"):
404 # We don't want to replace things inside ERT, so figure out
405 # where the end of the inset is.
406 ert_end = find_end_of_inset(lines, curline + 1)
407 continue
408 inert = ert_end >= curline
409 content += lyxline2latex(document, lines[curline], inert)
411 return content
414 ####################################################################
416 def convert_ltcaption(document):
417 i = 0
418 while True:
419 i = find_token(document.body, "\\begin_inset Tabular", i)
420 if i == -1:
421 return
422 j = find_end_of_inset(document.body, i + 1)
423 if j == -1:
424 document.warning("Malformed LyX document: Could not find end of tabular.")
425 continue
427 nrows = int(document.body[i+1].split('"')[3])
428 ncols = int(document.body[i+1].split('"')[5])
430 m = i + 1
431 for k in range(nrows):
432 m = find_token(document.body, "<row", m)
433 r = m
434 caption = 'false'
435 for k in range(ncols):
436 m = find_token(document.body, "<cell", m)
437 if (k == 0):
438 mend = find_token(document.body, "</cell>", m + 1)
439 # first look for caption insets
440 mcap = find_token(document.body, "\\begin_inset Caption", m + 1, mend)
441 # then look for ERT captions
442 if mcap == -1:
443 mcap = find_token(document.body, "caption", m + 1, mend)
444 if mcap > -1:
445 mcap = find_token(document.body, "\\backslash", mcap - 1, mcap)
446 if mcap > -1:
447 caption = 'true'
448 if caption == 'true':
449 if (k == 0):
450 set_option(document, r, 'caption', 'true')
451 set_option(document, m, 'multicolumn', '1')
452 set_option(document, m, 'bottomline', 'false')
453 set_option(document, m, 'topline', 'false')
454 set_option(document, m, 'rightline', 'false')
455 set_option(document, m, 'leftline', 'false')
456 #j = find_end_of_inset(document.body, j + 1)
457 else:
458 set_option(document, m, 'multicolumn', '2')
459 m = m + 1
460 m = m + 1
462 i = j + 1
465 #FIXME Use of wrap_into_ert can confuse lyx2lyx
466 def revert_ltcaption(document):
467 i = 0
468 while True:
469 i = find_token(document.body, "\\begin_inset Tabular", i)
470 if i == -1:
471 return
472 j = find_end_of_inset(document.body, i + 1)
473 if j == -1:
474 document.warning("Malformed LyX document: Could not find end of tabular.")
475 continue
477 m = i + 1
478 nrows = int(document.body[i+1].split('"')[3])
479 ncols = int(document.body[i+1].split('"')[5])
481 for k in range(nrows):
482 m = find_token(document.body, "<row", m)
483 caption = get_option(document, m, 'caption', 'false')
484 if caption == 'true':
485 remove_option(document, m, 'caption')
486 for k in range(ncols):
487 m = find_token(document.body, "<cell", m)
488 remove_option(document, m, 'multicolumn')
489 if k == 0:
490 m = find_token(document.body, "\\begin_inset Caption", m)
491 if m == -1:
492 return
493 m = find_end_of_inset(document.body, m + 1)
494 document.body[m] += wrap_into_ert("","","\\backslash\n\\backslash\n%")
495 m = m + 1
496 m = m + 1
497 i = j + 1
500 def convert_tablines(document):
501 i = 0
502 while True:
503 i = find_token(document.body, "\\begin_inset Tabular", i)
504 if i == -1:
505 # LyX 1.3 inserted an extra space between \begin_inset
506 # and Tabular so let us try if this is the case and fix it.
507 i = find_token(document.body, "\\begin_inset Tabular", i)
508 if i == -1:
509 return
510 else:
511 document.body[i] = "\\begin_inset Tabular"
512 j = find_end_of_inset(document.body, i + 1)
513 if j == -1:
514 document.warning("Malformed LyX document: Could not find end of tabular.")
515 continue
517 m = i + 1
518 nrows = int(document.body[i+1].split('"')[3])
519 ncols = int(document.body[i+1].split('"')[5])
521 col_info = []
522 for k in range(ncols):
523 m = find_token(document.body, "<column", m)
524 left = get_option(document, m, 'leftline', 'false')
525 right = get_option(document, m, 'rightline', 'false')
526 col_info.append([left, right])
527 remove_option(document, m, 'leftline')
528 remove_option(document, m, 'rightline')
529 m = m + 1
531 row_info = []
532 for k in range(nrows):
533 m = find_token(document.body, "<row", m)
534 top = get_option(document, m, 'topline', 'false')
535 bottom = get_option(document, m, 'bottomline', 'false')
536 row_info.append([top, bottom])
537 remove_option(document, m, 'topline')
538 remove_option(document, m, 'bottomline')
539 m = m + 1
541 m = i + 1
542 mc_info = []
543 for k in range(nrows*ncols):
544 m = find_token(document.body, "<cell", m)
545 mc_info.append(get_option(document, m, 'multicolumn', '0'))
546 m = m + 1
547 m = i + 1
548 for l in range(nrows):
549 for k in range(ncols):
550 m = find_token(document.body, '<cell', m)
551 if mc_info[l*ncols + k] == '0':
552 r = set_option(document, m, 'topline', row_info[l][0])
553 r = set_option(document, m, 'bottomline', row_info[l][1])
554 r = set_option(document, m, 'leftline', col_info[k][0])
555 r = set_option(document, m, 'rightline', col_info[k][1])
556 elif mc_info[l*ncols + k] == '1':
557 s = k + 1
558 while s < ncols and mc_info[l*ncols + s] == '2':
559 s = s + 1
560 if s < ncols and mc_info[l*ncols + s] != '1':
561 r = set_option(document, m, 'rightline', col_info[k][1])
562 if k > 0 and mc_info[l*ncols + k - 1] == '0':
563 r = set_option(document, m, 'leftline', col_info[k][0])
564 m = m + 1
565 i = j + 1
568 def revert_tablines(document):
569 i = 0
570 while True:
571 i = find_token(document.body, "\\begin_inset Tabular", i)
572 if i == -1:
573 return
574 j = find_end_of_inset(document.body, i + 1)
575 if j == -1:
576 document.warning("Malformed LyX document: Could not find end of tabular.")
577 continue
579 m = i + 1
580 nrows = int(document.body[i+1].split('"')[3])
581 ncols = int(document.body[i+1].split('"')[5])
583 lines = []
584 for k in range(nrows*ncols):
585 m = find_token(document.body, "<cell", m)
586 top = get_option(document, m, 'topline', 'false')
587 bottom = get_option(document, m, 'bottomline', 'false')
588 left = get_option(document, m, 'leftline', 'false')
589 right = get_option(document, m, 'rightline', 'false')
590 lines.append([top, bottom, left, right])
591 m = m + 1
593 # we will want to ignore longtable captions
594 m = i + 1
595 caption_info = []
596 for k in range(nrows):
597 m = find_token(document.body, "<row", m)
598 caption = get_option(document, m, 'caption', 'false')
599 caption_info.append([caption])
600 m = m + 1
602 m = i + 1
603 col_info = []
604 for k in range(ncols):
605 m = find_token(document.body, "<column", m)
606 left = 'true'
607 for l in range(nrows):
608 left = lines[l*ncols + k][2]
609 if left == 'false' and caption_info[l] == 'false':
610 break
611 set_option(document, m, 'leftline', left)
612 right = 'true'
613 for l in range(nrows):
614 right = lines[l*ncols + k][3]
615 if right == 'false' and caption_info[l] == 'false':
616 break
617 set_option(document, m, 'rightline', right)
618 m = m + 1
620 row_info = []
621 for k in range(nrows):
622 m = find_token(document.body, "<row", m)
623 top = 'true'
624 for l in range(ncols):
625 top = lines[k*ncols + l][0]
626 if top == 'false':
627 break
628 if caption_info[k] == 'false':
629 top = 'false'
630 set_option(document, m, 'topline', top)
631 bottom = 'true'
632 for l in range(ncols):
633 bottom = lines[k*ncols + l][1]
634 if bottom == 'false':
635 break
636 if caption_info[k] == 'false':
637 bottom = 'false'
638 set_option(document, m, 'bottomline', bottom)
639 m = m + 1
641 i = j + 1
644 def fix_wrong_tables(document):
645 i = 0
646 while True:
647 i = find_token(document.body, "\\begin_inset Tabular", i)
648 if i == -1:
649 return
650 j = find_end_of_inset(document.body, i + 1)
651 if j == -1:
652 document.warning("Malformed LyX document: Could not find end of tabular.")
653 continue
655 m = i + 1
656 nrows = int(document.body[i+1].split('"')[3])
657 ncols = int(document.body[i+1].split('"')[5])
659 for l in range(nrows):
660 prev_multicolumn = 0
661 for k in range(ncols):
662 m = find_token(document.body, '<cell', m)
664 if document.body[m].find('multicolumn') != -1:
665 multicol_cont = int(document.body[m].split('"')[1])
667 if multicol_cont == 2 and (k == 0 or prev_multicolumn == 0):
668 document.body[m] = document.body[m][:5] + document.body[m][21:]
669 prev_multicolumn = 0
670 else:
671 prev_multicolumn = multicol_cont
672 else:
673 prev_multicolumn = 0
675 i = j + 1
678 def close_begin_deeper(document):
679 i = 0
680 depth = 0
681 while True:
682 i = find_tokens(document.body, ["\\begin_deeper", "\\end_deeper"], i)
684 if i == -1:
685 break
687 if document.body[i][:13] == "\\begin_deeper":
688 depth += 1
689 else:
690 depth -= 1
692 i += 1
694 document.body[-2:-2] = ['\\end_deeper' for i in range(depth)]
697 def long_charstyle_names(document):
698 i = 0
699 while True:
700 i = find_token(document.body, "\\begin_inset CharStyle", i)
701 if i == -1:
702 return
703 document.body[i] = document.body[i].replace("CharStyle ", "CharStyle CharStyle:")
704 i += 1
706 def revert_long_charstyle_names(document):
707 i = 0
708 while True:
709 i = find_token(document.body, "\\begin_inset CharStyle", i)
710 if i == -1:
711 return
712 document.body[i] = document.body[i].replace("CharStyle CharStyle:", "CharStyle ")
713 i += 1
716 def axe_show_label(document):
717 i = 0
718 while True:
719 i = find_token(document.body, "\\begin_inset CharStyle", i)
720 if i == -1:
721 return
722 if document.body[i + 1].find("show_label") != -1:
723 if document.body[i + 1].find("true") != -1:
724 document.body[i + 1] = "status open"
725 del document.body[ i + 2]
726 else:
727 if document.body[i + 1].find("false") != -1:
728 document.body[i + 1] = "status collapsed"
729 del document.body[ i + 2]
730 else:
731 document.warning("Malformed LyX document: show_label neither false nor true.")
732 else:
733 document.warning("Malformed LyX document: show_label missing in CharStyle.")
735 i += 1
738 def revert_show_label(document):
739 i = 0
740 while True:
741 i = find_token(document.body, "\\begin_inset CharStyle", i)
742 if i == -1:
743 return
744 if document.body[i + 1].find("status open") != -1:
745 document.body.insert(i + 1, "show_label true")
746 else:
747 if document.body[i + 1].find("status collapsed") != -1:
748 document.body.insert(i + 1, "show_label false")
749 else:
750 document.warning("Malformed LyX document: no legal status line in CharStyle.")
751 i += 1
753 def revert_begin_modules(document):
754 i = 0
755 while True:
756 i = find_token(document.header, "\\begin_modules", i)
757 if i == -1:
758 return
759 j = find_end_of(document.header, i, "\\begin_modules", "\\end_modules")
760 if j == -1:
761 # this should not happen
762 break
763 document.header[i : j + 1] = []
765 def convert_flex(document):
766 "Convert CharStyle to Flex"
767 i = 0
768 while True:
769 i = find_token(document.body, "\\begin_inset CharStyle", i)
770 if i == -1:
771 return
772 document.body[i] = document.body[i].replace('\\begin_inset CharStyle', '\\begin_inset Flex')
774 def revert_flex(document):
775 "Convert Flex to CharStyle"
776 i = 0
777 while True:
778 i = find_token(document.body, "\\begin_inset Flex", i)
779 if i == -1:
780 return
781 document.body[i] = document.body[i].replace('\\begin_inset Flex', '\\begin_inset CharStyle')
784 def revert_pdf_options(document):
785 "Revert PDF options for hyperref."
786 # store the PDF options and delete the entries from the Lyx file
787 i = 0
788 hyperref = False
789 title = ""
790 author = ""
791 subject = ""
792 keywords = ""
793 bookmarks = ""
794 bookmarksnumbered = ""
795 bookmarksopen = ""
796 bookmarksopenlevel = ""
797 breaklinks = ""
798 pdfborder = ""
799 colorlinks = ""
800 backref = ""
801 pagebackref = ""
802 pagemode = ""
803 otheroptions = ""
804 i = find_token(document.header, "\\use_hyperref", i)
805 if i != -1:
806 hyperref = get_value(document.header, "\\use_hyperref", i) == 'true'
807 del document.header[i]
808 i = find_token(document.header, "\\pdf_store_options", i)
809 if i != -1:
810 del document.header[i]
811 i = find_token(document.header, "\\pdf_title", 0)
812 if i != -1:
813 title = get_value_string(document.header, '\\pdf_title', 0, 0, True)
814 title = ' pdftitle={' + title + '}'
815 del document.header[i]
816 i = find_token(document.header, "\\pdf_author", 0)
817 if i != -1:
818 author = get_value_string(document.header, '\\pdf_author', 0, 0, True)
819 if title == "":
820 author = ' pdfauthor={' + author + '}'
821 else:
822 author = ',\n pdfauthor={' + author + '}'
823 del document.header[i]
824 i = find_token(document.header, "\\pdf_subject", 0)
825 if i != -1:
826 subject = get_value_string(document.header, '\\pdf_subject', 0, 0, True)
827 if title == "" and author == "":
828 subject = ' pdfsubject={' + subject + '}'
829 else:
830 subject = ',\n pdfsubject={' + subject + '}'
831 del document.header[i]
832 i = find_token(document.header, "\\pdf_keywords", 0)
833 if i != -1:
834 keywords = get_value_string(document.header, '\\pdf_keywords', 0, 0, True)
835 if title == "" and author == "" and subject == "":
836 keywords = ' pdfkeywords={' + keywords + '}'
837 else:
838 keywords = ',\n pdfkeywords={' + keywords + '}'
839 del document.header[i]
840 i = find_token(document.header, "\\pdf_bookmarks", 0)
841 if i != -1:
842 bookmarks = get_value_string(document.header, '\\pdf_bookmarks', 0)
843 bookmarks = ',\n bookmarks=' + bookmarks
844 del document.header[i]
845 i = find_token(document.header, "\\pdf_bookmarksnumbered", i)
846 if i != -1:
847 bookmarksnumbered = get_value_string(document.header, '\\pdf_bookmarksnumbered', 0)
848 bookmarksnumbered = ',\n bookmarksnumbered=' + bookmarksnumbered
849 del document.header[i]
850 i = find_token(document.header, "\\pdf_bookmarksopen", i)
851 if i != -1:
852 bookmarksopen = get_value_string(document.header, '\\pdf_bookmarksopen', 0)
853 bookmarksopen = ',\n bookmarksopen=' + bookmarksopen
854 del document.header[i]
855 i = find_token(document.header, "\\pdf_bookmarksopenlevel", i)
856 if i != -1:
857 bookmarksopenlevel = get_value_string(document.header, '\\pdf_bookmarksopenlevel', 0, 0, True)
858 bookmarksopenlevel = ',\n bookmarksopenlevel=' + bookmarksopenlevel
859 del document.header[i]
860 i = find_token(document.header, "\\pdf_breaklinks", i)
861 if i != -1:
862 breaklinks = get_value_string(document.header, '\\pdf_breaklinks', 0)
863 breaklinks = ',\n breaklinks=' + breaklinks
864 del document.header[i]
865 i = find_token(document.header, "\\pdf_pdfborder", i)
866 if i != -1:
867 pdfborder = get_value_string(document.header, '\\pdf_pdfborder', 0)
868 if pdfborder == 'true':
869 pdfborder = ',\n pdfborder={0 0 0}'
870 else:
871 pdfborder = ',\n pdfborder={0 0 1}'
872 del document.header[i]
873 i = find_token(document.header, "\\pdf_colorlinks", i)
874 if i != -1:
875 colorlinks = get_value_string(document.header, '\\pdf_colorlinks', 0)
876 colorlinks = ',\n colorlinks=' + colorlinks
877 del document.header[i]
878 i = find_token(document.header, "\\pdf_backref", i)
879 if i != -1:
880 backref = get_value_string(document.header, '\\pdf_backref', 0)
881 backref = ',\n backref=' + backref
882 del document.header[i]
883 i = find_token(document.header, "\\pdf_pagebackref", i)
884 if i != -1:
885 pagebackref = get_value_string(document.header, '\\pdf_pagebackref', 0)
886 pagebackref = ',\n pagebackref=' + pagebackref
887 del document.header[i]
888 i = find_token(document.header, "\\pdf_pagemode", 0)
889 if i != -1:
890 pagemode = get_value_string(document.header, '\\pdf_pagemode', 0)
891 pagemode = ',\n pdfpagemode=' + pagemode
892 del document.header[i]
893 i = find_token(document.header, "\\pdf_quoted_options", 0)
894 if i != -1:
895 otheroptions = get_value_string(document.header, '\\pdf_quoted_options', 0, 0, True)
896 if title == "" and author == "" and subject == "" and keywords == "":
897 otheroptions = ' ' + otheroptions
898 else:
899 otheroptions = ',\n ' + otheroptions
900 del document.header[i]
902 # write to the preamble when hyperref was used
903 if hyperref == True:
904 # preamble write preparations
905 # bookmark numbers are only output when they are turned on
906 if bookmarksopen == ',\n bookmarksopen=true':
907 bookmarksopen = bookmarksopen + bookmarksopenlevel
908 if bookmarks == ',\n bookmarks=true':
909 bookmarks = bookmarks + bookmarksnumbered + bookmarksopen
910 else:
911 bookmarks = bookmarks
912 # hypersetup is only output when there are things to be set up
913 setupstart = '\\hypersetup{%\n'
914 setupend = ' }\n'
915 if otheroptions == "" and title == "" and author == ""\
916 and subject == "" and keywords == "":
917 setupstart = ""
918 setupend = ""
919 # write the preamble
920 # babel must be loaded before hyperref and hyperref the first part
921 # of the preamble, like in LyX 1.6
922 insert_to_preamble(0, document,
923 '% Commands inserted by lyx2lyx for PDF properties\n'
924 + '\\usepackage{babel}\n'
925 + '\\usepackage[unicode=true'
926 + bookmarks
927 + breaklinks
928 + pdfborder
929 + backref
930 + pagebackref
931 + colorlinks
932 + pagemode
933 + ']\n'
934 + ' {hyperref}\n'
935 + setupstart
936 + title
937 + author
938 + subject
939 + keywords
940 + otheroptions
941 + setupend)
944 def remove_inzip_options(document):
945 "Remove inzipName and embed options from the Graphics inset"
946 i = 0
947 while 1:
948 i = find_token(document.body, "\\begin_inset Graphics", i)
949 if i == -1:
950 return
951 j = find_end_of_inset(document.body, i + 1)
952 if j == -1:
953 # should not happen
954 document.warning("Malformed LyX document: Could not find end of graphics inset.")
955 # If there's a inzip param, just remove that
956 k = find_token(document.body, "\tinzipName", i + 1, j)
957 if k != -1:
958 del document.body[k]
959 # embed option must follow the inzipName option
960 del document.body[k+1]
961 i = i + 1
964 def convert_inset_command(document):
966 Convert:
967 \begin_inset LatexCommand cmd
969 \begin_inset CommandInset InsetType
970 LatexCommand cmd
972 i = 0
973 while 1:
974 i = find_token(document.body, "\\begin_inset LatexCommand", i)
975 if i == -1:
976 return
977 line = document.body[i]
978 r = re.compile(r'\\begin_inset LatexCommand (.*)$')
979 m = r.match(line)
980 cmdName = m.group(1)
981 insetName = ""
982 #this is adapted from factory.cpp
983 if cmdName[0:4].lower() == "cite":
984 insetName = "citation"
985 elif cmdName == "url" or cmdName == "htmlurl":
986 insetName = "url"
987 elif cmdName[-3:] == "ref":
988 insetName = "ref"
989 elif cmdName == "tableofcontents":
990 insetName = "toc"
991 elif cmdName == "printnomenclature":
992 insetName = "nomencl_print"
993 elif cmdName == "printindex":
994 insetName = "index_print"
995 else:
996 insetName = cmdName
997 insertion = ["\\begin_inset CommandInset " + insetName, "LatexCommand " + cmdName]
998 document.body[i : i+1] = insertion
1001 def revert_inset_command(document):
1003 Convert:
1004 \begin_inset CommandInset InsetType
1005 LatexCommand cmd
1007 \begin_inset LatexCommand cmd
1008 Some insets may end up being converted to insets earlier versions of LyX
1009 will not be able to recognize. Not sure what to do about that.
1011 i = 0
1012 while 1:
1013 i = find_token(document.body, "\\begin_inset CommandInset", i)
1014 if i == -1:
1015 return
1016 nextline = document.body[i+1]
1017 r = re.compile(r'LatexCommand\s+(.*)$')
1018 m = r.match(nextline)
1019 if not m:
1020 document.warning("Malformed LyX document: Missing LatexCommand in " + document.body[i] + ".")
1021 i += 1
1022 continue
1023 cmdName = m.group(1)
1024 insertion = ["\\begin_inset LatexCommand " + cmdName]
1025 document.body[i : i+2] = insertion
1028 def convert_wrapfig_options(document):
1029 "Convert optional options for wrap floats (wrapfig)."
1030 # adds the tokens "lines", "placement", and "overhang"
1031 i = 0
1032 while True:
1033 i = find_token(document.body, "\\begin_inset Wrap figure", i)
1034 if i == -1:
1035 return
1036 document.body.insert(i + 1, "lines 0")
1037 j = find_token(document.body, "placement", i)
1038 # placement can be already set or not; if not, set it
1039 if j == i+2:
1040 document.body.insert(i + 3, "overhang 0col%")
1041 else:
1042 document.body.insert(i + 2, "placement o")
1043 document.body.insert(i + 3, "overhang 0col%")
1044 i = i + 1
1047 def revert_wrapfig_options(document):
1048 "Revert optional options for wrap floats (wrapfig)."
1049 i = 0
1050 while True:
1051 i = find_token(document.body, "\\begin_inset Wrap figure", i)
1052 if i == -1:
1053 return
1054 j = find_end_of_inset(document.body, i)
1055 if j == -1:
1056 document.warning("Can't find end of Wrap inset at line " + str(i))
1057 i += 1
1058 continue
1059 k = find_default_layout(document, i, j)
1060 if k == -1:
1061 document.warning("Can't find default layout for Wrap figure!")
1062 i = j
1063 continue
1064 # Options should be between i and k now
1065 l = find_token(document.body, "lines", i, k)
1066 if l == -1:
1067 document.warning("Can't find lines option for Wrap figure!")
1068 i = k
1069 continue
1070 m = find_token(document.body, "overhang", i + 1, k)
1071 if m == -1:
1072 document.warning("Malformed LyX document: Couldn't find overhang parameter of wrap float!")
1073 i = k
1074 continue
1075 # Do these in reverse order
1076 del document.body[m]
1077 del document.body[l]
1078 i = k
1081 def convert_latexcommand_index(document):
1082 "Convert from LatexCommand form to collapsable form."
1083 i = 0
1084 r1 = re.compile('name "(.*)"')
1085 while True:
1086 i = find_token(document.body, "\\begin_inset CommandInset index", i)
1087 if i == -1:
1088 return
1089 if document.body[i + 1] != "LatexCommand index": # Might also be index_print
1090 i += 1
1091 continue
1092 j = find_end_of_inset(document.body, i + 1)
1093 if j == -1:
1094 document.warning("Unable to find end of index inset at line " + str(i) + "!")
1095 i += 2
1096 continue
1097 m = r1.match(document.body[i + 2])
1098 if m == None:
1099 document.warning("Unable to match: " + document.body[i+2])
1100 # this can happen with empty index insets!
1101 linelist = [""]
1102 else:
1103 fullcontent = m.group(1)
1104 linelist = latex2lyx(fullcontent, True)
1105 #document.warning(fullcontent)
1107 linelist = ["\\begin_inset Index", "status collapsed", "\\begin_layout Standard", ""] + \
1108 linelist + ["\\end_layout"]
1109 document.body[i : j] = linelist
1110 i += len(linelist) - (j - i)
1113 def revert_latexcommand_index(document):
1114 "Revert from collapsable form to LatexCommand form."
1115 i = 0
1116 while True:
1117 i = find_token(document.body, "\\begin_inset Index", i)
1118 if i == -1:
1119 return
1120 j = find_end_of_inset(document.body, i + 1)
1121 if j == -1:
1122 return
1124 content = lyx2latex(document, document.body[i:j])
1125 # escape quotes
1126 content = content.replace('"', r'\"')
1127 document.body[i:j] = ["\\begin_inset CommandInset index", "LatexCommand index",
1128 "name " + '"' + content + '"', ""]
1129 i += 5
1132 def revert_wraptable(document):
1133 "Revert wrap table to wrap figure."
1134 i = 0
1135 while True:
1136 i = find_token(document.body, "\\begin_inset Wrap table", i)
1137 if i == -1:
1138 return
1139 document.body[i] = document.body[i].replace('\\begin_inset Wrap table', '\\begin_inset Wrap figure')
1140 i = i + 1
1143 def revert_vietnamese(document):
1144 "Set language Vietnamese to English"
1145 # Set document language from Vietnamese to English
1146 i = 0
1147 if document.language == "vietnamese":
1148 document.language = "english"
1149 i = find_token(document.header, "\\language", 0)
1150 if i != -1:
1151 document.header[i] = "\\language english"
1152 j = 0
1153 while True:
1154 j = find_token(document.body, "\\lang vietnamese", j)
1155 if j == -1:
1156 return
1157 document.body[j] = document.body[j].replace("\\lang vietnamese", "\\lang english")
1158 j = j + 1
1161 def convert_japanese_cjk(document):
1162 "Set language japanese to japanese-cjk"
1163 # Set document language from japanese-plain to japanese
1164 i = 0
1165 if document.language == "japanese":
1166 document.language = "japanese-cjk"
1167 i = find_token(document.header, "\\language", 0)
1168 if i != -1:
1169 document.header[i] = "\\language japanese-cjk"
1170 j = 0
1171 while True:
1172 j = find_token(document.body, "\\lang japanese", j)
1173 if j == -1:
1174 return
1175 document.body[j] = document.body[j].replace("\\lang japanese", "\\lang japanese-cjk")
1176 j = j + 1
1179 def revert_japanese(document):
1180 "Set language japanese-plain to japanese"
1181 # Set document language from japanese-plain to japanese
1182 i = 0
1183 if document.language == "japanese-plain":
1184 document.language = "japanese"
1185 i = find_token(document.header, "\\language", 0)
1186 if i != -1:
1187 document.header[i] = "\\language japanese"
1188 j = 0
1189 while True:
1190 j = find_token(document.body, "\\lang japanese-plain", j)
1191 if j == -1:
1192 return
1193 document.body[j] = document.body[j].replace("\\lang japanese-plain", "\\lang japanese")
1194 j = j + 1
1197 def revert_japanese_cjk(document):
1198 "Set language japanese-cjk to japanese"
1199 # Set document language from japanese-plain to japanese
1200 i = 0
1201 if document.language == "japanese-cjk":
1202 document.language = "japanese"
1203 i = find_token(document.header, "\\language", 0)
1204 if i != -1:
1205 document.header[i] = "\\language japanese"
1206 j = 0
1207 while True:
1208 j = find_token(document.body, "\\lang japanese-cjk", j)
1209 if j == -1:
1210 return
1211 document.body[j] = document.body[j].replace("\\lang japanese-cjk", "\\lang japanese")
1212 j = j + 1
1215 def revert_japanese_encoding(document):
1216 "Set input encoding form EUC-JP-plain to EUC-JP etc."
1217 # Set input encoding form EUC-JP-plain to EUC-JP etc.
1218 i = 0
1219 i = find_token(document.header, "\\inputencoding EUC-JP-plain", 0)
1220 if i != -1:
1221 document.header[i] = "\\inputencoding EUC-JP"
1222 j = 0
1223 j = find_token(document.header, "\\inputencoding JIS-plain", 0)
1224 if j != -1:
1225 document.header[j] = "\\inputencoding JIS"
1226 k = 0
1227 k = find_token(document.header, "\\inputencoding SJIS-plain", 0)
1228 if k != -1: # convert to UTF8 since there is currently no SJIS encoding
1229 document.header[k] = "\\inputencoding UTF8"
1232 def revert_inset_info(document):
1233 'Replace info inset with its content'
1234 i = 0
1235 while 1:
1236 i = find_token(document.body, '\\begin_inset Info', i)
1237 if i == -1:
1238 return
1239 j = find_end_of_inset(document.body, i + 1)
1240 if j == -1:
1241 # should not happen
1242 document.warning("Malformed LyX document: Could not find end of Info inset.")
1243 type = 'unknown'
1244 arg = ''
1245 for k in range(i, j+1):
1246 if document.body[k].startswith("arg"):
1247 arg = document.body[k][3:].strip()
1248 # remove embracing quotation marks
1249 if arg[0] == '"':
1250 arg = arg[1:]
1251 if arg[len(arg) - 1] == '"':
1252 arg = arg[:len(arg) - 1]
1253 # \" to straight quote
1254 arg = arg.replace(r'\"', '"')
1255 # \ to \backslash
1256 arg = arg.replace(r'\\', "\\backslash\n")
1257 if document.body[k].startswith("type"):
1258 type = document.body[k][4:].strip().strip('"')
1259 # I think there is a newline after \\end_inset, which should be removed.
1260 if document.body[j + 1].strip() == "":
1261 document.body[i : (j + 2)] = [type + ':' + arg]
1262 else:
1263 document.body[i : (j + 1)] = [type + ':' + arg]
1266 def convert_pdf_options(document):
1267 # Set the pdfusetitle tag, delete the pdf_store_options,
1268 # set quotes for bookmarksopenlevel"
1269 has_hr = get_value(document.header, "\\use_hyperref", 0, default = "0")
1270 if has_hr == "1":
1271 k = find_token(document.header, "\\use_hyperref", 0)
1272 document.header.insert(k + 1, "\\pdf_pdfusetitle true")
1273 k = find_token(document.header, "\\pdf_store_options", 0)
1274 if k != -1:
1275 del document.header[k]
1276 i = find_token(document.header, "\\pdf_bookmarksopenlevel", k)
1277 if i == -1: return
1278 document.header[i] = document.header[i].replace('"', '')
1281 def revert_pdf_options_2(document):
1282 # reset the pdfusetitle tag, set quotes for bookmarksopenlevel"
1283 k = find_token(document.header, "\\use_hyperref", 0)
1284 i = find_token(document.header, "\\pdf_pdfusetitle", k)
1285 if i != -1:
1286 del document.header[i]
1287 i = find_token(document.header, "\\pdf_bookmarksopenlevel", k)
1288 if i == -1: return
1289 values = document.header[i].split()
1290 values[1] = ' "' + values[1] + '"'
1291 document.header[i] = ''.join(values)
1294 def convert_htmlurl(document):
1295 'Convert "htmlurl" to "href" insets for docbook'
1296 if document.backend != "docbook":
1297 return
1298 i = 0
1299 while True:
1300 i = find_token(document.body, "\\begin_inset CommandInset url", i)
1301 if i == -1:
1302 return
1303 document.body[i] = "\\begin_inset CommandInset href"
1304 document.body[i + 1] = "LatexCommand href"
1305 i = i + 1
1308 def convert_url(document):
1309 'Convert url insets to url charstyles'
1310 if document.backend == "docbook":
1311 return
1312 i = 0
1313 while True:
1314 i = find_token(document.body, "\\begin_inset CommandInset url", i)
1315 if i == -1:
1316 break
1317 n = find_token(document.body, "name", i)
1318 if n == i + 2:
1319 # place the URL name in typewriter before the new URL insert
1320 # grab the name 'bla' from the e.g. the line 'name "bla"',
1321 # therefore start with the 6th character
1322 name = document.body[n][6:-1]
1323 newname = [name + " "]
1324 document.body[i:i] = newname
1325 i = i + 1
1326 j = find_token(document.body, "target", i)
1327 if j == -1:
1328 document.warning("Malformed LyX document: Can't find target for url inset")
1329 i += 1
1330 continue
1331 target = document.body[j][8:-1]
1332 k = find_token(document.body, "\\end_inset", j)
1333 if k == -1:
1334 document.warning("Malformed LyX document: Can't find end of url inset")
1335 i = j
1336 continue
1337 newstuff = ["\\begin_inset Flex URL",
1338 "status collapsed", "",
1339 "\\begin_layout Standard",
1341 target,
1342 "\\end_layout",
1344 document.body[i:k] = newstuff
1345 i = i + len(newstuff)
1347 def convert_ams_classes(document):
1348 tc = document.textclass
1349 if (tc != "amsart" and tc != "amsart-plain" and
1350 tc != "amsart-seq" and tc != "amsbook"):
1351 return
1352 if tc == "amsart-plain":
1353 document.textclass = "amsart"
1354 document.set_textclass()
1355 document.add_module("Theorems (Starred)")
1356 return
1357 if tc == "amsart-seq":
1358 document.textclass = "amsart"
1359 document.set_textclass()
1360 document.add_module("Theorems (AMS)")
1362 #Now we want to see if any of the environments in the extended theorems
1363 #module were used in this document. If so, we'll add that module, too.
1364 layouts = ["Criterion", "Algorithm", "Axiom", "Condition", "Note", \
1365 "Notation", "Summary", "Acknowledgement", "Conclusion", "Fact", \
1366 "Assumption"]
1368 r = re.compile(r'^\\begin_layout (.*?)\*?\s*$')
1369 i = 0
1370 while True:
1371 i = find_token(document.body, "\\begin_layout", i)
1372 if i == -1:
1373 return
1374 m = r.match(document.body[i])
1375 if m == None:
1376 # This is an empty layout
1377 # document.warning("Weirdly formed \\begin_layout at line %d of body!" % i)
1378 i += 1
1379 continue
1380 m = m.group(1)
1381 if layouts.count(m) != 0:
1382 document.add_module("Theorems (AMS-Extended)")
1383 return
1384 i += 1
1386 def revert_href(document):
1387 'Reverts hyperlink insets (href) to url insets (url)'
1388 i = 0
1389 while True:
1390 i = find_token(document.body, "\\begin_inset CommandInset href", i)
1391 if i == -1:
1392 return
1393 document.body[i : i + 2] = \
1394 ["\\begin_inset CommandInset url", "LatexCommand url"]
1395 i = i + 2
1397 def revert_url(document):
1398 'Reverts Flex URL insets to old-style URL insets'
1399 i = 0
1400 while True:
1401 i = find_token(document.body, "\\begin_inset Flex URL", i)
1402 if i == -1:
1403 return
1404 j = find_end_of_inset(document.body, i)
1405 if j == -1:
1406 document.warning("Can't find end of inset in revert_url!")
1407 return
1408 k = find_default_layout(document, i, j)
1409 if k == -1:
1410 document.warning("Can't find default layout in revert_url!")
1411 i = j
1412 continue
1413 l = find_end_of(document.body, k, "\\begin_layout", "\\end_layout")
1414 if l == -1 or l >= j:
1415 document.warning("Can't find end of default layout in revert_url!")
1416 i = j
1417 continue
1418 # OK, so the inset's data is between lines k and l.
1419 data = " ".join(document.body[k+1:l])
1420 data = data.strip()
1421 newinset = ["\\begin_inset LatexCommand url", "target \"" + data + "\"",\
1422 "", "\\end_inset"]
1423 document.body[i:j+1] = newinset
1424 i = i + len(newinset)
1427 def convert_include(document):
1428 'Converts include insets to new format.'
1429 i = 0
1430 r = re.compile(r'\\begin_inset Include\s+\\([^{]+){([^}]*)}(?:\[(.*)\])?')
1431 while True:
1432 i = find_token(document.body, "\\begin_inset Include", i)
1433 if i == -1:
1434 return
1435 line = document.body[i]
1436 previewline = document.body[i + 1]
1437 m = r.match(line)
1438 if m == None:
1439 document.warning("Unable to match line " + str(i) + " of body!")
1440 i += 1
1441 continue
1442 cmd = m.group(1)
1443 fn = m.group(2)
1444 opt = m.group(3)
1445 insertion = ["\\begin_inset CommandInset include",
1446 "LatexCommand " + cmd, previewline,
1447 "filename \"" + fn + "\""]
1448 newlines = 2
1449 if opt:
1450 insertion.append("lstparams " + '"' + opt + '"')
1451 newlines += 1
1452 document.body[i : i + 2] = insertion
1453 i += newlines
1456 def revert_include(document):
1457 'Reverts include insets to old format.'
1458 i = 0
1459 r0 = re.compile('preview.*')
1460 r1 = re.compile('LatexCommand (.+)')
1461 r2 = re.compile('filename "(.+)"')
1462 r3 = re.compile('lstparams "(.*)"')
1463 while True:
1464 i = find_token(document.body, "\\begin_inset CommandInset include", i)
1465 if i == -1:
1466 return
1467 nextline = i + 1
1468 m = r1.match(document.body[nextline])
1469 if m == None:
1470 document.warning("Malformed LyX document: No LatexCommand line for `" +
1471 document.body[i] + "' on line " + str(i) + ".")
1472 i += 1
1473 continue
1474 cmd = m.group(1)
1475 nextline += 1
1476 if r0.match(document.body[nextline]):
1477 previewline = document.body[nextline]
1478 nextline += 1
1479 else:
1480 previewline = ""
1481 m = r2.match(document.body[nextline])
1482 if m == None:
1483 document.warning("Malformed LyX document: No filename line for `" + \
1484 document.body[i] + "' on line " + str(i) + ".")
1485 i += 2
1486 continue
1487 fn = m.group(1)
1488 nextline += 1
1489 options = ""
1490 if (cmd == "lstinputlisting"):
1491 m = r3.match(document.body[nextline])
1492 if m != None:
1493 options = m.group(1)
1494 numlines = 5
1495 nextline += 1
1496 newline = "\\begin_inset Include \\" + cmd + "{" + fn + "}"
1497 if options:
1498 newline += ("[" + options + "]")
1499 insertion = [newline]
1500 if previewline != "":
1501 insertion.append(previewline)
1502 document.body[i : nextline] = insertion
1503 i += 2
1506 def revert_albanian(document):
1507 "Set language Albanian to English"
1508 i = 0
1509 if document.language == "albanian":
1510 document.language = "english"
1511 i = find_token(document.header, "\\language", 0)
1512 if i != -1:
1513 document.header[i] = "\\language english"
1514 j = 0
1515 while True:
1516 j = find_token(document.body, "\\lang albanian", j)
1517 if j == -1:
1518 return
1519 document.body[j] = document.body[j].replace("\\lang albanian", "\\lang english")
1520 j = j + 1
1523 def revert_lowersorbian(document):
1524 "Set language lower Sorbian to English"
1525 i = 0
1526 if document.language == "lowersorbian":
1527 document.language = "english"
1528 i = find_token(document.header, "\\language", 0)
1529 if i != -1:
1530 document.header[i] = "\\language english"
1531 j = 0
1532 while True:
1533 j = find_token(document.body, "\\lang lowersorbian", j)
1534 if j == -1:
1535 return
1536 document.body[j] = document.body[j].replace("\\lang lowersorbian", "\\lang english")
1537 j = j + 1
1540 def revert_uppersorbian(document):
1541 "Set language uppersorbian to usorbian as this was used in LyX 1.5"
1542 i = 0
1543 if document.language == "uppersorbian":
1544 document.language = "usorbian"
1545 i = find_token(document.header, "\\language", 0)
1546 if i != -1:
1547 document.header[i] = "\\language usorbian"
1548 j = 0
1549 while True:
1550 j = find_token(document.body, "\\lang uppersorbian", j)
1551 if j == -1:
1552 return
1553 document.body[j] = document.body[j].replace("\\lang uppersorbian", "\\lang usorbian")
1554 j = j + 1
1557 def convert_usorbian(document):
1558 "Set language usorbian to uppersorbian"
1559 i = 0
1560 if document.language == "usorbian":
1561 document.language = "uppersorbian"
1562 i = find_token(document.header, "\\language", 0)
1563 if i != -1:
1564 document.header[i] = "\\language uppersorbian"
1565 j = 0
1566 while True:
1567 j = find_token(document.body, "\\lang usorbian", j)
1568 if j == -1:
1569 return
1570 document.body[j] = document.body[j].replace("\\lang usorbian", "\\lang uppersorbian")
1571 j = j + 1
1574 def convert_macro_global(document):
1575 "Remove TeX code command \global when it is in front of a macro"
1576 # math macros are nowadays already defined \global, so that an additional
1577 # \global would make the document uncompilable, see
1578 # http://bugzilla.lyx.org/show_bug.cgi?id=5371
1579 # We're looking for something like this:
1580 # \begin_inset ERT
1581 # status collapsed
1583 # \begin_layout Plain Layout
1586 # \backslash
1587 # global
1588 # \end_layout
1590 # \end_inset
1593 # \begin_inset FormulaMacro
1594 # \renewcommand{\foo}{123}
1595 # \end_inset
1596 i = 0
1597 while True:
1598 i = find_token(document.body, "\\begin_inset FormulaMacro", i)
1599 if i == -1:
1600 return
1601 # if i <= 13, then there isn't enough room for the ERT
1602 if i <= 12:
1603 i += 1
1604 continue
1605 if document.body[i-6] == "global":
1606 del document.body[i-13 : i]
1607 i = i - 12
1608 else:
1609 i += 1
1612 def revert_macro_optional_params(document):
1613 "Convert macro definitions with optional parameters into ERTs"
1614 # Stub to convert macro definitions with one or more optional parameters
1615 # into uninterpreted ERT insets
1618 def revert_hyperlinktype(document):
1619 'Reverts hyperlink type'
1620 i = 0
1621 j = 0
1622 while True:
1623 i = find_token(document.body, "target", i)
1624 if i == -1:
1625 return
1626 j = find_token(document.body, "type", i)
1627 if j == -1:
1628 return
1629 if j == i + 1:
1630 del document.body[j]
1631 i = i + 1
1634 def revert_pagebreak(document):
1635 'Reverts pagebreak to ERT'
1636 i = 0
1637 while True:
1638 i = find_token(document.body, "\\pagebreak", i)
1639 if i == -1:
1640 return
1641 document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1642 '\\begin_layout Standard\n\n\n\\backslash\n' \
1643 'pagebreak{}\n\\end_layout\n\n\\end_inset\n\n'
1644 i = i + 1
1647 def revert_linebreak(document):
1648 'Reverts linebreak to ERT'
1649 i = 0
1650 while True:
1651 i = find_token(document.body, "\\linebreak", i)
1652 if i == -1:
1653 return
1654 document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1655 '\\begin_layout Standard\n\n\n\\backslash\n' \
1656 'linebreak{}\n\\end_layout\n\n\\end_inset\n\n'
1657 i = i + 1
1660 def revert_latin(document):
1661 "Set language Latin to English"
1662 i = 0
1663 if document.language == "latin":
1664 document.language = "english"
1665 i = find_token(document.header, "\\language", 0)
1666 if i != -1:
1667 document.header[i] = "\\language english"
1668 j = 0
1669 while True:
1670 j = find_token(document.body, "\\lang latin", j)
1671 if j == -1:
1672 return
1673 document.body[j] = document.body[j].replace("\\lang latin", "\\lang english")
1674 j = j + 1
1677 def revert_samin(document):
1678 "Set language North Sami to English"
1679 i = 0
1680 if document.language == "samin":
1681 document.language = "english"
1682 i = find_token(document.header, "\\language", 0)
1683 if i != -1:
1684 document.header[i] = "\\language english"
1685 j = 0
1686 while True:
1687 j = find_token(document.body, "\\lang samin", j)
1688 if j == -1:
1689 return
1690 document.body[j] = document.body[j].replace("\\lang samin", "\\lang english")
1691 j = j + 1
1694 def convert_serbocroatian(document):
1695 "Set language Serbocroatian to Croatian as this was really Croatian in LyX 1.5"
1696 i = 0
1697 if document.language == "serbocroatian":
1698 document.language = "croatian"
1699 i = find_token(document.header, "\\language", 0)
1700 if i != -1:
1701 document.header[i] = "\\language croatian"
1702 j = 0
1703 while True:
1704 j = find_token(document.body, "\\lang serbocroatian", j)
1705 if j == -1:
1706 return
1707 document.body[j] = document.body[j].replace("\\lang serbocroatian", "\\lang croatian")
1708 j = j + 1
1711 def convert_framed_notes(document):
1712 "Convert framed notes to boxes. "
1713 i = 0
1714 while 1:
1715 i = find_tokens(document.body, ["\\begin_inset Note Framed", "\\begin_inset Note Shaded"], i)
1716 if i == -1:
1717 return
1718 subst = [document.body[i].replace("\\begin_inset Note", "\\begin_inset Box"),
1719 'position "t"',
1720 'hor_pos "c"',
1721 'has_inner_box 0',
1722 'inner_pos "t"',
1723 'use_parbox 0',
1724 'width "100col%"',
1725 'special "none"',
1726 'height "1in"',
1727 'height_special "totalheight"']
1728 document.body[i:i+1] = subst
1729 i = i + 9
1732 def convert_module_names(document):
1733 modulemap = { 'Braille' : 'braille', 'Endnote' : 'endnotes', 'Foot to End' : 'foottoend',\
1734 'Hanging' : 'hanging', 'Linguistics' : 'linguistics', 'Logical Markup' : 'logicalmkup', \
1735 'Theorems (AMS-Extended)' : 'theorems-ams-extended', 'Theorems (AMS)' : 'theorems-ams', \
1736 'Theorems (Order By Chapter)' : 'theorems-chap', 'Theorems (Order By Section)' : 'theorems-sec', \
1737 'Theorems (Starred)' : 'theorems-starred', 'Theorems' : 'theorems-std' }
1738 modlist = document.get_module_list()
1739 if len(modlist) == 0:
1740 return
1741 newmodlist = []
1742 for mod in modlist:
1743 if modulemap.has_key(mod):
1744 newmodlist.append(modulemap[mod])
1745 else:
1746 document.warning("Can't find module %s in the module map!" % mod)
1747 newmodlist.append(mod)
1748 document.set_module_list(newmodlist)
1751 def revert_module_names(document):
1752 modulemap = { 'braille' : 'Braille', 'endnotes' : 'Endnote', 'foottoend' : 'Foot to End',\
1753 'hanging' : 'Hanging', 'linguistics' : 'Linguistics', 'logicalmkup' : 'Logical Markup', \
1754 'theorems-ams-extended' : 'Theorems (AMS-Extended)', 'theorems-ams' : 'Theorems (AMS)', \
1755 'theorems-chap' : 'Theorems (Order By Chapter)', 'theorems-sec' : 'Theorems (Order By Section)', \
1756 'theorems-starred' : 'Theorems (Starred)', 'theorems-std' : 'Theorems'}
1757 modlist = document.get_module_list()
1758 if len(modlist) == 0:
1759 return
1760 newmodlist = []
1761 for mod in modlist:
1762 if modulemap.has_key(mod):
1763 newmodlist.append(modulemap[mod])
1764 else:
1765 document.warning("Can't find module %s in the module map!" % mod)
1766 newmodlist.append(mod)
1767 document.set_module_list(newmodlist)
1770 def revert_colsep(document):
1771 i = find_token(document.header, "\\columnsep", 0)
1772 if i == -1:
1773 return
1774 colsepline = document.header[i]
1775 r = re.compile(r'\\columnsep (.*)')
1776 m = r.match(colsepline)
1777 if not m:
1778 document.warning("Malformed column separation line!")
1779 return
1780 colsep = m.group(1)
1781 del document.header[i]
1782 #it seems to be safe to add the package even if it is already used
1783 pretext = ["\\usepackage{geometry}", "\\geometry{columnsep=" + colsep + "}"]
1785 add_to_preamble(document, pretext)
1788 def revert_framed_notes(document):
1789 "Revert framed boxes to notes. "
1790 i = 0
1791 while 1:
1792 i = find_tokens(document.body, ["\\begin_inset Box Framed", "\\begin_inset Box Shaded"], i)
1794 if i == -1:
1795 return
1796 j = find_end_of_inset(document.body, i + 1)
1797 if j == -1:
1798 # should not happen
1799 document.warning("Malformed LyX document: Could not find end of Box inset.")
1800 k = find_token(document.body, "status", i + 1, j)
1801 if k == -1:
1802 document.warning("Malformed LyX document: Missing `status' tag in Box inset.")
1803 return
1804 status = document.body[k]
1805 l = find_default_layout(document, i + 1, j)
1806 if l == -1:
1807 document.warning("Malformed LyX document: Missing `\\begin_layout' in Box inset.")
1808 return
1809 m = find_token(document.body, "\\end_layout", i + 1, j)
1810 if m == -1:
1811 document.warning("Malformed LyX document: Missing `\\end_layout' in Box inset.")
1812 return
1813 ibox = find_token(document.body, "has_inner_box 1", i + 1, k)
1814 pbox = find_token(document.body, "use_parbox 1", i + 1, k)
1815 if ibox == -1 and pbox == -1:
1816 document.body[i] = document.body[i].replace("\\begin_inset Box", "\\begin_inset Note")
1817 del document.body[i+1:k]
1818 else:
1819 document.body[i] = document.body[i].replace("\\begin_inset Box Shaded", "\\begin_inset Box Frameless")
1820 subst1 = [document.body[l],
1821 "\\begin_inset Note Shaded",
1822 status,
1823 '\\begin_layout Standard']
1824 document.body[l:l + 1] = subst1
1825 subst2 = [document.body[m], "\\end_layout", "\\end_inset"]
1826 document.body[m:m + 1] = subst2
1827 i = i + 1
1830 def revert_slash(document):
1831 'Revert \\SpecialChar \\slash{} to ERT'
1832 i = 0
1833 while i < len(document.body):
1834 m = re.match(r'(.*)\\SpecialChar \\slash{}(.*)', document.body[i])
1835 if m:
1836 before = m.group(1)
1837 after = m.group(2)
1838 subst = [before,
1839 '\\begin_inset ERT',
1840 'status collapsed', '',
1841 '\\begin_layout Standard',
1842 '', '', '\\backslash',
1843 'slash{}',
1844 '\\end_layout', '',
1845 '\\end_inset', '',
1846 after]
1847 document.body[i: i+1] = subst
1848 i = i + len(subst)
1849 else:
1850 i = i + 1
1853 def revert_nobreakdash(document):
1854 'Revert \\SpecialChar \\nobreakdash- to ERT'
1855 i = 0
1856 while i < len(document.body):
1857 m = re.match(r'(.*)\\SpecialChar \\nobreakdash-(.*)', document.body[i])
1858 if m:
1859 before = m.group(1)
1860 after = m.group(2)
1861 subst = [before,
1862 '\\begin_inset ERT',
1863 'status collapsed', '',
1864 '\\begin_layout Standard', '', '',
1865 '\\backslash',
1866 'nobreakdash-',
1867 '\\end_layout', '',
1868 '\\end_inset', '',
1869 after]
1870 document.body[i: i+1] = subst
1871 i = i + len(subst)
1872 j = find_token(document.header, "\\use_amsmath", 0)
1873 if j == -1:
1874 document.warning("Malformed LyX document: Missing '\\use_amsmath'.")
1875 return
1876 document.header[j] = "\\use_amsmath 2"
1877 else:
1878 i = i + 1
1881 #Returns number of lines added/removed
1882 def revert_nocite_key(body, start, end):
1883 'key "..." -> \nocite{...}'
1884 r = re.compile(r'^key "(.*)"')
1885 i = start
1886 j = end
1887 while i < j:
1888 m = r.match(body[i])
1889 if m:
1890 body[i:i+1] = ["\\backslash", "nocite{" + m.group(1) + "}"]
1891 j += 1 # because we added a line
1892 i += 2 # skip that line
1893 else:
1894 del body[i]
1895 j -= 1 # because we deleted a line
1896 # no need to change i, since it now points to the next line
1897 return j - end
1900 def revert_nocite(document):
1901 "Revert LatexCommand nocite to ERT"
1902 i = 0
1903 while 1:
1904 i = find_token(document.body, "\\begin_inset CommandInset citation", i)
1905 if i == -1:
1906 return
1907 if (document.body[i+1] != "LatexCommand nocite"):
1908 # note that we already incremented i
1909 i = i + 1
1910 continue
1911 insetEnd = find_end_of_inset(document.body, i)
1912 if insetEnd == -1:
1913 #this should not happen
1914 document.warning("End of CommandInset citation not found in revert_nocite!")
1915 return
1917 paramLocation = i + 2 #start of the inset's parameters
1918 addedLines = 0
1919 document.body[i:i+2] = \
1920 ["\\begin_inset ERT", "status collapsed", "", "\\begin_layout Standard"]
1921 # that added two lines
1922 paramLocation += 2
1923 insetEnd += 2
1924 #print insetEnd, document.body[i: insetEnd + 1]
1925 insetEnd += revert_nocite_key(document.body, paramLocation, insetEnd)
1926 #print insetEnd, document.body[i: insetEnd + 1]
1927 document.body.insert(insetEnd, "\\end_layout")
1928 document.body.insert(insetEnd + 1, "")
1929 i = insetEnd + 1
1932 def revert_btprintall(document):
1933 "Revert (non-bibtopic) btPrintAll option to ERT \nocite{*}"
1934 i = find_token(document.header, '\\use_bibtopic', 0)
1935 if i == -1:
1936 document.warning("Malformed lyx document: Missing '\\use_bibtopic'.")
1937 return
1938 if get_value(document.header, '\\use_bibtopic', 0) == "false":
1939 i = 0
1940 while i < len(document.body):
1941 i = find_token(document.body, "\\begin_inset CommandInset bibtex", i)
1942 if i == -1:
1943 return
1944 j = find_end_of_inset(document.body, i + 1)
1945 if j == -1:
1946 #this should not happen
1947 document.warning("End of CommandInset bibtex not found in revert_btprintall!")
1948 j = len(document.body)
1949 # this range isn't really right, but it should be OK, since we shouldn't
1950 # see more than one matching line in each inset
1951 addedlines = 0
1952 for k in range(i, j):
1953 if (document.body[k] == 'btprint "btPrintAll"'):
1954 del document.body[k]
1955 subst = ["\\begin_inset ERT",
1956 "status collapsed", "",
1957 "\\begin_layout Standard", "",
1958 "\\backslash",
1959 "nocite{*}",
1960 "\\end_layout",
1961 "\\end_inset"]
1962 document.body[i:i] = subst
1963 addlines = addedlines + len(subst) - 1
1964 i = j + addedlines
1967 def revert_bahasam(document):
1968 "Set language Bahasa Malaysia to Bahasa Indonesia"
1969 i = 0
1970 if document.language == "bahasam":
1971 document.language = "bahasa"
1972 i = find_token(document.header, "\\language", 0)
1973 if i != -1:
1974 document.header[i] = "\\language bahasa"
1975 j = 0
1976 while True:
1977 j = find_token(document.body, "\\lang bahasam", j)
1978 if j == -1:
1979 return
1980 document.body[j] = document.body[j].replace("\\lang bahasam", "\\lang bahasa")
1981 j = j + 1
1984 def revert_interlingua(document):
1985 "Set language Interlingua to English"
1986 i = 0
1987 if document.language == "interlingua":
1988 document.language = "english"
1989 i = find_token(document.header, "\\language", 0)
1990 if i != -1:
1991 document.header[i] = "\\language english"
1992 j = 0
1993 while True:
1994 j = find_token(document.body, "\\lang interlingua", j)
1995 if j == -1:
1996 return
1997 document.body[j] = document.body[j].replace("\\lang interlingua", "\\lang english")
1998 j = j + 1
2001 def revert_serbianlatin(document):
2002 "Set language Serbian-Latin to Croatian"
2003 i = 0
2004 if document.language == "serbian-latin":
2005 document.language = "croatian"
2006 i = find_token(document.header, "\\language", 0)
2007 if i != -1:
2008 document.header[i] = "\\language croatian"
2009 j = 0
2010 while True:
2011 j = find_token(document.body, "\\lang serbian-latin", j)
2012 if j == -1:
2013 return
2014 document.body[j] = document.body[j].replace("\\lang serbian-latin", "\\lang croatian")
2015 j = j + 1
2018 def revert_rotfloat(document):
2019 " Revert sideways custom floats. "
2020 i = 0
2021 while 1:
2022 # whitespace intended (exclude \\begin_inset FloatList)
2023 i = find_token(document.body, "\\begin_inset Float ", i)
2024 if i == -1:
2025 return
2026 line = document.body[i]
2027 r = re.compile(r'\\begin_inset Float (.*)$')
2028 m = r.match(line)
2029 if m == None:
2030 document.warning("Unable to match line " + str(i) + " of body!")
2031 i += 1
2032 continue
2033 floattype = m.group(1)
2034 if floattype == "figure" or floattype == "table":
2035 i += 1
2036 continue
2037 j = find_end_of_inset(document.body, i)
2038 if j == -1:
2039 document.warning("Malformed lyx document: Missing '\\end_inset' in revert_rotfloat.")
2040 i += 1
2041 continue
2042 addedLines = 0
2043 if get_value(document.body, 'sideways', i, j) == "false":
2044 i += 1
2045 continue
2046 l = find_default_layout(document, i + 1, j)
2047 if l == -1:
2048 document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
2049 return
2050 subst = ['\\begin_layout Standard',
2051 '\\begin_inset ERT',
2052 'status collapsed', '',
2053 '\\begin_layout Standard', '', '',
2054 '\\backslash', '',
2055 'end{sideways' + floattype + '}',
2056 '\\end_layout', '', '\\end_inset']
2057 document.body[j : j+1] = subst
2058 addedLines = len(subst) - 1
2059 del document.body[i+1 : l]
2060 addedLines -= (l-1) - (i+1)
2061 subst = ['\\begin_inset ERT', 'status collapsed', '',
2062 '\\begin_layout Standard', '', '', '\\backslash',
2063 'begin{sideways' + floattype + '}',
2064 '\\end_layout', '', '\\end_inset', '',
2065 '\\end_layout', '']
2066 document.body[i : i+1] = subst
2067 addedLines += len(subst) - 1
2068 if floattype == "algorithm":
2069 add_to_preamble(document,
2070 ['% Commands inserted by lyx2lyx for sideways algorithm float',
2071 '\\usepackage{rotfloat}',
2072 '\\floatstyle{ruled}',
2073 '\\newfloat{algorithm}{tbp}{loa}',
2074 '\\floatname{algorithm}{Algorithm}'])
2075 else:
2076 document.warning("Cannot create preamble definition for custom float" + floattype + ".")
2077 i += addedLines + 1
2080 def revert_widesideways(document):
2081 " Revert wide sideways floats. "
2082 i = 0
2083 while 1:
2084 # whitespace intended (exclude \\begin_inset FloatList)
2085 i = find_token(document.body, '\\begin_inset Float ', i)
2086 if i == -1:
2087 return
2088 line = document.body[i]
2089 r = re.compile(r'\\begin_inset Float (.*)$')
2090 m = r.match(line)
2091 if m == None:
2092 document.warning("Unable to match line " + str(i) + " of body!")
2093 i += 1
2094 continue
2095 floattype = m.group(1)
2096 if floattype != "figure" and floattype != "table":
2097 i += 1
2098 continue
2099 j = find_end_of_inset(document.body, i)
2100 if j == -1:
2101 document.warning("Malformed lyx document: Missing '\\end_inset' in revert_widesideways.")
2102 i += 1
2103 continue
2104 if get_value(document.body, 'sideways', i, j) == "false" or \
2105 get_value(document.body, 'wide', i, j) == "false":
2106 i += 1
2107 continue
2108 l = find_default_layout(document, i + 1, j)
2109 if l == -1:
2110 document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
2111 return
2112 subst = ['\\begin_layout Standard', '\\begin_inset ERT',
2113 'status collapsed', '',
2114 '\\begin_layout Standard', '', '', '\\backslash',
2115 'end{sideways' + floattype + '*}',
2116 '\\end_layout', '', '\\end_inset']
2117 document.body[j : j+1] = subst
2118 addedLines = len(subst) - 1
2119 del document.body[i+1:l-1]
2120 addedLines -= (l-1) - (i+1)
2121 subst = ['\\begin_inset ERT', 'status collapsed', '',
2122 '\\begin_layout Standard', '', '', '\\backslash',
2123 'begin{sideways' + floattype + '*}', '\\end_layout', '',
2124 '\\end_inset', '', '\\end_layout', '']
2125 document.body[i : i+1] = subst
2126 addedLines += len(subst) - 1
2127 add_to_preamble(document, ['\\usepackage{rotfloat}\n'])
2128 i += addedLines + 1
2131 def revert_inset_embedding(document, type):
2132 ' Remove embed tag from certain type of insets'
2133 i = 0
2134 while 1:
2135 i = find_token(document.body, "\\begin_inset %s" % type, i)
2136 if i == -1:
2137 return
2138 j = find_end_of_inset(document.body, i)
2139 if j == -1:
2140 document.warning("Malformed lyx document: Missing '\\end_inset' in revert_inset_embedding.")
2141 i = i + 1
2142 continue
2143 k = find_token(document.body, "\tembed", i, j)
2144 if k == -1:
2145 k = find_token(document.body, "embed", i, j)
2146 if k != -1:
2147 del document.body[k]
2148 i = i + 1
2151 def revert_external_embedding(document):
2152 ' Remove embed tag from external inset '
2153 revert_inset_embedding(document, 'External')
2156 def convert_subfig(document):
2157 " Convert subfigures to subfloats. "
2158 i = 0
2159 while 1:
2160 addedLines = 0
2161 i = find_token(document.body, '\\begin_inset Graphics', i)
2162 if i == -1:
2163 return
2164 endInset = find_end_of_inset(document.body, i)
2165 if endInset == -1:
2166 document.warning("Malformed lyx document: Missing '\\end_inset' in convert_subfig.")
2167 i += 1
2168 continue
2169 k = find_token(document.body, '\tsubcaption', i, endInset)
2170 if k == -1:
2171 i = endInset
2172 continue
2173 l = find_token(document.body, '\tsubcaptionText', i, endInset)
2174 if l == -1:
2175 caption = ""
2176 else:
2177 caption = document.body[l][16:].strip('"')
2178 del document.body[l]
2179 addedLines -= 1
2180 del document.body[k]
2181 addedLines -= 1
2182 subst = ['\\begin_inset Float figure', 'wide false', 'sideways false',
2183 'status open', '', '\\begin_layout Plain Layout', '\\begin_inset Caption',
2184 '', '\\begin_layout Plain Layout'] + latex2lyx(caption, False) + \
2185 [ '\\end_layout', '', '\\end_inset', '',
2186 '\\end_layout', '', '\\begin_layout Plain Layout']
2187 document.body[i : i] = subst
2188 addedLines += len(subst)
2189 endInset += addedLines
2190 subst = ['', '\\end_inset', '', '\\end_layout']
2191 document.body[endInset : endInset] = subst
2192 addedLines += len(subst)
2193 i += addedLines + 1
2196 def revert_subfig(document):
2197 " Revert subfloats. "
2198 i = 0
2199 while 1:
2200 # whitespace intended (exclude \\begin_inset FloatList)
2201 i = find_tokens(document.body, ['\\begin_inset Float ', '\\begin_inset Wrap'], i)
2202 if i == -1:
2203 return
2204 j = 0
2205 addedLines = 0
2206 while j != -1:
2207 j = find_end_of_inset(document.body, i)
2208 if j == -1:
2209 document.warning("Malformed lyx document: Missing '\\end_inset' (float) at line " + str(i + len(document.header)) + ".\n\t" + document.body[i])
2210 # document.warning(document.body[i-1] + "\n" + document.body[i+1])
2211 i += 1
2212 continue # this will get us back to the outer loop, since j == -1
2213 # look for embedded float (= subfloat)
2214 # whitespace intended (exclude \\begin_inset FloatList)
2215 k = find_token(document.body, '\\begin_inset Float ', i + 1, j)
2216 if k == -1:
2217 break
2218 # is the subfloat aligned?
2219 al = find_token(document.body, '\\align ', k - 1, j)
2220 alignment_beg = ""
2221 alignment_end = ""
2222 if al != -1:
2223 if get_value(document.body, '\\align', al) == "center":
2224 alignment_beg = "\\backslash\nbegin{centering}"
2225 alignment_end = "\\backslash\npar\\backslash\nend{centering}"
2226 elif get_value(document.body, '\\align', al) == "left":
2227 alignment_beg = "\\backslash\nbegin{raggedright}"
2228 alignment_end = "\\backslash\npar\\backslash\nend{raggedright}"
2229 elif get_value(document.body, '\\align', al) == "right":
2230 alignment_beg = "\\backslash\nbegin{raggedleft}"
2231 alignment_end = "\\backslash\npar\\backslash\nend{raggedleft}"
2232 l = find_end_of_inset(document.body, k)
2233 if l == -1:
2234 document.warning("Malformed lyx document: Missing '\\end_inset' (embedded float).")
2235 i += 1
2236 j = -1
2237 continue # escape to the outer loop
2238 m = find_default_layout(document, k + 1, l)
2239 # caption?
2240 cap = find_token(document.body, '\\begin_inset Caption', k + 1, l)
2241 caption = ''
2242 shortcap = ''
2243 capend = cap
2244 if cap != -1:
2245 capend = find_end_of_inset(document.body, cap)
2246 if capend == -1:
2247 document.warning("Malformed lyx document: Missing '\\end_inset' (caption).")
2248 return
2249 # label?
2250 label = ''
2251 lbl = find_token(document.body, '\\begin_inset CommandInset label', cap, capend)
2252 if lbl != -1:
2253 lblend = find_end_of_inset(document.body, lbl + 1)
2254 if lblend == -1:
2255 document.warning("Malformed lyx document: Missing '\\end_inset' (label).")
2256 return
2257 for line in document.body[lbl:lblend + 1]:
2258 if line.startswith('name '):
2259 label = line.split()[1].strip('"')
2260 break
2261 else:
2262 lbl = capend
2263 lblend = capend
2264 label = ''
2265 # opt arg?
2266 opt = find_token(document.body, '\\begin_inset OptArg', cap, capend)
2267 if opt != -1:
2268 optend = find_end_of_inset(document.body, opt)
2269 if optend == -1:
2270 document.warning("Malformed lyx document: Missing '\\end_inset' (OptArg).")
2271 return
2272 optc = find_default_layout(document, opt, optend)
2273 if optc == -1:
2274 document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
2275 return
2276 optcend = find_end_of(document.body, optc, "\\begin_layout", "\\end_layout")
2277 for line in document.body[optc:optcend]:
2278 if not line.startswith('\\'):
2279 shortcap += line.strip()
2280 else:
2281 opt = capend
2282 optend = capend
2283 for line in document.body[cap:capend]:
2284 if line in document.body[lbl:lblend]:
2285 continue
2286 elif line in document.body[opt:optend]:
2287 continue
2288 else:
2289 inert = True
2290 caption += lyxline2latex(document, line, inert)
2291 if len(label) > 0:
2292 caption += "\n\\backslash\nlabel{" + label + "}"
2293 subst = '\\begin_layout PlainLayout\n\\begin_inset ERT\nstatus collapsed\n\n' \
2294 '\\begin_layout PlainLayout\n\n}' + alignment_end + \
2295 '\n\\end_layout\n\n\\end_inset\n\n' \
2296 '\\end_layout\n\n\\begin_layout PlainLayout\n'
2297 subst = subst.split('\n')
2298 document.body[l : l+1] = subst
2299 addedLines = len(subst) - 1
2300 # this is before l and so is unchanged by the multiline insertion
2301 if cap != capend:
2302 del document.body[cap:capend+1]
2303 addedLines -= (capend + 1 - cap)
2304 del document.body[k+1:m-1]
2305 addedLines -= (m - 1 - (k + 1))
2306 insertion = '\\begin_inset ERT\nstatus collapsed\n\n' \
2307 '\\begin_layout PlainLayout\n\n' + alignment_beg + '\n\\backslash\n' \
2308 'subfloat'
2309 if len(shortcap) > 0:
2310 insertion = insertion + "[" + shortcap + "]"
2311 if len(caption) > 0:
2312 insertion = insertion + "[" + caption + "]"
2313 insertion = insertion + '{%\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n'
2314 insertion = insertion.split('\n')
2315 document.body[k : k + 1] = insertion
2316 addedLines += len(insertion) - 1
2317 al = find_token(document.body, '\\align ', k - 1, j + addedLines)
2318 if al != -1:
2319 del document.body[al]
2320 addedLines -= 1
2321 add_to_preamble(document, ['\\usepackage{subfig}\n'])
2322 i += addedLines + 1
2325 def revert_wrapplacement(document):
2326 " Revert placement options wrap floats (wrapfig). "
2327 i = 0
2328 while True:
2329 i = find_token(document.body, "\\begin_inset Wrap figure", i)
2330 if i == -1:
2331 return
2332 e = find_end_of_inset(document.body, i)
2333 j = find_token(document.body, "placement", i + 1, e)
2334 if j == -1:
2335 document.warning("Malformed LyX document: Couldn't find placement parameter of wrap float.")
2336 i += 1
2337 continue
2338 r = re.compile("placement (o|i|l|r|O|I|L|R)")
2339 m = r.match(document.body[j])
2340 if m == None:
2341 document.warning("Malformed LyX document: Placement option isn't O|I|R|L!")
2342 else:
2343 document.body[j] = "placement " + m.group(1).lower()
2344 i = j
2347 def remove_extra_embedded_files(document):
2348 " Remove \extra_embedded_files from buffer params "
2349 i = find_token(document.header, '\\extra_embedded_files', 0)
2350 if i == -1:
2351 return
2352 document.header.pop(i)
2355 def convert_spaceinset(document):
2356 " Convert '\\InsetSpace foo' to '\\begin_inset Space foo\n\\end_inset' "
2357 i = 0
2358 while i < len(document.body):
2359 m = re.match(r'(.*)\\InsetSpace (.*)', document.body[i])
2360 if m:
2361 before = m.group(1)
2362 after = m.group(2)
2363 subst = [before, "\\begin_inset Space " + after, "\\end_inset"]
2364 document.body[i: i+1] = subst
2365 i = i + len(subst)
2366 else:
2367 i = i + 1
2370 def revert_spaceinset(document):
2371 " Revert '\\begin_inset Space foo\n\\end_inset' to '\\InsetSpace foo' "
2372 i = 0
2373 while True:
2374 i = find_token(document.body, "\\begin_inset Space", i)
2375 if i == -1:
2376 return
2377 j = find_end_of_inset(document.body, i)
2378 if j == -1:
2379 document.warning("Malformed LyX document: Could not find end of space inset.")
2380 continue
2381 document.body[i] = document.body[i].replace('\\begin_inset Space', '\\InsetSpace')
2382 del document.body[j]
2385 def convert_hfill(document):
2386 " Convert hfill to space inset "
2387 i = 0
2388 while True:
2389 i = find_token(document.body, "\\hfill", i)
2390 if i == -1:
2391 return
2392 subst = document.body[i].replace('\\hfill', \
2393 '\n\\begin_inset Space \\hfill{}\n\\end_inset')
2394 subst = subst.split('\n')
2395 document.body[i : i+1] = subst
2396 i += len(subst)
2399 def revert_hfills(document):
2400 ' Revert \\hfill commands '
2401 hfill = re.compile(r'\\hfill')
2402 dotfill = re.compile(r'\\dotfill')
2403 hrulefill = re.compile(r'\\hrulefill')
2404 i = 0
2405 while True:
2406 i = find_token(document.body, "\\InsetSpace", i)
2407 if i == -1:
2408 return
2409 if hfill.search(document.body[i]):
2410 document.body[i] = \
2411 document.body[i].replace('\\InsetSpace \\hfill{}', '\\hfill')
2412 i += 1
2413 continue
2414 if dotfill.search(document.body[i]):
2415 subst = document.body[i].replace('\\InsetSpace \\dotfill{}', \
2416 '\\begin_inset ERT\nstatus collapsed\n\n' \
2417 '\\begin_layout Standard\n\n\n\\backslash\n' \
2418 'dotfill{}\n\\end_layout\n\n\\end_inset\n\n')
2419 subst = subst.split('\n')
2420 document.body[i : i+1] = subst
2421 i += len(subst)
2422 continue
2423 if hrulefill.search(document.body[i]):
2424 subst = document.body[i].replace('\\InsetSpace \\hrulefill{}', \
2425 '\\begin_inset ERT\nstatus collapsed\n\n' \
2426 '\\begin_layout Standard\n\n\n\\backslash\n' \
2427 'hrulefill{}\n\\end_layout\n\n\\end_inset\n\n')
2428 subst = subst.split('\n')
2429 document.body[i : i+1] = subst
2430 i += len(subst)
2431 continue
2432 i += 1
2434 def revert_hspace(document):
2435 ' Revert \\InsetSpace \\hspace{} to ERT '
2436 i = 0
2437 hspace = re.compile(r'\\hspace{}')
2438 hstar = re.compile(r'\\hspace\*{}')
2439 while True:
2440 i = find_token(document.body, "\\InsetSpace \\hspace", i)
2441 if i == -1:
2442 return
2443 length = get_value(document.body, '\\length', i+1)
2444 if length == '':
2445 document.warning("Malformed lyx document: Missing '\\length' in Space inset.")
2446 return
2447 del document.body[i+1]
2448 addedLines = -1
2449 if hstar.search(document.body[i]):
2450 subst = document.body[i].replace('\\InsetSpace \\hspace*{}', \
2451 '\\begin_inset ERT\nstatus collapsed\n\n' \
2452 '\\begin_layout Standard\n\n\n\\backslash\n' \
2453 'hspace*{' + length + '}\n\\end_layout\n\n\\end_inset\n\n')
2454 subst = subst.split('\n')
2455 document.body[i : i+1] = subst
2456 addedLines += len(subst) - 1
2457 i += addedLines + 1
2458 continue
2459 if hspace.search(document.body[i]):
2460 subst = document.body[i].replace('\\InsetSpace \\hspace{}', \
2461 '\\begin_inset ERT\nstatus collapsed\n\n' \
2462 '\\begin_layout Standard\n\n\n\\backslash\n' \
2463 'hspace{' + length + '}\n\\end_layout\n\n\\end_inset\n\n')
2464 subst = subst.split('\n')
2465 document.body[i : i+1] = subst
2466 addedLines += len(subst) - 1
2467 i += addedLines + 1
2468 continue
2469 i += 1
2472 def revert_protected_hfill(document):
2473 ' Revert \\begin_inset Space \\hspace*{\\fill} to ERT '
2474 i = 0
2475 while True:
2476 i = find_token(document.body, '\\begin_inset Space \\hspace*{\\fill}', i)
2477 if i == -1:
2478 return
2479 j = find_end_of_inset(document.body, i)
2480 if j == -1:
2481 document.warning("Malformed LyX document: Could not find end of space inset.")
2482 continue
2483 del document.body[j]
2484 subst = document.body[i].replace('\\begin_inset Space \\hspace*{\\fill}', \
2485 '\\begin_inset ERT\nstatus collapsed\n\n' \
2486 '\\begin_layout Standard\n\n\n\\backslash\n' \
2487 'hspace*{\n\\backslash\nfill}\n\\end_layout\n\n\\end_inset\n\n')
2488 subst = subst.split('\n')
2489 document.body[i : i+1] = subst
2490 i += len(subst)
2493 def revert_leftarrowfill(document):
2494 ' Revert \\begin_inset Space \\leftarrowfill{} to ERT '
2495 i = 0
2496 while True:
2497 i = find_token(document.body, '\\begin_inset Space \\leftarrowfill{}', i)
2498 if i == -1:
2499 return
2500 j = find_end_of_inset(document.body, i)
2501 if j == -1:
2502 document.warning("Malformed LyX document: Could not find end of space inset.")
2503 continue
2504 del document.body[j]
2505 subst = document.body[i].replace('\\begin_inset Space \\leftarrowfill{}', \
2506 '\\begin_inset ERT\nstatus collapsed\n\n' \
2507 '\\begin_layout Standard\n\n\n\\backslash\n' \
2508 'leftarrowfill{}\n\\end_layout\n\n\\end_inset\n\n')
2509 subst = subst.split('\n')
2510 document.body[i : i+1] = subst
2511 i += len(subst)
2514 def revert_rightarrowfill(document):
2515 ' Revert \\begin_inset Space \\rightarrowfill{} to ERT '
2516 i = 0
2517 while True:
2518 i = find_token(document.body, '\\begin_inset Space \\rightarrowfill{}', i)
2519 if i == -1:
2520 return
2521 j = find_end_of_inset(document.body, i)
2522 if j == -1:
2523 document.warning("Malformed LyX document: Could not find end of space inset.")
2524 continue
2525 del document.body[j]
2526 subst = document.body[i].replace('\\begin_inset Space \\rightarrowfill{}', \
2527 '\\begin_inset ERT\nstatus collapsed\n\n' \
2528 '\\begin_layout Standard\n\n\n\\backslash\n' \
2529 'rightarrowfill{}\n\\end_layout\n\n\\end_inset\n\n')
2530 subst = subst.split('\n')
2531 document.body[i : i+1] = subst
2532 i += len(subst)
2535 def revert_upbracefill(document):
2536 ' Revert \\begin_inset Space \\upbracefill{} to ERT '
2537 i = 0
2538 while True:
2539 i = find_token(document.body, '\\begin_inset Space \\upbracefill{}', i)
2540 if i == -1:
2541 return
2542 j = find_end_of_inset(document.body, i)
2543 if j == -1:
2544 document.warning("Malformed LyX document: Could not find end of space inset.")
2545 continue
2546 del document.body[j]
2547 subst = document.body[i].replace('\\begin_inset Space \\upbracefill{}', \
2548 '\\begin_inset ERT\nstatus collapsed\n\n' \
2549 '\\begin_layout Standard\n\n\n\\backslash\n' \
2550 'upbracefill{}\n\\end_layout\n\n\\end_inset\n\n')
2551 subst = subst.split('\n')
2552 document.body[i : i+1] = subst
2553 i += len(subst)
2556 def revert_downbracefill(document):
2557 ' Revert \\begin_inset Space \\downbracefill{} to ERT '
2558 i = 0
2559 while True:
2560 i = find_token(document.body, '\\begin_inset Space \\downbracefill{}', i)
2561 if i == -1:
2562 return
2563 j = find_end_of_inset(document.body, i)
2564 if j == -1:
2565 document.warning("Malformed LyX document: Could not find end of space inset.")
2566 continue
2567 del document.body[j]
2568 subst = document.body[i].replace('\\begin_inset Space \\downbracefill{}', \
2569 '\\begin_inset ERT\nstatus collapsed\n\n' \
2570 '\\begin_layout Standard\n\n\n\\backslash\n' \
2571 'downbracefill{}\n\\end_layout\n\n\\end_inset\n\n')
2572 subst = subst.split('\n')
2573 document.body[i : i+1] = subst
2574 i += len(subst)
2577 def revert_local_layout(document):
2578 ' Revert local layout headers.'
2579 i = 0
2580 while True:
2581 i = find_token(document.header, "\\begin_local_layout", i)
2582 if i == -1:
2583 return
2584 j = find_end_of(document.header, i, "\\begin_local_layout", "\\end_local_layout")
2585 if j == -1:
2586 # this should not happen
2587 break
2588 document.header[i : j + 1] = []
2591 def convert_pagebreaks(document):
2592 ' Convert inline Newpage insets to new format '
2593 i = 0
2594 while True:
2595 i = find_token(document.body, '\\newpage', i)
2596 if i == -1:
2597 break
2598 document.body[i:i+1] = ['\\begin_inset Newpage newpage',
2599 '\\end_inset']
2600 i = 0
2601 while True:
2602 i = find_token(document.body, '\\pagebreak', i)
2603 if i == -1:
2604 break
2605 document.body[i:i+1] = ['\\begin_inset Newpage pagebreak',
2606 '\\end_inset']
2607 i = 0
2608 while True:
2609 i = find_token(document.body, '\\clearpage', i)
2610 if i == -1:
2611 break
2612 document.body[i:i+1] = ['\\begin_inset Newpage clearpage',
2613 '\\end_inset']
2614 i = 0
2615 while True:
2616 i = find_token(document.body, '\\cleardoublepage', i)
2617 if i == -1:
2618 break
2619 document.body[i:i+1] = ['\\begin_inset Newpage cleardoublepage',
2620 '\\end_inset']
2623 def revert_pagebreaks(document):
2624 ' Revert \\begin_inset Newpage to previous inline format '
2625 i = 0
2626 while True:
2627 i = find_token(document.body, '\\begin_inset Newpage', i)
2628 if i == -1:
2629 return
2630 j = find_end_of_inset(document.body, i)
2631 if j == -1:
2632 document.warning("Malformed LyX document: Could not find end of Newpage inset.")
2633 continue
2634 del document.body[j]
2635 document.body[i] = document.body[i].replace('\\begin_inset Newpage newpage', '\\newpage')
2636 document.body[i] = document.body[i].replace('\\begin_inset Newpage pagebreak', '\\pagebreak')
2637 document.body[i] = document.body[i].replace('\\begin_inset Newpage clearpage', '\\clearpage')
2638 document.body[i] = document.body[i].replace('\\begin_inset Newpage cleardoublepage', '\\cleardoublepage')
2641 def convert_linebreaks(document):
2642 ' Convert inline Newline insets to new format '
2643 i = 0
2644 while True:
2645 i = find_token(document.body, '\\newline', i)
2646 if i == -1:
2647 break
2648 document.body[i:i+1] = ['\\begin_inset Newline newline',
2649 '\\end_inset']
2650 i = 0
2651 while True:
2652 i = find_token(document.body, '\\linebreak', i)
2653 if i == -1:
2654 break
2655 document.body[i:i+1] = ['\\begin_inset Newline linebreak',
2656 '\\end_inset']
2659 def revert_linebreaks(document):
2660 ' Revert \\begin_inset Newline to previous inline format '
2661 i = 0
2662 while True:
2663 i = find_token(document.body, '\\begin_inset Newline', i)
2664 if i == -1:
2665 return
2666 j = find_end_of_inset(document.body, i)
2667 if j == -1:
2668 document.warning("Malformed LyX document: Could not find end of Newline inset.")
2669 continue
2670 del document.body[j]
2671 document.body[i] = document.body[i].replace('\\begin_inset Newline newline', '\\newline')
2672 document.body[i] = document.body[i].replace('\\begin_inset Newline linebreak', '\\linebreak')
2675 def convert_japanese_plain(document):
2676 ' Set language japanese-plain to japanese '
2677 i = 0
2678 if document.language == "japanese-plain":
2679 document.language = "japanese"
2680 i = find_token(document.header, "\\language", 0)
2681 if i != -1:
2682 document.header[i] = "\\language japanese"
2683 j = 0
2684 while True:
2685 j = find_token(document.body, "\\lang japanese-plain", j)
2686 if j == -1:
2687 return
2688 document.body[j] = document.body[j].replace("\\lang japanese-plain", "\\lang japanese")
2689 j = j + 1
2692 def revert_pdfpages(document):
2693 ' Revert pdfpages external inset to ERT '
2694 i = 0
2695 while 1:
2696 i = find_token(document.body, "\\begin_inset External", i)
2697 if i == -1:
2698 return
2699 j = find_end_of_inset(document.body, i)
2700 if j == -1:
2701 document.warning("Malformed lyx document: Missing '\\end_inset' in revert_pdfpages.")
2702 i = i + 1
2703 continue
2704 if get_value(document.body, 'template', i, j) == "PDFPages":
2705 filename = get_value(document.body, 'filename', i, j)
2706 extra = ''
2707 r = re.compile(r'\textra PDFLaTeX \"(.*)\"$')
2708 for k in range(i, j):
2709 m = r.match(document.body[k])
2710 if m:
2711 extra = m.group(1)
2712 angle = get_value(document.body, 'rotateAngle', i, j)
2713 width = get_value(document.body, 'width', i, j)
2714 height = get_value(document.body, 'height', i, j)
2715 scale = get_value(document.body, 'scale', i, j)
2716 keepAspectRatio = find_token(document.body, "\tkeepAspectRatio", i, j)
2717 options = extra
2718 if angle != '':
2719 if options != '':
2720 options += ",angle=" + angle
2721 else:
2722 options += "angle=" + angle
2723 if width != '':
2724 if options != '':
2725 options += ",width=" + convert_len(width)
2726 else:
2727 options += "width=" + convert_len(width)
2728 if height != '':
2729 if options != '':
2730 options += ",height=" + convert_len(height)
2731 else:
2732 options += "height=" + convert_len(height)
2733 if scale != '':
2734 if options != '':
2735 options += ",scale=" + scale
2736 else:
2737 options += "scale=" + scale
2738 if keepAspectRatio != '':
2739 if options != '':
2740 options += ",keepaspectratio"
2741 else:
2742 options += "keepaspectratio"
2743 if options != '':
2744 options = '[' + options + ']'
2745 del document.body[i+1:j+1]
2746 document.body[i:i+1] = ['\\begin_inset ERT',
2747 'status collapsed',
2749 '\\begin_layout Standard',
2751 '\\backslash',
2752 'includepdf' + options + '{' + filename + '}',
2753 '\\end_layout',
2755 '\\end_inset']
2756 add_to_preamble(document, ['\\usepackage{pdfpages}\n'])
2757 i = i + 1
2758 continue
2759 i = i + 1
2762 def revert_mexican(document):
2763 ' Set language Spanish(Mexico) to Spanish '
2764 i = 0
2765 if document.language == "spanish-mexico":
2766 document.language = "spanish"
2767 i = find_token(document.header, "\\language", 0)
2768 if i != -1:
2769 document.header[i] = "\\language spanish"
2770 j = 0
2771 while True:
2772 j = find_token(document.body, "\\lang spanish-mexico", j)
2773 if j == -1:
2774 return
2775 document.body[j] = document.body[j].replace("\\lang spanish-mexico", "\\lang spanish")
2776 j = j + 1
2779 def remove_embedding(document):
2780 ' Remove embed tag from all insets '
2781 revert_inset_embedding(document, 'Graphics')
2782 revert_inset_embedding(document, 'External')
2783 revert_inset_embedding(document, 'CommandInset include')
2784 revert_inset_embedding(document, 'CommandInset bibtex')
2787 def revert_master(document):
2788 ' Remove master param '
2789 i = find_token(document.header, "\\master", 0)
2790 if i != -1:
2791 del document.header[i]
2794 def revert_graphics_group(document):
2795 ' Revert group information from graphics insets '
2796 i = 0
2797 while 1:
2798 i = find_token(document.body, "\\begin_inset Graphics", i)
2799 if i == -1:
2800 return
2801 j = find_end_of_inset(document.body, i)
2802 if j == -1:
2803 document.warning("Malformed lyx document: Missing '\\end_inset' in revert_graphics_group.")
2804 i = i + 1
2805 continue
2806 k = find_token(document.body, " groupId", i, j)
2807 if k == -1:
2808 i = i + 1
2809 continue
2810 del document.body[k]
2811 i = i + 1
2814 def update_apa_styles(document):
2815 ' Replace obsolete styles '
2817 if document.textclass != "apa":
2818 return
2820 obsoletedby = { "Acknowledgments": "Acknowledgements",
2821 "Section*": "Section",
2822 "Subsection*": "Subsection",
2823 "Subsubsection*": "Subsubsection",
2824 "Paragraph*": "Paragraph",
2825 "Subparagraph*": "Subparagraph"}
2826 i = 0
2827 while 1:
2828 i = find_token(document.body, "\\begin_layout", i)
2829 if i == -1:
2830 return
2832 layout = document.body[i][14:]
2833 if layout in obsoletedby:
2834 document.body[i] = "\\begin_layout " + obsoletedby[layout]
2836 i += 1
2839 def convert_paper_sizes(document):
2840 ' exchange size options legalpaper and executivepaper to correct order '
2841 # routine is needed to fix http://bugzilla.lyx.org/show_bug.cgi?id=4868
2842 i = 0
2843 j = 0
2844 i = find_token(document.header, "\\papersize executivepaper", 0)
2845 if i != -1:
2846 document.header[i] = "\\papersize legalpaper"
2847 return
2848 j = find_token(document.header, "\\papersize legalpaper", 0)
2849 if j != -1:
2850 document.header[j] = "\\papersize executivepaper"
2853 def revert_paper_sizes(document):
2854 ' exchange size options legalpaper and executivepaper to correct order '
2855 i = 0
2856 j = 0
2857 i = find_token(document.header, "\\papersize executivepaper", 0)
2858 if i != -1:
2859 document.header[i] = "\\papersize legalpaper"
2860 return
2861 j = find_token(document.header, "\\papersize legalpaper", 0)
2862 if j != -1:
2863 document.header[j] = "\\papersize executivepaper"
2866 def convert_InsetSpace(document):
2867 " Convert '\\begin_inset Space foo' to '\\begin_inset space foo'"
2868 i = 0
2869 while True:
2870 i = find_token(document.body, "\\begin_inset Space", i)
2871 if i == -1:
2872 return
2873 document.body[i] = document.body[i].replace('\\begin_inset Space', '\\begin_inset space')
2876 def revert_InsetSpace(document):
2877 " Revert '\\begin_inset space foo' to '\\begin_inset Space foo'"
2878 i = 0
2879 while True:
2880 i = find_token(document.body, "\\begin_inset space", i)
2881 if i == -1:
2882 return
2883 document.body[i] = document.body[i].replace('\\begin_inset space', '\\begin_inset Space')
2886 def convert_display_enum(document):
2887 " Convert 'display foo' to 'display false/true'"
2888 i = 0
2889 while True:
2890 i = find_token(document.body, "\tdisplay", i)
2891 if i == -1:
2892 return
2893 val = get_value(document.body, 'display', i)
2894 if val == "none":
2895 document.body[i] = document.body[i].replace('none', 'false')
2896 if val == "default":
2897 document.body[i] = document.body[i].replace('default', 'true')
2898 if val == "monochrome":
2899 document.body[i] = document.body[i].replace('monochrome', 'true')
2900 if val == "grayscale":
2901 document.body[i] = document.body[i].replace('grayscale', 'true')
2902 if val == "color":
2903 document.body[i] = document.body[i].replace('color', 'true')
2904 if val == "preview":
2905 document.body[i] = document.body[i].replace('preview', 'true')
2906 i += 1
2909 def revert_display_enum(document):
2910 " Revert 'display false/true' to 'display none/color'"
2911 i = 0
2912 while True:
2913 i = find_token(document.body, "\tdisplay", i)
2914 if i == -1:
2915 return
2916 val = get_value(document.body, 'display', i)
2917 if val == "false":
2918 document.body[i] = document.body[i].replace('false', 'none')
2919 if val == "true":
2920 document.body[i] = document.body[i].replace('true', 'default')
2921 i += 1
2924 def remove_fontsCJK(document):
2925 ' Remove font_cjk param '
2926 i = find_token(document.header, "\\font_cjk", 0)
2927 if i != -1:
2928 del document.header[i]
2931 def convert_plain_layout(document):
2932 " Convert 'PlainLayout' to 'Plain Layout'"
2933 i = 0
2934 while True:
2935 i = find_token(document.body, '\\begin_layout PlainLayout', i)
2936 if i == -1:
2937 return
2938 document.body[i] = document.body[i].replace('\\begin_layout PlainLayout', \
2939 '\\begin_layout Plain Layout')
2940 i += 1
2943 def revert_plain_layout(document):
2944 " Revert 'Plain Layout' to 'PlainLayout'"
2945 i = 0
2946 while True:
2947 i = find_token(document.body, '\\begin_layout Plain Layout', i)
2948 if i == -1:
2949 return
2950 document.body[i] = document.body[i].replace('\\begin_layout Plain Layout', \
2951 '\\begin_layout PlainLayout')
2952 i += 1
2955 def revert_plainlayout(document):
2956 " Revert 'PlainLayout' to 'Standard'"
2957 i = 0
2958 while True:
2959 i = find_token(document.body, '\\begin_layout PlainLayout', i)
2960 if i == -1:
2961 return
2962 # This will be incorrect for some document classes, since Standard is not always
2963 # the default. But (a) it is probably the best we can do and (b) it will actually
2964 # work, in fact, since an unknown layout will be converted to default.
2965 document.body[i] = document.body[i].replace('\\begin_layout PlainLayout', \
2966 '\\begin_layout Standard')
2967 i += 1
2970 def revert_polytonicgreek(document):
2971 "Set language polytonic Greek to Greek"
2972 i = 0
2973 if document.language == "polutonikogreek":
2974 document.language = "greek"
2975 i = find_token(document.header, "\\language", 0)
2976 if i != -1:
2977 document.header[i] = "\\language greek"
2978 j = 0
2979 while True:
2980 j = find_token(document.body, "\\lang polutonikogreek", j)
2981 if j == -1:
2982 return
2983 document.body[j] = document.body[j].replace("\\lang polutonikogreek", "\\lang greek")
2984 j = j + 1
2987 def revert_removed_modules(document):
2988 i = 0
2989 while True:
2990 i = find_token(document.header, "\\begin_remove_modules", i)
2991 if i == -1:
2992 return
2993 j = find_end_of(document.header, i, "\\begin_remove_modules", "\\end_remove_modules")
2994 if j == -1:
2995 # this should not happen
2996 break
2997 document.header[i : j + 1] = []
3000 def add_plain_layout(document):
3001 i = 0
3002 while True:
3003 i = find_token(document.body, "\\begin_layout", i)
3004 if i == -1:
3005 return
3006 if len(document.body[i].split()) == 1:
3007 document.body[i] = "\\begin_layout Plain Layout"
3008 i += 1
3011 def revert_tabulators(document):
3012 "Revert tabulators to 4 spaces"
3013 i = 0
3014 while True:
3015 i = find_token(document.body, "\t", i)
3016 if i == -1:
3017 return
3018 document.body[i] = document.body[i].replace("\t", " ")
3019 i += 1
3022 def revert_tabsize(document):
3023 "Revert the tabsize parameter of listings"
3024 i = 0
3025 j = 0
3026 while True:
3027 # either it is the only parameter
3028 i = find_token(document.body, 'lstparams "tabsize=4"', i)
3029 if i != -1:
3030 del document.body[i]
3031 # or the last one
3032 j = find_token(document.body, "lstparams", j)
3033 if j == -1:
3034 return
3035 pos = document.body[j].find(",tabsize=")
3036 document.body[j] = document.body[j][:pos] + '"'
3037 i += 1
3038 j += 1
3041 def revert_mongolian(document):
3042 "Set language Mongolian to English"
3043 i = 0
3044 if document.language == "mongolian":
3045 document.language = "english"
3046 i = find_token(document.header, "\\language", 0)
3047 if i != -1:
3048 document.header[i] = "\\language english"
3049 j = 0
3050 while True:
3051 j = find_token(document.body, "\\lang mongolian", j)
3052 if j == -1:
3053 return
3054 document.body[j] = document.body[j].replace("\\lang mongolian", "\\lang english")
3055 j = j + 1
3058 def revert_default_options(document):
3059 ' Remove param use_default_options '
3060 i = find_token(document.header, "\\use_default_options", 0)
3061 if i != -1:
3062 del document.header[i]
3065 def convert_default_options(document):
3066 ' Add param use_default_options and set it to false '
3067 i = find_token(document.header, "\\textclass", 0)
3068 if i == -1:
3069 document.warning("Malformed LyX document: Missing `\\textclass'.")
3070 return
3071 document.header.insert(i, '\\use_default_options false')
3074 def revert_backref_options(document):
3075 ' Revert option pdf_backref=page to pagebackref '
3076 i = find_token(document.header, "\\pdf_backref page", 0)
3077 if i != -1:
3078 document.header[i] = "\\pdf_pagebackref true"
3081 def convert_backref_options(document):
3082 ' We have changed the option pagebackref to backref=true '
3083 i = find_token(document.header, "\\pdf_pagebackref true", 0)
3084 if i != -1:
3085 document.header[i] = "\\pdf_backref page"
3086 j = find_token(document.header, "\\pdf_pagebackref false", 0)
3087 if j != -1:
3088 del document.header[j]
3089 # backref=true was not a valid option, we meant backref=section
3090 k = find_token(document.header, "\\pdf_backref true", 0)
3091 if k != -1 and i != -1:
3092 del document.header[k]
3093 elif k != -1 and j != -1:
3094 document.header[k] = "\\pdf_backref section"
3097 def convert_charstyle_element(document):
3098 "Convert CharStyle to Element for docbook backend"
3099 if document.backend != "docbook":
3100 return
3101 i = 0
3102 while True:
3103 i = find_token(document.body, "\\begin_inset Flex CharStyle:", i)
3104 if i == -1:
3105 return
3106 document.body[i] = document.body[i].replace('\\begin_inset Flex CharStyle:',
3107 '\\begin_inset Flex Element:')
3109 def revert_charstyle_element(document):
3110 "Convert Element to CharStyle for docbook backend"
3111 if document.backend != "docbook":
3112 return
3113 i = 0
3114 while True:
3115 i = find_token(document.body, "\\begin_inset Flex Element:", i)
3116 if i == -1:
3117 return
3118 document.body[i] = document.body[i].replace('\\begin_inset Flex Element:',
3119 '\\begin_inset Flex CharStyle:')
3122 # Conversion hub
3125 supported_versions = ["1.6.0","1.6"]
3126 convert = [[277, [fix_wrong_tables]],
3127 [278, [close_begin_deeper]],
3128 [279, [long_charstyle_names]],
3129 [280, [axe_show_label]],
3130 [281, []],
3131 [282, []],
3132 [283, [convert_flex]],
3133 [284, []],
3134 [285, []],
3135 [286, []],
3136 [287, [convert_wrapfig_options]],
3137 [288, [convert_inset_command]],
3138 [289, [convert_latexcommand_index]],
3139 [290, []],
3140 [291, []],
3141 [292, [convert_japanese_cjk]],
3142 [293, []],
3143 [294, [convert_pdf_options]],
3144 [295, [convert_htmlurl, convert_url]],
3145 [296, [convert_include]],
3146 [297, [convert_usorbian]],
3147 [298, [convert_macro_global]],
3148 [299, []],
3149 [300, []],
3150 [301, []],
3151 [302, []],
3152 [303, [convert_serbocroatian]],
3153 [304, [convert_framed_notes]],
3154 [305, []],
3155 [306, []],
3156 [307, []],
3157 [308, []],
3158 [309, []],
3159 [310, []],
3160 [311, [convert_ams_classes]],
3161 [312, []],
3162 [313, [convert_module_names]],
3163 [314, []],
3164 [315, []],
3165 [316, [convert_subfig]],
3166 [317, []],
3167 [318, []],
3168 [319, [convert_spaceinset, convert_hfill]],
3169 [320, []],
3170 [321, [convert_tablines]],
3171 [322, [convert_plain_layout]],
3172 [323, [convert_pagebreaks]],
3173 [324, [convert_linebreaks]],
3174 [325, [convert_japanese_plain]],
3175 [326, []],
3176 [327, []],
3177 [328, [remove_embedding, remove_extra_embedded_files, remove_inzip_options]],
3178 [329, []],
3179 [330, []],
3180 [331, [convert_ltcaption]],
3181 [332, []],
3182 [333, [update_apa_styles]],
3183 [334, [convert_paper_sizes]],
3184 [335, [convert_InsetSpace]],
3185 [336, []],
3186 [337, [convert_display_enum]],
3187 [338, []],
3188 [339, []],
3189 [340, [add_plain_layout]],
3190 [341, []],
3191 [342, []],
3192 [343, [convert_default_options]],
3193 [344, [convert_backref_options]],
3194 [345, [convert_charstyle_element]]
3197 revert = [[344, [revert_charstyle_element]],
3198 [343, [revert_backref_options]],
3199 [342, [revert_default_options]],
3200 [341, [revert_mongolian]],
3201 [340, [revert_tabulators, revert_tabsize]],
3202 [339, []],
3203 [338, [revert_removed_modules]],
3204 [337, [revert_polytonicgreek]],
3205 [336, [revert_display_enum]],
3206 [335, [remove_fontsCJK]],
3207 [334, [revert_InsetSpace]],
3208 [333, [revert_paper_sizes]],
3209 [332, []],
3210 [331, [revert_graphics_group]],
3211 [330, [revert_ltcaption]],
3212 [329, [revert_leftarrowfill, revert_rightarrowfill, revert_upbracefill, revert_downbracefill]],
3213 [328, [revert_master]],
3214 [327, []],
3215 [326, [revert_mexican]],
3216 [325, [revert_pdfpages]],
3217 [324, []],
3218 [323, [revert_linebreaks]],
3219 [322, [revert_pagebreaks]],
3220 [321, [revert_local_layout, revert_plain_layout]],
3221 [320, [revert_tablines]],
3222 [319, [revert_protected_hfill]],
3223 [318, [revert_spaceinset, revert_hfills, revert_hspace]],
3224 [317, [remove_extra_embedded_files]],
3225 [316, [revert_wrapplacement]],
3226 [315, [revert_subfig]],
3227 [314, [revert_colsep, revert_plainlayout]],
3228 [313, []],
3229 [312, [revert_module_names]],
3230 [311, [revert_rotfloat, revert_widesideways]],
3231 [310, [revert_external_embedding]],
3232 [309, [revert_btprintall]],
3233 [308, [revert_nocite]],
3234 [307, [revert_serbianlatin]],
3235 [306, [revert_slash, revert_nobreakdash]],
3236 [305, [revert_interlingua]],
3237 [304, [revert_bahasam]],
3238 [303, [revert_framed_notes]],
3239 [302, []],
3240 [301, [revert_latin, revert_samin]],
3241 [300, [revert_linebreak]],
3242 [299, [revert_pagebreak]],
3243 [298, [revert_hyperlinktype]],
3244 [297, [revert_macro_optional_params]],
3245 [296, [revert_albanian, revert_lowersorbian, revert_uppersorbian]],
3246 [295, [revert_include]],
3247 [294, [revert_href, revert_url]],
3248 [293, [revert_pdf_options_2]],
3249 [292, [revert_inset_info]],
3250 [291, [revert_japanese, revert_japanese_encoding, revert_japanese_cjk]],
3251 [290, [revert_vietnamese]],
3252 [289, [revert_wraptable]],
3253 [288, [revert_latexcommand_index]],
3254 [287, [revert_inset_command]],
3255 [286, [revert_wrapfig_options]],
3256 [285, [revert_pdf_options]],
3257 [284, [remove_inzip_options]],
3258 [283, []],
3259 [282, [revert_flex]],
3260 [281, []],
3261 [280, [revert_begin_modules]],
3262 [279, [revert_show_label]],
3263 [278, [revert_long_charstyle_names]],
3264 [277, []],
3265 [276, []]
3269 if __name__ == "__main__":
3270 pass