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 ####################################################################
73 def get_option(document, m, option, default):
74 l = document.body[m].find(option)
77 val = document.body[m][l:].split('"')[1]
80 def remove_option(document, m, option):
81 l = document.body[m].find(option)
83 val = document.body[m][l:].split('"')[1]
84 document.body[m] = document.body[m][:l-1] + document.body[m][l+len(option + '="' + val + '"'):]
87 def set_option(document, m, option, value):
88 l = document.body[m].find(option)
90 oldval = document.body[m][l:].split('"')[1]
91 l = l + len(option + '="')
92 document.body[m] = document.body[m][:l] + value + document.body[m][l+len(oldval):]
94 document.body[m] = document.body[m][:-1] + ' ' + option + '="' + value + '">'
97 def convert_tablines(document):
100 i = find_token(document.body, "\\begin_inset Tabular", i)
102 # LyX 1.3 inserted an extra space between \begin_inset
103 # and Tabular so let us try if this is the case and fix it.
104 i = find_token(document.body, "\\begin_inset Tabular", i)
108 document.body[i] = "\\begin_inset Tabular"
109 j = find_end_of_inset(document.body, i + 1)
111 document.warning("Malformed LyX document: Could not find end of tabular.")
115 nrows = int(document.body[i+1].split('"')[3])
116 ncols = int(document.body[i+1].split('"')[5])
119 for k in range(ncols):
120 m = find_token(document.body, "<column", m)
121 left = get_option(document, m, 'leftline', 'false')
122 right = get_option(document, m, 'rightline', 'false')
123 col_info.append([left, right])
124 remove_option(document, m, 'leftline')
125 remove_option(document, m, 'rightline')
129 for k in range(nrows):
130 m = find_token(document.body, "<row", m)
131 top = get_option(document, m, 'topline', 'false')
132 bottom = get_option(document, m, 'bottomline', 'false')
133 row_info.append([top, bottom])
134 remove_option(document, m, 'topline')
135 remove_option(document, m, 'bottomline')
140 for k in range(nrows*ncols):
141 m = find_token(document.body, "<cell", m)
142 mc_info.append(get_option(document, m, 'multicolumn', '0'))
145 for l in range(nrows):
146 for k in range(ncols):
147 m = find_token(document.body, '<cell', m)
148 if mc_info[l*ncols + k] == '0':
149 r = set_option(document, m, 'topline', row_info[l][0])
150 r = set_option(document, m, 'bottomline', row_info[l][1])
151 r = set_option(document, m, 'leftline', col_info[k][0])
152 r = set_option(document, m, 'rightline', col_info[k][1])
153 elif mc_info[l*ncols + k] == '1':
155 while s < ncols and mc_info[l*ncols + s] == '2':
157 if s < ncols and mc_info[l*ncols + s] != '1':
158 r = set_option(document, m, 'rightline', col_info[k][1])
159 if k > 0 and mc_info[l*ncols + k - 1] == '0':
160 r = set_option(document, m, 'leftline', col_info[k][0])
165 def revert_tablines(document):
168 i = find_token(document.body, "\\begin_inset Tabular", i)
171 j = find_end_of_inset(document.body, i + 1)
173 document.warning("Malformed LyX document: Could not find end of tabular.")
177 nrows = int(document.body[i+1].split('"')[3])
178 ncols = int(document.body[i+1].split('"')[5])
181 for k in range(nrows*ncols):
182 m = find_token(document.body, "<cell", m)
183 top = get_option(document, m, 'topline', 'false')
184 bottom = get_option(document, m, 'bottomline', 'false')
185 left = get_option(document, m, 'leftline', 'false')
186 right = get_option(document, m, 'rightline', 'false')
187 lines.append([top, bottom, left, right])
192 for k in range(ncols):
193 m = find_token(document.body, "<column", m)
195 for l in range(nrows):
196 left = lines[k*ncols + k][2]
199 set_option(document, m, 'leftline', left)
201 for l in range(nrows):
202 right = lines[k*ncols + k][3]
205 set_option(document, m, 'rightline', right)
209 for k in range(nrows):
210 m = find_token(document.body, "<row", m)
212 for l in range(ncols):
213 top = lines[k*ncols + l][0]
216 set_option(document, m, 'topline', top)
218 for l in range(ncols):
219 bottom = lines[k*ncols + l][1]
220 if bottom == 'false':
222 set_option(document, m, 'bottomline', bottom)
228 def fix_wrong_tables(document):
231 i = find_token(document.body, "\\begin_inset Tabular", i)
234 j = find_end_of_inset(document.body, i + 1)
236 document.warning("Malformed LyX document: Could not find end of tabular.")
240 nrows = int(document.body[i+1].split('"')[3])
241 ncols = int(document.body[i+1].split('"')[5])
243 for l in range(nrows):
245 for k in range(ncols):
246 m = find_token(document.body, '<cell', m)
248 if document.body[m].find('multicolumn') != -1:
249 multicol_cont = int(document.body[m].split('"')[1])
251 if multicol_cont == 2 and (k == 0 or prev_multicolumn == 0):
252 document.body[m] = document.body[m][:5] + document.body[m][21:]
255 prev_multicolumn = multicol_cont
262 def close_begin_deeper(document):
266 i = find_tokens(document.body, ["\\begin_deeper", "\\end_deeper"], i)
271 if document.body[i][:13] == "\\begin_deeper":
278 document.body[-2:-2] = ['\\end_deeper' for i in range(depth)]
281 def long_charstyle_names(document):
284 i = find_token(document.body, "\\begin_inset CharStyle", i)
287 document.body[i] = document.body[i].replace("CharStyle ", "CharStyle CharStyle:")
290 def revert_long_charstyle_names(document):
293 i = find_token(document.body, "\\begin_inset CharStyle", i)
296 document.body[i] = document.body[i].replace("CharStyle CharStyle:", "CharStyle")
300 def axe_show_label(document):
303 i = find_token(document.body, "\\begin_inset CharStyle", i)
306 if document.body[i + 1].find("show_label") != -1:
307 if document.body[i + 1].find("true") != -1:
308 document.body[i + 1] = "status open"
309 del document.body[ i + 2]
311 if document.body[i + 1].find("false") != -1:
312 document.body[i + 1] = "status collapsed"
313 del document.body[ i + 2]
315 document.warning("Malformed LyX document: show_label neither false nor true.")
317 document.warning("Malformed LyX document: show_label missing in CharStyle.")
322 def revert_show_label(document):
325 i = find_token(document.body, "\\begin_inset CharStyle", i)
328 if document.body[i + 1].find("status open") != -1:
329 document.body.insert(i + 1, "show_label true")
331 if document.body[i + 1].find("status collapsed") != -1:
332 document.body.insert(i + 1, "show_label false")
334 document.warning("Malformed LyX document: no legal status line in CharStyle.")
337 def revert_begin_modules(document):
340 i = find_token(document.header, "\\begin_modules", i)
343 j = find_end_of(document.header, i, "\\begin_modules", "\\end_modules")
345 # this should not happen
347 document.header[i : j + 1] = []
349 def convert_flex(document):
350 "Convert CharStyle to Flex"
353 i = find_token(document.body, "\\begin_inset CharStyle", i)
356 document.body[i] = document.body[i].replace('\\begin_inset CharStyle', '\\begin_inset Flex')
358 def revert_flex(document):
359 "Convert Flex to CharStyle"
362 i = find_token(document.body, "\\begin_inset Flex", i)
365 document.body[i] = document.body[i].replace('\\begin_inset Flex', '\\begin_inset CharStyle')
368 # Discard PDF options for hyperref
369 def revert_pdf_options(document):
370 "Revert PDF options for hyperref."
371 # store the PDF options and delete the entries from the Lyx file
379 bookmarksnumbered = ""
381 bookmarksopenlevel = ""
389 i = find_token(document.header, "\\use_hyperref", i)
391 hyperref = get_value(document.header, "\\use_hyperref", i) == 'true'
392 del document.header[i]
393 i = find_token(document.header, "\\pdf_store_options", i)
395 del document.header[i]
396 i = find_token(document.header, "\\pdf_title", 0)
398 title = get_value_string(document.header, '\\pdf_title', 0, 0, True)
399 title = ' pdftitle={' + title + '}'
400 del document.header[i]
401 i = find_token(document.header, "\\pdf_author", 0)
403 author = get_value_string(document.header, '\\pdf_author', 0, 0, True)
405 author = ' pdfauthor={' + author + '}'
407 author = ',\n pdfauthor={' + author + '}'
408 del document.header[i]
409 i = find_token(document.header, "\\pdf_subject", 0)
411 subject = get_value_string(document.header, '\\pdf_subject', 0, 0, True)
412 if title == "" and author == "":
413 subject = ' pdfsubject={' + subject + '}'
415 subject = ',\n pdfsubject={' + subject + '}'
416 del document.header[i]
417 i = find_token(document.header, "\\pdf_keywords", 0)
419 keywords = get_value_string(document.header, '\\pdf_keywords', 0, 0, True)
420 if title == "" and author == "" and subject == "":
421 keywords = ' pdfkeywords={' + keywords + '}'
423 keywords = ',\n pdfkeywords={' + keywords + '}'
424 del document.header[i]
425 i = find_token(document.header, "\\pdf_bookmarks", 0)
427 bookmarks = get_value_string(document.header, '\\pdf_bookmarks', 0)
428 bookmarks = ',\n bookmarks=' + bookmarks
429 del document.header[i]
430 i = find_token(document.header, "\\pdf_bookmarksnumbered", i)
432 bookmarksnumbered = get_value_string(document.header, '\\pdf_bookmarksnumbered', 0)
433 bookmarksnumbered = ',\n bookmarksnumbered=' + bookmarksnumbered
434 del document.header[i]
435 i = find_token(document.header, "\\pdf_bookmarksopen", i)
437 bookmarksopen = get_value_string(document.header, '\\pdf_bookmarksopen', 0)
438 bookmarksopen = ',\n bookmarksopen=' + bookmarksopen
439 del document.header[i]
440 i = find_token(document.header, "\\pdf_bookmarksopenlevel", i)
442 bookmarksopenlevel = get_value_string(document.header, '\\pdf_bookmarksopenlevel', 0, 0, True)
443 bookmarksopenlevel = ',\n bookmarksopenlevel=' + bookmarksopenlevel
444 del document.header[i]
445 i = find_token(document.header, "\\pdf_breaklinks", i)
447 breaklinks = get_value_string(document.header, '\\pdf_breaklinks', 0)
448 breaklinks = ',\n breaklinks=' + breaklinks
449 del document.header[i]
450 i = find_token(document.header, "\\pdf_pdfborder", i)
452 pdfborder = get_value_string(document.header, '\\pdf_pdfborder', 0)
453 if pdfborder == 'true':
454 pdfborder = ',\n pdfborder={0 0 0}'
456 pdfborder = ',\n pdfborder={0 0 1}'
457 del document.header[i]
458 i = find_token(document.header, "\\pdf_colorlinks", i)
460 colorlinks = get_value_string(document.header, '\\pdf_colorlinks', 0)
461 colorlinks = ',\n colorlinks=' + colorlinks
462 del document.header[i]
463 i = find_token(document.header, "\\pdf_backref", i)
465 backref = get_value_string(document.header, '\\pdf_backref', 0)
466 backref = ',\n backref=' + backref
467 del document.header[i]
468 i = find_token(document.header, "\\pdf_pagebackref", i)
470 pagebackref = get_value_string(document.header, '\\pdf_pagebackref', 0)
471 pagebackref = ',\n pagebackref=' + pagebackref
472 del document.header[i]
473 i = find_token(document.header, "\\pdf_pagemode", 0)
475 pagemode = get_value_string(document.header, '\\pdf_pagemode', 0)
476 pagemode = ',\n pdfpagemode=' + pagemode
477 del document.header[i]
478 i = find_token(document.header, "\\pdf_quoted_options", 0)
480 otheroptions = get_value_string(document.header, '\\pdf_quoted_options', 0, 0, True)
481 if title == "" and author == "" and subject == "" and keywords == "":
482 otheroptions = ' ' + otheroptions
484 otheroptions = ',\n ' + otheroptions
485 del document.header[i]
487 # write to the preamble when hyperref was used
489 # preamble write preparations
490 # bookmark numbers are only output when they are turned on
491 if bookmarksopen == ',\n bookmarksopen=true':
492 bookmarksopen = bookmarksopen + bookmarksopenlevel
493 if bookmarks == ',\n bookmarks=true':
494 bookmarks = bookmarks + bookmarksnumbered + bookmarksopen
496 bookmarks = bookmarks
497 # hypersetup is only output when there are things to be set up
498 setupstart = '\\hypersetup{%\n'
500 if otheroptions == "" and title == "" and author == ""\
501 and subject == "" and keywords == "":
505 add_to_preamble(document,
506 ['% Commands inserted by lyx2lyx for PDF properties',
507 '\\usepackage[unicode=true'
526 def remove_inzip_options(document):
527 "Remove inzipName and embed options from the Graphics inset"
530 i = find_token(document.body, "\\begin_inset Graphics", i)
533 j = find_end_of_inset(document.body, i + 1)
536 document.warning("Malformed LyX document: Could not find end of graphics inset.")
537 # If there's a inzip param, just remove that
538 k = find_token(document.body, "\tinzipName", i + 1, j)
541 # embed option must follow the inzipName option
542 del document.body[k+1]
546 def convert_inset_command(document):
549 \begin_inset LatexCommand cmd
551 \begin_inset CommandInset InsetType
556 i = find_token(document.body, "\\begin_inset LatexCommand", i)
559 line = document.body[i]
560 r = re.compile(r'\\begin_inset LatexCommand (.*)$')
564 #this is adapted from factory.cpp
565 if cmdName[0:4].lower() == "cite":
566 insetName = "citation"
567 elif cmdName == "url" or cmdName == "htmlurl":
569 elif cmdName[-3:] == "ref":
571 elif cmdName == "tableofcontents":
573 elif cmdName == "printnomenclature":
574 insetName = "nomencl_print"
575 elif cmdName == "printindex":
576 insetName = "index_print"
579 insertion = ["\\begin_inset CommandInset " + insetName, "LatexCommand " + cmdName]
580 document.body[i : i+1] = insertion
583 def revert_inset_command(document):
586 \begin_inset CommandInset InsetType
589 \begin_inset LatexCommand cmd
590 Some insets may end up being converted to insets earlier versions of LyX
591 will not be able to recognize. Not sure what to do about that.
595 i = find_token(document.body, "\\begin_inset CommandInset", i)
598 nextline = document.body[i+1]
599 r = re.compile(r'LatexCommand\s+(.*)$')
600 m = r.match(nextline)
602 document.warning("Malformed LyX document: Missing LatexCommand in " + document.body[i] + ".")
605 insertion = ["\\begin_inset LatexCommand " + cmdName]
606 document.body[i : i+2] = insertion
609 def convert_wrapfig_options(document):
610 "Convert optional options for wrap floats (wrapfig)."
611 # adds the tokens "lines", "placement", and "overhang"
614 i = find_token(document.body, "\\begin_inset Wrap figure", i)
617 document.body.insert(i + 1, "lines 0")
618 j = find_token(document.body, "placement", i)
619 # placement can be already set or not; if not, set it
621 document.body.insert(i + 3, "overhang 0col%")
623 document.body.insert(i + 2, "placement o")
624 document.body.insert(i + 3, "overhang 0col%")
628 def revert_wrapfig_options(document):
629 "Revert optional options for wrap floats (wrapfig)."
632 i = find_token(document.body, "lines", i)
635 j = find_token(document.body, "overhang", i+1)
636 if j != i + 2 and j != -1:
637 document.warning("Malformed LyX document: Couldn't find overhang parameter of wrap float.")
641 del document.body[j-1]
645 def convert_latexcommand_index(document):
646 "Convert from LatexCommand form to collapsable form."
649 i = find_token(document.body, "\\begin_inset CommandInset index", i)
652 if document.body[i + 1] != "LatexCommand index": # Might also be index_print
654 fullcontent = document.body[i + 2][6:].strip('"')
655 document.body[i:i + 2] = ["\\begin_inset Index",
657 "\\begin_layout Standard"]
658 # Put here the conversions needed from LaTeX string to LyXText.
659 # Here we do a minimal conversion to prevent crashes and data loss.
660 # Manual patch-up may be needed.
661 # Umlauted characters (most common ones, can be extended):
662 fullcontent = fullcontent.replace(r'\\\"a', u'ä').replace(r'\\\"o', u'ö').replace(r'\\\"u', u'ü')
664 fullcontent = wrap_into_ert(fullcontent, r'\"', '"')
665 #fullcontent = fullcontent.replace(r'\"', '\n\\begin_inset ERT\nstatus collapsed\n\\begin_layout standard\n"\n\\end_layout\n\\end_inset\n')
667 r = re.compile('^(.*?)(\$.*?\$)(.*)')
672 f = m.group(2).replace('\\\\', '\\')
676 s = wrap_into_ert(s, r'\\', '\\backslash')
677 s = wrap_into_ert(s, '{', '{')
678 s = wrap_into_ert(s, '}', '}')
679 document.body.insert(i + 3, s)
681 document.body.insert(i + 3, "\\begin_inset Formula " + f)
682 document.body.insert(i + 4, "\\end_inset")
684 # Generic, \\ -> \backslash:
685 g = wrap_into_ert(g, r'\\', '\\backslash{}')
686 g = wrap_into_ert(g, '{', '{')
687 g = wrap_into_ert(g, '}', '}')
688 document.body.insert(i + 3, g)
689 document.body[i + 4] = "\\end_layout"
693 def revert_latexcommand_index(document):
694 "Revert from collapsable form to LatexCommand form."
697 i = find_token(document.body, "\\begin_inset Index", i)
700 j = find_end_of_inset(document.body, i + 1)
703 del document.body[j - 1]
704 del document.body[j - 2] # \end_layout
705 document.body[i] = "\\begin_inset CommandInset index"
706 document.body[i + 1] = "LatexCommand index"
707 # clean up multiline stuff
709 for k in range(i + 3, j - 2):
710 line = document.body[k]
711 if line.startswith("\\begin_inset ERT"):
713 if line.startswith("\\begin_inset Formula"):
715 if line.startswith("\\begin_layout Standard"):
717 if line.startswith("\\begin_layout Plain"):
719 if line.startswith("\\end_layout"):
721 if line.startswith("\\end_inset"):
723 if line.startswith("status collapsed"):
725 line = line.replace(u'ä', r'\\\"a').replace(u'ö', r'\\\"o').replace(u'ü', r'\\\"u')
726 content = content + line;
727 document.body[i + 3] = "name " + '"' + content + '"'
728 for k in range(i + 4, j - 2):
729 del document.body[i + 4]
730 document.body.insert(i + 4, "")
731 del document.body[i + 2] # \begin_layout standard
735 def revert_wraptable(document):
736 "Revert wrap table to wrap figure."
739 i = find_token(document.body, "\\begin_inset Wrap table", i)
742 document.body[i] = document.body[i].replace('\\begin_inset Wrap table', '\\begin_inset Wrap figure')
746 def revert_vietnamese(document):
747 "Set language Vietnamese to English"
748 # Set document language from Vietnamese to English
750 if document.language == "vietnamese":
751 document.language = "english"
752 i = find_token(document.header, "\\language", 0)
754 document.header[i] = "\\language english"
757 j = find_token(document.body, "\\lang vietnamese", j)
760 document.body[j] = document.body[j].replace("\\lang vietnamese", "\\lang english")
764 def revert_japanese(document):
765 "Set language japanese-plain to japanese"
766 # Set document language from japanese-plain to japanese
768 if document.language == "japanese-plain":
769 document.language = "japanese"
770 i = find_token(document.header, "\\language", 0)
772 document.header[i] = "\\language japanese"
775 j = find_token(document.body, "\\lang japanese-plain", j)
778 document.body[j] = document.body[j].replace("\\lang japanese-plain", "\\lang japanese")
782 def revert_japanese_encoding(document):
783 "Set input encoding form EUC-JP-plain to EUC-JP etc."
784 # Set input encoding form EUC-JP-plain to EUC-JP etc.
786 i = find_token(document.header, "\\inputencoding EUC-JP-plain", 0)
788 document.header[i] = "\\inputencoding EUC-JP"
790 j = find_token(document.header, "\\inputencoding JIS-plain", 0)
792 document.header[j] = "\\inputencoding JIS"
794 k = find_token(document.header, "\\inputencoding SJIS-plain", 0)
795 if k != -1: # convert to UTF8 since there is currently no SJIS encoding
796 document.header[k] = "\\inputencoding UTF8"
799 def revert_inset_info(document):
800 'Replace info inset with its content'
803 i = find_token(document.body, '\\begin_inset Info', i)
806 j = find_end_of_inset(document.body, i + 1)
809 document.warning("Malformed LyX document: Could not find end of Info inset.")
812 for k in range(i, j+1):
813 if document.body[k].startswith("arg"):
814 arg = document.body[k][3:].strip().strip('"')
815 if document.body[k].startswith("type"):
816 type = document.body[k][4:].strip().strip('"')
817 # I think there is a newline after \\end_inset, which should be removed.
818 if document.body[j + 1].strip() == "":
819 document.body[i : (j + 2)] = [type + ':' + arg]
821 document.body[i : (j + 1)] = [type + ':' + arg]
824 def convert_pdf_options(document):
825 # Set the pdfusetitle tag, delete the pdf_store_options,
826 # set quotes for bookmarksopenlevel"
827 has_hr = get_value(document.header, "\\use_hyperref", 0, default = "0")
829 k = find_token(document.header, "\\use_hyperref", 0)
830 document.header.insert(k + 1, "\\pdf_pdfusetitle true")
831 k = find_token(document.header, "\\pdf_store_options", 0)
833 del document.header[k]
834 i = find_token(document.header, "\\pdf_bookmarksopenlevel", k)
836 document.header[i] = document.header[i].replace('"', '')
839 def revert_pdf_options_2(document):
840 # reset the pdfusetitle tag, set quotes for bookmarksopenlevel"
841 k = find_token(document.header, "\\use_hyperref", 0)
842 i = find_token(document.header, "\\pdf_pdfusetitle", k)
844 del document.header[i]
845 i = find_token(document.header, "\\pdf_bookmarksopenlevel", k)
847 values = document.header[i].split()
848 values[1] = ' "' + values[1] + '"'
849 document.header[i] = ''.join(values)
852 def convert_htmlurl(document):
853 'Convert "htmlurl" to "href" insets for docbook'
854 if document.backend != "docbook":
858 i = find_token(document.body, "\\begin_inset CommandInset url", i)
861 document.body[i] = "\\begin_inset CommandInset href"
862 document.body[i + 1] = "LatexCommand href"
866 def convert_url(document):
867 'Convert url insets to url charstyles'
868 if document.backend == "docbook":
872 i = find_token(document.body, "\\begin_inset CommandInset url", i)
875 n = find_token(document.body, "name", i)
877 # place the URL name in typewriter before the new URL insert
878 # grab the name 'bla' from the e.g. the line 'name "bla"',
879 # therefore start with the 6th character
880 name = document.body[n][6:-1]
881 newname = [name + " "]
882 document.body[i:i] = newname
884 j = find_token(document.body, "target", i)
886 document.warning("Malformed LyX document: Can't find target for url inset")
889 target = document.body[j][8:-1]
890 k = find_token(document.body, "\\end_inset", j)
892 document.warning("Malformed LyX document: Can't find end of url inset")
895 newstuff = ["\\begin_inset Flex URL",
896 "status collapsed", "",
897 "\\begin_layout Standard",
902 document.body[i:k] = newstuff
905 def convert_ams_classes(document):
906 tc = document.textclass
907 if (tc != "amsart" and tc != "amsart-plain" and
908 tc != "amsart-seq" and tc != "amsbook"):
910 if tc == "amsart-plain":
911 document.textclass = "amsart"
912 document.set_textclass()
913 document.add_module("Theorems (Starred)")
915 if tc == "amsart-seq":
916 document.textclass = "amsart"
917 document.set_textclass()
918 document.add_module("Theorems (AMS)")
920 #Now we want to see if any of the environments in the extended theorems
921 #module were used in this document. If so, we'll add that module, too.
922 layouts = ["Criterion", "Algorithm", "Axiom", "Condition", "Note", \
923 "Notation", "Summary", "Acknowledgement", "Conclusion", "Fact", \
926 r = re.compile(r'^\\begin_layout (.*?)\*?\s*$')
929 i = find_token(document.body, "\\begin_layout", i)
932 m = r.match(document.body[i])
934 document.warning("Weirdly formed \\begin_layout at line %d of body!" % i)
938 if layouts.count(m) != 0:
939 document.add_module("Theorems (AMS-Extended)")
943 def revert_href(document):
944 'Reverts hyperlink insets (href) to url insets (url)'
947 i = find_token(document.body, "\\begin_inset CommandInset href", i)
950 document.body[i : i + 2] = \
951 ["\\begin_inset CommandInset url", "LatexCommand url"]
955 def convert_include(document):
956 'Converts include insets to new format.'
958 r = re.compile(r'\\begin_inset Include\s+\\([^{]+){([^}]*)}(?:\[(.*)\])?')
960 i = find_token(document.body, "\\begin_inset Include", i)
963 line = document.body[i]
964 previewline = document.body[i + 1]
967 document.warning("Unable to match line " + str(i) + " of body!")
973 insertion = ["\\begin_inset CommandInset include",
974 "LatexCommand " + cmd, previewline,
975 "filename \"" + fn + "\""]
978 insertion.append("lstparams " + '"' + opt + '"')
980 document.body[i : i + 2] = insertion
984 def revert_include(document):
985 'Reverts include insets to old format.'
987 r1 = re.compile('LatexCommand (.+)')
988 r2 = re.compile('filename (.+)')
989 r3 = re.compile('options (.*)')
991 i = find_token(document.body, "\\begin_inset CommandInset include", i)
994 previewline = document.body[i + 1]
995 m = r1.match(document.body[i + 2])
997 document.warning("Malformed LyX document: No LatexCommand line for `" +
998 document.body[i] + "' on line " + str(i) + ".")
1002 m = r2.match(document.body[i + 3])
1004 document.warning("Malformed LyX document: No filename line for `" + \
1005 document.body[i] + "' on line " + str(i) + ".")
1011 if (cmd == "lstinputlisting"):
1012 m = r3.match(document.body[i + 4])
1014 options = m.group(1)
1016 newline = "\\begin_inset Include \\" + cmd + "{" + fn + "}"
1018 newline += ("[" + options + "]")
1019 insertion = [newline, previewline]
1020 document.body[i : i + numlines] = insertion
1024 def revert_albanian(document):
1025 "Set language Albanian to English"
1027 if document.language == "albanian":
1028 document.language = "english"
1029 i = find_token(document.header, "\\language", 0)
1031 document.header[i] = "\\language english"
1034 j = find_token(document.body, "\\lang albanian", j)
1037 document.body[j] = document.body[j].replace("\\lang albanian", "\\lang english")
1041 def revert_lowersorbian(document):
1042 "Set language lower Sorbian to English"
1044 if document.language == "lowersorbian":
1045 document.language = "english"
1046 i = find_token(document.header, "\\language", 0)
1048 document.header[i] = "\\language english"
1051 j = find_token(document.body, "\\lang lowersorbian", j)
1054 document.body[j] = document.body[j].replace("\\lang lowersorbian", "\\lang english")
1058 def revert_uppersorbian(document):
1059 "Set language uppersorbian to usorbian as this was used in LyX 1.5"
1061 if document.language == "uppersorbian":
1062 document.language = "usorbian"
1063 i = find_token(document.header, "\\language", 0)
1065 document.header[i] = "\\language usorbian"
1068 j = find_token(document.body, "\\lang uppersorbian", j)
1071 document.body[j] = document.body[j].replace("\\lang uppersorbian", "\\lang usorbian")
1075 def convert_usorbian(document):
1076 "Set language usorbian to uppersorbian"
1078 if document.language == "usorbian":
1079 document.language = "uppersorbian"
1080 i = find_token(document.header, "\\language", 0)
1082 document.header[i] = "\\language uppersorbian"
1085 j = find_token(document.body, "\\lang usorbian", j)
1088 document.body[j] = document.body[j].replace("\\lang usorbian", "\\lang uppersorbian")
1092 def revert_macro_optional_params(document):
1093 "Convert macro definitions with optional parameters into ERTs"
1094 # Stub to convert macro definitions with one or more optional parameters
1095 # into uninterpreted ERT insets
1098 def revert_hyperlinktype(document):
1099 'Reverts hyperlink type'
1103 i = find_token(document.body, "target", i)
1106 j = find_token(document.body, "type", i)
1110 del document.body[j]
1114 def revert_pagebreak(document):
1115 'Reverts pagebreak to ERT'
1118 i = find_token(document.body, "\\pagebreak", i)
1121 document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1122 '\\begin_layout Standard\n\n\n\\backslash\n' \
1123 'pagebreak{}\n\\end_layout\n\n\\end_inset\n\n'
1127 def revert_linebreak(document):
1128 'Reverts linebreak to ERT'
1131 i = find_token(document.body, "\\linebreak", i)
1134 document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1135 '\\begin_layout Standard\n\n\n\\backslash\n' \
1136 'linebreak{}\n\\end_layout\n\n\\end_inset\n\n'
1140 def revert_latin(document):
1141 "Set language Latin to English"
1143 if document.language == "latin":
1144 document.language = "english"
1145 i = find_token(document.header, "\\language", 0)
1147 document.header[i] = "\\language english"
1150 j = find_token(document.body, "\\lang latin", j)
1153 document.body[j] = document.body[j].replace("\\lang latin", "\\lang english")
1157 def revert_samin(document):
1158 "Set language North Sami to English"
1160 if document.language == "samin":
1161 document.language = "english"
1162 i = find_token(document.header, "\\language", 0)
1164 document.header[i] = "\\language english"
1167 j = find_token(document.body, "\\lang samin", j)
1170 document.body[j] = document.body[j].replace("\\lang samin", "\\lang english")
1174 def convert_serbocroatian(document):
1175 "Set language Serbocroatian to Croatian as this was really Croatian in LyX 1.5"
1177 if document.language == "serbocroatian":
1178 document.language = "croatian"
1179 i = find_token(document.header, "\\language", 0)
1181 document.header[i] = "\\language croatian"
1184 j = find_token(document.body, "\\lang serbocroatian", j)
1187 document.body[j] = document.body[j].replace("\\lang serbocroatian", "\\lang croatian")
1191 def convert_framed_notes(document):
1192 "Convert framed notes to boxes. "
1195 i = find_tokens(document.body, ["\\begin_inset Note Framed", "\\begin_inset Note Shaded"], i)
1199 document.body[i] = document.body[i].replace("\\begin_inset Note", "\\begin_inset Box")
1200 document.body.insert(i + 1, 'position "t"\nhor_pos "c"\nhas_inner_box 0\ninner_pos "t"\n' \
1201 'use_parbox 0\nwidth "100col%"\nspecial "none"\nheight "1in"\n' \
1202 'height_special "totalheight"')
1206 def convert_module_names(document):
1207 modulemap = { 'Braille' : 'braille', 'Endnote' : 'endnotes', 'Foot to End' : 'foottoend',\
1208 'Hanging' : 'hanging', 'Linguistics' : 'linguistics', 'Logical Markup' : 'logicalmkup', \
1209 'Theorems (AMS-Extended)' : 'theorems-ams-extended', 'Theorems (AMS)' : 'theorems-ams', \
1210 'Theorems (Order By Chapter)' : 'theorems-chap', 'Theorems (Order By Section)' : 'theorems-sec', \
1211 'Theorems (Starred)' : 'theorems-starred', 'Theorems' : 'theorems-std' }
1212 modlist = document.get_module_list()
1213 if len(modlist) == 0:
1217 if modulemap.has_key(mod):
1218 newmodlist.append(modulemap[mod])
1220 document.warning("Can't find module %s in the module map!" % mod)
1221 newmodlist.append(mod)
1222 document.set_module_list(newmodlist)
1225 def revert_module_names(document):
1226 modulemap = { 'braille' : 'Braille', 'endnotes' : 'Endnote', 'foottoend' : 'Foot to End',\
1227 'hanging' : 'Hanging', 'linguistics' : 'Linguistics', 'logicalmkup' : 'Logical Markup', \
1228 'theorems-ams-extended' : 'Theorems (AMS-Extended)', 'theorems-ams' : 'Theorems (AMS)', \
1229 'theorems-chap' : 'Theorems (Order By Chapter)', 'theorems-sec' : 'Theorems (Order By Section)', \
1230 'theorems-starred' : 'Theorems (Starred)', 'theorems-std' : 'Theorems'}
1231 modlist = document.get_module_list()
1232 if len(modlist) == 0:
1236 if modulemap.has_key(mod):
1237 newmodlist.append(modulemap[mod])
1239 document.warning("Can't find module %s in the module map!" % mod)
1240 newmodlist.append(mod)
1241 document.set_module_list(newmodlist)
1244 def revert_colsep(document):
1245 i = find_token(document.header, "\\columnsep", 0)
1248 colsepline = document.header[i]
1249 r = re.compile(r'\\columnsep (.*)')
1250 m = r.match(colsepline)
1252 document.warning("Malformed column separation line!")
1255 del document.header[i]
1256 #it seems to be safe to add the package even if it is already used
1257 pretext = ["\\usepackage{geometry}", "\\geometry{columnsep=" + colsep + "}"]
1259 add_to_preamble(document, pretext)
1262 def revert_framed_notes(document):
1263 "Revert framed boxes to notes. "
1266 i = find_tokens(document.body, ["\\begin_inset Box Framed", "\\begin_inset Box Shaded"], i)
1270 j = find_end_of_inset(document.body, i + 1)
1273 document.warning("Malformed LyX document: Could not find end of Box inset.")
1274 k = find_token(document.body, "status", i + 1, j)
1276 document.warning("Malformed LyX document: Missing `status' tag in Box inset.")
1278 status = document.body[k]
1279 l = find_token(document.body, "\\begin_layout Standard", i + 1, j)
1281 l = find_token(document.body, "\\begin_layout Plain", i + 1, j)
1283 document.warning("Malformed LyX document: Missing `\\begin_layout' in Box inset.")
1285 m = find_token(document.body, "\\end_layout", i + 1, j)
1287 document.warning("Malformed LyX document: Missing `\\end_layout' in Box inset.")
1289 ibox = find_token(document.body, "has_inner_box 1", i + 1, k)
1290 pbox = find_token(document.body, "use_parbox 1", i + 1, k)
1291 if ibox == -1 and pbox == -1:
1292 document.body[i] = document.body[i].replace("\\begin_inset Box", "\\begin_inset Note")
1293 del document.body[i+1:k]
1295 document.body[i] = document.body[i].replace("\\begin_inset Box Shaded", "\\begin_inset Box Frameless")
1296 document.body.insert(l + 1, "\\begin_inset Note Shaded\n" + status + "\n\\begin_layout Standard\n")
1297 document.body.insert(m + 1, "\\end_layout\n\\end_inset")
1301 def revert_slash(document):
1302 'Revert \\SpecialChar \\slash{} to ERT'
1303 for i in range(len(document.body)):
1304 document.body[i] = document.body[i].replace('\\SpecialChar \\slash{}', \
1305 '\\begin_inset ERT\nstatus collapsed\n\n' \
1306 '\\begin_layout Standard\n\n\n\\backslash\n' \
1307 'slash{}\n\\end_layout\n\n\\end_inset\n\n')
1310 def revert_nobreakdash(document):
1311 'Revert \\SpecialChar \\nobreakdash- to ERT'
1313 for i in range(len(document.body)):
1314 line = document.body[i]
1315 r = re.compile(r'\\SpecialChar \\nobreakdash-')
1319 document.body[i] = document.body[i].replace('\\SpecialChar \\nobreakdash-', \
1320 '\\begin_inset ERT\nstatus collapsed\n\n' \
1321 '\\begin_layout Standard\n\n\n\\backslash\n' \
1322 'nobreakdash-\n\\end_layout\n\n\\end_inset\n\n')
1325 j = find_token(document.header, "\\use_amsmath", 0)
1327 document.warning("Malformed LyX document: Missing '\\use_amsmath'.")
1329 document.header[j] = "\\use_amsmath 2"
1332 def revert_nocite_key(body, start, end):
1333 'key "..." -> \nocite{...}'
1334 for i in range(start, end):
1335 if (body[i][0:5] == 'key "'):
1336 body[i] = body[i].replace('key "', "\\backslash\nnocite{")
1337 body[i] = body[i].replace('"', "}")
1342 def revert_nocite(document):
1343 "Revert LatexCommand nocite to ERT"
1346 i = find_token(document.body, "\\begin_inset CommandInset citation", i)
1350 if (document.body[i] == "LatexCommand nocite"):
1351 j = find_end_of_inset(document.body, i + 1)
1353 #this should not happen
1354 document.warning("End of CommandInset citation not found in revert_nocite!")
1355 revert_nocite_key(document.body, i + 1, len(document.body))
1357 revert_nocite_key(document.body, i + 1, j)
1358 document.body[i-1] = "\\begin_inset ERT"
1359 document.body[i] = "status collapsed\n\n" \
1360 "\\begin_layout Standard"
1361 document.body.insert(j, "\\end_layout\n");
1365 def revert_btprintall(document):
1366 "Revert (non-bibtopic) btPrintAll option to ERT \nocite{*}"
1367 i = find_token(document.header, '\\use_bibtopic', 0)
1369 document.warning("Malformed lyx document: Missing '\\use_bibtopic'.")
1371 if get_value(document.header, '\\use_bibtopic', 0) == "false":
1373 while i < len(document.body):
1374 i = find_token(document.body, "\\begin_inset CommandInset bibtex", i)
1377 j = find_end_of_inset(document.body, i + 1)
1379 #this should not happen
1380 document.warning("End of CommandInset bibtex not found in revert_btprintall!")
1381 j = len(document.body)
1382 for k in range(i, j):
1383 if (document.body[k] == 'btprint "btPrintAll"'):
1384 del document.body[k]
1385 document.body.insert(i, "\\begin_inset ERT\n" \
1386 "status collapsed\n\n\\begin_layout Standard\n\n" \
1387 "\\backslash\nnocite{*}\n" \
1388 "\\end_layout\n\\end_inset\n")
1392 def revert_bahasam(document):
1393 "Set language Bahasa Malaysia to Bahasa Indonesia"
1395 if document.language == "bahasam":
1396 document.language = "bahasa"
1397 i = find_token(document.header, "\\language", 0)
1399 document.header[i] = "\\language bahasa"
1402 j = find_token(document.body, "\\lang bahasam", j)
1405 document.body[j] = document.body[j].replace("\\lang bahasam", "\\lang bahasa")
1409 def revert_interlingua(document):
1410 "Set language Interlingua to English"
1412 if document.language == "interlingua":
1413 document.language = "english"
1414 i = find_token(document.header, "\\language", 0)
1416 document.header[i] = "\\language english"
1419 j = find_token(document.body, "\\lang interlingua", j)
1422 document.body[j] = document.body[j].replace("\\lang interlingua", "\\lang english")
1426 def revert_serbianlatin(document):
1427 "Set language Serbian-Latin to Croatian"
1429 if document.language == "serbian-latin":
1430 document.language = "croatian"
1431 i = find_token(document.header, "\\language", 0)
1433 document.header[i] = "\\language croatian"
1436 j = find_token(document.body, "\\lang serbian-latin", j)
1439 document.body[j] = document.body[j].replace("\\lang serbian-latin", "\\lang croatian")
1443 def revert_rotfloat(document):
1444 " Revert sideways custom floats. "
1447 i = find_token(document.body, "\\begin_inset Float", i)
1450 line = document.body[i]
1451 r = re.compile(r'\\begin_inset Float (.*)$')
1453 floattype = m.group(1)
1454 if floattype == "figure" or floattype == "table":
1457 j = find_end_of_inset(document.body, i)
1459 document.warning("Malformed lyx document: Missing '\\end_inset'.")
1462 if get_value(document.body, 'sideways', i, j) != "false":
1463 l = find_token(document.body, "\\begin_layout Standard", i + 1, j)
1465 l = find_token(document.body, "\\begin_layout Plain", i + 1, j)
1467 document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
1469 document.body[j] = '\\begin_layout Standard\n\\begin_inset ERT\nstatus collapsed\n\n' \
1470 '\\begin_layout Standard\n\n\n\\backslash\n' \
1471 'end{sideways' + floattype + '}\n\\end_layout\n\n\\end_inset\n'
1472 del document.body[i+1:l-1]
1473 document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1474 '\\begin_layout Standard\n\n\n\\backslash\n' \
1475 'begin{sideways' + floattype + '}\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n\n'
1476 if floattype == "algorithm":
1477 add_to_preamble(document,
1478 ['% Commands inserted by lyx2lyx for sideways algorithm float',
1479 '\\usepackage{rotfloat}\n'
1480 '\\floatstyle{ruled}\n'
1481 '\\newfloat{algorithm}{tbp}{loa}\n'
1482 '\\floatname{algorithm}{Algorithm}\n'])
1484 document.warning("Cannot create preamble definition for custom float" + floattype + ".")
1490 def revert_widesideways(document):
1491 " Revert wide sideways floats. "
1494 i = find_token(document.body, '\\begin_inset Float', i)
1497 line = document.body[i]
1498 r = re.compile(r'\\begin_inset Float (.*)$')
1500 floattype = m.group(1)
1501 if floattype != "figure" and floattype != "table":
1504 j = find_end_of_inset(document.body, i)
1506 document.warning("Malformed lyx document: Missing '\\end_inset'.")
1509 if get_value(document.body, 'sideways', i, j) != "false":
1510 if get_value(document.body, 'wide', i, j) != "false":
1511 l = find_token(document.body, "\\begin_layout Standard", i + 1, j)
1513 l = find_token(document.body, "\\begin_layout Plain", i + 1, j)
1515 document.warning("Malformed LyX document: Missing `\\begin_layout' in Float inset.")
1517 document.body[j] = '\\begin_layout Standard\n\\begin_inset ERT\nstatus collapsed\n\n' \
1518 '\\begin_layout Standard\n\n\n\\backslash\n' \
1519 'end{sideways' + floattype + '*}\n\\end_layout\n\n\\end_inset\n'
1520 del document.body[i+1:l-1]
1521 document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1522 '\\begin_layout Standard\n\n\n\\backslash\n' \
1523 'begin{sideways' + floattype + '*}\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n\n'
1524 add_to_preamble(document,
1525 ['\\usepackage{rotfloat}\n'])
1531 def revert_external_embedding(document):
1532 ' Remove embed tag from external inset '
1535 i = find_token(document.body, "\\begin_inset External", i)
1538 j = find_end_of_inset(document.body, i)
1540 document.warning("Malformed lyx document: Missing '\\end_inset'.")
1543 k = find_token(document.body, "\tembed", i, j)
1545 del document.body[k]
1549 def convert_subfig(document):
1550 " Convert subfigures to subfloats. "
1553 i = find_token(document.body, '\\begin_inset Graphics', i)
1556 j = find_end_of_inset(document.body, i)
1558 document.warning("Malformed lyx document: Missing '\\end_inset'.")
1561 k = find_token(document.body, '\tsubcaption', i, j)
1565 l = find_token(document.body, '\tsubcaptionText', i, j)
1566 caption = document.body[l][16:].strip('"')
1567 savestr = document.body[i]
1568 del document.body[l]
1569 del document.body[k]
1570 document.body[i] = '\\begin_inset Float figure\nwide false\nsideways false\n' \
1571 'status open\n\n\\begin_layout Plain Layout\n\\begin_inset Caption\n\n\\begin_layout Plain Layout\n' \
1572 + caption + '\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n\n\\begin_layout Plain Layout\n' + savestr
1573 savestr = document.body[j]
1574 document.body[j] = '\n\\end_layout\n\n\\end_inset\n' + savestr
1577 def revert_subfig(document):
1578 " Revert subfloats. "
1581 i = find_token(document.body, '\\begin_inset Float', i)
1585 j = find_end_of_inset(document.body, i)
1587 document.warning("Malformed lyx document: Missing '\\end_inset' (float).")
1590 # look for embedded float (= subfloat)
1591 k = find_token(document.body, '\\begin_inset Float', i + 1, j)
1594 l = find_end_of_inset(document.body, k)
1596 document.warning("Malformed lyx document: Missing '\\end_inset' (embedded float).")
1599 m = find_token(document.body, "\\begin_layout Plain Layout", k + 1, l)
1601 cap = find_token(document.body, '\\begin_inset Caption', k + 1, l)
1605 capend = find_end_of_inset(document.body, cap)
1607 document.warning("Malformed lyx document: Missing '\\end_inset' (caption).")
1611 lbl = find_token(document.body, '\\begin_inset CommandInset label', cap, capend)
1613 lblend = find_end_of_inset(document.body, lbl + 1)
1615 document.warning("Malformed lyx document: Missing '\\end_inset' (label).")
1617 for line in document.body[lbl:lblend + 1]:
1618 if line.startswith('name '):
1619 label = line.split()[1].strip('"')
1626 opt = find_token(document.body, '\\begin_inset OptArg', cap, capend)
1628 optend = find_end_of_inset(document.body, opt)
1630 document.warning("Malformed lyx document: Missing '\\end_inset' (OptArg).")
1632 optc = find_token(document.body, "\\begin_layout Plain Layout", opt, optend)
1634 document.warning("Malformed LyX document: Missing `\\begin_layout Plain Layout' in Float inset.")
1636 optcend = find_end_of(document.body, optc, "\\begin_layout", "\\end_layout")
1637 for line in document.body[optc:optcend]:
1638 if not line.startswith('\\'):
1639 shortcap += line.strip()
1643 for line in document.body[cap:capend]:
1644 if line in document.body[lbl:lblend]:
1646 elif line in document.body[opt:optend]:
1648 elif not line.startswith('\\'):
1649 caption += line.strip()
1651 caption += "\\backslash\nlabel{" + label + "}"
1652 document.body[l] = '\\begin_layout Plain Layout\n\\begin_inset ERT\nstatus collapsed\n\n' \
1653 '\\begin_layout Plain Layout\n\n}\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n\n\\begin_layout Plain Layout\n'
1654 del document.body[cap:capend+1]
1655 del document.body[k+1:m-1]
1656 insertion = '\\begin_inset ERT\nstatus collapsed\n\n' \
1657 '\\begin_layout Plain Layout\n\n\\backslash\n' \
1659 if len(shortcap) > 0:
1660 insertion = insertion + "[" + shortcap + "]"
1661 if len(caption) > 0:
1662 insertion = insertion + "[" + caption + "]"
1663 insertion = insertion + '{%\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n'
1664 document.body[k] = insertion
1665 add_to_preamble(document,
1666 ['\\usepackage{subfig}\n'])
1670 def revert_wrapplacement(document):
1671 " Revert placement options wrap floats (wrapfig). "
1674 i = find_token(document.body, "lines", i)
1677 j = find_token(document.body, "placement", i+1)
1679 document.warning("Malformed LyX document: Couldn't find placement parameter of wrap float.")
1681 document.body[j] = document.body[j].replace("placement O", "placement o")
1682 document.body[j] = document.body[j].replace("placement I", "placement i")
1683 document.body[j] = document.body[j].replace("placement L", "placement l")
1684 document.body[j] = document.body[j].replace("placement R", "placement r")
1688 def remove_extra_embedded_files(document):
1689 " Remove \extra_embedded_files from buffer params "
1690 i = find_token(document.header, '\\extra_embedded_files', 0)
1692 document.warning("Malformed lyx document: Missing '\\extra_embedded_files'.")
1694 document.header.pop(i)
1697 def convert_spaceinset(document):
1698 " Convert '\\InsetSpace foo' to '\\begin_inset Space foo\n\\end_inset' "
1699 for i in range(len(document.body)):
1700 if re.search(r'\InsetSpace', document.body[i]):
1701 document.body[i] = document.body[i].replace('\\InsetSpace', '\n\\begin_inset Space')
1702 document.body[i] = document.body[i] + "\n\\end_inset"
1705 def revert_spaceinset(document):
1706 " Revert '\\begin_inset Space foo\n\\end_inset' to '\\InsetSpace foo' "
1709 i = find_token(document.body, "\\begin_inset Space", i)
1712 j = find_end_of_inset(document.body, i)
1714 document.warning("Malformed LyX document: Could not find end of space inset.")
1716 document.body[i] = document.body[i].replace('\\begin_inset Space', '\\InsetSpace')
1717 del document.body[j]
1720 def convert_hfill(document):
1721 " Convert hfill to space inset "
1724 i = find_token(document.body, "\\hfill", i)
1727 document.body[i] = document.body[i].replace('\\hfill', '\n\\begin_inset Space \\hfill{}\n\\end_inset')
1730 def revert_hfills(document):
1731 ' Revert \\hfill commands '
1732 for i in range(len(document.body)):
1733 document.body[i] = document.body[i].replace('\\InsetSpace \\hfill{}', '\\hfill')
1734 document.body[i] = document.body[i].replace('\\InsetSpace \\dotfill{}', \
1735 '\\begin_inset ERT\nstatus collapsed\n\n' \
1736 '\\begin_layout Standard\n\n\n\\backslash\n' \
1737 'dotfill{}\n\\end_layout\n\n\\end_inset\n\n')
1738 document.body[i] = document.body[i].replace('\\InsetSpace \\hrulefill{}', \
1739 '\\begin_inset ERT\nstatus collapsed\n\n' \
1740 '\\begin_layout Standard\n\n\n\\backslash\n' \
1741 'hrulefill{}\n\\end_layout\n\n\\end_inset\n\n')
1744 def revert_hspace(document):
1745 ' Revert \\InsetSpace \\hspace{} to ERT '
1748 i = find_token(document.body, "\\InsetSpace \\hspace", i)
1751 length = get_value(document.body, '\\length', i+1)
1753 document.warning("Malformed lyx document: Missing '\\length' in Space inset.")
1755 del document.body[i+1]
1756 document.body[i] = document.body[i].replace('\\InsetSpace \\hspace*{}', \
1757 '\\begin_inset ERT\nstatus collapsed\n\n' \
1758 '\\begin_layout Standard\n\n\n\\backslash\n' \
1759 'hspace*{' + length + '}\n\\end_layout\n\n\\end_inset\n\n')
1760 document.body[i] = document.body[i].replace('\\InsetSpace \\hspace{}', \
1761 '\\begin_inset ERT\nstatus collapsed\n\n' \
1762 '\\begin_layout Standard\n\n\n\\backslash\n' \
1763 'hspace{' + length + '}\n\\end_layout\n\n\\end_inset\n\n')
1766 def revert_protected_hfill(document):
1767 ' Revert \\begin_inset Space \\hspace*{\\fill} to ERT '
1770 i = find_token(document.body, '\\begin_inset Space \\hspace*{\\fill}', i)
1773 j = find_end_of_inset(document.body, i)
1775 document.warning("Malformed LyX document: Could not find end of space inset.")
1777 del document.body[j]
1778 document.body[i] = document.body[i].replace('\\begin_inset Space \\hspace*{\\fill}', \
1779 '\\begin_inset ERT\nstatus collapsed\n\n' \
1780 '\\begin_layout Standard\n\n\n\\backslash\n' \
1781 'hspace*{\n\\backslash\nfill}\n\\end_layout\n\n\\end_inset\n\n')
1784 def revert_local_layout(document):
1785 ' Revert local layout headers.'
1788 i = find_token(document.header, "\\begin_local_layout", i)
1791 j = find_end_of(document.header, i, "\\begin_local_layout", "\\end_local_layout")
1793 # this should not happen
1795 document.header[i : j + 1] = []
1798 def convert_pagebreaks(document):
1799 ' Convert inline Newpage insets to new format '
1802 i = find_token(document.body, '\\newpage', i)
1805 document.body[i:i+1] = ['\\begin_inset Newpage newpage',
1809 i = find_token(document.body, '\\pagebreak', i)
1812 document.body[i:i+1] = ['\\begin_inset Newpage pagebreak',
1816 i = find_token(document.body, '\\clearpage', i)
1819 document.body[i:i+1] = ['\\begin_inset Newpage clearpage',
1823 i = find_token(document.body, '\\cleardoublepage', i)
1826 document.body[i:i+1] = ['\\begin_inset Newpage cleardoublepage',
1830 def revert_pagebreaks(document):
1831 ' Revert \\begin_inset Newpage to previous inline format '
1834 i = find_token(document.body, '\\begin_inset Newpage', i)
1837 j = find_end_of_inset(document.body, i)
1839 document.warning("Malformed LyX document: Could not find end of Newpage inset.")
1841 del document.body[j]
1842 document.body[i] = document.body[i].replace('\\begin_inset Newpage newpage', '\\newpage')
1843 document.body[i] = document.body[i].replace('\\begin_inset Newpage pagebreak', '\\pagebreak')
1844 document.body[i] = document.body[i].replace('\\begin_inset Newpage clearpage', '\\clearpage')
1845 document.body[i] = document.body[i].replace('\\begin_inset Newpage cleardoublepage', '\\cleardoublepage')
1848 def convert_linebreaks(document):
1849 ' Convert inline Newline insets to new format '
1852 i = find_token(document.body, '\\newline', i)
1855 document.body[i:i+1] = ['\\begin_inset Newline newline',
1859 i = find_token(document.body, '\\linebreak', i)
1862 document.body[i:i+1] = ['\\begin_inset Newline linebreak',
1866 def revert_linebreaks(document):
1867 ' Revert \\begin_inset Newline to previous inline format '
1870 i = find_token(document.body, '\\begin_inset Newline', i)
1873 j = find_end_of_inset(document.body, i)
1875 document.warning("Malformed LyX document: Could not find end of Newline inset.")
1877 del document.body[j]
1878 document.body[i] = document.body[i].replace('\\begin_inset Newline newline', '\\newline')
1879 document.body[i] = document.body[i].replace('\\begin_inset Newline linebreak', '\\linebreak')
1882 def convert_japanese_plain(document):
1883 ' Set language japanese-plain to japanese '
1885 if document.language == "japanese-plain":
1886 document.language = "japanese"
1887 i = find_token(document.header, "\\language", 0)
1889 document.header[i] = "\\language japanese"
1892 j = find_token(document.body, "\\lang japanese-plain", j)
1895 document.body[j] = document.body[j].replace("\\lang japanese-plain", "\\lang japanese")
1899 def revert_pdfpages(document):
1900 ' Revert pdfpages external inset to ERT '
1903 i = find_token(document.body, "\\begin_inset External", i)
1906 j = find_end_of_inset(document.body, i)
1908 document.warning("Malformed lyx document: Missing '\\end_inset'.")
1911 if get_value(document.body, 'template', i, j) == "PDFPages":
1912 filename = get_value(document.body, 'filename', i, j)
1914 r = re.compile(r'\textra PDFLaTeX \"(.*)\"$')
1915 for k in range(i, j):
1916 m = r.match(document.body[k])
1919 angle = get_value(document.body, 'rotateAngle', i, j)
1920 width = get_value(document.body, 'width', i, j)
1921 height = get_value(document.body, 'height', i, j)
1922 scale = get_value(document.body, 'scale', i, j)
1923 keepAspectRatio = find_token(document.body, "\tkeepAspectRatio", i, j)
1927 options += ",angle=" + angle
1929 options += "angle=" + angle
1932 options += ",width=" + convert_len(width)
1934 options += "width=" + convert_len(width)
1937 options += ",height=" + convert_len(height)
1939 options += "height=" + convert_len(height)
1942 options += ",scale=" + scale
1944 options += "scale=" + scale
1945 if keepAspectRatio != '':
1947 options += ",keepaspectratio"
1949 options += "keepaspectratio"
1951 options = '[' + options + ']'
1952 del document.body[i+1:j+1]
1953 document.body[i:i+1] = ['\\begin_inset ERT',
1956 '\\begin_layout Standard',
1959 'includepdf' + options + '{' + filename + '}',
1963 add_to_preamble(document, ['\\usepackage{pdfpages}\n'])
1973 supported_versions = ["1.6.0","1.6"]
1974 convert = [[277, [fix_wrong_tables]],
1975 [278, [close_begin_deeper]],
1976 [279, [long_charstyle_names]],
1977 [280, [axe_show_label]],
1980 [283, [convert_flex]],
1984 [287, [convert_wrapfig_options]],
1985 [288, [convert_inset_command]],
1986 [289, [convert_latexcommand_index]],
1991 [294, [convert_pdf_options]],
1992 [295, [convert_htmlurl, convert_url]],
1993 [296, [convert_include]],
1994 [297, [convert_usorbian]],
2000 [303, [convert_serbocroatian]],
2001 [304, [convert_framed_notes]],
2008 [311, [convert_ams_classes]],
2010 [313, [convert_module_names]],
2013 [316, [convert_subfig]],
2016 [319, [convert_spaceinset, convert_hfill]],
2018 [321, [convert_tablines]],
2020 [323, [convert_pagebreaks]],
2021 [324, [convert_linebreaks]],
2022 [325, [convert_japanese_plain]],
2026 revert = [[325, [revert_pdfpages]],
2028 [323, [revert_linebreaks]],
2029 [322, [revert_pagebreaks]],
2030 [321, [revert_local_layout]],
2031 [320, [revert_tablines]],
2032 [319, [revert_protected_hfill]],
2033 [318, [revert_spaceinset, revert_hfills, revert_hspace]],
2034 [317, [remove_extra_embedded_files]],
2035 [316, [revert_wrapplacement]],
2036 [315, [revert_subfig]],
2037 [314, [revert_colsep]],
2039 [312, [revert_module_names]],
2040 [311, [revert_rotfloat, revert_widesideways]],
2041 [310, [revert_external_embedding]],
2042 [309, [revert_btprintall]],
2043 [308, [revert_nocite]],
2044 [307, [revert_serbianlatin]],
2045 [306, [revert_slash, revert_nobreakdash]],
2046 [305, [revert_interlingua]],
2047 [304, [revert_bahasam]],
2048 [303, [revert_framed_notes]],
2050 [301, [revert_latin, revert_samin]],
2051 [300, [revert_linebreak]],
2052 [299, [revert_pagebreak]],
2053 [298, [revert_hyperlinktype]],
2054 [297, [revert_macro_optional_params]],
2055 [296, [revert_albanian, revert_lowersorbian, revert_uppersorbian]],
2056 [295, [revert_include]],
2057 [294, [revert_href]],
2058 [293, [revert_pdf_options_2]],
2059 [292, [revert_inset_info]],
2060 [291, [revert_japanese, revert_japanese_encoding]],
2061 [290, [revert_vietnamese]],
2062 [289, [revert_wraptable]],
2063 [288, [revert_latexcommand_index]],
2064 [287, [revert_inset_command]],
2065 [286, [revert_wrapfig_options]],
2066 [285, [revert_pdf_options]],
2067 [284, [remove_inzip_options]],
2069 [282, [revert_flex]],
2071 [280, [revert_begin_modules]],
2072 [279, [revert_show_label]],
2073 [278, [revert_long_charstyle_names]],
2079 if __name__ == "__main__":