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"""
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 def wrap_into_ert(string, src, dst):
35 " Wrap a something into an ERT"
36 return string.replace(src, '\n\\begin_inset ERT\nstatus collapsed\n\\begin_layout Standard\n'
37 + dst + '\n\\end_layout\n\\end_inset\n')
39 def add_to_preamble(document, text):
40 """ Add text to the preamble if it is not already there.
41 Only the first line is checked!"""
43 if find_token(document.preamble, text[0], 0) != -1:
46 document.preamble.extend(text)
48 # Convert a LyX length into a LaTeX length
50 units = {"text%":"\\backslash\ntextwidth", "col%":"\\backslash\ncolumnwidth",
51 "page%":"\\backslash\npagewidth", "line%":"\\backslash\nlinewidth",
52 "theight%":"\\backslash\ntextheight", "pheight%":"\\backslash\npageheight"}
54 # Convert LyX units to LaTeX units
55 for unit in units.keys():
56 if len.find(unit) != -1:
57 len = '%f' % (len2value(len) / 100)
58 len = len.strip('0') + units[unit]
63 # Return the value of len without the unit in numerical form.
65 result = re.search('([+-]?[0-9.]+)', len)
67 return float(result.group(1))
71 # Unfortunately, this doesn't really work, since Standard isn't always default.
72 # But it's as good as we can do right now.
73 def find_default_layout(document, start, end):
74 l = find_token(document.body, "\\begin_layout Standard", start, end)
76 l = find_token(document.body, "\\begin_layout PlainLayout", start, end)
78 l = find_token(document.body, "\\begin_layout Plain Layout", start, end)
81 def get_option(document, m, option, default):
82 l = document.body[m].find(option)
85 val = document.body[m][l:].split('"')[1]
88 def remove_option(document, m, option):
89 l = document.body[m].find(option)
91 val = document.body[m][l:].split('"')[1]
92 document.body[m] = document.body[m][:l-1] + document.body[m][l+len(option + '="' + val + '"'):]
95 def set_option(document, m, option, value):
96 l = document.body[m].find(option)
98 oldval = document.body[m][l:].split('"')[1]
99 l = l + len(option + '="')
100 document.body[m] = document.body[m][:l] + value + document.body[m][l+len(oldval):]
102 document.body[m] = document.body[m][:-1] + ' ' + option + '="' + value + '">'
106 ####################################################################
108 def convert_ltcaption(document):
111 i = find_token(document.body, "\\begin_inset Tabular", i)
114 j = find_end_of_inset(document.body, i + 1)
116 document.warning("Malformed LyX document: Could not find end of tabular.")
119 nrows = int(document.body[i+1].split('"')[3])
120 ncols = int(document.body[i+1].split('"')[5])
123 for k in range(nrows):
124 m = find_token(document.body, "<row", m)
127 for k in range(ncols):
128 m = find_token(document.body, "<cell", m)
130 mend = find_token(document.body, "</cell>", m + 1)
131 # first look for caption insets
132 mcap = find_token(document.body, "\\begin_inset Caption", m + 1, mend)
133 # then look for ERT captions
135 mcap = find_token(document.body, "caption", m + 1, mend)
137 mcap = find_token(document.body, "\\backslash", mcap - 1, mcap)
140 if caption == 'true':
142 set_option(document, r, 'caption', 'true')
143 set_option(document, m, 'multicolumn', '1')
144 set_option(document, m, 'bottomline', 'false')
145 set_option(document, m, 'topline', 'false')
146 set_option(document, m, 'rightline', 'false')
147 set_option(document, m, 'leftline', 'false')
148 #j = find_end_of_inset(document.body, j + 1)
150 set_option(document, m, 'multicolumn', '2')
156 def revert_ltcaption(document):
159 i = find_token(document.body, "\\begin_inset Tabular", i)
162 j = find_end_of_inset(document.body, i + 1)
164 document.warning("Malformed LyX document: Could not find end of tabular.")
168 nrows = int(document.body[i+1].split('"')[3])
169 ncols = int(document.body[i+1].split('"')[5])
171 for k in range(nrows):
172 m = find_token(document.body, "<row", m)
173 caption = get_option(document, m, 'caption', 'false')
174 if caption == 'true':
175 remove_option(document, m, 'caption')
176 for k in range(ncols):
177 m = find_token(document.body, "<cell", m)
178 remove_option(document, m, 'multicolumn')
180 m = find_token(document.body, "\\begin_inset Caption", m)
183 m = find_end_of_inset(document.body, m + 1)
184 document.body[m] += wrap_into_ert("","","\\backslash\n\\backslash\n%")
190 def convert_tablines(document):
193 i = find_token(document.body, "\\begin_inset Tabular", i)
195 # LyX 1.3 inserted an extra space between \begin_inset
196 # and Tabular so let us try if this is the case and fix it.
197 i = find_token(document.body, "\\begin_inset Tabular", i)
201 document.body[i] = "\\begin_inset Tabular"
202 j = find_end_of_inset(document.body, i + 1)
204 document.warning("Malformed LyX document: Could not find end of tabular.")
208 nrows = int(document.body[i+1].split('"')[3])
209 ncols = int(document.body[i+1].split('"')[5])
212 for k in range(ncols):
213 m = find_token(document.body, "<column", m)
214 left = get_option(document, m, 'leftline', 'false')
215 right = get_option(document, m, 'rightline', 'false')
216 col_info.append([left, right])
217 remove_option(document, m, 'leftline')
218 remove_option(document, m, 'rightline')
222 for k in range(nrows):
223 m = find_token(document.body, "<row", m)
224 top = get_option(document, m, 'topline', 'false')
225 bottom = get_option(document, m, 'bottomline', 'false')
226 row_info.append([top, bottom])
227 remove_option(document, m, 'topline')
228 remove_option(document, m, 'bottomline')
233 for k in range(nrows*ncols):
234 m = find_token(document.body, "<cell", m)
235 mc_info.append(get_option(document, m, 'multicolumn', '0'))
238 for l in range(nrows):
239 for k in range(ncols):
240 m = find_token(document.body, '<cell', m)
241 if mc_info[l*ncols + k] == '0':
242 r = set_option(document, m, 'topline', row_info[l][0])
243 r = set_option(document, m, 'bottomline', row_info[l][1])
244 r = set_option(document, m, 'leftline', col_info[k][0])
245 r = set_option(document, m, 'rightline', col_info[k][1])
246 elif mc_info[l*ncols + k] == '1':
248 while s < ncols and mc_info[l*ncols + s] == '2':
250 if s < ncols and mc_info[l*ncols + s] != '1':
251 r = set_option(document, m, 'rightline', col_info[k][1])
252 if k > 0 and mc_info[l*ncols + k - 1] == '0':
253 r = set_option(document, m, 'leftline', col_info[k][0])
258 def revert_tablines(document):
261 i = find_token(document.body, "\\begin_inset Tabular", i)
264 j = find_end_of_inset(document.body, i + 1)
266 document.warning("Malformed LyX document: Could not find end of tabular.")
270 nrows = int(document.body[i+1].split('"')[3])
271 ncols = int(document.body[i+1].split('"')[5])
274 for k in range(nrows*ncols):
275 m = find_token(document.body, "<cell", m)
276 top = get_option(document, m, 'topline', 'false')
277 bottom = get_option(document, m, 'bottomline', 'false')
278 left = get_option(document, m, 'leftline', 'false')
279 right = get_option(document, m, 'rightline', 'false')
280 lines.append([top, bottom, left, right])
283 # we will want to ignore longtable captions
286 for k in range(nrows):
287 m = find_token(document.body, "<row", m)
288 caption = get_option(document, m, 'caption', 'false')
289 caption_info.append([caption])
294 for k in range(ncols):
295 m = find_token(document.body, "<column", m)
297 for l in range(nrows):
298 left = lines[l*ncols + k][2]
299 if left == 'false' and caption_info[l] == 'false':
301 set_option(document, m, 'leftline', left)
303 for l in range(nrows):
304 right = lines[l*ncols + k][3]
305 if right == 'false' and caption_info[l] == 'false':
307 set_option(document, m, 'rightline', right)
311 for k in range(nrows):
312 m = find_token(document.body, "<row", m)
314 for l in range(ncols):
315 top = lines[k*ncols + l][0]
318 if caption_info[k] == 'false':
320 set_option(document, m, 'topline', top)
322 for l in range(ncols):
323 bottom = lines[k*ncols + l][1]
324 if bottom == 'false':
326 if caption_info[k] == 'false':
328 set_option(document, m, 'bottomline', bottom)
334 def fix_wrong_tables(document):
337 i = find_token(document.body, "\\begin_inset Tabular", i)
340 j = find_end_of_inset(document.body, i + 1)
342 document.warning("Malformed LyX document: Could not find end of tabular.")
346 nrows = int(document.body[i+1].split('"')[3])
347 ncols = int(document.body[i+1].split('"')[5])
349 for l in range(nrows):
351 for k in range(ncols):
352 m = find_token(document.body, '<cell', m)
354 if document.body[m].find('multicolumn') != -1:
355 multicol_cont = int(document.body[m].split('"')[1])
357 if multicol_cont == 2 and (k == 0 or prev_multicolumn == 0):
358 document.body[m] = document.body[m][:5] + document.body[m][21:]
361 prev_multicolumn = multicol_cont
368 def close_begin_deeper(document):
372 i = find_tokens(document.body, ["\\begin_deeper", "\\end_deeper"], i)
377 if document.body[i][:13] == "\\begin_deeper":
384 document.body[-2:-2] = ['\\end_deeper' for i in range(depth)]
387 def long_charstyle_names(document):
390 i = find_token(document.body, "\\begin_inset CharStyle", i)
393 document.body[i] = document.body[i].replace("CharStyle ", "CharStyle CharStyle:")
396 def revert_long_charstyle_names(document):
399 i = find_token(document.body, "\\begin_inset CharStyle", i)
402 document.body[i] = document.body[i].replace("CharStyle CharStyle:", "CharStyle")
406 def axe_show_label(document):
409 i = find_token(document.body, "\\begin_inset CharStyle", i)
412 if document.body[i + 1].find("show_label") != -1:
413 if document.body[i + 1].find("true") != -1:
414 document.body[i + 1] = "status open"
415 del document.body[ i + 2]
417 if document.body[i + 1].find("false") != -1:
418 document.body[i + 1] = "status collapsed"
419 del document.body[ i + 2]
421 document.warning("Malformed LyX document: show_label neither false nor true.")
423 document.warning("Malformed LyX document: show_label missing in CharStyle.")
428 def revert_show_label(document):
431 i = find_token(document.body, "\\begin_inset CharStyle", i)
434 if document.body[i + 1].find("status open") != -1:
435 document.body.insert(i + 1, "show_label true")
437 if document.body[i + 1].find("status collapsed") != -1:
438 document.body.insert(i + 1, "show_label false")
440 document.warning("Malformed LyX document: no legal status line in CharStyle.")
443 def revert_begin_modules(document):
446 i = find_token(document.header, "\\begin_modules", i)
449 j = find_end_of(document.header, i, "\\begin_modules", "\\end_modules")
451 # this should not happen
453 document.header[i : j + 1] = []
455 def convert_flex(document):
456 "Convert CharStyle to Flex"
459 i = find_token(document.body, "\\begin_inset CharStyle", i)
462 document.body[i] = document.body[i].replace('\\begin_inset CharStyle', '\\begin_inset Flex')
464 def revert_flex(document):
465 "Convert Flex to CharStyle"
468 i = find_token(document.body, "\\begin_inset Flex", i)
471 document.body[i] = document.body[i].replace('\\begin_inset Flex', '\\begin_inset CharStyle')
474 # Discard PDF options for hyperref
475 def revert_pdf_options(document):
476 "Revert PDF options for hyperref."
477 # store the PDF options and delete the entries from the Lyx file
485 bookmarksnumbered = ""
487 bookmarksopenlevel = ""
495 i = find_token(document.header, "\\use_hyperref", i)
497 hyperref = get_value(document.header, "\\use_hyperref", i) == 'true'
498 del document.header[i]
499 i = find_token(document.header, "\\pdf_store_options", i)
501 del document.header[i]
502 i = find_token(document.header, "\\pdf_title", 0)
504 title = get_value_string(document.header, '\\pdf_title', 0, 0, True)
505 title = ' pdftitle={' + title + '}'
506 del document.header[i]
507 i = find_token(document.header, "\\pdf_author", 0)
509 author = get_value_string(document.header, '\\pdf_author', 0, 0, True)
511 author = ' pdfauthor={' + author + '}'
513 author = ',\n pdfauthor={' + author + '}'
514 del document.header[i]
515 i = find_token(document.header, "\\pdf_subject", 0)
517 subject = get_value_string(document.header, '\\pdf_subject', 0, 0, True)
518 if title == "" and author == "":
519 subject = ' pdfsubject={' + subject + '}'
521 subject = ',\n pdfsubject={' + subject + '}'
522 del document.header[i]
523 i = find_token(document.header, "\\pdf_keywords", 0)
525 keywords = get_value_string(document.header, '\\pdf_keywords', 0, 0, True)
526 if title == "" and author == "" and subject == "":
527 keywords = ' pdfkeywords={' + keywords + '}'
529 keywords = ',\n pdfkeywords={' + keywords + '}'
530 del document.header[i]
531 i = find_token(document.header, "\\pdf_bookmarks", 0)
533 bookmarks = get_value_string(document.header, '\\pdf_bookmarks', 0)
534 bookmarks = ',\n bookmarks=' + bookmarks
535 del document.header[i]
536 i = find_token(document.header, "\\pdf_bookmarksnumbered", i)
538 bookmarksnumbered = get_value_string(document.header, '\\pdf_bookmarksnumbered', 0)
539 bookmarksnumbered = ',\n bookmarksnumbered=' + bookmarksnumbered
540 del document.header[i]
541 i = find_token(document.header, "\\pdf_bookmarksopen", i)
543 bookmarksopen = get_value_string(document.header, '\\pdf_bookmarksopen', 0)
544 bookmarksopen = ',\n bookmarksopen=' + bookmarksopen
545 del document.header[i]
546 i = find_token(document.header, "\\pdf_bookmarksopenlevel", i)
548 bookmarksopenlevel = get_value_string(document.header, '\\pdf_bookmarksopenlevel', 0, 0, True)
549 bookmarksopenlevel = ',\n bookmarksopenlevel=' + bookmarksopenlevel
550 del document.header[i]
551 i = find_token(document.header, "\\pdf_breaklinks", i)
553 breaklinks = get_value_string(document.header, '\\pdf_breaklinks', 0)
554 breaklinks = ',\n breaklinks=' + breaklinks
555 del document.header[i]
556 i = find_token(document.header, "\\pdf_pdfborder", i)
558 pdfborder = get_value_string(document.header, '\\pdf_pdfborder', 0)
559 if pdfborder == 'true':
560 pdfborder = ',\n pdfborder={0 0 0}'
562 pdfborder = ',\n pdfborder={0 0 1}'
563 del document.header[i]
564 i = find_token(document.header, "\\pdf_colorlinks", i)
566 colorlinks = get_value_string(document.header, '\\pdf_colorlinks', 0)
567 colorlinks = ',\n colorlinks=' + colorlinks
568 del document.header[i]
569 i = find_token(document.header, "\\pdf_backref", i)
571 backref = get_value_string(document.header, '\\pdf_backref', 0)
572 backref = ',\n backref=' + backref
573 del document.header[i]
574 i = find_token(document.header, "\\pdf_pagebackref", i)
576 pagebackref = get_value_string(document.header, '\\pdf_pagebackref', 0)
577 pagebackref = ',\n pagebackref=' + pagebackref
578 del document.header[i]
579 i = find_token(document.header, "\\pdf_pagemode", 0)
581 pagemode = get_value_string(document.header, '\\pdf_pagemode', 0)
582 pagemode = ',\n pdfpagemode=' + pagemode
583 del document.header[i]
584 i = find_token(document.header, "\\pdf_quoted_options", 0)
586 otheroptions = get_value_string(document.header, '\\pdf_quoted_options', 0, 0, True)
587 if title == "" and author == "" and subject == "" and keywords == "":
588 otheroptions = ' ' + otheroptions
590 otheroptions = ',\n ' + otheroptions
591 del document.header[i]
593 # write to the preamble when hyperref was used
595 # preamble write preparations
596 # bookmark numbers are only output when they are turned on
597 if bookmarksopen == ',\n bookmarksopen=true':
598 bookmarksopen = bookmarksopen + bookmarksopenlevel
599 if bookmarks == ',\n bookmarks=true':
600 bookmarks = bookmarks + bookmarksnumbered + bookmarksopen
602 bookmarks = bookmarks
603 # hypersetup is only output when there are things to be set up
604 setupstart = '\\hypersetup{%\n'
606 if otheroptions == "" and title == "" and author == ""\
607 and subject == "" and keywords == "":
611 add_to_preamble(document,
612 ['% Commands inserted by lyx2lyx for PDF properties',
613 '\\usepackage[unicode=true'
632 def remove_inzip_options(document):
633 "Remove inzipName and embed options from the Graphics inset"
636 i = find_token(document.body, "\\begin_inset Graphics", i)
639 j = find_end_of_inset(document.body, i + 1)
642 document.warning("Malformed LyX document: Could not find end of graphics inset.")
643 # If there's a inzip param, just remove that
644 k = find_token(document.body, "\tinzipName", i + 1, j)
647 # embed option must follow the inzipName option
648 del document.body[k+1]
652 def convert_inset_command(document):
655 \begin_inset LatexCommand cmd
657 \begin_inset CommandInset InsetType
662 i = find_token(document.body, "\\begin_inset LatexCommand", i)
665 line = document.body[i]
666 r = re.compile(r'\\begin_inset LatexCommand (.*)$')
670 #this is adapted from factory.cpp
671 if cmdName[0:4].lower() == "cite":
672 insetName = "citation"
673 elif cmdName == "url" or cmdName == "htmlurl":
675 elif cmdName[-3:] == "ref":
677 elif cmdName == "tableofcontents":
679 elif cmdName == "printnomenclature":
680 insetName = "nomencl_print"
681 elif cmdName == "printindex":
682 insetName = "index_print"
685 insertion = ["\\begin_inset CommandInset " + insetName, "LatexCommand " + cmdName]
686 document.body[i : i+1] = insertion
689 def revert_inset_command(document):
692 \begin_inset CommandInset InsetType
695 \begin_inset LatexCommand cmd
696 Some insets may end up being converted to insets earlier versions of LyX
697 will not be able to recognize. Not sure what to do about that.
701 i = find_token(document.body, "\\begin_inset CommandInset", i)
704 nextline = document.body[i+1]
705 r = re.compile(r'LatexCommand\s+(.*)$')
706 m = r.match(nextline)
708 document.warning("Malformed LyX document: Missing LatexCommand in " + document.body[i] + ".")
711 insertion = ["\\begin_inset LatexCommand " + cmdName]
712 document.body[i : i+2] = insertion
715 def convert_wrapfig_options(document):
716 "Convert optional options for wrap floats (wrapfig)."
717 # adds the tokens "lines", "placement", and "overhang"
720 i = find_token(document.body, "\\begin_inset Wrap figure", i)
723 document.body.insert(i + 1, "lines 0")
724 j = find_token(document.body, "placement", i)
725 # placement can be already set or not; if not, set it
727 document.body.insert(i + 3, "overhang 0col%")
729 document.body.insert(i + 2, "placement o")
730 document.body.insert(i + 3, "overhang 0col%")
734 def revert_wrapfig_options(document):
735 "Revert optional options for wrap floats (wrapfig)."
738 i = find_token(document.body, "lines", i)
741 j = find_token(document.body, "overhang", i+1)
742 if j != i + 2 and j != -1:
743 document.warning("Malformed LyX document: Couldn't find overhang parameter of wrap float.")
747 del document.body[j-1]
751 def convert_latexcommand_index(document):
752 "Convert from LatexCommand form to collapsable form."
755 i = find_token(document.body, "\\begin_inset CommandInset index", i)
758 if document.body[i + 1] != "LatexCommand index": # Might also be index_print
760 fullcontent = document.body[i + 2][6:].strip('"')
761 document.body[i:i + 2] = ["\\begin_inset Index",
763 "\\begin_layout Standard"]
764 # Put here the conversions needed from LaTeX string to LyXText.
765 # Here we do a minimal conversion to prevent crashes and data loss.
766 # Manual patch-up may be needed.
767 # Umlauted characters (most common ones, can be extended):
768 fullcontent = fullcontent.replace(r'\\\"a', u'ä').replace(r'\\\"o', u'ö').replace(r'\\\"u', u'ü')
770 fullcontent = wrap_into_ert(fullcontent, r'\"', '"')
771 #fullcontent = fullcontent.replace(r'\"', '\n\\begin_inset ERT\nstatus collapsed\n\\begin_layout standard\n"\n\\end_layout\n\\end_inset\n')
773 r = re.compile('^(.*?)(\$.*?\$)(.*)')
778 f = m.group(2).replace('\\\\', '\\')
782 s = wrap_into_ert(s, r'\\', '\\backslash')
783 s = wrap_into_ert(s, '{', '{')
784 s = wrap_into_ert(s, '}', '}')
785 document.body.insert(i + 3, s)
787 document.body.insert(i + 3, "\\begin_inset Formula " + f)
788 document.body.insert(i + 4, "\\end_inset")
790 # Generic, \\ -> \backslash:
791 g = wrap_into_ert(g, r'\\', '\\backslash')
792 g = wrap_into_ert(g, '{', '{')
793 g = wrap_into_ert(g, '}', '}')
794 document.body.insert(i + 3, g)
795 document.body[i + 4] = "\\end_layout"
799 def revert_latexcommand_index(document):
800 "Revert from collapsable form to LatexCommand form."
803 i = find_token(document.body, "\\begin_inset Index", i)
806 j = find_end_of_inset(document.body, i + 1)
809 del document.body[j - 1]
810 del document.body[j - 2] # \end_layout
811 document.body[i] = "\\begin_inset CommandInset index"
812 document.body[i + 1] = "LatexCommand index"
813 # clean up multiline stuff
816 for k in range(i + 3, j - 2):
817 line = document.body[k]
818 if line.startswith("\\begin_inset ERT"):
819 ert_end = find_end_of_inset(document.body, k + 1)
821 if line.startswith("\\begin_inset Formula"):
823 if line.startswith("\\begin_layout Standard"):
825 if line.startswith("\\begin_layout Plain Layout"):
827 if line.startswith("\\end_layout"):
829 if line.startswith("\\end_inset"):
831 if line.startswith("status collapsed"):
833 if line.startswith("status open"):
835 # a lossless reversion is not possible
836 # try at least to handle some common insets and settings
837 # do not replace inside ERTs
839 line = line.replace(u'ä', r'\\\"a').replace(u'ö', r'\\\"o').replace(u'ü', r'\\\"u')
840 line = line.replace(r'\backslash', r'\textbackslash{}')
841 line = line.replace(r'\series bold', r'\bfseries{}').replace(r'\series default', r'\mdseries{}')
842 line = line.replace(r'\shape italic', r'\itshape{}').replace(r'\shape smallcaps', r'\scshape{}')
843 line = line.replace(r'\shape slanted', r'\slshape{}').replace(r'\shape default', r'\upshape{}')
844 line = line.replace(r'\emph on', r'\em{}').replace(r'\emph default', r'\em{}')
845 line = line.replace(r'\noun on', r'\scshape{}').replace(r'\noun default', r'\upshape{}')
846 line = line.replace(r'\bar under', r'\underbar{').replace(r'\bar default', r'}')
847 line = line.replace(r'\family sans', r'\sffamily{}').replace(r'\family default', r'\normalfont{}')
848 line = line.replace(r'\family typewriter', r'\ttfamily{}').replace(r'\family roman', r'\rmfamily{}')
849 line = line.replace(r'\InsetSpace ', r'').replace(r'\SpecialChar ', r'')
851 line = line.replace(r'\backslash', r'\\')
852 content = content + line;
853 document.body[i + 3] = "name " + '"' + content + '"'
854 for k in range(i + 4, j - 2):
855 del document.body[i + 4]
856 document.body.insert(i + 4, "")
857 del document.body[i + 2] # \begin_layout standard
861 def revert_wraptable(document):
862 "Revert wrap table to wrap figure."
865 i = find_token(document.body, "\\begin_inset Wrap table", i)
868 document.body[i] = document.body[i].replace('\\begin_inset Wrap table', '\\begin_inset Wrap figure')
872 def revert_vietnamese(document):
873 "Set language Vietnamese to English"
874 # Set document language from Vietnamese to English
876 if document.language == "vietnamese":
877 document.language = "english"
878 i = find_token(document.header, "\\language", 0)
880 document.header[i] = "\\language english"
883 j = find_token(document.body, "\\lang vietnamese", j)
886 document.body[j] = document.body[j].replace("\\lang vietnamese", "\\lang english")
890 def revert_japanese(document):
891 "Set language japanese-plain to japanese"
892 # Set document language from japanese-plain to japanese
894 if document.language == "japanese-plain":
895 document.language = "japanese"
896 i = find_token(document.header, "\\language", 0)
898 document.header[i] = "\\language japanese"
901 j = find_token(document.body, "\\lang japanese-plain", j)
904 document.body[j] = document.body[j].replace("\\lang japanese-plain", "\\lang japanese")
908 def revert_japanese_encoding(document):
909 "Set input encoding form EUC-JP-plain to EUC-JP etc."
910 # Set input encoding form EUC-JP-plain to EUC-JP etc.
912 i = find_token(document.header, "\\inputencoding EUC-JP-plain", 0)
914 document.header[i] = "\\inputencoding EUC-JP"
916 j = find_token(document.header, "\\inputencoding JIS-plain", 0)
918 document.header[j] = "\\inputencoding JIS"
920 k = find_token(document.header, "\\inputencoding SJIS-plain", 0)
921 if k != -1: # convert to UTF8 since there is currently no SJIS encoding
922 document.header[k] = "\\inputencoding UTF8"
925 def revert_inset_info(document):
926 'Replace info inset with its content'
929 i = find_token(document.body, '\\begin_inset Info', i)
932 j = find_end_of_inset(document.body, i + 1)
935 document.warning("Malformed LyX document: Could not find end of Info inset.")
938 for k in range(i, j+1):
939 if document.body[k].startswith("arg"):
940 arg = document.body[k][3:].strip().strip('"')
941 if document.body[k].startswith("type"):
942 type = document.body[k][4:].strip().strip('"')
943 # I think there is a newline after \\end_inset, which should be removed.
944 if document.body[j + 1].strip() == "":
945 document.body[i : (j + 2)] = [type + ':' + arg]
947 document.body[i : (j + 1)] = [type + ':' + arg]
950 def convert_pdf_options(document):
951 # Set the pdfusetitle tag, delete the pdf_store_options,
952 # set quotes for bookmarksopenlevel"
953 has_hr = get_value(document.header, "\\use_hyperref", 0, default = "0")
955 k = find_token(document.header, "\\use_hyperref", 0)
956 document.header.insert(k + 1, "\\pdf_pdfusetitle true")
957 k = find_token(document.header, "\\pdf_store_options", 0)
959 del document.header[k]
960 i = find_token(document.header, "\\pdf_bookmarksopenlevel", k)
962 document.header[i] = document.header[i].replace('"', '')
965 def revert_pdf_options_2(document):
966 # reset the pdfusetitle tag, set quotes for bookmarksopenlevel"
967 k = find_token(document.header, "\\use_hyperref", 0)
968 i = find_token(document.header, "\\pdf_pdfusetitle", k)
970 del document.header[i]
971 i = find_token(document.header, "\\pdf_bookmarksopenlevel", k)
973 values = document.header[i].split()
974 values[1] = ' "' + values[1] + '"'
975 document.header[i] = ''.join(values)
978 def convert_htmlurl(document):
979 'Convert "htmlurl" to "href" insets for docbook'
980 if document.backend != "docbook":
984 i = find_token(document.body, "\\begin_inset CommandInset url", i)
987 document.body[i] = "\\begin_inset CommandInset href"
988 document.body[i + 1] = "LatexCommand href"
992 def convert_url(document):
993 'Convert url insets to url charstyles'
994 if document.backend == "docbook":
998 i = find_token(document.body, "\\begin_inset CommandInset url", i)
1001 n = find_token(document.body, "name", i)
1003 # place the URL name in typewriter before the new URL insert
1004 # grab the name 'bla' from the e.g. the line 'name "bla"',
1005 # therefore start with the 6th character
1006 name = document.body[n][6:-1]
1007 newname = [name + " "]
1008 document.body[i:i] = newname
1010 j = find_token(document.body, "target", i)
1012 document.warning("Malformed LyX document: Can't find target for url inset")
1015 target = document.body[j][8:-1]
1016 k = find_token(document.body, "\\end_inset", j)
1018 document.warning("Malformed LyX document: Can't find end of url inset")
1021 newstuff = ["\\begin_inset Flex URL",
1022 "status collapsed", "",
1023 "\\begin_layout Standard",
1028 document.body[i:k] = newstuff
1031 def convert_ams_classes(document):
1032 tc = document.textclass
1033 if (tc != "amsart" and tc != "amsart-plain" and
1034 tc != "amsart-seq" and tc != "amsbook"):
1036 if tc == "amsart-plain":
1037 document.textclass = "amsart"
1038 document.set_textclass()
1039 document.add_module("Theorems (Starred)")
1041 if tc == "amsart-seq":
1042 document.textclass = "amsart"
1043 document.set_textclass()
1044 document.add_module("Theorems (AMS)")
1046 #Now we want to see if any of the environments in the extended theorems
1047 #module were used in this document. If so, we'll add that module, too.
1048 layouts = ["Criterion", "Algorithm", "Axiom", "Condition", "Note", \
1049 "Notation", "Summary", "Acknowledgement", "Conclusion", "Fact", \
1052 r = re.compile(r'^\\begin_layout (.*?)\*?\s*$')
1055 i = find_token(document.body, "\\begin_layout", i)
1058 m = r.match(document.body[i])
1060 document.warning("Weirdly formed \\begin_layout at line %d of body!" % i)
1064 if layouts.count(m) != 0:
1065 document.add_module("Theorems (AMS-Extended)")
1069 def revert_href(document):
1070 'Reverts hyperlink insets (href) to url insets (url)'
1073 i = find_token(document.body, "\\begin_inset CommandInset href", i)
1076 document.body[i : i + 2] = \
1077 ["\\begin_inset CommandInset url", "LatexCommand url"]
1081 def convert_include(document):
1082 'Converts include insets to new format.'
1084 r = re.compile(r'\\begin_inset Include\s+\\([^{]+){([^}]*)}(?:\[(.*)\])?')
1086 i = find_token(document.body, "\\begin_inset Include", i)
1089 line = document.body[i]
1090 previewline = document.body[i + 1]
1093 document.warning("Unable to match line " + str(i) + " of body!")
1099 insertion = ["\\begin_inset CommandInset include",
1100 "LatexCommand " + cmd, previewline,
1101 "filename \"" + fn + "\""]
1104 insertion.append("lstparams " + '"' + opt + '"')
1106 document.body[i : i + 2] = insertion
1110 def revert_include(document):
1111 'Reverts include insets to old format.'
1113 r1 = re.compile('LatexCommand (.+)')
1114 r2 = re.compile('filename (.+)')
1115 r3 = re.compile('options (.*)')
1117 i = find_token(document.body, "\\begin_inset CommandInset include", i)
1120 previewline = document.body[i + 1]
1121 m = r1.match(document.body[i + 2])
1123 document.warning("Malformed LyX document: No LatexCommand line for `" +
1124 document.body[i] + "' on line " + str(i) + ".")
1128 m = r2.match(document.body[i + 3])
1130 document.warning("Malformed LyX document: No filename line for `" + \
1131 document.body[i] + "' on line " + str(i) + ".")
1137 if (cmd == "lstinputlisting"):
1138 m = r3.match(document.body[i + 4])
1140 options = m.group(1)
1142 newline = "\\begin_inset Include \\" + cmd + "{" + fn + "}"
1144 newline += ("[" + options + "]")
1145 insertion = [newline, previewline]
1146 document.body[i : i + numlines] = insertion
1150 def revert_albanian(document):
1151 "Set language Albanian to English"
1153 if document.language == "albanian":
1154 document.language = "english"
1155 i = find_token(document.header, "\\language", 0)
1157 document.header[i] = "\\language english"
1160 j = find_token(document.body, "\\lang albanian", j)
1163 document.body[j] = document.body[j].replace("\\lang albanian", "\\lang english")
1167 def revert_lowersorbian(document):
1168 "Set language lower Sorbian to English"
1170 if document.language == "lowersorbian":
1171 document.language = "english"
1172 i = find_token(document.header, "\\language", 0)
1174 document.header[i] = "\\language english"
1177 j = find_token(document.body, "\\lang lowersorbian", j)
1180 document.body[j] = document.body[j].replace("\\lang lowersorbian", "\\lang english")
1184 def revert_uppersorbian(document):
1185 "Set language uppersorbian to usorbian as this was used in LyX 1.5"
1187 if document.language == "uppersorbian":
1188 document.language = "usorbian"
1189 i = find_token(document.header, "\\language", 0)
1191 document.header[i] = "\\language usorbian"
1194 j = find_token(document.body, "\\lang uppersorbian", j)
1197 document.body[j] = document.body[j].replace("\\lang uppersorbian", "\\lang usorbian")
1201 def convert_usorbian(document):
1202 "Set language usorbian to uppersorbian"
1204 if document.language == "usorbian":
1205 document.language = "uppersorbian"
1206 i = find_token(document.header, "\\language", 0)
1208 document.header[i] = "\\language uppersorbian"
1211 j = find_token(document.body, "\\lang usorbian", j)
1214 document.body[j] = document.body[j].replace("\\lang usorbian", "\\lang uppersorbian")
1218 def revert_macro_optional_params(document):
1219 "Convert macro definitions with optional parameters into ERTs"
1220 # Stub to convert macro definitions with one or more optional parameters
1221 # into uninterpreted ERT insets
1224 def revert_hyperlinktype(document):
1225 'Reverts hyperlink type'
1229 i = find_token(document.body, "target", i)
1232 j = find_token(document.body, "type", i)
1236 del document.body[j]
1240 def revert_pagebreak(document):
1241 'Reverts pagebreak to ERT'
1244 i = find_token(document.body, "\\pagebreak", i)
1247 document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1248 '\\begin_layout Standard\n\n\n\\backslash\n' \
1249 'pagebreak{}\n\\end_layout\n\n\\end_inset\n\n'
1253 def revert_linebreak(document):
1254 'Reverts linebreak to ERT'
1257 i = find_token(document.body, "\\linebreak", i)
1260 document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1261 '\\begin_layout Standard\n\n\n\\backslash\n' \
1262 'linebreak{}\n\\end_layout\n\n\\end_inset\n\n'
1266 def revert_latin(document):
1267 "Set language Latin to English"
1269 if document.language == "latin":
1270 document.language = "english"
1271 i = find_token(document.header, "\\language", 0)
1273 document.header[i] = "\\language english"
1276 j = find_token(document.body, "\\lang latin", j)
1279 document.body[j] = document.body[j].replace("\\lang latin", "\\lang english")
1283 def revert_samin(document):
1284 "Set language North Sami to English"
1286 if document.language == "samin":
1287 document.language = "english"
1288 i = find_token(document.header, "\\language", 0)
1290 document.header[i] = "\\language english"
1293 j = find_token(document.body, "\\lang samin", j)
1296 document.body[j] = document.body[j].replace("\\lang samin", "\\lang english")
1300 def convert_serbocroatian(document):
1301 "Set language Serbocroatian to Croatian as this was really Croatian in LyX 1.5"
1303 if document.language == "serbocroatian":
1304 document.language = "croatian"
1305 i = find_token(document.header, "\\language", 0)
1307 document.header[i] = "\\language croatian"
1310 j = find_token(document.body, "\\lang serbocroatian", j)
1313 document.body[j] = document.body[j].replace("\\lang serbocroatian", "\\lang croatian")
1317 def convert_framed_notes(document):
1318 "Convert framed notes to boxes. "
1321 i = find_tokens(document.body, ["\\begin_inset Note Framed", "\\begin_inset Note Shaded"], i)
1324 subst = [document.body[i].replace("\\begin_inset Note", "\\begin_inset Box"),
1333 'height_special "totalheight"']
1334 document.body[i:i+1] = subst
1338 def convert_module_names(document):
1339 modulemap = { 'Braille' : 'braille', 'Endnote' : 'endnotes', 'Foot to End' : 'foottoend',\
1340 'Hanging' : 'hanging', 'Linguistics' : 'linguistics', 'Logical Markup' : 'logicalmkup', \
1341 'Theorems (AMS-Extended)' : 'theorems-ams-extended', 'Theorems (AMS)' : 'theorems-ams', \
1342 'Theorems (Order By Chapter)' : 'theorems-chap', 'Theorems (Order By Section)' : 'theorems-sec', \
1343 'Theorems (Starred)' : 'theorems-starred', 'Theorems' : 'theorems-std' }
1344 modlist = document.get_module_list()
1345 if len(modlist) == 0:
1349 if modulemap.has_key(mod):
1350 newmodlist.append(modulemap[mod])
1352 document.warning("Can't find module %s in the module map!" % mod)
1353 newmodlist.append(mod)
1354 document.set_module_list(newmodlist)
1357 def revert_module_names(document):
1358 modulemap = { 'braille' : 'Braille', 'endnotes' : 'Endnote', 'foottoend' : 'Foot to End',\
1359 'hanging' : 'Hanging', 'linguistics' : 'Linguistics', 'logicalmkup' : 'Logical Markup', \
1360 'theorems-ams-extended' : 'Theorems (AMS-Extended)', 'theorems-ams' : 'Theorems (AMS)', \
1361 'theorems-chap' : 'Theorems (Order By Chapter)', 'theorems-sec' : 'Theorems (Order By Section)', \
1362 'theorems-starred' : 'Theorems (Starred)', 'theorems-std' : 'Theorems'}
1363 modlist = document.get_module_list()
1364 if len(modlist) == 0:
1368 if modulemap.has_key(mod):
1369 newmodlist.append(modulemap[mod])
1371 document.warning("Can't find module %s in the module map!" % mod)
1372 newmodlist.append(mod)
1373 document.set_module_list(newmodlist)
1376 def revert_colsep(document):
1377 i = find_token(document.header, "\\columnsep", 0)
1380 colsepline = document.header[i]
1381 r = re.compile(r'\\columnsep (.*)')
1382 m = r.match(colsepline)
1384 document.warning("Malformed column separation line!")
1387 del document.header[i]
1388 #it seems to be safe to add the package even if it is already used
1389 pretext = ["\\usepackage{geometry}", "\\geometry{columnsep=" + colsep + "}"]
1391 add_to_preamble(document, pretext)
1394 def revert_framed_notes(document):
1395 "Revert framed boxes to notes. "
1398 i = find_tokens(document.body, ["\\begin_inset Box Framed", "\\begin_inset Box Shaded"], i)
1402 j = find_end_of_inset(document.body, i + 1)
1405 document.warning("Malformed LyX document: Could not find end of Box inset.")
1406 k = find_token(document.body, "status", i + 1, j)
1408 document.warning("Malformed LyX document: Missing `status' tag in Box inset.")
1410 status = document.body[k]
1411 l = find_default_layout(document, i + 1, j)
1413 document.warning("Malformed LyX document: Missing `\\begin_layout' in Box inset.")
1415 m = find_token(document.body, "\\end_layout", i + 1, j)
1417 document.warning("Malformed LyX document: Missing `\\end_layout' in Box inset.")
1419 ibox = find_token(document.body, "has_inner_box 1", i + 1, k)
1420 pbox = find_token(document.body, "use_parbox 1", i + 1, k)
1421 if ibox == -1 and pbox == -1:
1422 document.body[i] = document.body[i].replace("\\begin_inset Box", "\\begin_inset Note")
1423 del document.body[i+1:k]
1425 document.body[i] = document.body[i].replace("\\begin_inset Box Shaded", "\\begin_inset Box Frameless")
1426 subst1 = [document.body[l],
1427 "\\begin_inset Note Shaded",
1429 '\\begin_layout Standard']
1430 document.body[l:l + 1] = subst1
1431 subst2 = [document.body[m], "\\end_layout", "\\end_inset"]
1432 document.body[m:m + 1] = subst2
1436 def revert_slash(document):
1437 'Revert \\SpecialChar \\slash{} to ERT'
1438 r = re.compile(r'\\SpecialChar \\slash{}')
1440 while i < len(document.body):
1441 m = r.match(document.body[i])
1443 subst = ['\\begin_inset ERT',
1444 'status collapsed', '',
1445 '\\begin_layout Standard',
1446 '', '', '\\backslash',
1450 document.body[i: i+1] = subst
1456 def revert_nobreakdash(document):
1457 'Revert \\SpecialChar \\nobreakdash- to ERT'
1459 while i < len(document.body):
1460 line = document.body[i]
1461 r = re.compile(r'\\SpecialChar \\nobreakdash-')
1464 subst = ['\\begin_inset ERT',
1465 'status collapsed', '',
1466 '\\begin_layout Standard', '', '',
1471 document.body[i:i+1] = subst
1473 j = find_token(document.header, "\\use_amsmath", 0)
1475 document.warning("Malformed LyX document: Missing '\\use_amsmath'.")
1477 document.header[j] = "\\use_amsmath 2"
1482 #Returns number of lines added/removed
1483 def revert_nocite_key(body, start, end):
1484 'key "..." -> \nocite{...}'
1485 r = re.compile(r'^key "(.*)"')
1489 m = r.match(body[i])
1491 body[i:i+1] = ["\\backslash", "nocite{" + m.group(1) + "}"]
1492 j += 1 # because we added a line
1493 i += 2 # skip that line
1496 j -= 1 # because we deleted a line
1497 # no need to change i, since it now points to the next line
1501 def revert_nocite(document):
1502 "Revert LatexCommand nocite to ERT"
1505 i = find_token(document.body, "\\begin_inset CommandInset citation", i)
1508 if (document.body[i+1] != "LatexCommand nocite"):
1509 # note that we already incremented i
1512 insetEnd = find_end_of_inset(document.body, i)
1514 #this should not happen
1515 document.warning("End of CommandInset citation not found in revert_nocite!")
1518 paramLocation = i + 2 #start of the inset's parameters
1520 document.body[i:i+2] = \
1521 ["\\begin_inset ERT", "status collapsed", "", "\\begin_layout Standard"]
1522 # that added two lines
1525 #print insetEnd, document.body[i: insetEnd + 1]
1526 insetEnd += revert_nocite_key(document.body, paramLocation, insetEnd)
1527 #print insetEnd, document.body[i: insetEnd + 1]
1528 document.body.insert(insetEnd, "\\end_layout")
1529 document.body.insert(insetEnd + 1, "")
1533 def revert_btprintall(document):
1534 "Revert (non-bibtopic) btPrintAll option to ERT \nocite{*}"
1535 i = find_token(document.header, '\\use_bibtopic', 0)
1537 document.warning("Malformed lyx document: Missing '\\use_bibtopic'.")
1539 if get_value(document.header, '\\use_bibtopic', 0) == "false":
1541 while i < len(document.body):
1542 i = find_token(document.body, "\\begin_inset CommandInset bibtex", i)
1545 j = find_end_of_inset(document.body, i + 1)
1547 #this should not happen
1548 document.warning("End of CommandInset bibtex not found in revert_btprintall!")
1549 j = len(document.body)
1550 # this range isn't really right, but it should be OK, since we shouldn't
1551 # see more than one matching line in each inset
1553 for k in range(i, j):
1554 if (document.body[k] == 'btprint "btPrintAll"'):
1555 del document.body[k]
1556 subst = ["\\begin_inset ERT",
1557 "status collapsed", "",
1558 "\\begin_layout Standard", "",
1563 document.body[i:i] = subst
1564 addlines = addedlines + len(subst) - 1
1568 def revert_bahasam(document):
1569 "Set language Bahasa Malaysia to Bahasa Indonesia"
1571 if document.language == "bahasam":
1572 document.language = "bahasa"
1573 i = find_token(document.header, "\\language", 0)
1575 document.header[i] = "\\language bahasa"
1578 j = find_token(document.body, "\\lang bahasam", j)
1581 document.body[j] = document.body[j].replace("\\lang bahasam", "\\lang bahasa")
1585 def revert_interlingua(document):
1586 "Set language Interlingua to English"
1588 if document.language == "interlingua":
1589 document.language = "english"
1590 i = find_token(document.header, "\\language", 0)
1592 document.header[i] = "\\language english"
1595 j = find_token(document.body, "\\lang interlingua", j)
1598 document.body[j] = document.body[j].replace("\\lang interlingua", "\\lang english")
1602 def revert_serbianlatin(document):
1603 "Set language Serbian-Latin to Croatian"
1605 if document.language == "serbian-latin":
1606 document.language = "croatian"
1607 i = find_token(document.header, "\\language", 0)
1609 document.header[i] = "\\language croatian"
1612 j = find_token(document.body, "\\lang serbian-latin", j)
1615 document.body[j] = document.body[j].replace("\\lang serbian-latin", "\\lang croatian")
1619 def revert_rotfloat(document):
1620 " Revert sideways custom floats. "
1623 # whitespace intended (exclude \\begin_inset FloatList)
1624 i = find_token(document.body, "\\begin_inset Float ", i)
1627 line = document.body[i]
1628 r = re.compile(r'\\begin_inset Float (.*)$')
1631 document.warning("Unable to match line " + str(i) + " of body!")
1634 floattype = m.group(1)
1635 if floattype == "figure" or floattype == "table":
1638 j = find_end_of_inset(document.body, i)
1640 document.warning("Malformed lyx document: Missing '\\end_inset'.")
1643 if get_value(document.body, 'sideways', i, j) != "false":
1644 l = find_default_layout(document, i + 1, j)
1646 document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
1648 document.body[j] = '\\begin_layout Standard\n\\begin_inset ERT\nstatus collapsed\n\n' \
1649 '\\begin_layout Standard\n\n\n\\backslash\n' \
1650 'end{sideways' + floattype + '}\n\\end_layout\n\n\\end_inset\n'
1651 del document.body[i+1:l-1]
1652 document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1653 '\\begin_layout Standard\n\n\n\\backslash\n' \
1654 'begin{sideways' + floattype + '}\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n\n'
1655 if floattype == "algorithm":
1656 add_to_preamble(document,
1657 ['% Commands inserted by lyx2lyx for sideways algorithm float',
1658 '\\usepackage{rotfloat}',
1659 '\\floatstyle{ruled}',
1660 '\\newfloat{algorithm}{tbp}{loa}',
1661 '\\floatname{algorithm}{Algorithm}'])
1663 document.warning("Cannot create preamble definition for custom float" + floattype + ".")
1669 def revert_widesideways(document):
1670 " Revert wide sideways floats. "
1673 # whitespace intended (exclude \\begin_inset FloatList)
1674 i = find_token(document.body, '\\begin_inset Float ', i)
1677 line = document.body[i]
1678 r = re.compile(r'\\begin_inset Float (.*)$')
1681 document.warning("Unable to match line " + str(i) + " of body!")
1684 floattype = m.group(1)
1685 if floattype != "figure" and floattype != "table":
1688 j = find_end_of_inset(document.body, i)
1690 document.warning("Malformed lyx document: Missing '\\end_inset'.")
1693 if get_value(document.body, 'sideways', i, j) != "false":
1694 if get_value(document.body, 'wide', i, j) != "false":
1695 l = find_default_layout(document, i + 1, j)
1697 document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
1699 document.body[j] = '\\begin_layout Standard\n\\begin_inset ERT\nstatus collapsed\n\n' \
1700 '\\begin_layout Standard\n\n\n\\backslash\n' \
1701 'end{sideways' + floattype + '*}\n\\end_layout\n\n\\end_inset\n'
1702 del document.body[i+1:l-1]
1703 document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1704 '\\begin_layout Standard\n\n\n\\backslash\n' \
1705 'begin{sideways' + floattype + '*}\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n\n'
1706 add_to_preamble(document,
1707 ['\\usepackage{rotfloat}\n'])
1713 def revert_inset_embedding(document, type):
1714 ' Remove embed tag from certain type of insets'
1717 i = find_token(document.body, "\\begin_inset %s" % type, i)
1720 j = find_end_of_inset(document.body, i)
1722 document.warning("Malformed lyx document: Missing '\\end_inset'.")
1725 k = find_token(document.body, "\tembed", i, j)
1727 k = find_token(document.body, "embed", i, j)
1729 del document.body[k]
1733 def revert_external_embedding(document):
1734 ' Remove embed tag from external inset '
1735 revert_inset_embedding(document, 'External')
1738 def convert_subfig(document):
1739 " Convert subfigures to subfloats. "
1742 i = find_token(document.body, '\\begin_inset Graphics', i)
1745 j = find_end_of_inset(document.body, i)
1747 document.warning("Malformed lyx document: Missing '\\end_inset'.")
1750 k = find_token(document.body, '\tsubcaption', i, j)
1754 l = find_token(document.body, '\tsubcaptionText', i, j)
1755 caption = document.body[l][16:].strip('"')
1756 savestr = document.body[i]
1757 del document.body[l]
1758 del document.body[k]
1759 document.body[i] = '\\begin_inset Float figure\nwide false\nsideways false\n' \
1760 'status open\n\n\\begin_layout Plain Layout\n\\begin_inset Caption\n\n\\begin_layout Plain Layout\n' \
1761 + caption + '\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n\n\\begin_layout Plain Layout\n' + savestr
1762 savestr = document.body[j]
1763 document.body[j] = '\n\\end_layout\n\n\\end_inset\n' + savestr
1766 def revert_subfig(document):
1767 " Revert subfloats. "
1770 # whitespace intended (exclude \\begin_inset FloatList)
1771 i = find_token(document.body, '\\begin_inset Float ', i)
1775 j = find_end_of_inset(document.body, i)
1777 document.warning("Malformed lyx document: Missing '\\end_inset' (float).")
1780 # look for embedded float (= subfloat)
1781 # whitespace intended (exclude \\begin_inset FloatList)
1782 k = find_token(document.body, '\\begin_inset Float ', i + 1, j)
1785 l = find_end_of_inset(document.body, k)
1787 document.warning("Malformed lyx document: Missing '\\end_inset' (embedded float).")
1790 m = find_default_layout(document, k + 1, l)
1792 cap = find_token(document.body, '\\begin_inset Caption', k + 1, l)
1796 capend = find_end_of_inset(document.body, cap)
1798 document.warning("Malformed lyx document: Missing '\\end_inset' (caption).")
1802 lbl = find_token(document.body, '\\begin_inset CommandInset label', cap, capend)
1804 lblend = find_end_of_inset(document.body, lbl + 1)
1806 document.warning("Malformed lyx document: Missing '\\end_inset' (label).")
1808 for line in document.body[lbl:lblend + 1]:
1809 if line.startswith('name '):
1810 label = line.split()[1].strip('"')
1817 opt = find_token(document.body, '\\begin_inset OptArg', cap, capend)
1819 optend = find_end_of_inset(document.body, opt)
1821 document.warning("Malformed lyx document: Missing '\\end_inset' (OptArg).")
1823 optc = find_default_layout(document, opt, optend)
1825 document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
1827 optcend = find_end_of(document.body, optc, "\\begin_layout", "\\end_layout")
1828 for line in document.body[optc:optcend]:
1829 if not line.startswith('\\'):
1830 shortcap += line.strip()
1834 for line in document.body[cap:capend]:
1835 if line in document.body[lbl:lblend]:
1837 elif line in document.body[opt:optend]:
1839 elif not line.startswith('\\'):
1840 caption += line.strip()
1842 caption += "\\backslash\nlabel{" + label + "}"
1843 document.body[l] = '\\begin_layout Plain Layout\n\\begin_inset ERT\nstatus collapsed\n\n' \
1844 '\\begin_layout Plain Layout\n\n}\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n\n\\begin_layout Plain Layout\n'
1845 del document.body[cap:capend+1]
1846 del document.body[k+1:m-1]
1847 insertion = '\\begin_inset ERT\nstatus collapsed\n\n' \
1848 '\\begin_layout Plain Layout\n\n\\backslash\n' \
1850 if len(shortcap) > 0:
1851 insertion = insertion + "[" + shortcap + "]"
1852 if len(caption) > 0:
1853 insertion = insertion + "[" + caption + "]"
1854 insertion = insertion + '{%\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n'
1855 document.body[k] = insertion
1856 add_to_preamble(document,
1857 ['\\usepackage{subfig}\n'])
1861 def revert_wrapplacement(document):
1862 " Revert placement options wrap floats (wrapfig). "
1865 i = find_token(document.body, "lines", i)
1868 j = find_token(document.body, "placement", i+1)
1870 document.warning("Malformed LyX document: Couldn't find placement parameter of wrap float.")
1872 document.body[j] = document.body[j].replace("placement O", "placement o")
1873 document.body[j] = document.body[j].replace("placement I", "placement i")
1874 document.body[j] = document.body[j].replace("placement L", "placement l")
1875 document.body[j] = document.body[j].replace("placement R", "placement r")
1879 def remove_extra_embedded_files(document):
1880 " Remove \extra_embedded_files from buffer params "
1881 i = find_token(document.header, '\\extra_embedded_files', 0)
1884 document.header.pop(i)
1887 def convert_spaceinset(document):
1888 " Convert '\\InsetSpace foo' to '\\begin_inset Space foo\n\\end_inset' "
1890 while i < len(document.body):
1891 m = re.match(r'(.*)\\InsetSpace (.*)', document.body[i])
1895 subst = [before, "\\begin_inset Space " + after, "\\end_inset"]
1896 document.body[i: i+1] = subst
1902 def revert_spaceinset(document):
1903 " Revert '\\begin_inset Space foo\n\\end_inset' to '\\InsetSpace foo' "
1906 i = find_token(document.body, "\\begin_inset Space", i)
1909 j = find_end_of_inset(document.body, i)
1911 document.warning("Malformed LyX document: Could not find end of space inset.")
1913 document.body[i] = document.body[i].replace('\\begin_inset Space', '\\InsetSpace')
1914 del document.body[j]
1917 def convert_hfill(document):
1918 " Convert hfill to space inset "
1921 i = find_token(document.body, "\\hfill", i)
1924 document.body[i] = document.body[i].replace('\\hfill', '\n\\begin_inset Space \\hfill{}\n\\end_inset')
1927 def revert_hfills(document):
1928 ' Revert \\hfill commands '
1929 for i in range(len(document.body)):
1930 document.body[i] = document.body[i].replace('\\InsetSpace \\hfill{}', '\\hfill')
1931 document.body[i] = document.body[i].replace('\\InsetSpace \\dotfill{}', \
1932 '\\begin_inset ERT\nstatus collapsed\n\n' \
1933 '\\begin_layout Standard\n\n\n\\backslash\n' \
1934 'dotfill{}\n\\end_layout\n\n\\end_inset\n\n')
1935 document.body[i] = document.body[i].replace('\\InsetSpace \\hrulefill{}', \
1936 '\\begin_inset ERT\nstatus collapsed\n\n' \
1937 '\\begin_layout Standard\n\n\n\\backslash\n' \
1938 'hrulefill{}\n\\end_layout\n\n\\end_inset\n\n')
1941 def revert_hspace(document):
1942 ' Revert \\InsetSpace \\hspace{} to ERT '
1945 i = find_token(document.body, "\\InsetSpace \\hspace", i)
1948 length = get_value(document.body, '\\length', i+1)
1950 document.warning("Malformed lyx document: Missing '\\length' in Space inset.")
1952 del document.body[i+1]
1953 document.body[i] = document.body[i].replace('\\InsetSpace \\hspace*{}', \
1954 '\\begin_inset ERT\nstatus collapsed\n\n' \
1955 '\\begin_layout Standard\n\n\n\\backslash\n' \
1956 'hspace*{' + length + '}\n\\end_layout\n\n\\end_inset\n\n')
1957 document.body[i] = document.body[i].replace('\\InsetSpace \\hspace{}', \
1958 '\\begin_inset ERT\nstatus collapsed\n\n' \
1959 '\\begin_layout Standard\n\n\n\\backslash\n' \
1960 'hspace{' + length + '}\n\\end_layout\n\n\\end_inset\n\n')
1963 def revert_protected_hfill(document):
1964 ' Revert \\begin_inset Space \\hspace*{\\fill} to ERT '
1967 i = find_token(document.body, '\\begin_inset Space \\hspace*{\\fill}', i)
1970 j = find_end_of_inset(document.body, i)
1972 document.warning("Malformed LyX document: Could not find end of space inset.")
1974 del document.body[j]
1975 document.body[i] = document.body[i].replace('\\begin_inset Space \\hspace*{\\fill}', \
1976 '\\begin_inset ERT\nstatus collapsed\n\n' \
1977 '\\begin_layout Standard\n\n\n\\backslash\n' \
1978 'hspace*{\n\\backslash\nfill}\n\\end_layout\n\n\\end_inset\n\n')
1981 def revert_leftarrowfill(document):
1982 ' Revert \\begin_inset Space \\leftarrowfill{} to ERT '
1985 i = find_token(document.body, '\\begin_inset Space \\leftarrowfill{}', i)
1988 j = find_end_of_inset(document.body, i)
1990 document.warning("Malformed LyX document: Could not find end of space inset.")
1992 del document.body[j]
1993 document.body[i] = document.body[i].replace('\\begin_inset Space \\leftarrowfill{}', \
1994 '\\begin_inset ERT\nstatus collapsed\n\n' \
1995 '\\begin_layout Standard\n\n\n\\backslash\n' \
1996 'leftarrowfill{}\n\\end_layout\n\n\\end_inset\n\n')
1999 def revert_rightarrowfill(document):
2000 ' Revert \\begin_inset Space \\rightarrowfill{} to ERT '
2003 i = find_token(document.body, '\\begin_inset Space \\rightarrowfill{}', i)
2006 j = find_end_of_inset(document.body, i)
2008 document.warning("Malformed LyX document: Could not find end of space inset.")
2010 del document.body[j]
2011 document.body[i] = document.body[i].replace('\\begin_inset Space \\rightarrowfill{}', \
2012 '\\begin_inset ERT\nstatus collapsed\n\n' \
2013 '\\begin_layout Standard\n\n\n\\backslash\n' \
2014 'rightarrowfill{}\n\\end_layout\n\n\\end_inset\n\n')
2017 def revert_upbracefill(document):
2018 ' Revert \\begin_inset Space \\upbracefill{} to ERT '
2021 i = find_token(document.body, '\\begin_inset Space \\upbracefill{}', i)
2024 j = find_end_of_inset(document.body, i)
2026 document.warning("Malformed LyX document: Could not find end of space inset.")
2028 del document.body[j]
2029 document.body[i] = document.body[i].replace('\\begin_inset Space \\upbracefill{}', \
2030 '\\begin_inset ERT\nstatus collapsed\n\n' \
2031 '\\begin_layout Standard\n\n\n\\backslash\n' \
2032 'upbracefill{}\n\\end_layout\n\n\\end_inset\n\n')
2035 def revert_downbracefill(document):
2036 ' Revert \\begin_inset Space \\downbracefill{} to ERT '
2039 i = find_token(document.body, '\\begin_inset Space \\downbracefill{}', i)
2042 j = find_end_of_inset(document.body, i)
2044 document.warning("Malformed LyX document: Could not find end of space inset.")
2046 del document.body[j]
2047 document.body[i] = document.body[i].replace('\\begin_inset Space \\downbracefill{}', \
2048 '\\begin_inset ERT\nstatus collapsed\n\n' \
2049 '\\begin_layout Standard\n\n\n\\backslash\n' \
2050 'downbracefill{}\n\\end_layout\n\n\\end_inset\n\n')
2053 def revert_local_layout(document):
2054 ' Revert local layout headers.'
2057 i = find_token(document.header, "\\begin_local_layout", i)
2060 j = find_end_of(document.header, i, "\\begin_local_layout", "\\end_local_layout")
2062 # this should not happen
2064 document.header[i : j + 1] = []
2067 def convert_pagebreaks(document):
2068 ' Convert inline Newpage insets to new format '
2071 i = find_token(document.body, '\\newpage', i)
2074 document.body[i:i+1] = ['\\begin_inset Newpage newpage',
2078 i = find_token(document.body, '\\pagebreak', i)
2081 document.body[i:i+1] = ['\\begin_inset Newpage pagebreak',
2085 i = find_token(document.body, '\\clearpage', i)
2088 document.body[i:i+1] = ['\\begin_inset Newpage clearpage',
2092 i = find_token(document.body, '\\cleardoublepage', i)
2095 document.body[i:i+1] = ['\\begin_inset Newpage cleardoublepage',
2099 def revert_pagebreaks(document):
2100 ' Revert \\begin_inset Newpage to previous inline format '
2103 i = find_token(document.body, '\\begin_inset Newpage', i)
2106 j = find_end_of_inset(document.body, i)
2108 document.warning("Malformed LyX document: Could not find end of Newpage inset.")
2110 del document.body[j]
2111 document.body[i] = document.body[i].replace('\\begin_inset Newpage newpage', '\\newpage')
2112 document.body[i] = document.body[i].replace('\\begin_inset Newpage pagebreak', '\\pagebreak')
2113 document.body[i] = document.body[i].replace('\\begin_inset Newpage clearpage', '\\clearpage')
2114 document.body[i] = document.body[i].replace('\\begin_inset Newpage cleardoublepage', '\\cleardoublepage')
2117 def convert_linebreaks(document):
2118 ' Convert inline Newline insets to new format '
2121 i = find_token(document.body, '\\newline', i)
2124 document.body[i:i+1] = ['\\begin_inset Newline newline',
2128 i = find_token(document.body, '\\linebreak', i)
2131 document.body[i:i+1] = ['\\begin_inset Newline linebreak',
2135 def revert_linebreaks(document):
2136 ' Revert \\begin_inset Newline to previous inline format '
2139 i = find_token(document.body, '\\begin_inset Newline', i)
2142 j = find_end_of_inset(document.body, i)
2144 document.warning("Malformed LyX document: Could not find end of Newline inset.")
2146 del document.body[j]
2147 document.body[i] = document.body[i].replace('\\begin_inset Newline newline', '\\newline')
2148 document.body[i] = document.body[i].replace('\\begin_inset Newline linebreak', '\\linebreak')
2151 def convert_japanese_plain(document):
2152 ' Set language japanese-plain to japanese '
2154 if document.language == "japanese-plain":
2155 document.language = "japanese"
2156 i = find_token(document.header, "\\language", 0)
2158 document.header[i] = "\\language japanese"
2161 j = find_token(document.body, "\\lang japanese-plain", j)
2164 document.body[j] = document.body[j].replace("\\lang japanese-plain", "\\lang japanese")
2168 def revert_pdfpages(document):
2169 ' Revert pdfpages external inset to ERT '
2172 i = find_token(document.body, "\\begin_inset External", i)
2175 j = find_end_of_inset(document.body, i)
2177 document.warning("Malformed lyx document: Missing '\\end_inset'.")
2180 if get_value(document.body, 'template', i, j) == "PDFPages":
2181 filename = get_value(document.body, 'filename', i, j)
2183 r = re.compile(r'\textra PDFLaTeX \"(.*)\"$')
2184 for k in range(i, j):
2185 m = r.match(document.body[k])
2188 angle = get_value(document.body, 'rotateAngle', i, j)
2189 width = get_value(document.body, 'width', i, j)
2190 height = get_value(document.body, 'height', i, j)
2191 scale = get_value(document.body, 'scale', i, j)
2192 keepAspectRatio = find_token(document.body, "\tkeepAspectRatio", i, j)
2196 options += ",angle=" + angle
2198 options += "angle=" + angle
2201 options += ",width=" + convert_len(width)
2203 options += "width=" + convert_len(width)
2206 options += ",height=" + convert_len(height)
2208 options += "height=" + convert_len(height)
2211 options += ",scale=" + scale
2213 options += "scale=" + scale
2214 if keepAspectRatio != '':
2216 options += ",keepaspectratio"
2218 options += "keepaspectratio"
2220 options = '[' + options + ']'
2221 del document.body[i+1:j+1]
2222 document.body[i:i+1] = ['\\begin_inset ERT',
2225 '\\begin_layout Standard',
2228 'includepdf' + options + '{' + filename + '}',
2232 add_to_preamble(document, ['\\usepackage{pdfpages}\n'])
2238 def revert_mexican(document):
2239 ' Set language Spanish(Mexico) to Spanish '
2241 if document.language == "spanish-mexico":
2242 document.language = "spanish"
2243 i = find_token(document.header, "\\language", 0)
2245 document.header[i] = "\\language spanish"
2248 j = find_token(document.body, "\\lang spanish-mexico", j)
2251 document.body[j] = document.body[j].replace("\\lang spanish-mexico", "\\lang spanish")
2255 def remove_embedding(document):
2256 ' Remove embed tag from all insets '
2257 revert_inset_embedding(document, 'Graphics')
2258 revert_inset_embedding(document, 'External')
2259 revert_inset_embedding(document, 'CommandInset include')
2260 revert_inset_embedding(document, 'CommandInset bibtex')
2263 def revert_master(document):
2264 ' Remove master param '
2265 i = find_token(document.header, "\\master", 0)
2267 del document.header[i]
2270 def revert_graphics_group(document):
2271 ' Revert group information from graphics insets '
2274 i = find_token(document.body, "\\begin_inset Graphics", i)
2277 j = find_end_of_inset(document.body, i)
2279 document.warning("Malformed lyx document: Missing '\\end_inset'.")
2282 k = find_token(document.body, " groupId", i, j)
2286 del document.body[k]
2290 def update_apa_styles(document):
2291 ' Replace obsolete styles '
2293 if document.textclass != "apa":
2296 obsoletedby = { "Acknowledgments": "Acknowledgements",
2297 "Section*": "Section",
2298 "Subsection*": "Subsection",
2299 "Subsubsection*": "Subsubsection",
2300 "Paragraph*": "Paragraph",
2301 "Subparagraph*": "Subparagraph"}
2304 i = find_token(document.body, "\\begin_layout", i)
2308 layout = document.body[i][14:]
2309 if layout in obsoletedby:
2310 document.body[i] = "\\begin_layout " + obsoletedby[layout]
2315 def convert_paper_sizes(document):
2316 ' exchange size options legalpaper and executivepaper to correct order '
2317 # routine is needed to fix http://bugzilla.lyx.org/show_bug.cgi?id=4868
2320 i = find_token(document.header, "\\papersize executivepaper", 0)
2322 document.header[i] = "\\papersize legalpaper"
2324 j = find_token(document.header, "\\papersize legalpaper", 0)
2326 document.header[j] = "\\papersize executivepaper"
2329 def revert_paper_sizes(document):
2330 ' exchange size options legalpaper and executivepaper to correct order '
2333 i = find_token(document.header, "\\papersize executivepaper", 0)
2335 document.header[i] = "\\papersize legalpaper"
2337 j = find_token(document.header, "\\papersize legalpaper", 0)
2339 document.header[j] = "\\papersize executivepaper"
2342 def convert_InsetSpace(document):
2343 " Convert '\\begin_inset Space foo' to '\\begin_inset space foo'"
2346 i = find_token(document.body, "\\begin_inset Space", i)
2349 document.body[i] = document.body[i].replace('\\begin_inset Space', '\\begin_inset space')
2352 def revert_InsetSpace(document):
2353 " Revert '\\begin_inset space foo' to '\\begin_inset Space foo'"
2356 i = find_token(document.body, "\\begin_inset space", i)
2359 document.body[i] = document.body[i].replace('\\begin_inset space', '\\begin_inset Space')
2366 supported_versions = ["1.6.0","1.6"]
2367 convert = [[277, [fix_wrong_tables]],
2368 [278, [close_begin_deeper]],
2369 [279, [long_charstyle_names]],
2370 [280, [axe_show_label]],
2373 [283, [convert_flex]],
2377 [287, [convert_wrapfig_options]],
2378 [288, [convert_inset_command]],
2379 [289, [convert_latexcommand_index]],
2384 [294, [convert_pdf_options]],
2385 [295, [convert_htmlurl, convert_url]],
2386 [296, [convert_include]],
2387 [297, [convert_usorbian]],
2393 [303, [convert_serbocroatian]],
2394 [304, [convert_framed_notes]],
2401 [311, [convert_ams_classes]],
2403 [313, [convert_module_names]],
2406 [316, [convert_subfig]],
2409 [319, [convert_spaceinset, convert_hfill]],
2411 [321, [convert_tablines]],
2413 [323, [convert_pagebreaks]],
2414 [324, [convert_linebreaks]],
2415 [325, [convert_japanese_plain]],
2418 [328, [remove_embedding, remove_extra_embedded_files, remove_inzip_options]],
2421 [331, [convert_ltcaption]],
2423 [333, [update_apa_styles]],
2424 [334, [convert_paper_sizes]],
2425 [335, [convert_InsetSpace]],
2428 revert = [[334, [revert_InsetSpace]],
2429 [333, [revert_paper_sizes]],
2431 [331, [revert_graphics_group]],
2432 [330, [revert_ltcaption]],
2433 [329, [revert_leftarrowfill, revert_rightarrowfill, revert_upbracefill, revert_downbracefill]],
2434 [328, [revert_master]],
2436 [326, [revert_mexican]],
2437 [325, [revert_pdfpages]],
2439 [323, [revert_linebreaks]],
2440 [322, [revert_pagebreaks]],
2441 [321, [revert_local_layout]],
2442 [320, [revert_tablines]],
2443 [319, [revert_protected_hfill]],
2444 [318, [revert_spaceinset, revert_hfills, revert_hspace]],
2445 [317, [remove_extra_embedded_files]],
2446 [316, [revert_wrapplacement]],
2447 [315, [revert_subfig]],
2448 [314, [revert_colsep]],
2450 [312, [revert_module_names]],
2451 [311, [revert_rotfloat, revert_widesideways]],
2452 [310, [revert_external_embedding]],
2453 [309, [revert_btprintall]],
2454 [308, [revert_nocite]],
2455 [307, [revert_serbianlatin]],
2456 [306, [revert_slash, revert_nobreakdash]],
2457 [305, [revert_interlingua]],
2458 [304, [revert_bahasam]],
2459 [303, [revert_framed_notes]],
2461 [301, [revert_latin, revert_samin]],
2462 [300, [revert_linebreak]],
2463 [299, [revert_pagebreak]],
2464 [298, [revert_hyperlinktype]],
2465 [297, [revert_macro_optional_params]],
2466 [296, [revert_albanian, revert_lowersorbian, revert_uppersorbian]],
2467 [295, [revert_include]],
2468 [294, [revert_href]],
2469 [293, [revert_pdf_options_2]],
2470 [292, [revert_inset_info]],
2471 [291, [revert_japanese, revert_japanese_encoding]],
2472 [290, [revert_vietnamese]],
2473 [289, [revert_wraptable]],
2474 [288, [revert_latexcommand_index]],
2475 [287, [revert_inset_command]],
2476 [286, [revert_wrapfig_options]],
2477 [285, [revert_pdf_options]],
2478 [284, [remove_inzip_options]],
2480 [282, [revert_flex]],
2482 [280, [revert_begin_modules]],
2483 [279, [revert_show_label]],
2484 [278, [revert_long_charstyle_names]],
2490 if __name__ == "__main__":