3 # convert-mudela.py -- convertor for mudela versions
5 # source file of the GNU LilyPond music typesetter
10 # use -f and -t for -s output
16 program_name = 'convert-mudela'
28 mudela_version_re_str = '\\\\version *\"(.*)\"'
29 mudela_version_re = re.compile(mudela_version_re_str)
32 return '%s version %s' %(program_name, version);
35 sys.stderr.write (program_id () + '\n')
44 print 'can\'t open file: ' + f + '\n'
48 print 'gulped empty file: ' + f + '\n'
54 return tuple (map (atoi, split (s,'.')))
57 return join (map (lambda x: '%s' % x, list (t)), '.')
59 def version_cmp (t1, t2):
66 def guess_mudela_version(filename):
67 s = gulp_file (filename)
68 m = mudela_version_re.search (s)
76 ("Usage: %s [OPTION]... [FILE]...\n"
77 + "Try to convert to newer mudela-versions\n"
79 + " -h, --help print this help\n"
80 + ' -e, --edit in place edit\n'
81 + ' -f, --from=VERSION start from version\n'
82 + ' -s, --show-rules print out all rules.\n'
83 + ' -t, --to=VERSION target version\n') % program_name)
86 class FatalConversionError:
91 def show_rules (file):
93 file.write ('%s: %s\n' % (tup_to_str (x[0]), x[2]))
95 ############################
97 if 1: # need new a namespace
101 if re.search ('\\\\octave', x):
105 sys.stderr.write ('\nNot smart enough to convert \\octave')
106 raise FatalConversionError()
111 ((0,1,19), conv, 'deprecated \\octave; can\'t convert automatically'))
114 if 1: # need new a namespace
118 x = re.sub ('\\\\textstyle([^;]+);',
119 '\\\\property Lyrics . textstyle = \\1', x)
120 x = re.sub ('\\\\key([^;]+);', '\\\\accidentals \\1;', x)
126 ((0,1,20), conv, 'deprecated \\textstyle, new \key syntax'))
129 if 1: # need new a namespace
133 x = re.sub ('\\\\musical_pitch',
134 '\\\\musicalpitch',x)
135 x = re.sub ('\\\\meter',
142 ((0,1,21), conv, '\\musical_pitch -> \\musicalpitch, '+
143 '\\meter -> \\time'))
145 if 1: # need new a namespace
150 ((1,0,0), conv, '0.1.21 -> 1.0.0 '))
153 if 1: # need new a namespace
157 x = re.sub ('\\\\accidentals',
158 '\\\\keysignature',x)
159 x = re.sub ('specialaccidentals *= *1',
160 'keyoctaviation = 0',x)
161 x = re.sub ('specialaccidentals *= *0',
162 'keyoctaviation = 1',x)
168 ((1,0,1), conv, '\\accidentals -> \\keysignature, ' +
169 'specialaccidentals -> keyoctaviation'))
175 if re.search ('\\\\header', x):
179 sys.stderr.write ('\nNot smart enough to convert to new \\header format')
182 conversions.append ((1,0,2), conv, '\\header { key = concat + with + operator }')
188 x = re.sub ('\\\\melodic', '\\\\notes',x)
192 conversions.append ((1,0,3), conv, '\\melodic -> \\notes')
198 x = re.sub ('default_paper *=', '',x)
199 x = re.sub ('default_midi *=', '',x)
203 conversions.append ((1,0,4), conv, 'default_{paper,midi}')
209 x = re.sub ('ChoireStaff', 'ChoirStaff',x)
210 x = re.sub ('\\output', 'output = ',x)
214 conversions.append ((1,0,5), conv, 'ChoireStaff -> ChoirStaff')
221 found = re.search ('[a-zA-Z]+ = *\\translator',x)
225 sys.stderr.write ('\nNot smart enough to \\translator syntax')
226 raise FatalConversionError()
229 conversions.append ((1,0,6), conv, 'foo = \\translator {\\type .. } ->\\translator {\\type ..; foo; }')
236 x = re.sub ('\\\\lyric', '\\\\lyrics',x)
240 conversions.append ((1,0,7), conv, '\\lyric -> \\lyrics')
246 x = re.sub ('\\\\\\[/3+', '\\\\times 2/3 { ',x)
247 x = re.sub ('\\[/3+', '\\\\times 2/3 { [',x)
248 x = re.sub ('\\\\\\[([0-9/]+)', '\\\\times \\1 {',x)
249 x = re.sub ('\\[([0-9/]+)', '\\\\times \\1 { [',x)
250 x = re.sub ('\\\\\\]([0-9/]+)', '}', x)
251 x = re.sub ('\\\\\\]', '}',x)
252 x = re.sub ('\\]([0-9/]+)', '] }', x)
257 conversions.append ((1,0,10), conv, '[2/3 ]1/1 -> \\times 2/3 ')
260 ############################
263 def get_conversions (from_version, to_version):
264 def version_b (v, f = from_version, t = to_version):
265 return version_cmp (v[0], f) > 0 and version_cmp (v[0], t) <= 0
266 return filter (version_b, conversions)
269 def latest_version ():
270 return conversions[-1][0]
272 def do_conversion (infile, from_version, outfile, to_version):
274 conv_list = get_conversions (from_version, to_version)
276 sys.stderr.write ('Applying conversions: ')
277 lines = infile.readlines();
281 sys.stderr.write (tup_to_str (x[0]) + ', ')
283 last_conversion = x[0]
286 except FatalConversionError:
287 sys.stderr.write ('Error while converting; I won\'t convert any further')
291 x = re.sub (mudela_version_re_str, '\\\\version \"%s\"' % tup_to_str (last_conversion), x)
294 class UnknownVersion:
297 def do_one_file (infile_name):
298 sys.stderr.write ('Processing `%s\' ... '% infile_name)
301 outfile_name = infile_name + '.NEW'
302 elif __main__.outfile_name:
303 outfile_name = __main__.outfile_name
305 if __main__.from_version:
306 from_version = __main__.from_version
308 guess = guess_mudela_version (infile_name)
310 raise UnknownVersion()
311 from_version = str_to_tuple (guess)
313 if __main__.to_version:
314 to_version = __main__.to_version
316 to_version = latest_version ()
320 infile = open (infile_name,'r')
325 outfile = open (outfile_name, 'w')
330 do_conversion (infile, from_version, outfile, to_version)
340 os.remove(infile_name + '~')
343 os.rename (infile_name, infile_name + '~')
344 os.rename (infile_name + '.NEW', infile_name)
346 sys.stderr.write ('\n')
355 (options, files) = getopt.getopt (
356 sys.argv[1:], 'f:t:seh', ['show-rules', 'help', 'edit', 'from', 'to'])
361 if o== '--help' or o == '-h':
363 elif o== '--from' or o=='-f':
364 from_version = str_to_tuple (a)
365 elif o== '--to' or o=='-t':
366 to_version = str_to_tuple (a)
367 elif o== '--edit' or o == '-e':
369 elif o== '--show-rules' or o == '-s':
370 show_rules (sys.stdout)
382 except UnknownVersion: