mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-30 13:20:58 +00:00
430869a1bd
Bring this file in line with the other python scripts: * use four spaces for indentation instead of a tab Remove empty whitespace at the end of lines.
203 lines
5.8 KiB
Python
203 lines
5.8 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
# file prefs2prefs.py
|
|
# This file is part of LyX, the document processor.
|
|
# Licence details can be found in the file COPYING.
|
|
|
|
# author Richard Heck
|
|
|
|
# Full author contact details are available in file CREDITS
|
|
|
|
# This is the main file for the user preferences conversion system.
|
|
# There are two subsidiary files:
|
|
# prefs2prefs_lfuns.py
|
|
# prefs2prefs_prefs.py
|
|
# The former is used to convert bind and ui files; the latter, to convert
|
|
# the preferences file.
|
|
#
|
|
# I've organized it this way because, in many ways, converting bind and ui
|
|
# files lfuns) and converting the preferences file are the same task. It's
|
|
# very line-by-line, unlike lyx2lyx and layout2layout, where changes can be
|
|
# more "global". So we read the file, line by line, and give a bunch of
|
|
# converter functions a chance to see if they want to modify that line.
|
|
|
|
# The converter functions are all in the subsidiary files. They take a line
|
|
# as argument and return a list: (Bool, NewLine), where the Bool says if
|
|
# we've modified anything and the NewLine is the new line, if so, which will
|
|
# be used to replace the old line.
|
|
|
|
# The format of the existing files is format 0, as of 2.0.alpha6. We'll
|
|
# introduce new format numbers as we proceed, just as with layout2layout.
|
|
# These will be different for the bind and ui files and for the preferences
|
|
# file.
|
|
|
|
from __future__ import print_function
|
|
import os, re, string, sys
|
|
from getopt import getopt
|
|
import io
|
|
|
|
###########################################################
|
|
# Utility functions, borrowed from layout2layout.py
|
|
|
|
def trim_bom(line):
|
|
" Remove byte order mark."
|
|
if line[0:3] == u"\357\273\277":
|
|
return line[3:]
|
|
else:
|
|
return line
|
|
|
|
|
|
def read(source):
|
|
" Read input file and strip lineendings."
|
|
lines = source.read().splitlines() or ['']
|
|
lines[0] = trim_bom(lines[0])
|
|
return lines
|
|
|
|
|
|
def write(output, lines):
|
|
" Write output file with native lineendings."
|
|
output.write(os.linesep.join(lines) + os.linesep)
|
|
|
|
|
|
# for use by find_format_lines
|
|
re_comment = re.compile(r'^#')
|
|
re_empty = re.compile(r'^\s*$')
|
|
|
|
def find_format_line(lines):
|
|
'''
|
|
Returns (bool, int), where int is number of the line the `Format'
|
|
specification is on, or else the number of the first non-blank,
|
|
non-comment line. The bool tells whether we found a format line.
|
|
'''
|
|
for i in range(len(lines)):
|
|
l = lines[i]
|
|
if re_comment.search(l) or re_empty.search(l):
|
|
continue
|
|
m = re_format.search(l)
|
|
if m:
|
|
return (True, i)
|
|
# we're done when we have hit a non-comment, non-empty line
|
|
break
|
|
return (False, i)
|
|
|
|
|
|
# for use by get_format
|
|
re_format = re.compile(r'^Format\s+(\d+)\s*$')
|
|
|
|
def get_format(lines):
|
|
" Gets format of current file and replaces the format line with a new one "
|
|
(found, format_line) = find_format_line(lines)
|
|
if not found:
|
|
return 0
|
|
line = lines[format_line]
|
|
m = re_format.search(line)
|
|
if not m:
|
|
sys.stderr.write("Couldn't match format line!\n" + line + "\n")
|
|
sys.exit(1)
|
|
return int(m.group(1))
|
|
|
|
|
|
def update_format(lines):
|
|
" Writes new format line "
|
|
(found, format_line) = find_format_line(lines)
|
|
if not found:
|
|
lines[format_line:format_line] = ("Format 1", "")
|
|
return
|
|
|
|
line = lines[format_line]
|
|
m = re_format.search(line)
|
|
if not m:
|
|
sys.stderr.write("Couldn't match format line!\n" + line + "\n")
|
|
sys.exit(1)
|
|
format = int(m.group(1))
|
|
lines[format_line] = "Format " + str(format + 1)
|
|
|
|
|
|
def abort(msg):
|
|
sys.stderr.write("\n%s\n" % (msg))
|
|
sys.exit(10)
|
|
|
|
#
|
|
###########################################################
|
|
|
|
def usage():
|
|
print ("%s [-l] [-p] infile outfile" % sys.argv[0])
|
|
print ("or: %s [-l] [-p] <infile >outfile" % sys.argv[0])
|
|
print (" -l: convert LFUNs (bind and ui files)")
|
|
print (" -p: convert preferences")
|
|
print ("Note that exactly one of -l and -p is required.")
|
|
|
|
|
|
def main(argv):
|
|
try:
|
|
(options, args) = getopt(sys.argv[1:], "lp")
|
|
except:
|
|
usage()
|
|
abort("Unrecognized option")
|
|
|
|
opened_files = False
|
|
# Open files
|
|
if len(args) == 0:
|
|
source = sys.stdin
|
|
output = sys.stdout
|
|
elif len(args) == 2:
|
|
source = io.open(args[0], 'r', encoding='utf_8', errors='surrogateescape')
|
|
output = io.open(args[1], 'w', encoding='utf_8', newline='\n')
|
|
opened_files = True
|
|
else:
|
|
usage()
|
|
abort("Either zero or two arguments must be given.")
|
|
|
|
conversions = False
|
|
|
|
for (opt, param) in options:
|
|
if opt == "-l":
|
|
from prefs2prefs_lfuns import conversions
|
|
elif opt == "-p":
|
|
from prefs2prefs_prefs import conversions
|
|
|
|
if not conversions:
|
|
usage()
|
|
abort("Neither -l nor -p given.")
|
|
elif len(options) > 1:
|
|
usage()
|
|
abort("Only one of -l or -p should be given.")
|
|
|
|
current_format = len(conversions)
|
|
lines = read(source)
|
|
format = get_format(lines)
|
|
|
|
while format < current_format:
|
|
target_format, convert = conversions[format]
|
|
old_format = format
|
|
|
|
# make sure the conversion list is sequential
|
|
if int(old_format) + 1 != target_format:
|
|
abort("Something is wrong with the conversion chain.")
|
|
|
|
for c in convert:
|
|
for i in range(len(lines)):
|
|
(update, newline) = c(lines[i])
|
|
if update:
|
|
lines[i] = newline
|
|
|
|
update_format(lines)
|
|
format = get_format(lines)
|
|
|
|
# sanity check
|
|
if int(old_format) + 1 != int(format):
|
|
abort("Failed to convert to new format!")
|
|
|
|
write(output, lines)
|
|
|
|
# Close files
|
|
if opened_files:
|
|
source.close()
|
|
output.close()
|
|
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main(sys.argv)
|