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