]> git.donarmstrong.com Git - lilypond.git/blob - scripts/convert-ly.py
Merge commit 'ce4b499'
[lilypond.git] / scripts / convert-ly.py
1 #!@TARGET_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--2007  Han-Wen Nienhuys <hanwen@xs4all.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 string
16 import re
17
18 """
19 @relocate-preamble@
20 """
21
22 import lilylib as ly
23 global _;_=ly._
24
25 import convertrules
26
27 lilypond_version_re_str = '\\\\version *\"([0-9.]+)"'
28 lilypond_version_re = re.compile (lilypond_version_re_str)
29
30
31 help_summary = (
32 _ ('''Update LilyPond input to newer version.  By default, update from the
33 version taken from the \\version command, to the current LilyPond version.''')
34 + _ ("Examples:")
35 + '''
36   convert-ly -e old.ly
37   convert-ly --from=2.3.28 --to 2.5.21 foobar.ly
38 ''')
39
40 copyright = ('Jan Nieuwenhuizen <janneke@gnu.org>',
41              'Han-Wen Nienhuys <hanwen@xs4all.nl>')
42
43 program_name = os.path.basename (sys.argv[0])
44 program_version = '@TOPLEVEL_VERSION@'
45
46 def warning (s):
47     ly.stderr_write (program_name + ": " + _ ("warning: %s") % s + '\n')
48
49 def error (s):
50     ly.stderr_write (program_name + ": " + _ ("error: %s") % s + '\n')
51
52 def identify (port=sys.stderr):
53     ly.encoded_write (port, '%s (GNU LilyPond) %s\n' % (program_name, program_version))
54
55 def warranty ():
56     identify ()
57     ly.encoded_write (sys.stdout, '''
58 Copyright (c) %s by
59
60   Han-Wen Nienhuys
61   Jan Nieuwenhuizen
62
63 %s
64 %s
65 '''  ( '2001--2006',
66        _ ("Distributed under terms of the GNU General Public License."),
67        _ ('It comes with NO WARRANTY.')))
68
69
70 def get_option_parser ():
71     p = ly.get_option_parser (usage=_ ("%s [OPTION]... FILE") % 'convert-ly',
72                   version="@TOPLEVEL_VERSION@",
73                   description=help_summary)
74
75     p.add_option ('-f', '--from', 
76               action="store",
77               metavar=_ ("VERSION"),
78               dest="from_version",
79               help=_ ("start from VERSION [default: \\version found in file]"),
80               default='')
81     
82     p.add_option ('-e', '--edit', help=_ ("edit in place"),
83               action='store_true')
84     p.add_option ('-n', '--no-version',
85               help=_ ("do not add \\version command if missing"),
86               action='store_true',
87               dest='skip_version_add',
88               default=False)
89     
90     p.add_option ("-s", '--show-rules',
91               help=_ ("show rules [default: --from=0, --to=@TOPLEVEL_VERSION@]"),
92               dest='show_rules',
93               action='store_true', default=False)
94     
95     p.add_option ('-t', '--to',
96               help=_ ("convert to VERSION [default: @TOPLEVEL_VERSION@]"),
97               metavar=_ ('VERSION'),
98               action='store',
99               dest="to_version",
100               default='')
101
102     p.add_option_group ('bugs',
103                         description=(_ ("Report bugs via")
104                                      + ''' http://post.gmane.org/post.php'''
105                                      '''?group=gmane.comp.gnu.lilypond.bugs\n'''))
106     
107     return p
108
109
110
111 def str_to_tuple (s):
112     return tuple (map (int, string.split (s, '.')))
113
114 def tup_to_str (t):
115     return string.join (map (lambda x: '%s' % x, list (t)), '.')
116
117 def version_cmp (t1, t2):
118     for x in [0, 1, 2]:
119         if t1[x] - t2[x]:
120             return t1[x] - t2[x]
121     return 0
122
123 def get_conversions (from_version, to_version):
124     def is_applicable (v, f = from_version, t = to_version):
125         return version_cmp (v[0], f) > 0 and version_cmp (v[0], t) <= 0
126     return filter (is_applicable, convertrules.conversions)
127
128 def latest_version ():
129     return convertrules.conversions[-1][0]
130
131 def show_rules (file, from_version, to_version):
132     for x in convertrules.conversions:
133         if (not from_version or x[0] > from_version) \
134            and (not to_version or x[0] <= to_version):
135             file.write  ('%s: %s\n' % (tup_to_str (x[0]), x[2]))
136
137 def do_conversion (str, from_version, to_version):
138     """Apply conversions from FROM_VERSION to TO_VERSION.  Return
139 tuple (LAST,STR), with the last succesful conversion and the resulting
140 string."""
141     conv_list = get_conversions (from_version, to_version)
142
143     if convertrules.error_file:
144         convertrules.error_file.write (_ ("Applying conversion: "))
145         
146     last_conversion = ()
147     try:
148         for x in conv_list:
149             convertrules.error_file.write (tup_to_str (x[0]))
150             if x != conv_list[-1]:
151                 convertrules.error_file.write (', ')
152             str = x[1] (str)
153             last_conversion = x[0]
154
155     except convertrules.FatalConversionError:
156         convertrules.error_file.write ('\n'
157                                        + _ ("Error while converting")
158                                        + '\n'
159                                        + _ ("Stopping at last succesful rule")
160                                        + '\n')
161
162     return (last_conversion, str)
163
164
165
166 def guess_lilypond_version (filename):
167     s = open (filename).read ()
168     m = lilypond_version_re.search (s)
169     if m:
170         return m.group (1)
171     else:
172         return ''
173
174 class FatalConversionError:
175     pass
176
177 class UnknownVersion:
178     pass
179
180 def do_one_file (infile_name):
181     ly.stderr_write (_ ("Processing `%s\'... ") % infile_name)
182     sys.stderr.write ('\n')
183
184     from_version = None
185     to_version = None
186     if global_options.from_version:
187         from_version = global_options.from_version
188     else:
189         guess = guess_lilypond_version (infile_name)
190         if not guess:
191             raise UnknownVersion ()
192         from_version = str_to_tuple (guess)
193
194     if global_options.to_version:
195         to_version = global_options.to_version
196     else:
197         to_version = latest_version ()
198
199
200     if infile_name:
201         infile = open (infile_name, 'r')
202     else:
203         infile = sys.stdin
204
205
206     (last, result) = do_conversion (infile.read (), from_version, to_version)
207     infile.close ()
208
209     if last:
210         newversion = r'\version "%s"' % tup_to_str (last)
211         if lilypond_version_re.search (result):
212             result = re.sub (lilypond_version_re_str,
213                      '\\' + newversion, result)
214         elif not global_options.skip_version_add:
215             result = newversion + '\n' + result
216             
217         convertrules.error_file.write ('\n')            
218     
219         if global_options.edit:
220             try:
221                 os.remove(infile_name + '~')
222             except:
223                 pass
224             os.rename (infile_name, infile_name + '~')
225             outfile = open (infile_name, 'w')
226         else:
227             outfile = sys.stdout
228
229
230         outfile.write (result)
231
232     sys.stderr.flush ()
233
234 def do_options ():
235     opt_parser = get_option_parser()
236     (options, args) = opt_parser.parse_args ()
237
238
239     if options.from_version:
240         options.from_version = str_to_tuple (options.from_version)
241     if options.to_version:
242         options.to_version = str_to_tuple (options.to_version)
243
244     options.outfile_name = ''
245     global global_options
246     global_options = options
247
248     if not args and not options.show_rules:
249         opt_parser.print_help ()
250         sys.exit (2)
251
252     return args
253
254 def main ():
255     files = do_options ()
256
257     # should parse files[] to read \version?
258     if global_options.show_rules:
259         show_rules (sys.stdout, global_options.from_version, global_options.to_version)
260         sys.exit (0)
261
262     identify (sys.stderr)
263
264     for f in files:
265         if f == '-':
266             f = ''
267         elif not os.path.isfile (f):
268             error (_ ("cannot open file: `%s'") % f)
269             if len (files) == 1:
270                 sys.exit (1)
271             continue
272         try:
273             do_one_file (f)
274         except UnknownVersion:
275             error (_ ("cannot determine version for `%s'.  Skipping") % f)
276
277     sys.stderr.write ('\n')
278
279 main ()