1 # -*- coding: utf-8 -*-
4 # This file is part of LyX, the document processor.
5 # Licence details can be found in the file COPYING.
7 # author Richard Kimberly Heck
9 # Full author contact details are available in file CREDITS
11 # This is the main file for the user preferences conversion system.
12 # There are two subsidiary files:
13 # prefs2prefs_lfuns.py
14 # prefs2prefs_prefs.py
15 # The former is used to convert bind and ui files; the latter, to convert
16 # the preferences file. The converter functions are all in the subsidiary
19 # The format of the existing files was format 0, as of 2.0.alpha6.
21 from __future__ import print_function
22 import os, re, string, sys
23 from getopt import getopt
26 ###########################################################
27 # Utility functions, borrowed from layout2layout.py
30 " Remove byte order mark."
31 if line[0:3] == u"\357\273\277":
38 " Read input file and strip lineendings."
39 lines = source.read().splitlines() or ['']
40 lines[0] = trim_bom(lines[0])
44 def write(output, lines):
45 " Write output file with native lineendings."
46 output.write(os.linesep.join(lines) + os.linesep)
49 # for use by find_format_lines
50 re_comment = re.compile(r'^#')
51 re_empty = re.compile(r'^\s*$')
53 def find_format_line(lines):
55 Returns (bool, int), where int is number of the line the `Format'
56 specification is on, or else the number of the first non-blank,
57 non-comment line. The bool tells whether we found a format line.
59 for i in range(len(lines)):
61 if re_comment.search(l) or re_empty.search(l):
63 m = re_format.search(l)
66 # we're done when we have hit a non-comment, non-empty line
71 # for use by get_format
72 re_format = re.compile(r'^Format\s+(\d+)\s*$')
74 def get_format(lines):
75 " Gets format of current file and replaces the format line with a new one "
76 (found, format_line) = find_format_line(lines)
79 line = lines[format_line]
80 m = re_format.search(line)
82 sys.stderr.write("Couldn't match format line!\n" + line + "\n")
84 return int(m.group(1))
87 def update_format(lines):
88 " Writes new format line "
89 (found, format_line) = find_format_line(lines)
91 lines[format_line:format_line] = ("Format 1", "")
94 line = lines[format_line]
95 m = re_format.search(line)
97 sys.stderr.write("Couldn't match format line!\n" + line + "\n")
99 format = int(m.group(1))
100 lines[format_line] = "Format " + str(format + 1)
104 sys.stderr.write("\n%s\n" % (msg))
108 ###########################################################
111 print ("%s [-l] [-p] infile outfile" % sys.argv[0])
112 print ("or: %s [-l] [-p] <infile >outfile" % sys.argv[0])
113 print (" -l: convert LFUNs (bind and ui files)")
114 print (" -p: convert preferences")
115 print ("Note that exactly one of -l and -p is required.")
120 (options, args) = getopt(sys.argv[1:], "lp")
123 abort("Unrecognized option")
131 source = io.open(args[0], 'r', encoding='utf_8', errors='surrogateescape')
132 output = io.open(args[1], 'w', encoding='utf_8', newline='\n')
136 abort("Either zero or two arguments must be given.")
140 for (opt, param) in options:
142 from prefs2prefs_lfuns import conversions
144 from prefs2prefs_prefs import conversions
148 abort("Neither -l nor -p given.")
149 elif len(options) > 1:
151 abort("Only one of -l or -p should be given.")
153 current_format = len(conversions)
155 format = get_format(lines)
157 while format < current_format:
158 target_format, convert = conversions[format]
161 # make sure the conversion list is sequential
162 if int(old_format) + 1 != target_format:
163 abort("Something is wrong with the conversion chain.")
167 # first see if the routine will accept a list of lines
170 # if not, it wants individual lines
171 for i in range(len(lines)):
172 (update, newline) = c(lines[i])
177 format = get_format(lines)
180 if int(old_format) + 1 != int(format):
181 abort("Failed to convert to new format!")
193 if __name__ == "__main__":