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
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 ####################################################################
50 def fix_wrong_tables(document):
53 i = find_token(document.body, "\\begin_inset Tabular", i)
56 j = find_end_of_inset(document.body, i + 1)
58 document.warning("Malformed LyX document: Could not find end of tabular.")
62 nrows = int(document.body[i+1].split('"')[3])
63 ncols = int(document.body[i+1].split('"')[5])
65 for l in range(nrows):
67 for k in range(ncols):
68 m = find_token(document.body, '<cell', m)
70 if document.body[m].find('multicolumn') != -1:
71 multicol_cont = int(document.body[m].split('"')[1])
73 if multicol_cont == 2 and (k == 0 or prev_multicolumn == 0):
74 document.body[m] = document.body[m][:5] + document.body[m][21:]
77 prev_multicolumn = multicol_cont
84 def close_begin_deeper(document):
88 i = find_tokens(document.body, ["\\begin_deeper", "\\end_deeper"], i)
93 if document.body[i][:13] == "\\begin_deeper":
100 document.body[-2:-2] = ['\\end_deeper' for i in range(depth)]
103 def long_charstyle_names(document):
106 i = find_token(document.body, "\\begin_inset CharStyle", i)
109 document.body[i] = document.body[i].replace("CharStyle ", "CharStyle CharStyle:")
112 def revert_long_charstyle_names(document):
115 i = find_token(document.body, "\\begin_inset CharStyle", i)
118 document.body[i] = document.body[i].replace("CharStyle CharStyle:", "CharStyle")
122 def axe_show_label(document):
125 i = find_token(document.body, "\\begin_inset CharStyle", i)
128 if document.body[i + 1].find("show_label") != -1:
129 if document.body[i + 1].find("true") != -1:
130 document.body[i + 1] = "status open"
131 del document.body[ i + 2]
133 if document.body[i + 1].find("false") != -1:
134 document.body[i + 1] = "status collapsed"
135 del document.body[ i + 2]
137 document.warning("Malformed LyX document: show_label neither false nor true.")
139 document.warning("Malformed LyX document: show_label missing in CharStyle.")
144 def revert_show_label(document):
147 i = find_token(document.body, "\\begin_inset CharStyle", i)
150 if document.body[i + 1].find("status open") != -1:
151 document.body.insert(i + 1, "show_label true")
153 if document.body[i + 1].find("status collapsed") != -1:
154 document.body.insert(i + 1, "show_label false")
156 document.warning("Malformed LyX document: no legal status line in CharStyle.")
159 def revert_begin_modules(document):
162 i = find_token(document.header, "\\begin_modules", i)
165 j = find_end_of(document.header, i, "\\begin_modules", "\\end_modules")
167 # this should not happen
169 document.header[i : j + 1] = []
171 def convert_flex(document):
172 "Convert CharStyle to Flex"
175 i = find_token(document.body, "\\begin_inset CharStyle", i)
178 document.body[i] = document.body[i].replace('\\begin_inset CharStyle', '\\begin_inset Flex')
180 def revert_flex(document):
181 "Convert Flex to CharStyle"
184 i = find_token(document.body, "\\begin_inset Flex", i)
187 document.body[i] = document.body[i].replace('\\begin_inset Flex', '\\begin_inset CharStyle')
190 # Discard PDF options for hyperref
191 def revert_pdf_options(document):
192 "Revert PDF options for hyperref."
194 i = find_token(document.header, "\\use_hyperref", i)
196 del document.header[i]
197 i = find_token(document.header, "\\pdf_store_options", i)
199 del document.header[i]
200 i = find_token(document.header, "\\pdf_title", 0)
202 del document.header[i]
203 i = find_token(document.header, "\\pdf_author", 0)
205 del document.header[i]
206 i = find_token(document.header, "\\pdf_subject", 0)
208 del document.header[i]
209 i = find_token(document.header, "\\pdf_keywords", 0)
211 del document.header[i]
212 i = find_token(document.header, "\\pdf_bookmarks", 0)
214 del document.header[i]
215 i = find_token(document.header, "\\pdf_bookmarksnumbered", i)
217 del document.header[i]
218 i = find_token(document.header, "\\pdf_bookmarksopen", i)
220 del document.header[i]
221 i = find_token(document.header, "\\pdf_bookmarksopenlevel", i)
223 del document.header[i]
224 i = find_token(document.header, "\\pdf_breaklinks", i)
226 del document.header[i]
227 i = find_token(document.header, "\\pdf_pdfborder", i)
229 del document.header[i]
230 i = find_token(document.header, "\\pdf_colorlinks", i)
232 del document.header[i]
233 i = find_token(document.header, "\\pdf_backref", i)
235 del document.header[i]
236 i = find_token(document.header, "\\pdf_pagebackref", i)
238 del document.header[i]
239 i = find_token(document.header, "\\pdf_pagemode", 0)
241 del document.header[i]
242 i = find_token(document.header, "\\pdf_quoted_options", 0)
244 del document.header[i]
247 def remove_inzip_options(document):
248 "Remove inzipName and embed options from the Graphics inset"
251 i = find_token(document.body, "\\begin_inset Graphics", i)
254 j = find_end_of_inset(document.body, i + 1)
257 document.warning("Malformed LyX document: Could not find end of graphics inset.")
258 # If there's a inzip param, just remove that
259 k = find_token(document.body, "\tinzipName", i + 1, j)
262 # embed option must follow the inzipName option
263 del document.body[k+1]
267 def convert_inset_command(document):
270 \begin_inset LatexCommand cmd
272 \begin_inset CommandInset InsetType
277 i = find_token(document.body, "\\begin_inset LatexCommand", i)
280 line = document.body[i]
281 r = re.compile(r'\\begin_inset LatexCommand (.*)$')
285 #this is adapted from factory.cpp
286 if cmdName[0:4].lower() == "cite":
287 insetName = "citation"
288 elif cmdName == "url" or cmdName == "htmlurl":
290 elif cmdName[-3:] == "ref":
292 elif cmdName == "tableofcontents":
294 elif cmdName == "printnomenclature":
295 insetName = "nomencl_print"
296 elif cmdName == "printindex":
297 insetName = "index_print"
300 insertion = ["\\begin_inset CommandInset " + insetName, "LatexCommand " + cmdName]
301 document.body[i : i+1] = insertion
304 def revert_inset_command(document):
307 \begin_inset CommandInset InsetType
310 \begin_inset LatexCommand cmd
311 Some insets may end up being converted to insets earlier versions of LyX
312 will not be able to recognize. Not sure what to do about that.
316 i = find_token(document.body, "\\begin_inset CommandInset", i)
319 nextline = document.body[i+1]
320 r = re.compile(r'LatexCommand\s+(.*)$')
321 m = r.match(nextline)
323 document.warning("Malformed LyX document: Missing LatexCommand in " + document.body[i] + ".")
326 insertion = ["\\begin_inset LatexCommand " + cmdName]
327 document.body[i : i+2] = insertion
330 def convert_wrapfig_options(document):
331 "Convert optional options for wrap floats (wrapfig)."
332 # adds the tokens "lines", "placement", and "overhang"
335 i = find_token(document.body, "\\begin_inset Wrap figure", i)
338 document.body.insert(i + 1, "lines 0")
339 j = find_token(document.body, "placement", i)
340 # placement can be already set or not; if not, set it
342 document.body.insert(i + 3, "overhang 0col%")
344 document.body.insert(i + 2, "placement o")
345 document.body.insert(i + 3, "overhang 0col%")
349 def revert_wrapfig_options(document):
350 "Revert optional options for wrap floats (wrapfig)."
353 i = find_token(document.body, "lines", i)
356 j = find_token(document.body, "overhang", i+1)
357 if j != i + 2 and j != -1:
358 document.warning("Malformed LyX document: Couldn't find overhang parameter of wrap float.")
362 del document.body[j-1]
366 def convert_latexcommand_index(document):
367 "Convert from LatexCommand form to collapsable form."
370 i = find_token(document.body, "\\begin_inset CommandInset index", i)
373 if document.body[i + 1] != "LatexCommand index": # Might also be index_print
375 fullcontent = document.body[i + 2][6:].strip('"')
376 document.body[i:i + 2] = ["\\begin_inset Index",
378 "\\begin_layout Standard"]
379 # Put here the conversions needed from LaTeX string to LyXText.
380 # Here we do a minimal conversion to prevent crashes and data loss.
381 # Manual patch-up may be needed.
382 # Umlauted characters (most common ones, can be extended):
383 fullcontent = fullcontent.replace(r'\\\"a', u'ä').replace(r'\\\"o', u'ö').replace(r'\\\"u', u'ü')
385 fullcontent = wrap_into_ert(fullcontent, r'\"', '"')
386 #fullcontent = fullcontent.replace(r'\"', '\n\\begin_inset ERT\nstatus collapsed\n\\begin_layout standard\n"\n\\end_layout\n\\end_inset\n')
388 r = re.compile('^(.*?)(\$.*?\$)(.*)')
393 f = m.group(2).replace('\\\\', '\\')
397 s = wrap_into_ert(s, r'\\', '\\backslash')
398 s = wrap_into_ert(s, '{', '{')
399 s = wrap_into_ert(s, '}', '}')
400 document.body.insert(i + 3, s)
402 document.body.insert(i + 3, "\\begin_inset Formula " + f)
403 document.body.insert(i + 4, "\\end_inset")
405 # Generic, \\ -> \backslash:
406 g = wrap_into_ert(g, r'\\', '\\backslash{}')
407 g = wrap_into_ert(g, '{', '{')
408 g = wrap_into_ert(g, '}', '}')
409 document.body.insert(i + 3, g)
410 document.body[i + 4] = "\\end_layout"
414 def revert_latexcommand_index(document):
415 "Revert from collapsable form to LatexCommand form."
418 i = find_token(document.body, "\\begin_inset Index", i)
421 j = find_end_of_inset(document.body, i + 1)
424 del document.body[j - 1]
425 del document.body[j - 2] # \end_layout
426 document.body[i] = "\\begin_inset CommandInset index"
427 document.body[i + 1] = "LatexCommand index"
428 # clean up multiline stuff
430 for k in range(i + 3, j - 2):
431 line = document.body[k]
432 if line.startswith("\\begin_inset ERT"):
434 if line.startswith("\\begin_inset Formula"):
436 if line.startswith("\\begin_layout Standard"):
438 if line.startswith("\\end_layout"):
440 if line.startswith("\\end_inset"):
442 if line.startswith("status collapsed"):
444 line = line.replace(u'ä', r'\\\"a').replace(u'ö', r'\\\"o').replace(u'ü', r'\\\"u')
445 content = content + line;
446 document.body[i + 3] = "name " + '"' + content + '"'
447 for k in range(i + 4, j - 2):
448 del document.body[i + 4]
449 document.body.insert(i + 4, "")
450 del document.body[i + 2] # \begin_layout standard
454 def revert_wraptable(document):
455 "Revert wrap table to wrap figure."
458 i = find_token(document.body, "\\begin_inset Wrap table", i)
461 document.body[i] = document.body[i].replace('\\begin_inset Wrap table', '\\begin_inset Wrap figure')
465 def revert_vietnamese(document):
466 "Set language Vietnamese to English"
467 # Set document language from Vietnamese to English
469 if document.language == "vietnamese":
470 document.language = "english"
471 i = find_token(document.header, "\\language", 0)
473 document.header[i] = "\\language english"
476 j = find_token(document.body, "\\lang vietnamese", j)
479 document.body[j] = document.body[j].replace("\\lang vietnamese", "\\lang english")
483 def revert_japanese(document):
484 "Set language japanese-plain to japanese"
485 # Set document language from japanese-plain to japanese
487 if document.language == "japanese-plain":
488 document.language = "japanese"
489 i = find_token(document.header, "\\language", 0)
491 document.header[i] = "\\language japanese"
494 j = find_token(document.body, "\\lang japanese-plain", j)
497 document.body[j] = document.body[j].replace("\\lang japanese-plain", "\\lang japanese")
501 def revert_japanese_encoding(document):
502 "Set input encoding form EUC-JP-plain to EUC-JP etc."
503 # Set input encoding form EUC-JP-plain to EUC-JP etc.
505 i = find_token(document.header, "\\inputencoding EUC-JP-plain", 0)
507 document.header[i] = "\\inputencoding EUC-JP"
509 j = find_token(document.header, "\\inputencoding JIS-plain", 0)
511 document.header[j] = "\\inputencoding JIS"
513 k = find_token(document.header, "\\inputencoding SJIS-plain", 0)
514 if k != -1: # convert to UTF8 since there is currently no SJIS encoding
515 document.header[k] = "\\inputencoding UTF8"
518 def revert_inset_info(document):
519 'Replace info inset with its content'
522 i = find_token(document.body, '\\begin_inset Info', i)
525 j = find_end_of_inset(document.body, i + 1)
528 document.warning("Malformed LyX document: Could not find end of Info inset.")
531 for k in range(i, j+1):
532 if document.body[k].startswith("arg"):
533 arg = document.body[k][3:].strip().strip('"')
534 if document.body[k].startswith("type"):
535 type = document.body[k][4:].strip().strip('"')
536 # I think there is a newline after \\end_inset, which should be removed.
537 if document.body[j + 1].strip() == "":
538 document.body[i : (j + 2)] = [type + ':' + arg]
540 document.body[i : (j + 1)] = [type + ':' + arg]
543 def convert_pdf_options(document):
544 # Set the pdfusetitle tag, delete the pdf_store_options,
545 # set quotes for bookmarksopenlevel"
546 has_hr = get_value(document.header, "\\use_hyperref", 0, default = "0")
548 k = find_token(document.header, "\\use_hyperref", 0)
549 document.header.insert(k + 1, "\\pdf_pdfusetitle true")
550 k = find_token(document.header, "\\pdf_store_options", 0)
552 del document.header[k]
553 i = find_token(document.header, "\\pdf_bookmarksopenlevel", k)
555 document.header[i] = document.header[i].replace('"', '')
558 def revert_pdf_options_2(document):
559 # reset the pdfusetitle tag, set quotes for bookmarksopenlevel"
560 k = find_token(document.header, "\\use_hyperref", 0)
561 i = find_token(document.header, "\\pdf_pdfusetitle", k)
563 del document.header[i]
564 i = find_token(document.header, "\\pdf_bookmarksopenlevel", k)
566 values = document.header[i].split()
567 values[1] = ' "' + values[1] + '"'
568 document.header[i] = ''.join(values)
571 def convert_htmlurl(document):
572 'Convert "htmlurl" to "href" insets for docbook'
573 if document.backend != "docbook":
577 i = find_token(document.body, "\\begin_inset CommandInset url", i)
580 document.body[i] = "\\begin_inset CommandInset href"
581 document.body[i + 1] = "LatexCommand href"
585 def convert_url(document):
586 'Convert url insets to url charstyles'
587 if document.backend == "docbook":
591 i = find_token(document.body, "\\begin_inset CommandInset url", i)
594 n = find_token(document.body, "name", i)
596 # place the URL name in typewriter before the new URL insert
597 # grab the name 'bla' from the e.g. the line 'name "bla"',
598 # therefore start with the 6th character
599 name = document.body[n][6:-1]
600 newname = [name + " "]
601 document.body[i:i] = newname
603 j = find_token(document.body, "target", i)
605 document.warning("Malformed LyX document: Can't find target for url inset")
608 target = document.body[j][8:-1]
609 k = find_token(document.body, "\\end_inset", j)
611 document.warning("Malformed LyX document: Can't find end of url inset")
614 newstuff = ["\\begin_inset Flex URL",
615 "status collapsed", "",
616 "\\begin_layout Standard",
621 document.body[i:k] = newstuff
624 def convert_ams_classes(document):
625 tc = document.textclass
626 if (tc != "amsart" and tc != "amsart-plain" and
627 tc != "amsart-seq" and tc != "amsbook"):
629 if tc == "amsart-plain":
630 document.textclass = "amsart"
631 document.set_textclass()
632 document.add_module("Theorems (Starred)")
634 if tc == "amsart-seq":
635 document.textclass = "amsart"
636 document.set_textclass()
637 document.add_module("Theorems (AMS)")
639 #Now we want to see if any of the environments in the extended theorems
640 #module were used in this document. If so, we'll add that module, too.
641 layouts = ["Criterion", "Algorithm", "Axiom", "Condition", "Note", \
642 "Notation", "Summary", "Acknowledgement", "Conclusion", "Fact", \
645 r = re.compile(r'^\\begin_layout (.*?)\*?\s*$')
648 i = find_token(document.body, "\\begin_layout", i)
651 m = r.match(document.body[i])
653 document.warning("Weirdly formed \\begin_layout at line " + i + " of body!")
657 if layouts.count(m) != 0:
658 document.add_module("Theorems (AMS-Extended)")
662 def revert_href(document):
663 'Reverts hyperlink insets (href) to url insets (url)'
666 i = find_token(document.body, "\\begin_inset CommandInset href", i)
669 document.body[i : i + 2] = \
670 ["\\begin_inset CommandInset url", "LatexCommand url"]
674 def convert_include(document):
675 'Converts include insets to new format.'
677 r = re.compile(r'\\begin_inset Include\s+\\([^{]+){([^}]*)}(?:\[(.*)\])?')
679 i = find_token(document.body, "\\begin_inset Include", i)
682 line = document.body[i]
683 previewline = document.body[i + 1]
686 document.warning("Unable to match line " + str(i) + " of body!")
692 insertion = ["\\begin_inset CommandInset include",
693 "LatexCommand " + cmd, previewline,
694 "filename \"" + fn + "\""]
697 insertion.append("lstparams " + '"' + opt + '"')
699 document.body[i : i + 2] = insertion
703 def revert_include(document):
704 'Reverts include insets to old format.'
706 r1 = re.compile('LatexCommand (.+)')
707 r2 = re.compile('filename (.+)')
708 r3 = re.compile('options (.*)')
710 i = find_token(document.body, "\\begin_inset CommandInset include", i)
713 previewline = document.body[i + 1]
714 m = r1.match(document.body[i + 2])
716 document.warning("Malformed LyX document: No LatexCommand line for `" +
717 document.body[i] + "' on line " + str(i) + ".")
721 m = r2.match(document.body[i + 3])
723 document.warning("Malformed LyX document: No filename line for `" + \
724 document.body[i] + "' on line " + str(i) + ".")
730 if (cmd == "lstinputlisting"):
731 m = r3.match(document.body[i + 4])
735 newline = "\\begin_inset Include \\" + cmd + "{" + fn + "}"
737 newline += ("[" + options + "]")
738 insertion = [newline, previewline]
739 document.body[i : i + numlines] = insertion
743 def revert_albanian(document):
744 "Set language Albanian to English"
746 if document.language == "albanian":
747 document.language = "english"
748 i = find_token(document.header, "\\language", 0)
750 document.header[i] = "\\language english"
753 j = find_token(document.body, "\\lang albanian", j)
756 document.body[j] = document.body[j].replace("\\lang albanian", "\\lang english")
760 def revert_lowersorbian(document):
761 "Set language lower Sorbian to English"
763 if document.language == "lowersorbian":
764 document.language = "english"
765 i = find_token(document.header, "\\language", 0)
767 document.header[i] = "\\language english"
770 j = find_token(document.body, "\\lang lowersorbian", j)
773 document.body[j] = document.body[j].replace("\\lang lowersorbian", "\\lang english")
777 def revert_uppersorbian(document):
778 "Set language uppersorbian to usorbian as this was used in LyX 1.5"
780 if document.language == "uppersorbian":
781 document.language = "usorbian"
782 i = find_token(document.header, "\\language", 0)
784 document.header[i] = "\\language usorbian"
787 j = find_token(document.body, "\\lang uppersorbian", j)
790 document.body[j] = document.body[j].replace("\\lang uppersorbian", "\\lang usorbian")
794 def convert_usorbian(document):
795 "Set language usorbian to uppersorbian"
797 if document.language == "usorbian":
798 document.language = "uppersorbian"
799 i = find_token(document.header, "\\language", 0)
801 document.header[i] = "\\language uppersorbian"
804 j = find_token(document.body, "\\lang usorbian", j)
807 document.body[j] = document.body[j].replace("\\lang usorbian", "\\lang uppersorbian")
811 def revert_macro_optional_params(document):
812 "Convert macro definitions with optional parameters into ERTs"
813 # Stub to convert macro definitions with one or more optional parameters
814 # into uninterpreted ERT insets
817 def revert_hyperlinktype(document):
818 'Reverts hyperlink type'
822 i = find_token(document.body, "target", i)
825 j = find_token(document.body, "type", i)
833 def revert_pagebreak(document):
834 'Reverts pagebreak to ERT'
837 i = find_token(document.body, "\\pagebreak", i)
840 document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
841 '\\begin_layout Standard\n\n\n\\backslash\n' \
842 'pagebreak{}\n\\end_layout\n\n\\end_inset\n\n'
846 def revert_linebreak(document):
847 'Reverts linebreak to ERT'
850 i = find_token(document.body, "\\linebreak", i)
853 document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
854 '\\begin_layout Standard\n\n\n\\backslash\n' \
855 'linebreak{}\n\\end_layout\n\n\\end_inset\n\n'
859 def revert_latin(document):
860 "Set language Latin to English"
862 if document.language == "latin":
863 document.language = "english"
864 i = find_token(document.header, "\\language", 0)
866 document.header[i] = "\\language english"
869 j = find_token(document.body, "\\lang latin", j)
872 document.body[j] = document.body[j].replace("\\lang latin", "\\lang english")
876 def revert_samin(document):
877 "Set language North Sami to English"
879 if document.language == "samin":
880 document.language = "english"
881 i = find_token(document.header, "\\language", 0)
883 document.header[i] = "\\language english"
886 j = find_token(document.body, "\\lang samin", j)
889 document.body[j] = document.body[j].replace("\\lang samin", "\\lang english")
893 def convert_serbocroatian(document):
894 "Set language Serbocroatian to Croatian as this was really Croatian in LyX 1.5"
896 if document.language == "serbocroatian":
897 document.language = "croatian"
898 i = find_token(document.header, "\\language", 0)
900 document.header[i] = "\\language croatian"
903 j = find_token(document.body, "\\lang serbocroatian", j)
906 document.body[j] = document.body[j].replace("\\lang serbocroatian", "\\lang croatian")
910 def convert_framed_notes(document):
911 "Convert framed notes to boxes. "
914 i = find_tokens(document.body, ["\\begin_inset Note Framed", "\\begin_inset Note Shaded"], i)
918 document.body[i] = document.body[i].replace("\\begin_inset Note", "\\begin_inset Box")
919 document.body.insert(i + 1, 'position "t"\nhor_pos "c"\nhas_inner_box 0\ninner_pos "t"\n' \
920 'use_parbox 0\nwidth "100col%"\nspecial "none"\nheight "1in"\n' \
921 'height_special "totalheight"')
925 def convert_module_names(document):
926 modulemap = { 'Braille' : 'braille', 'Endnote' : 'endnotes', 'Foot to End' : 'foottoend',\
927 'Hanging' : 'hanging', 'Linguistics' : 'linguistics', 'Logical Markup' : 'logicalmkup', \
928 'Theorems (AMS-Extended)' : 'theorems-ams-extended', 'Theorems (AMS)' : 'theorems-ams', \
929 'Theorems (Order By Chapter)' : 'theorems-chap', 'Theorems (Order By Section)' : 'theorems-sec', \
930 'Theorems (Starred)' : 'theorems-starred', 'Theorems' : 'theorems-std' }
931 modlist = document.get_module_list()
932 if len(modlist) == 0:
936 if modulemap.has_key(mod):
937 newmodlist.append(modulemap[mod])
939 document.warning("Can't find module %s in the module map!" % mod)
940 newmodlist.append(mod)
941 document.set_module_list(newmodlist)
944 def revert_module_names(document):
945 modulemap = { 'braille' : 'Braille', 'endnotes' : 'Endnote', 'foottoend' : 'Foot to End',\
946 'hanging' : 'Hanging', 'linguistics' : 'Linguistics', 'logicalmkup' : 'Logical Markup', \
947 'theorems-ams-extended' : 'Theorems (AMS-Extended)', 'theorems-ams' : 'Theorems (AMS)', \
948 'theorems-chap' : 'Theorems (Order By Chapter)', 'theorems-sec' : 'Theorems (Order By Section)', \
949 'theorems-starred' : 'Theorems (Starred)', 'theorems-std' : 'Theorems'}
950 modlist = document.get_module_list()
951 if len(modlist) == 0:
955 if modulemap.has_key(mod):
956 newmodlist.append(modulemap[mod])
958 document.warning("Can't find module %s in the module map!" % mod)
959 newmodlist.append(mod)
960 document.set_module_list(newmodlist)
963 def revert_colsep(document):
964 i = find_token(document.header, "\\columnsep", 0)
967 colsepline = document.header[i]
968 r = re.compile(r'\\columnsep (.*)')
969 m = r.match(colsepline)
971 document.warning("Malformed column separation line!")
974 del document.header[i]
975 #it seems to be safe to add the package even if it is already used
976 pretext = ["\\usepackage{geometry}", "\\geometry{columnsep=" + colsep + "}"]
978 add_to_preamble(document, pretext)
981 def revert_framed_notes(document):
982 "Revert framed boxes to notes. "
985 i = find_tokens(document.body, ["\\begin_inset Box Framed", "\\begin_inset Box Shaded"], i)
989 j = find_end_of_inset(document.body, i + 1)
992 document.warning("Malformed LyX document: Could not find end of Box inset.")
993 k = find_token(document.body, "status", i + 1, j)
995 document.warning("Malformed LyX document: Missing `status' tag in Box inset.")
997 status = document.body[k]
998 l = find_token(document.body, "\\begin_layout Standard", i + 1, j)
1000 document.warning("Malformed LyX document: Missing `\\begin_layout Standard' in Box inset.")
1002 m = find_token(document.body, "\\end_layout", i + 1, j)
1004 document.warning("Malformed LyX document: Missing `\\end_layout' in Box inset.")
1006 ibox = find_token(document.body, "has_inner_box 1", i + 1, k)
1007 pbox = find_token(document.body, "use_parbox 1", i + 1, k)
1008 if ibox == -1 and pbox == -1:
1009 document.body[i] = document.body[i].replace("\\begin_inset Box", "\\begin_inset Note")
1010 del document.body[i+1:k]
1012 document.body[i] = document.body[i].replace("\\begin_inset Box Shaded", "\\begin_inset Box Frameless")
1013 document.body.insert(l + 1, "\\begin_inset Note Shaded\n" + status + "\n\\begin_layout Standard\n")
1014 document.body.insert(m + 1, "\\end_layout\n\\end_inset")
1018 def revert_slash(document):
1019 'Revert \\SpecialChar \\slash{} to ERT'
1020 for i in range(len(document.body)):
1021 document.body[i] = document.body[i].replace('\\SpecialChar \\slash{}', \
1022 '\\begin_inset ERT\nstatus collapsed\n\n' \
1023 '\\begin_layout Standard\n\n\n\\backslash\n' \
1024 'slash{}\n\\end_layout\n\n\\end_inset\n\n')
1027 def revert_nobreakdash(document):
1028 'Revert \\SpecialChar \\nobreakdash- to ERT'
1030 for i in range(len(document.body)):
1031 line = document.body[i]
1032 r = re.compile(r'\\SpecialChar \\nobreakdash-')
1036 document.body[i] = document.body[i].replace('\\SpecialChar \\nobreakdash-', \
1037 '\\begin_inset ERT\nstatus collapsed\n\n' \
1038 '\\begin_layout Standard\n\n\n\\backslash\n' \
1039 'nobreakdash-\n\\end_layout\n\n\\end_inset\n\n')
1042 j = find_token(document.header, "\\use_amsmath", 0)
1044 document.warning("Malformed LyX document: Missing '\\use_amsmath'.")
1046 document.header[j] = "\\use_amsmath 2"
1049 def revert_nocite_key(body, start, end):
1050 'key "..." -> \nocite{...}'
1051 for i in range(start, end):
1052 if (body[i][0:5] == 'key "'):
1053 body[i] = body[i].replace('key "', "\\backslash\nnocite{")
1054 body[i] = body[i].replace('"', "}")
1059 def revert_nocite(document):
1060 "Revert LatexCommand nocite to ERT"
1063 i = find_token(document.body, "\\begin_inset CommandInset citation", i)
1067 if (document.body[i] == "LatexCommand nocite"):
1068 j = find_end_of_inset(document.body, i + 1)
1070 #this should not happen
1071 document.warning("End of CommandInset citation not found in revert_nocite!")
1072 revert_nocite_key(document.body, i + 1, len(document.body))
1074 revert_nocite_key(document.body, i + 1, j)
1075 document.body[i-1] = "\\begin_inset ERT"
1076 document.body[i] = "status collapsed\n\n" \
1077 "\\begin_layout Standard"
1078 document.body.insert(j, "\\end_layout\n");
1082 def revert_btprintall(document):
1083 "Revert (non-bibtopic) btPrintAll option to ERT \nocite{*}"
1084 i = find_token(document.header, '\\use_bibtopic', 0)
1086 document.warning("Malformed lyx document: Missing '\\use_bibtopic'.")
1088 if get_value(document.header, '\\use_bibtopic', 0) == "false":
1090 while i < len(document.body):
1091 i = find_token(document.body, "\\begin_inset CommandInset bibtex", i)
1094 j = find_end_of_inset(document.body, i + 1)
1096 #this should not happen
1097 document.warning("End of CommandInset bibtex not found in revert_btprintall!")
1098 j = len(document.body)
1099 for k in range(i, j):
1100 if (document.body[k] == 'btprint "btPrintAll"'):
1101 del document.body[k]
1102 document.body.insert(i, "\\begin_inset ERT\n" \
1103 "status collapsed\n\n\\begin_layout Standard\n\n" \
1104 "\\backslash\nnocite{*}\n" \
1105 "\\end_layout\n\\end_inset\n")
1109 def revert_bahasam(document):
1110 "Set language Bahasa Malaysia to Bahasa Indonesia"
1112 if document.language == "bahasam":
1113 document.language = "bahasa"
1114 i = find_token(document.header, "\\language", 0)
1116 document.header[i] = "\\language bahasa"
1119 j = find_token(document.body, "\\lang bahasam", j)
1122 document.body[j] = document.body[j].replace("\\lang bahasam", "\\lang bahasa")
1126 def revert_interlingua(document):
1127 "Set language Interlingua to English"
1129 if document.language == "interlingua":
1130 document.language = "english"
1131 i = find_token(document.header, "\\language", 0)
1133 document.header[i] = "\\language english"
1136 j = find_token(document.body, "\\lang interlingua", j)
1139 document.body[j] = document.body[j].replace("\\lang interlingua", "\\lang english")
1143 def revert_serbianlatin(document):
1144 "Set language Serbian-Latin to Croatian"
1146 if document.language == "serbian-latin":
1147 document.language = "croatian"
1148 i = find_token(document.header, "\\language", 0)
1150 document.header[i] = "\\language croatian"
1153 j = find_token(document.body, "\\lang serbian-latin", j)
1156 document.body[j] = document.body[j].replace("\\lang serbian-latin", "\\lang croatian")
1160 def revert_rotfloat(document):
1161 " Revert sideways custom floats. "
1164 i = find_token(document.body, "\\begin_inset Float", i)
1167 line = document.body[i]
1168 r = re.compile(r'\\begin_inset Float (.*)$')
1170 floattype = m.group(1)
1171 if floattype == "figure" or floattype == "table":
1174 j = find_end_of_inset(document.body, i)
1176 document.warning("Malformed lyx document: Missing '\\end_inset'.")
1179 if get_value(document.body, 'sideways', i, j) != "false":
1180 l = find_token(document.body, "\\begin_layout Standard", i + 1, j)
1182 document.warning("Malformed LyX document: Missing `\\begin_layout Standard' in Float inset.")
1184 document.body[j] = '\\begin_layout Standard\n\\begin_inset ERT\nstatus collapsed\n\n' \
1185 '\\begin_layout Standard\n\n\n\\backslash\n' \
1186 'end{sideways' + floattype + '}\n\\end_layout\n\n\\end_inset\n'
1187 del document.body[i+1:l-1]
1188 document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1189 '\\begin_layout Standard\n\n\n\\backslash\n' \
1190 'begin{sideways' + floattype + '}\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n\n'
1191 if floattype == "algorithm":
1192 add_to_preamble(document,
1193 ['% Commands inserted by lyx2lyx for sideways algorithm float',
1194 '\\usepackage{rotfloat}\n'
1195 '\\floatstyle{ruled}\n'
1196 '\\newfloat{algorithm}{tbp}{loa}\n'
1197 '\\floatname{algorithm}{Algorithm}\n'])
1199 document.warning("Cannot create preamble definition for custom float" + floattype + ".")
1205 def revert_widesideways(document):
1206 " Revert wide sideways floats. "
1209 i = find_token(document.body, '\\begin_inset Float', i)
1212 line = document.body[i]
1213 r = re.compile(r'\\begin_inset Float (.*)$')
1215 floattype = m.group(1)
1216 if floattype != "figure" and floattype != "table":
1219 j = find_end_of_inset(document.body, i)
1221 document.warning("Malformed lyx document: Missing '\\end_inset'.")
1224 if get_value(document.body, 'sideways', i, j) != "false":
1225 if get_value(document.body, 'wide', i, j) != "false":
1226 l = find_token(document.body, "\\begin_layout Standard", i + 1, j)
1228 document.warning("Malformed LyX document: Missing `\\begin_layout Standard' in Float inset.")
1230 document.body[j] = '\\begin_layout Standard\n\\begin_inset ERT\nstatus collapsed\n\n' \
1231 '\\begin_layout Standard\n\n\n\\backslash\n' \
1232 'end{sideways' + floattype + '*}\n\\end_layout\n\n\\end_inset\n'
1233 del document.body[i+1:l-1]
1234 document.body[i] = '\\begin_inset ERT\nstatus collapsed\n\n' \
1235 '\\begin_layout Standard\n\n\n\\backslash\n' \
1236 'begin{sideways' + floattype + '*}\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n\n'
1237 add_to_preamble(document,
1238 ['\\usepackage{rotfloat}\n'])
1244 def convert_subfig(document):
1245 " Convert subfigures to subfloats. "
1248 i = find_token(document.body, '\\begin_inset Graphics', i)
1251 j = find_end_of_inset(document.body, i)
1253 document.warning("Malformed lyx document: Missing '\\end_inset'.")
1256 k = find_token(document.body, '\tsubcaption', i, j)
1260 l = find_token(document.body, '\tsubcaptionText', i, j)
1261 caption = get_value(document.body, '\tsubcaptionText', i, j).strip('"')
1262 savestr = document.body[i]
1263 document.body[i] = '\\begin_inset Float figure\nwide false\nsideways false\n' \
1264 'status open\n\n\\begin_layout PlainLayout\n\\begin_inset Caption\n\n\\begin_layout PlainLayout\n' \
1265 + caption + '\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n\n\\begin_layout PlainLayout\n' + savestr
1266 savestr = document.body[j]
1267 document.body[j] = '\n\\end_layout\n\n\\end_inset\n' + savestr
1268 del document.body[k]
1269 del document.body[l]
1272 def revert_subfig(document):
1273 " Revert subfloats. "
1276 i = find_token(document.body, '\\begin_inset Float', i)
1280 j = find_end_of_inset(document.body, i)
1282 document.warning("Malformed lyx document: Missing '\\end_inset' (float).")
1285 # look for embedded float (= subfloat)
1286 k = find_token(document.body, '\\begin_inset Float', i + 1, j)
1289 l = find_end_of_inset(document.body, k)
1291 document.warning("Malformed lyx document: Missing '\\end_inset' (embedded float).")
1294 m = find_token(document.body, "\\begin_layout PlainLayout", k + 1, l)
1296 cap = find_token(document.body, '\\begin_inset Caption', k + 1, l)
1300 capend = find_end_of_inset(document.body, cap)
1302 document.warning("Malformed lyx document: Missing '\\end_inset' (caption).")
1306 lbl = find_token(document.body, '\\begin_inset CommandInset label', cap, capend)
1308 lblend = find_end_of_inset(document.body, lbl + 1)
1310 document.warning("Malformed lyx document: Missing '\\end_inset' (label).")
1312 for line in document.body[lbl:lblend + 1]:
1313 if line.startswith('name '):
1314 label = line.split()[1].strip('"')
1321 opt = find_token(document.body, '\\begin_inset OptArg', cap, capend)
1323 optend = find_end_of_inset(document.body, opt)
1325 document.warning("Malformed lyx document: Missing '\\end_inset' (OptArg).")
1327 optc = find_token(document.body, "\\begin_layout PlainLayout", opt, optend)
1329 document.warning("Malformed LyX document: Missing `\\begin_layout PlainLayout' in Float inset.")
1331 optcend = find_end_of(document.body, optc, "\\begin_layout", "\\end_layout")
1332 for line in document.body[optc:optcend]:
1333 if not line.startswith('\\'):
1334 shortcap += line.strip()
1338 for line in document.body[cap:capend]:
1339 if line in document.body[lbl:lblend]:
1341 elif line in document.body[opt:optend]:
1343 elif not line.startswith('\\'):
1344 caption += line.strip()
1346 caption += "\\backslash\nlabel{" + label + "}"
1347 document.body[l] = '\\begin_layout PlainLayout\n\\begin_inset ERT\nstatus collapsed\n\n' \
1348 '\\begin_layout PlainLayout\n\n}\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n\n\\begin_layout PlainLayout\n'
1349 del document.body[cap:capend+1]
1350 del document.body[k+1:m-1]
1351 insertion = '\\begin_inset ERT\nstatus collapsed\n\n' \
1352 '\\begin_layout PlainLayout\n\n\\backslash\n' \
1354 if len(shortcap) > 0:
1355 insertion = insertion + "[" + shortcap + "]"
1356 if len(caption) > 0:
1357 insertion = insertion + "[" + caption + "]"
1358 insertion = insertion + '{%\n\\end_layout\n\n\\end_inset\n\n\\end_layout\n'
1359 document.body[k] = insertion
1360 add_to_preamble(document,
1361 ['\\usepackage{subfig}\n'])
1365 def revert_wrapplacement(document):
1366 "Revert placement options wrap floats (wrapfig)."
1369 i = find_token(document.body, "lines", i)
1372 j = find_token(document.body, "placement", i+1)
1374 document.warning("Malformed LyX document: Couldn't find placement parameter of wrap float.")
1376 document.body[j] = document.body[j].replace("placement O", "placement o")
1377 document.body[j] = document.body[j].replace("placement I", "placement i")
1378 document.body[j] = document.body[j].replace("placement L", "placement l")
1379 document.body[j] = document.body[j].replace("placement R", "placement r")
1387 supported_versions = ["1.6.0","1.6"]
1388 convert = [[277, [fix_wrong_tables]],
1389 [278, [close_begin_deeper]],
1390 [279, [long_charstyle_names]],
1391 [280, [axe_show_label]],
1394 [283, [convert_flex]],
1398 [287, [convert_wrapfig_options]],
1399 [288, [convert_inset_command]],
1400 [289, [convert_latexcommand_index]],
1405 [294, [convert_pdf_options]],
1406 [295, [convert_htmlurl, convert_url]],
1407 [296, [convert_include]],
1408 [297, [convert_usorbian]],
1414 [303, [convert_serbocroatian]],
1415 [304, [convert_framed_notes]],
1422 [311, [convert_ams_classes]],
1424 [313, [convert_module_names]],
1427 [316, [convert_subfig]],
1431 revert = [[316, [revert_wrapplacement]],
1432 [315, [revert_subfig]],
1433 [314, [revert_colsep]],
1435 [312, [revert_module_names]],
1436 [311, [revert_rotfloat, revert_widesideways]],
1438 [309, [revert_btprintall]],
1439 [308, [revert_nocite]],
1440 [307, [revert_serbianlatin]],
1441 [306, [revert_slash, revert_nobreakdash]],
1442 [305, [revert_interlingua]],
1443 [304, [revert_bahasam]],
1444 [303, [revert_framed_notes]],
1446 [301, [revert_latin, revert_samin]],
1447 [300, [revert_linebreak]],
1448 [299, [revert_pagebreak]],
1449 [298, [revert_hyperlinktype]],
1450 [297, [revert_macro_optional_params]],
1451 [296, [revert_albanian, revert_lowersorbian, revert_uppersorbian]],
1452 [295, [revert_include]],
1453 [294, [revert_href]],
1454 [293, [revert_pdf_options_2]],
1455 [292, [revert_inset_info]],
1456 [291, [revert_japanese, revert_japanese_encoding]],
1457 [290, [revert_vietnamese]],
1458 [289, [revert_wraptable]],
1459 [288, [revert_latexcommand_index]],
1460 [287, [revert_inset_command]],
1461 [286, [revert_wrapfig_options]],
1462 [285, [revert_pdf_options]],
1463 [284, [remove_inzip_options]],
1465 [282, [revert_flex]],
1467 [280, [revert_begin_modules]],
1468 [279, [revert_show_label]],
1469 [278, [revert_long_charstyle_names]],
1475 if __name__ == "__main__":