]> git.lyx.org Git - lyx.git/blob - lib/lyx2lyx/lyx_2_4.py
1c22756447af0e86a3e508a79bb997266a8fcaec
[lyx.git] / lib / lyx2lyx / lyx_2_4.py
1 # -*- coding: utf-8 -*-
2 # This file is part of lyx2lyx
3 # Copyright (C) 2018 The LyX team
4 #
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 """ Convert files to the file format generated by lyx 2.4"""
20
21 import re, string
22 import unicodedata
23 import sys, os
24
25 # Uncomment only what you need to import, please.
26
27 from parser_tools import (count_pars_in_inset, find_end_of_inset, find_end_of_layout,
28 find_token, get_bool_value, get_option_value, get_value, get_quoted_value)
29 #    del_token, del_value, del_complete_lines,
30 #    find_complete_lines, find_end_of,
31 #    find_re, find_substring, find_token_backwards,
32 #    get_containing_inset, get_containing_layout,
33 #    is_in_inset, set_bool_value
34 #    find_tokens, find_token_exact, check_token
35
36 from lyx2lyx_tools import (put_cmd_in_ert, add_to_preamble)
37 #  revert_font_attrs, insert_to_preamble, latex_length
38 #  get_ert, lyx2latex, lyx2verbatim, length_in_bp, convert_info_insets
39 #  revert_flex_inset, hex2ratio, str2bool
40
41 ####################################################################
42 # Private helper functions
43
44
45
46 ###############################################################################
47 ###
48 ### Conversion and reversion routines
49 ###
50 ###############################################################################
51
52 def removeFrontMatterStyles(document):
53     " Remove styles Begin/EndFromatter"
54
55     layouts = ['BeginFrontmatter', 'EndFrontmatter']
56     for layout in layouts:
57         i = 0
58         while True:
59             i = find_token(document.body, '\\begin_layout ' + layout, i)
60             if i == -1:
61                 break
62             j = find_end_of_layout(document.body, i)
63             if j == -1:
64                 document.warning("Malformed LyX document: Can't find end of layout at line %d" % i)
65                 i += 1
66                 continue
67             while i > 0 and document.body[i-1].strip() == '':
68                 i -= 1
69             while document.body[j+1].strip() == '':
70                 j = j + 1
71             document.body[i:j+1] = ['']
72
73 def addFrontMatterStyles(document):
74     " Use styles Begin/EndFrontmatter for elsarticle"
75
76     def insertFrontmatter(prefix, line):
77         above = line
78         while above > 0 and document.body[above-1].strip() == '':
79             above -= 1
80         below = line
81         while document.body[below].strip() == '':
82             below += 1
83         document.body[above:below] = ['', '\\begin_layout ' + prefix + 'Frontmatter',
84                                     '\\begin_inset Note Note',
85                                     'status open', '',
86                                     '\\begin_layout Plain Layout',
87                                     'Keep this empty!',
88                                     '\\end_layout', '',
89                                     '\\end_inset', '', '',
90                                     '\\end_layout', '']
91
92     if document.textclass == "elsarticle":
93         layouts = ['Title', 'Title footnote', 'Author', 'Author footnote',
94                    'Corresponding author', 'Address', 'Email', 'Abstract', 'Keywords']
95         first = -1
96         last = -1
97         for layout in layouts:
98             i = 0
99             while True:
100                 i = find_token(document.body, '\\begin_layout ' + layout, i)
101                 if i == -1:
102                     break
103                 k = find_end_of_layout(document.body, i)
104                 if k == -1:
105                     document.warning("Malformed LyX document: Can't find end of layout at line %d" % i)
106                     i += 1;
107                     continue
108                 if first == -1 or i < first:
109                     first = i
110                 if last == -1 or last <= k:
111                     last = k+1
112                 i = k+1
113         if first == -1:
114             return
115         insertFrontmatter('End', last)
116         insertFrontmatter('Begin', first)
117
118 def convert_lst_literalparam(document):
119     " Add param literal to include inset "
120
121     i = 0
122     while True:
123         i = find_token(document.body, '\\begin_inset CommandInset include', i)
124         if i == -1:
125             break
126         j = find_end_of_inset(document.body, i)
127         if j == -1:
128             document.warning("Malformed LyX document: Can't find end of command inset at line %d" % i)
129             i += 1
130             continue
131         while i < j and document.body[i].strip() != '':
132             i += 1
133         document.body.insert(i, "literal \"true\"")
134
135
136 def revert_lst_literalparam(document):
137     " Remove param literal from include inset "
138
139     i = 0
140     while True:
141         i = find_token(document.body, '\\begin_inset CommandInset include', i)
142         if i == -1:
143             break
144         j = find_end_of_inset(document.body, i)
145         if j == -1:
146             document.warning("Malformed LyX document: Can't find end of include inset at line %d" % i)
147             i += 1
148             continue
149         k = find_token(document.body, 'literal', i, j)
150         if k == -1:
151             i += 1
152             continue
153         del document.body[k]
154
155
156 def revert_paratype(document):
157     " Revert ParaType font definitions to LaTeX "
158
159     if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
160         preamble = ""
161         i1 = find_token(document.header, "\\font_roman \"PTSerif-TLF\"", 0)
162         i2 = find_token(document.header, "\\font_sans \"default\"", 0)
163         i3 = find_token(document.header, "\\font_typewriter \"default\"", 0)
164         j = find_token(document.header, "\\font_sans \"PTSans-TLF\"", 0)
165         sfval = get_value(document.header, "\\font_sf_scale", 0)
166         # cutoff " 100"
167         sfval = sfval[:-4]
168         sfoption = ""
169         if sfval != "100":
170             sfoption = "scaled=" + format(float(sfval) / 100, '.2f')
171         k = find_token(document.header, "\\font_typewriter \"PTMono-TLF\"", 0)
172         ttval = get_value(document.header, "\\font_tt_scale", 0)
173         # cutoff " 100"
174         ttval = ttval[:-4]
175         ttoption = ""
176         if ttval != "100":
177             ttoption = "scaled=" + format(float(ttval) / 100, '.2f')
178         if i1 != -1 and i2 != -1 and i3!= -1:
179             add_to_preamble(document, ["\\usepackage{paratype}"])
180         else:
181             if i1!= -1:
182                 add_to_preamble(document, ["\\usepackage{PTSerif}"])
183                 document.header[i1] = document.header[i1].replace("PTSerif-TLF", "default")
184             if j!= -1:
185                 if sfoption != "":
186                     add_to_preamble(document, ["\\usepackage[" + sfoption + "]{PTSans}"])
187                 else:
188                     add_to_preamble(document, ["\\usepackage{PTSans}"])
189                 document.header[j] = document.header[j].replace("PTSans-TLF", "default")
190             if k!= -1:
191                 if ttoption != "":
192                     add_to_preamble(document, ["\\usepackage[" + ttoption + "]{PTMono}"])
193                 else:
194                     add_to_preamble(document, ["\\usepackage{PTMono}"])
195                 document.header[k] = document.header[k].replace("PTMono-TLF", "default")
196
197
198 def revert_xcharter(document):
199     " Revert XCharter font definitions to LaTeX "
200
201     i = find_token(document.header, "\\font_roman \"xcharter\"", 0)
202     if i == -1:
203         return
204
205     # replace unsupported font setting
206     document.header[i] = document.header[i].replace("xcharter", "default")
207     # no need for preamble code with system fonts
208     if get_bool_value(document.header, "\\use_non_tex_fonts"):
209         return
210
211     # transfer old style figures setting to package options
212     j = find_token(document.header, "\\font_osf true")
213     if j != -1:
214         options = "[osf]"
215         document.header[j] = "\\font_osf false"
216     else:
217         options = ""
218     if i != -1:
219         add_to_preamble(document, ["\\usepackage%s{XCharter}"%options])
220
221
222 def revert_lscape(document):
223     " Reverts the landscape environment (Landscape module) to TeX-code "
224
225     if not "landscape" in document.get_module_list():
226         return
227
228     i = 0
229     while True:
230         i = find_token(document.body, "\\begin_inset Flex Landscape", i)
231         if i == -1:
232             return
233         j = find_end_of_inset(document.body, i)
234         if j == -1:
235             document.warning("Malformed LyX document: Can't find end of Landscape inset")
236             i += 1
237             continue
238
239         if document.body[i] == "\\begin_inset Flex Landscape (Floating)":
240             document.body[j - 2 : j + 1] = put_cmd_in_ert("\\end{landscape}}")
241             document.body[i : i + 4] = put_cmd_in_ert("\\afterpage{\\begin{landscape}")
242             add_to_preamble(document, ["\\usepackage{afterpage}"])
243         else:
244             document.body[j - 2 : j + 1] = put_cmd_in_ert("\\end{landscape}")
245             document.body[i : i + 4] = put_cmd_in_ert("\\begin{landscape}")
246
247         add_to_preamble(document, ["\\usepackage{pdflscape}"])
248         # no need to reset i
249
250
251 def convert_fontenc(document):
252     " Convert default fontenc setting "
253
254     i = find_token(document.header, "\\fontencoding global", 0)
255     if i == -1:
256         return
257
258     document.header[i] = document.header[i].replace("global", "auto")
259
260
261 def revert_fontenc(document):
262     " Revert default fontenc setting "
263
264     i = find_token(document.header, "\\fontencoding auto", 0)
265     if i == -1:
266         return
267
268     document.header[i] = document.header[i].replace("auto", "global")
269
270
271 def revert_nospellcheck(document):
272     " Remove nospellcheck font info param "
273
274     i = 0
275     while True:
276         i = find_token(document.body, '\\nospellcheck', i)
277         if i == -1:
278             return
279         del document.body[i]
280
281
282 def revert_floatpclass(document):
283     " Remove float placement params 'document' and 'class' "
284
285     i = 0
286     i = find_token(document.header, "\\float_placement class", 0)
287     if i != -1:
288         del document.header[i]
289
290     i = 0
291     while True:
292         i = find_token(document.body, '\\begin_inset Float', i)
293         if i == -1:
294             break
295         j = find_end_of_inset(document.body, i)
296         k = find_token(document.body, 'placement class', i, i + 2)
297         if k == -1:
298             k = find_token(document.body, 'placement document', i, i + 2)
299             if k != -1:
300                 del document.body[k]
301             i = j
302             continue
303         del document.body[k]
304
305
306 def revert_floatalignment(document):
307     " Remove float alignment params "
308
309     i = 0
310     i = find_token(document.header, "\\float_alignment", 0)
311     galignment = ""
312     if i != -1:
313         galignment = get_value(document.header, "\\float_alignment", i)
314         del document.header[i]
315
316     i = 0
317     while True:
318         i = find_token(document.body, '\\begin_inset Float', i)
319         if i == -1:
320             break
321         j = find_end_of_inset(document.body, i)
322         if j == -1:
323             document.warning("Malformed LyX document: Can't find end of inset at line " + str(i))
324             i += 1
325         k = find_token(document.body, 'alignment', i, i + 4)
326         if k == -1:
327             i = j
328             continue
329         alignment = get_value(document.body, "alignment", k)
330         if alignment == "document":
331             alignment = galignment
332         del document.body[k]
333         l = find_token(document.body, "\\begin_layout Plain Layout", i, j)
334         if l == -1:
335             document.warning("Can't find float layout!")
336             i = j
337             continue
338         alcmd = []
339         if alignment == "left":
340             alcmd = put_cmd_in_ert("\\raggedright{}")
341         elif alignment == "center":
342             alcmd = put_cmd_in_ert("\\centering{}")
343         elif alignment == "right":
344             alcmd = put_cmd_in_ert("\\raggedleft{}")
345         if len(alcmd) > 0:
346             document.body[l+1:l+1] = alcmd
347         i = j 
348
349
350 def revert_tuftecite(document):
351     " Revert \cite commands in tufte classes "
352
353     tufte = ["tufte-book", "tufte-handout"]
354     if document.textclass not in tufte:
355         return
356
357     i = 0
358     while (True):
359         i = find_token(document.body, "\\begin_inset CommandInset citation", i)
360         if i == -1:
361             break
362         j = find_end_of_inset(document.body, i)
363         if j == -1:
364             document.warning("Can't find end of citation inset at line %d!!" %(i))
365             i += 1
366             continue
367         k = find_token(document.body, "LatexCommand", i, j)
368         if k == -1:
369             document.warning("Can't find LatexCommand for citation inset at line %d!" %(i))
370             i = j + 1
371             continue
372         cmd = get_value(document.body, "LatexCommand", k)
373         if cmd != "cite":
374             i = j + 1
375             continue
376         pre = get_quoted_value(document.body, "before", i, j)
377         post = get_quoted_value(document.body, "after", i, j)
378         key = get_quoted_value(document.body, "key", i, j)
379         if not key:
380             document.warning("Citation inset at line %d does not have a key!" %(i))
381             key = "???"
382         # Replace command with ERT
383         res = "\\cite"
384         if pre:
385             res += "[" + pre + "]"
386         if post:
387             res += "[" + post + "]"
388         elif pre:
389             res += "[]"
390         res += "{" + key + "}"
391         document.body[i:j+1] = put_cmd_in_ert([res])
392         i = j + 1
393
394
395 def revert_stretchcolumn(document):
396     " We remove the column varwidth flags or everything else will become a mess. "
397     i = 0
398     while True:
399         i = find_token(document.body, "\\begin_inset Tabular", i)
400         if i == -1:
401             return
402         j = find_end_of_inset(document.body, i + 1)
403         if j == -1:
404             document.warning("Malformed LyX document: Could not find end of tabular.")
405             continue
406         for k in range(i, j):
407             if re.search('^<column.*varwidth="[^"]+".*>$', document.body[k]):
408                 document.warning("Converting 'tabularx'/'xltabular' table to normal table.")
409                 document.body[k] = document.body[k].replace(' varwidth="true"', '')
410         i = i + 1
411
412
413 def revert_vcolumns(document):
414     " Revert standard columns with line breaks etc. "
415     i = 0
416     needvarwidth = False
417     needarray = False
418     try:
419         while True:
420             i = find_token(document.body, "\\begin_inset Tabular", i)
421             if i == -1:
422                 return
423             j = find_end_of_inset(document.body, i)
424             if j == -1:
425                 document.warning("Malformed LyX document: Could not find end of tabular.")
426                 i += 1
427                 continue
428
429             # Collect necessary column information
430             m = i + 1
431             nrows = int(document.body[i+1].split('"')[3])
432             ncols = int(document.body[i+1].split('"')[5])
433             col_info = []
434             for k in range(ncols):
435                 m = find_token(document.body, "<column", m)
436                 width = get_option_value(document.body[m], 'width')
437                 varwidth = get_option_value(document.body[m], 'varwidth')
438                 alignment = get_option_value(document.body[m], 'alignment')
439                 special = get_option_value(document.body[m], 'special')
440                 col_info.append([width, varwidth, alignment, special, m])
441
442             # Now parse cells
443             m = i + 1
444             lines = []
445             for row in range(nrows):
446                 for col in range(ncols):
447                     m = find_token(document.body, "<cell", m)
448                     multicolumn = get_option_value(document.body[m], 'multicolumn')
449                     multirow = get_option_value(document.body[m], 'multirow')
450                     width = get_option_value(document.body[m], 'width')
451                     rotate = get_option_value(document.body[m], 'rotate')
452                     # Check for: linebreaks, multipars, non-standard environments
453                     begcell = m
454                     endcell = find_token(document.body, "</cell>", begcell)
455                     vcand = False
456                     if find_token(document.body, "\\begin_inset Newline", begcell, endcell) != -1:
457                         vcand = True
458                     elif count_pars_in_inset(document.body, begcell + 2) > 1:
459                         vcand = True
460                     elif get_value(document.body, "\\begin_layout", begcell) != "Plain Layout":
461                         vcand = True
462                     if vcand and rotate == "" and ((multicolumn == "" and multirow == "") or width == ""):
463                         if col_info[col][0] == "" and col_info[col][1] == "" and col_info[col][3] == "":
464                             needvarwidth = True
465                             alignment = col_info[col][2]
466                             col_line = col_info[col][4]
467                             vval = ""
468                             if alignment == "center":
469                                 vval = ">{\\centering}"
470                             elif  alignment == "left":
471                                 vval = ">{\\raggedright}"
472                             elif alignment == "right":
473                                 vval = ">{\\raggedleft}"
474                             if vval != "":
475                                 needarray = True
476                             vval += "V{\\linewidth}"
477                 
478                             document.body[col_line] = document.body[col_line][:-1] + " special=\"" + vval + "\">"
479                             # ERT newlines and linebreaks (since LyX < 2.4 automatically inserts parboxes
480                             # with newlines, and we do not want that)
481                             while True:
482                                 endcell = find_token(document.body, "</cell>", begcell)
483                                 linebreak = False
484                                 nl = find_token(document.body, "\\begin_inset Newline newline", begcell, endcell)
485                                 if nl == -1:
486                                     nl = find_token(document.body, "\\begin_inset Newline linebreak", begcell, endcell)
487                                     if nl == -1:
488                                          break
489                                     linebreak = True
490                                 nle = find_end_of_inset(document.body, nl)
491                                 del(document.body[nle:nle+1])
492                                 if linebreak:
493                                     document.body[nl:nl+1] = put_cmd_in_ert("\\linebreak{}")
494                                 else:
495                                     document.body[nl:nl+1] = put_cmd_in_ert("\\\\")
496                     m += 1
497
498             i = j + 1
499
500     finally:
501         if needarray == True:
502             add_to_preamble(document, ["\\usepackage{array}"])
503         if needvarwidth == True:
504             add_to_preamble(document, ["\\usepackage{varwidth}"])
505
506
507 def revert_bibencoding(document):
508     " Revert bibliography encoding "
509
510     # Get cite engine
511     engine = "basic"
512     i = find_token(document.header, "\\cite_engine", 0)
513     if i == -1:
514         document.warning("Malformed document! Missing \\cite_engine")
515     else:
516         engine = get_value(document.header, "\\cite_engine", i)
517
518     # Check if biblatex
519     biblatex = False
520     if engine in ["biblatex", "biblatex-natbib"]:
521         biblatex = True
522
523     # Map lyx to latex encoding names 
524     encodings = {
525         "utf8" : "utf8",
526         "utf8x" : "utf8x",
527         "armscii8" : "armscii8",
528         "iso8859-1" : "latin1",
529         "iso8859-2" : "latin2",
530         "iso8859-3" : "latin3",
531         "iso8859-4" : "latin4",
532         "iso8859-5" : "iso88595",
533         "iso8859-6" : "8859-6",
534         "iso8859-7" : "iso-8859-7",
535         "iso8859-8" : "8859-8",
536         "iso8859-9" : "latin5",
537         "iso8859-13" : "latin7",
538         "iso8859-15" : "latin9",
539         "iso8859-16" : "latin10",
540         "applemac" : "applemac",
541         "cp437" : "cp437",
542         "cp437de" : "cp437de",
543         "cp850" : "cp850",
544         "cp852" : "cp852",
545         "cp855" : "cp855",
546         "cp858" : "cp858",
547         "cp862" : "cp862",
548         "cp865" : "cp865",
549         "cp866" : "cp866",
550         "cp1250" : "cp1250",
551         "cp1251" : "cp1251",
552         "cp1252" : "cp1252",
553         "cp1255" : "cp1255",
554         "cp1256" : "cp1256",
555         "cp1257" : "cp1257",
556         "koi8-r" : "koi8-r",
557         "koi8-u" : "koi8-u",
558         "pt154" : "pt154",
559         "utf8-platex" : "utf8",
560         "ascii" : "ascii"
561     }
562
563     i = 0
564     bibresources = []
565     while (True):
566         i = find_token(document.body, "\\begin_inset CommandInset bibtex", i)
567         if i == -1:
568             break
569         j = find_end_of_inset(document.body, i)
570         if j == -1:
571             document.warning("Can't find end of bibtex inset at line %d!!" %(i))
572             i += 1
573             continue
574         encoding = get_quoted_value(document.body, "encoding", i, j)
575         if not encoding:
576             i += 1
577             continue
578         # remove encoding line
579         k = find_token(document.body, "encoding", i, j)
580         if k != -1:
581             del document.body[k]
582         # Re-find inset end line
583         j = find_end_of_inset(document.body, i)
584         if biblatex:
585             biblio_options = ""
586             h = find_token(document.header, "\\biblio_options", 0)
587             if h != -1:
588                 biblio_options = get_value(document.header, "\\biblio_options", h)
589                 if not "bibencoding" in biblio_options:
590                      document.header[h] += ",bibencoding=%s" % encodings[encoding]
591             else:
592                 bs = find_token(document.header, "\\biblatex_bibstyle", 0)
593                 if bs == -1:
594                     # this should not happen
595                     document.warning("Malformed LyX document! No \\biblatex_bibstyle header found!")
596                 else:
597                     document.header[bs-1 : bs-1] = ["\\biblio_options bibencoding=" + encodings[encoding]]
598         else:
599             document.body[j+1:j+1] = put_cmd_in_ert("\\egroup")
600             document.body[i:i] = put_cmd_in_ert("\\bgroup\\inputencoding{" + encodings[encoding] + "}")
601
602         i = j + 1
603
604
605
606 def convert_vcsinfo(document):
607     " Separate vcs Info inset from buffer Info inset. "
608
609     types = {
610         "vcs-revision" : "revision",
611         "vcs-tree-revision" : "tree-revision",
612         "vcs-author" : "author",
613         "vcs-time" : "time",
614         "vcs-date" : "date"
615     }
616     i = 0
617     while True:
618         i = find_token(document.body, "\\begin_inset Info", i)
619         if i == -1:
620             return
621         j = find_end_of_inset(document.body, i + 1)
622         if j == -1:
623             document.warning("Malformed LyX document: Could not find end of Info inset.")
624             i = i + 1
625             continue
626         tp = find_token(document.body, 'type', i, j)
627         tpv = get_quoted_value(document.body, "type", tp)
628         if tpv != "buffer":
629             i = i + 1
630             continue
631         arg = find_token(document.body, 'arg', i, j)
632         argv = get_quoted_value(document.body, "arg", arg)
633         if argv not in list(types.keys()):
634             i = i + 1
635             continue
636         document.body[tp] = "type \"vcs\""
637         document.body[arg] = "arg \"" + types[argv] + "\""
638         i = i + 1
639
640
641 def revert_vcsinfo(document):
642     " Merge vcs Info inset to buffer Info inset. "
643
644     args = ["revision", "tree-revision", "author", "time", "date" ]
645     i = 0
646     while True:
647         i = find_token(document.body, "\\begin_inset Info", i)
648         if i == -1:
649             return
650         j = find_end_of_inset(document.body, i + 1)
651         if j == -1:
652             document.warning("Malformed LyX document: Could not find end of Info inset.")
653             i = i + 1
654             continue
655         tp = find_token(document.body, 'type', i, j)
656         tpv = get_quoted_value(document.body, "type", tp)
657         if tpv != "vcs":
658             i = i + 1
659             continue
660         arg = find_token(document.body, 'arg', i, j)
661         argv = get_quoted_value(document.body, "arg", arg)
662         if argv not in args:
663             document.warning("Malformed Info inset. Invalid vcs arg.")
664             i = i + 1
665             continue
666         document.body[tp] = "type \"buffer\""
667         document.body[arg] = "arg \"vcs-" + argv + "\""
668         i = i + 1
669
670
671 ##
672 # Conversion hub
673 #
674
675 supported_versions = ["2.4.0", "2.4"]
676 convert = [
677            [545, [convert_lst_literalparam]],
678            [546, []],
679            [547, []],
680            [548, []],
681            [549, []],
682            [550, [convert_fontenc]],
683            [551, []],
684            [552, []],
685            [553, []],
686            [554, []],
687            [555, []],
688            [556, []],
689            [557, [convert_vcsinfo]],
690            [558, [removeFrontMatterStyles]]
691           ]
692
693 revert =  [
694            [557, [addFrontMatterStyles]],
695            [556, [revert_vcsinfo]],
696            [555, [revert_bibencoding]],
697            [554, [revert_vcolumns]],
698            [553, [revert_stretchcolumn]],
699            [552, [revert_tuftecite]],
700            [551, [revert_floatpclass, revert_floatalignment]],
701            [550, [revert_nospellcheck]],
702            [549, [revert_fontenc]],
703            [548, []],# dummy format change
704            [547, [revert_lscape]],
705            [546, [revert_xcharter]],
706            [545, [revert_paratype]],
707            [544, [revert_lst_literalparam]]
708           ]
709
710
711 if __name__ == "__main__":
712     pass