3 # convert-ly.py -- Update old LilyPond input files (fix name?)
4 # converting rules are found in python/convertrules.py
6 # This file is part of LilyPond, the GNU music typesetter.
8 # Copyright (C) 1998--2010 Han-Wen Nienhuys <hanwen@xs4all.nl>
9 # Jan Nieuwenhuizen <janneke@gnu.org>
11 # LilyPond is free software: you can redistribute it and/or modify
12 # it under the terms of the GNU General Public License as published by
13 # the Free Software Foundation, either version 3 of the License, or
14 # (at your option) any later version.
16 # LilyPond is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 # GNU General Public License for more details.
21 # You should have received a copy of the GNU General Public License
22 # along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
35 ly
.require_python_version ()
39 lilypond_version_re_str
= '\\\\version *\"([0-9.]+)"'
40 lilypond_version_re
= re
.compile (lilypond_version_re_str
)
44 _ ('''Update LilyPond input to newer version. By default, update from the
45 version taken from the \\version command, to the current LilyPond version.''')
48 $ convert-ly -e old.ly
49 $ convert-ly --from=2.3.28 --to=2.5.21 foobar.ly > foobar-new.ly
52 copyright
= ('Jan Nieuwenhuizen <janneke@gnu.org>',
53 'Han-Wen Nienhuys <hanwen@xs4all.nl>')
55 program_name
= os
.path
.basename (sys
.argv
[0])
56 program_version
= '@TOPLEVEL_VERSION@'
58 authors
= ('Jan Nieuwenhuizen <janneke@gnu.org>',
59 'Han-Wen Nienhuys <hanwen@xs4all.nl>')
61 error_file_write
= ly
.stderr_write
64 ly
.stderr_write (program_name
+ ": " + _ ("warning: %s") % s
+ '\n')
67 ly
.stderr_write (program_name
+ ": " + _ ("error: %s") % s
+ '\n')
69 def identify (port
=sys
.stderr
):
70 ly
.encoded_write (port
, '%s (GNU LilyPond) %s\n' % (program_name
, program_version
))
74 ly
.encoded_write (sys
.stdout
, '''
81 ''' % ( _ ('Copyright (c) %s by') % '2001--2010',
83 _ ('Distributed under terms of the GNU General Public License.'),
84 _ ('It comes with NO WARRANTY.')))
86 def get_option_parser ():
87 p
= ly
.get_option_parser (usage
=_ ("%s [OPTION]... FILE") % 'convert-ly',
88 description
=help_summary
,
89 add_help_option
=False)
91 p
.version
="@TOPLEVEL_VERSION@"
92 p
.add_option("--version",
94 help=_ ("show version number and exit"))
96 p
.add_option("-h", "--help",
98 help=_ ("show this help and exit"))
100 p
.add_option ('-f', '--from',
102 metavar
=_ ("VERSION"),
104 help=_ ("start from VERSION [default: \\version found in file]"),
107 p
.add_option ('-e', '--edit', help=_ ("edit in place"),
110 p
.add_option ('-n', '--no-version',
111 help=_ ("do not add \\version command if missing"),
113 dest
='skip_version_add',
116 p
.add_option ('-c', '--current-version',
117 help=_ ("force updating \\version number to %s") % program_version
,
119 dest
='force_current_version',
122 p
.add_option ("-s", '--show-rules',
123 help=_ ("show rules [default: -f 0, -t %s]") % program_version
,
125 action
='store_true', default
=False)
127 p
.add_option ('-t', '--to',
128 help=_ ("convert to VERSION [default: %s]") % program_version
,
129 metavar
=_ ('VERSION'),
133 p
.add_option ('-w', '--warranty', help=_ ("show warranty and copyright"),
136 p
.add_option_group ('',
138 _ ("Report bugs via %s")
139 % 'http://post.gmane.org/post.php'
140 '?group=gmane.comp.gnu.lilypond.bugs') + '\n')
146 def str_to_tuple (s
):
147 return tuple ([int(n
) for n
in s
.split ('.')])
150 return '.'.join (['%s' % x
for x
in t
])
152 def version_cmp (t1
, t2
):
158 def get_conversions (from_version
, to_version
):
159 def is_applicable (v
, f
= from_version
, t
= to_version
):
160 return version_cmp (v
[0], f
) > 0 and version_cmp (v
[0], t
) <= 0
161 return filter (is_applicable
, convertrules
.conversions
)
163 def latest_version ():
164 return convertrules
.conversions
[-1][0]
166 def show_rules (file, from_version
, to_version
):
167 for x
in convertrules
.conversions
:
168 if (not from_version
or x
[0] > from_version
) \
169 and (not to_version
or x
[0] <= to_version
):
170 ly
.encoded_write (file, '%s: %s\n' % (tup_to_str (x
[0]), x
[2]))
172 def do_conversion (str, from_version
, to_version
):
173 """Apply conversions from FROM_VERSION to TO_VERSION. Return
174 tuple (LAST,STR), with the last succesful conversion and the resulting
176 conv_list
= get_conversions (from_version
, to_version
)
178 error_file_write (_ ("Applying conversion: "))
183 error_file_write (tup_to_str (x
[0]))
184 if x
!= conv_list
[-1]:
185 error_file_write (', ')
187 last_conversion
= x
[0]
189 except convertrules
.FatalConversionError
:
190 error_file_write ('\n'
191 + _ ("Error while converting")
193 + _ ("Stopping at last successful rule")
196 return (last_conversion
, str)
200 def guess_lilypond_version (input):
201 m
= lilypond_version_re
.search (input)
207 class FatalConversionError (Exception):
210 class UnknownVersion (Exception):
213 class InvalidVersion (Exception):
214 def __init__ (self
, version
):
215 self
.version
= version
217 def do_one_file (infile_name
):
218 ly
.stderr_write (_ ("Processing `%s\'... ") % infile_name
)
219 sys
.stderr
.write ('\n')
222 infile
= open (infile_name
, 'r')
223 input = infile
.read ()
226 input = sys
.stdin
.read ()
230 if global_options
.from_version
:
231 from_version
= global_options
.from_version
233 guess
= guess_lilypond_version (input)
235 raise UnknownVersion ()
236 from_version
= str_to_tuple (guess
)
238 if global_options
.to_version
:
239 to_version
= global_options
.to_version
241 to_version
= latest_version ()
243 if len (from_version
) != 3:
244 raise InvalidVersion (".".join ([str(n
) for n
in from_version
]))
247 (last
, result
) = do_conversion (input, from_version
, to_version
)
250 if global_options
.force_current_version
and last
== to_version
:
251 last
= str_to_tuple (program_version
)
253 newversion
= r
'\version "%s"' % tup_to_str (last
)
254 if lilypond_version_re
.search (result
):
255 result
= re
.sub (lilypond_version_re_str
,
256 '\\' + newversion
, result
)
257 elif not global_options
.skip_version_add
:
258 result
= newversion
+ '\n' + result
260 error_file_write ('\n')
262 if global_options
.edit
:
264 os
.remove(infile_name
+ '~')
267 os
.rename (infile_name
, infile_name
+ '~')
268 outfile
= open (infile_name
, 'w')
273 outfile
.write (result
)
278 opt_parser
= get_option_parser()
279 (options
, args
) = opt_parser
.parse_args ()
285 if options
.from_version
:
286 options
.from_version
= str_to_tuple (options
.from_version
)
287 if options
.to_version
:
288 options
.to_version
= str_to_tuple (options
.to_version
)
290 options
.outfile_name
= ''
291 global global_options
292 global_options
= options
294 if not args
and not options
.show_rules
:
295 opt_parser
.print_help ()
301 files
= do_options ()
303 # should parse files[] to read \version?
304 if global_options
.show_rules
:
305 show_rules (sys
.stdout
, global_options
.from_version
, global_options
.to_version
)
308 identify (sys
.stderr
)
313 elif not os
.path
.isfile (f
):
314 error (_ ("%s: Unable to open file") % f
)
320 except UnknownVersion
:
321 error (_ ("%s: Unable to determine version. Skipping") % f
)
322 except InvalidVersion
:
323 # Compat code for 2.x and 3.0 syntax ("except .. as v" doesn't
324 # work in python 2.4!):
325 t
, v
, b
= sys
.exc_info ()
326 error (_ ("%s: Invalid version string `%s' \n"
327 "Valid version strings consist of three numbers, "
328 "separated by dots, e.g. `2.8.12'") % (f
, v
.version
) )
330 sys
.stderr
.write ('\n')