]> git.donarmstrong.com Git - lilypond.git/blob - scripts/convert-ly.py
b9cac64f59b6140baae5866c94f323f42561da29
[lilypond.git] / scripts / convert-ly.py
1 #!@PYTHON@
2 #
3 # convert-ly.py -- Update old LilyPond input files (fix name?)
4 #
5 # source file of the GNU LilyPond music typesetter
6 #
7 # (c) 1998--2006  Han-Wen Nienhuys <hanwen@cs.uu.nl>
8 #                 Jan Nieuwenhuizen <janneke@gnu.org>
9 #
10 # converting rules are found in python/convertrules.py
11 #
12
13 import os
14 import sys
15 import __main__
16 import getopt
17 import string
18
19 datadir = '@local_lilypond_datadir@'
20 if not os.path.isdir (datadir):
21         datadir = '@lilypond_datadir@'
22 if os.environ.has_key ('LILYPONDPREFIX'):
23         datadir = os.environ['LILYPONDPREFIX']
24         while datadir[-1] == os.sep:
25                 datadir = datadir[:-1]
26
27 if os.path.exists (os.path.join (datadir, 'share/lilypond/@TOPLEVEL_VERSION@/')):
28         datadir = os.path.join (datadir, 'share/lilypond/@TOPLEVEL_VERSION@/')
29
30 sys.path.insert (0, os.path.join (datadir, 'python'))
31
32 import lilylib as ly
33 import fontextract
34 global _;_=ly._
35 global re;re = ly.re
36
37 from convertrules import *
38
39 lilypond_version_re_str = '\\\\version *\"([0-9.]+)"'
40 lilypond_version_re = re.compile (lilypond_version_re_str)
41
42
43 help_summary = _ (
44 '''Update LilyPond input to newer version.  By default, update from the
45 version taken from the \\version command, to the current LilyPond version.
46
47 Examples:
48
49   convert-ly -e old.ly
50   convert-ly --from=2.3.28 --to 2.5.21 foobar.ly
51 ''')
52
53 copyright = ('Jan Nieuwenhuizen <janneke@gnu.org>',
54              'Han-Wen Nienhuys <hanwen@cs.uu.nl>')
55
56 option_definitions = [
57         ('', 'e', 'edit',_('edit in place')),
58         (_('VERSION'), 'f', 'from',
59          _('start from VERSION [default: \\version found in file]')),
60         ('', 'h', 'help',_('print this help')),
61         ('',  'n', 'no-version',_ ('do not add \\version command if missing')),
62         ('','s', 'show-rules', _('print rules [default: --from=0, --to=@TOPLEVEL_VERSION@]')),
63         (_('VERSION'), 't', 'to',_('convert to VERSION [default: @TOPLEVEL_VERSION@]')),
64         ('','v','version',_('print program version"'))
65 ]       
66
67 program_name = os.path.basename (sys.argv[0])
68 program_version = '@TOPLEVEL_VERSION@'
69
70 add_version = 1
71
72 def str_to_tuple (s):
73         return tuple (map (string.atoi, string.split (s, '.')))
74
75 def tup_to_str (t):
76         return string.join (map (lambda x: '%s' % x, list (t)), '.')
77
78 def version_cmp (t1, t2):
79         for x in [0, 1, 2]:
80                 if t1[x] - t2[x]:
81                         return t1[x] - t2[x]
82         return 0
83
84 def get_conversions (from_version, to_version):
85         def is_applicable (v, f = from_version, t = to_version):
86                 return version_cmp (v[0], f) > 0 and version_cmp (v[0], t) <= 0
87         return filter (is_applicable, conversions)
88
89 def latest_version ():
90         return conversions[-1][0]
91
92 def show_rules (file, from_version, to_version):
93         for x in conversions:
94                 if (not from_version or x[0] > from_version) \
95                    and (not to_version or x[0] <= to_version):
96                         file.write  ('%s: %s\n' % (tup_to_str (x[0]), x[2]))
97
98 def do_conversion (str, from_version, to_version):
99         """Apply conversions from FROM_VERSION to TO_VERSION.  Return
100 tuple (LAST,STR), with the last succesful conversion and the resulting
101 string."""
102         conv_list = get_conversions (from_version, to_version)
103
104         if error_file:
105                 error_file.write (_ ("Applying conversion: "))
106                 
107         last_conversion = ()
108         try:
109                 for x in conv_list:
110                         error_file.write (tup_to_str (x[0]))
111                         if x != conv_list[-1]:
112                                 error_file.write (', ')
113                         str = x[1] (str)
114                         last_conversion = x[0]
115
116         except FatalConversionError:
117                 error_file.write (_ ("error while converting")) 
118                 error_file.write ('\n')
119                 error_file.write (_ ("Aborting"))
120                 error_file.write ('\n')
121
122
123
124         return (last_conversion, str)
125
126
127
128 def guess_lilypond_version (filename):
129         s = open (filename).read ()
130         m = lilypond_version_re.search (s)
131         if m:
132                 return m.group (1)
133         else:
134                 return ''
135
136 class FatalConversionError:
137         pass
138
139 class UnknownVersion:
140         pass
141
142 def do_one_file (infile_name):
143         sys.stderr.write (_ ("Processing `%s\'... ") % infile_name)
144         sys.stderr.write ('\n')
145         outfile_name = ''
146         if __main__.edit:
147                 outfile_name = infile_name + '.NEW'
148         elif __main__.outfile_name:
149                 outfile_name = __main__.outfile_name
150
151         if __main__.from_version:
152                 from_version = __main__.from_version
153         else:
154                 guess = guess_lilypond_version (infile_name)
155                 if not guess:
156                         raise UnknownVersion ()
157                 from_version = str_to_tuple (guess)
158
159         if __main__.to_version:
160                 to_version = __main__.to_version
161         else:
162                 to_version = latest_version ()
163
164
165         if infile_name:
166                 infile = open (infile_name, 'r')
167         else:
168                 infile = sys.stdin
169
170
171         (last, result) = do_conversion (infile.read (), from_version, to_version)
172         infile.close ()
173
174         if last:
175                 newversion = r'\version "%s"' % tup_to_str (last)
176                 if lilypond_version_re.search (result):
177                         result = re.sub (lilypond_version_re_str,
178                                          '\\' + newversion, result)
179                 elif add_version:
180                         result = newversion + '\n' + result
181                         
182                 error_file.write ('\n')                 
183         
184                 if __main__.edit:
185                         try:
186                                 os.remove(infile_name + '~')
187                         except:
188                                 pass
189                         os.rename (infile_name, infile_name + '~')
190                         outfile = open (infile_name, 'w')
191                 else:
192                         outfile = sys.stdout
193
194
195                 outfile.write (result)
196
197         sys.stderr.flush ()
198
199 edit = 0
200 to_version = ()
201 from_version = ()
202 outfile_name = ''
203 show_rules_p = 0
204
205 def do_options ():
206         global from_version, to_version, edit, show_rules_p, add_version
207
208         (sh, long) = ly.getopt_args (option_definitions)
209         try:
210                 (options, files) = getopt.getopt (sys.argv[1:], sh, long)
211         except getopt.error, s:
212                 sys.stderr.write ('\n')
213                 ly.error (_ ("getopt says: `%s'" % s))
214                 sys.stderr.write ('\n')
215                 ly.help ()
216                 ly.exit (2)
217
218         for opt in options:
219                 o = opt[0]
220                 a = opt[1]
221
222                 if o == '--help' or o == '-h':
223                         ly.help ()
224                         sys.exit (0)
225                 elif o == '--version' or o == '-v':
226                         ly.identify (sys.stdout)
227                         sys.exit (0)
228                 elif o== '--from' or o=='-f':
229                         from_version = str_to_tuple (a)
230                 elif o== '--to' or o=='-t':
231                         to_version = str_to_tuple (a)
232                 elif o== '--edit' or o == '-e':
233                         edit = 1
234                 elif o== '--show-rules' or o == '-s':
235                         show_rules_p = 1
236                 elif o == '--no-version' or o == '-n':
237                         add_version = 0
238                 else:
239                         print o
240                         raise getopt.error
241
242         return files
243
244
245 def main ():
246         files = do_options ()
247
248         # should parse files[] to read \version?
249         if show_rules_p:
250                 show_rules (sys.stdout, from_version, to_version)
251                 sys.exit (0)
252
253         ly.identify (sys.stderr)
254
255         if not files:
256                 ly.help ()
257                 sys.exit (2)
258
259         for f in files:
260                 if f == '-':
261                         f = ''
262                 elif not os.path.isfile (f):
263                         ly.error (_ ("can't open file: `%s'") % f)
264                         if len (files) == 1:
265                                 sys.exit (1)
266                         continue
267                 try:
268                         do_one_file (f)
269                 except UnknownVersion:
270                         ly.error (_ ("can't determine version for `%s'. Skipping") % f)
271
272         sys.stderr.write ('\n')
273
274 main ()