2 # -*- coding: utf-8 -*-
5 # This file is part of LyX, the document processor.
6 # Licence details can be found in the file COPYING.
10 # Full author contact details are available in file CREDITS
12 # This is the main file for the user preferences conversion system.
13 # There are two subsidiary files:
14 # prefs2prefs_lfuns.py
15 # prefs2prefs_prefs.py
16 # The former is used to convert bind and ui files; the latter, to convert
17 # the preferences file.
19 # I've organized it this way because, in many ways, converting bind and ui
20 # files lfuns) and converting the preferences file are the same task. It's
21 # very line-by-line, unlike lyx2lyx and layout2layout, where changes can be
22 # more "global". So we read the file, line by line, and give a bunch of
23 # converter functions a chance to see if they want to modify that line.
25 # The converter functions are all in the subsidiary files. They take a line
26 # as argument and return a list: (Bool, NewLine), where the Bool says if
27 # we've modified anything and the NewLine is the new line, if so, which will
28 # be used to replace the old line.
30 # The format of the existing files is format 0, as of 2.0.alpha6. We'll
31 # introduce new format numbers as we proceed, just as with layout2layout.
32 # These will be different for the bind and ui files and for the preferences
35 import os, re, string, sys
36 from getopt import getopt
38 ###########################################################
39 # Utility functions, borrowed from layout2layout.py
42 " Remove byte order mark."
43 if line[0:3] == "\357\273\277":
50 " Read input file and strip lineendings."
51 lines = source.read().splitlines()
52 lines[0] = trim_bom(lines[0])
56 def write(output, lines):
57 " Write output file with native lineendings."
58 output.write(os.linesep.join(lines) + os.linesep)
61 # for use by find_format_lines
62 re_comment = re.compile(r'^#')
63 re_empty = re.compile(r'^\s*$')
65 def find_format_line(lines):
67 Returns (bool, int), where int is number of the line the `Format'
68 specification is on, or else the number of the first non-blank,
69 non-comment line. The bool tells whether we found a format line.
71 for i in range(len(lines)):
73 if re_comment.search(l) or re_empty.search(l):
75 m = re_format.search(l)
78 # we're done when we have hit a non-comment, non-empty line
83 # for use by get_format
84 re_format = re.compile(r'^Format\s+(\d+)\s*$')
86 def get_format(lines):
87 " Gets format of current file and replaces the format line with a new one "
88 (found, format_line) = find_format_line(lines)
91 line = lines[format_line]
92 m = re_format.search(line)
94 sys.stderr.write("Couldn't match format line!\n" + line + "\n")
96 return int(m.group(1))
99 def update_format(lines):
100 " Writes new format line "
101 (found, format_line) = find_format_line(lines)
103 lines.insert(format_line, "Format 1")
106 line = lines[format_line]
107 m = re_format.search(l)
109 sys.stderr.write("Couldn't match format line!\n" + line + "\n")
111 format = int(m.group(1))
112 lines[i] = "Format " + str(format + 1)
116 ###########################################################
119 print "%s [-l] [-p] infile outfile" % sys.argv[0]
120 print "or: %s [-l] [-p] <infile >outfile" % sys.argv[0]
121 print " -l: convert LFUNs (bind and ui files)"
122 print " -p: convert preferences"
123 print "Note that one of -l and -p is required."
128 (options, args) = getopt(sys.argv[1:], "lp")
131 print "\nUnrecognized option"
140 source = open(args[1], 'rb')
141 output = open(args[2], 'wb')
145 print "\nEither zero or two arguments must be given."
150 for (opt, param) in options:
152 from prefs2prefs_lfuns import conversions, current_format
154 from prefs2prefs_prefs import conversions, current_format
158 print "\nNeither -l nor -p given"
162 format = get_format(lines)
164 while format < current_format:
165 for c in conversions[format]:
166 for i in range(len(lines)):
167 (update, newline) = c(lines[i])
175 format = get_format(lines)
176 if int(old_format) + 1 != int(format):
177 sys.stderr.write("Failed to convert to new format!\n")
190 if __name__ == "__main__":