]> git.donarmstrong.com Git - lilypond.git/blob - scripts/convert-mudela.py
release: 1.2.6
[lilypond.git] / scripts / convert-mudela.py
1 #!@PYTHON@
2
3 # convert-mudela.py -- convertor for mudela versions
4
5 # source file of the GNU LilyPond music typesetter
6
7 # (c) 1998 
8
9 # TODO
10 #   use -f and -t for -s output
11
12 # NEWS
13 # 0.2
14 #  - rewrite in python
15
16 program_name = 'convert-mudela'
17 version = '@TOPLEVEL_VERSION@'
18
19 import os
20 import sys
21 import __main__
22 import getopt
23 from string import *
24 import re
25 import time
26
27 mudela_version_re_str = '\\\\version *\"(.*)\"'
28 mudela_version_re = re.compile(mudela_version_re_str)
29
30 def program_id ():
31         return '%s (GNU LilyPond) %s' %(program_name,  version);
32
33 def identify ():
34         sys.stderr.write (program_id () + '\n')
35
36 def usage ():
37         sys.stdout.write (
38                 r"""Usage: %s [OPTION]... [FILE]... 
39 Try to convert to newer mudela-versions.  The version number of the
40 input is guessed by default from \version directive
41
42 Options:
43   -h, --help             print this help
44   -e, --edit             in place edit
45   -f, --from=VERSION     start from version
46   -s, --show-rules       print all rules.
47   -t, --to=VERSION       target version
48       --version          print program version
49
50 Report bugs to bugs-gnu-music@gnu.org
51
52 """ % program_name)
53         
54         
55         sys.exit (0)
56
57 def print_version ():
58         
59         sys.stdout.write (r"""%s
60
61 This is free software.  It is covered by the GNU General Public
62 License, and you are welcome to change it and/or distribute copies of
63 it under certain conditions.  invoke as `%s --warranty' for more
64 information.
65
66 """ % (program_id() , program_name))
67         
68 def gulp_file(f):
69         try:
70                 i = open(f)
71                 i.seek (0, 2)
72                 n = i.tell ()
73                 i.seek (0,0)
74         except:
75                 print 'can\'t open file: ' + f + '\n'
76                 return ''
77         s = i.read (n)
78         if len (s) <= 0:
79                 print 'gulped empty file: ' + f + '\n'
80         i.close ()
81         return s
82
83 def str_to_tuple (s):
84         return tuple (map (atoi, split (s,'.')))
85
86 def tup_to_str (t):
87         return join (map (lambda x: '%s' % x, list (t)), '.')
88
89 def version_cmp (t1, t2):
90         for x in [0,1,2]:
91                 if t1[x] - t2[x]:
92                         return t1[x] - t2[x]
93         return 0
94
95 def guess_mudela_version(filename):
96         s = gulp_file (filename)
97         m = mudela_version_re.search (s)
98         if m:
99                 return m.group(1)
100         else:
101                 return ''
102
103 class FatalConversionError:
104         pass
105
106 conversions = []
107
108 def show_rules (file):
109         for x in conversions:
110                 file.write  ('%s: %s\n' % (tup_to_str (x[0]), x[2]))
111
112 ############################
113                 
114 if 1:                                   # need new a namespace
115         def conv (lines):
116                 if re.search ('\\\\octave', str):
117                         sys.stderr.write ('\nNot smart enough to convert \\octave')
118                         raise FatalConversionError()
119                 
120                 return lines
121
122         conversions.append (
123                 ((0,1,19), conv, 'deprecated \\octave; can\'t convert automatically'))
124
125
126 if 1:                                   # need new a namespace
127         def conv (lines):
128                 x = re.sub ('\\\\textstyle([^;]+);',
129                                          '\\\\property Lyrics . textstyle = \\1', str)
130                 x = re.sub ('\\\\key([^;]+);', '\\\\accidentals \\1;', str)
131                         
132                 return str
133
134         conversions.append (
135                 ((0,1,20), conv, 'deprecated \\textstyle, new \key syntax'))
136
137
138 if 1:
139         def conv (lines):
140                 x = re.sub ('\\\\musical_pitch', '\\\\musicalpitch',str)
141                 x = re.sub ('\\\\meter', '\\\\time',str)
142                         
143                 return str
144
145         conversions.append (
146                 ((0,1,21), conv, '\\musical_pitch -> \\musicalpitch, '+
147                  '\\meter -> \\time'))
148
149 if 1:
150         def conv (lines):
151                 return lines
152
153         conversions.append (
154                 ((1,0,0), conv, '0.1.21 -> 1.0.0 '))
155
156
157 if 1:
158         def conv (lines):
159                 x = re.sub ('\\\\accidentals', '\\\\keysignature',str)
160                 x = re.sub ('specialaccidentals *= *1', 'keyoctaviation = 0',str)
161                 x = re.sub ('specialaccidentals *= *0', 'keyoctaviation = 1',str)
162                         
163                 return str
164
165         conversions.append (
166                 ((1,0,1), conv, '\\accidentals -> \\keysignature, ' +
167                  'specialaccidentals -> keyoctaviation'))
168
169 if 1:
170         def conv(lines):
171                 if re.search ('\\\\header', lines):
172                         sys.stderr.write ('\nNot smart enough to convert to new \\header format')
173                 return lines
174         
175         conversions.append ((1,0,2), conv, '\\header { key = concat + with + operator }')
176
177 if 1:
178         def conv(lines):
179                 x =  re.sub ('\\\\melodic', '\\\\notes',str)
180                         
181                 return str
182         
183         conversions.append ((1,0,3), conv, '\\melodic -> \\notes')
184
185 if 1:
186         def conv(lines):
187                 x =  re.sub ('default_paper *=', '',str)
188                 x =  re.sub ('default_midi *=', '',x)                   
189                         
190                 return str
191         
192         conversions.append ((1,0,4), conv, 'default_{paper,midi}')
193
194 if 1:
195         def conv(lines):
196                 x =  re.sub ('ChoireStaff', 'ChoirStaff',str)
197                 x =  re.sub ('\\output', 'output = ',str)
198                         
199                 return str
200         
201         conversions.append ((1,0,5), conv, 'ChoireStaff -> ChoirStaff')
202
203 if 1:
204         def conv(lines):
205                 if re.search ('[a-zA-Z]+ = *\\translator',str):
206                         sys.stderr.write ('\nNot smart enough to change \\translator syntax')
207                         raise FatalConversionError()
208                 return str
209         
210         conversions.append ((1,0,6), conv, 'foo = \\translator {\\type .. } ->\\translator {\\type ..; foo; }')
211
212
213 if 1:
214         def conv(lines):
215                 x =  re.sub ('\\\\lyric', '\\\\lyrics',str)
216                         
217                 return str
218         
219         conversions.append ((1,0,7), conv, '\\lyric -> \\lyrics')
220
221 if 1:
222         def conv(lines):
223                 x =  re.sub ('\\\\\\[/3+', '\\\\times 2/3 { ',str)
224                 x =  re.sub ('\\[/3+', '\\\\times 2/3 { [',str)
225                 x =  re.sub ('\\\\\\[([0-9/]+)', '\\\\times \\1 {',str)
226                 x =  re.sub ('\\[([0-9/]+)', '\\\\times \\1 { [',str)
227                 x =  re.sub ('\\\\\\]([0-9/]+)', '}', str)
228                 x =  re.sub ('\\\\\\]', '}',str)
229                 x =  re.sub ('\\]([0-9/]+)', '] }', str)
230                 return str
231         
232         conversions.append ((1,0,10), conv, '[2/3 ]1/1 -> \\times 2/3 ')
233
234 if 1:
235         def conv(lines):
236                 return lines
237         conversions.append ((1,0,12), conv, 'Chord syntax stuff')
238
239
240 if 1:
241         def conv(lines):
242                 
243                 
244                 x =  re.sub ('<([^>~]+)~([^>]*)>','<\\1 \\2> ~', str)
245                         
246                 return str
247         
248         conversions.append ((1,0,13), conv, '<a ~ b> c -> <a b> ~ c')
249
250 if 1:
251         def conv(lines):
252                 x =  re.sub ('<\\[','[<', str)
253                 x =  re.sub ('\\]>','>]', str)
254                         
255                 return str
256         
257         conversions.append ((1,0,14), conv, '<[a b> <a b]>c -> [<a b> <a b>]')
258
259
260 if 1:
261         def conv(lines):
262                 x =  re.sub ('\\\\type','\\\\context', str)
263                 x =  re.sub ('textstyle','textStyle', str)
264                         
265                 return str
266         
267         conversions.append ((1,0,16), conv, '\\type -> \\context, textstyle -> textStyle')
268
269
270 if 1:
271         def conv(lines):
272                 if re.search ('\\\\repeat',str):
273                         sys.stderr.write ('\nNot smart enough to convert \\repeat')
274                         raise FatalConversionError()
275                 return str
276         
277         conversions.append ((1,0,18), conv,
278                             '\\repeat NUM Music Alternative -> \\repeat FOLDSTR Music Alternative')
279
280 if 1:
281         def conv(lines):
282                 x =  re.sub ('SkipBars','skipBars', str)
283                 x =  re.sub ('fontsize','fontSize', str)
284                 x =  re.sub ('midi_instrument','midiInstrument', x)                     
285                         
286                 return str
287
288         conversions.append ((1,0,19), conv,
289                             'fontsize -> fontSize, midi_instrument -> midiInstrument, SkipBars -> skipBars')
290
291
292 if 1:
293         def conv(lines):
294                 x =  re.sub ('tieydirection','tieVerticalDirection', str)
295                 x =  re.sub ('slurydirection','slurVerticalDirection', str)
296                 x =  re.sub ('ydirection','verticalDirection', x)                       
297                         
298                 return str
299
300         conversions.append ((1,0,20), conv,
301                             '{,tie,slur}ydirection -> {v,tieV,slurV}erticalDirection')
302
303
304 if 1:
305         def conv(lines):
306                 x =  re.sub ('hshift','horizontalNoteShift', str)
307                         
308                 return str
309
310         conversions.append ((1,0,21), conv,
311                             'hshift -> horizontalNoteShift')
312
313
314 if 1:
315         def conv(lines):
316                 x =  re.sub ('\\\\grouping[^;]*;','', str)
317                         
318                 return str
319
320         conversions.append ((1,1,52), conv,
321                             'deprecate \\grouping')
322
323
324 if 1:
325         def conv(lines):
326                 x =  re.sub ('\\\\wheel','\\\\coda', str)
327                         
328                 return str
329
330         conversions.append ((1,1,55), conv,
331                             '\\wheel -> \\coda')
332
333 if 1:
334         def conv(lines):
335                 x =  re.sub ('keyoctaviation','keyOctaviation', str)
336                 x =  re.sub ('slurdash','slurDash', str)
337                         
338                 return str
339
340         conversions.append ((1,1,65), conv,
341                             'slurdash -> slurDash, keyoctaviation -> keyOctaviation')
342
343 if 1:
344         def conv(lines):
345                 x =  re.sub ('\\\\repeat *\"?semi\"?','\\\\repeat "volta"', str)
346                         
347                 return str
348
349         conversions.append ((1,1,66), conv,
350                             'semi -> volta')
351
352
353 if 1:
354         def conv(lines):
355                 x =  re.sub ('\"?beamAuto\"? *= *\"?0?\"?','noAutoBeaming = "1"', str)
356                         
357                 return str
358
359         conversions.append ((1,1,67), conv,
360                             'beamAuto -> noAutoBeaming')
361
362 if 1:
363         def conv(lines):
364                 x =  re.sub ('automaticMelismas', 'automaticMelismata', str)
365                         
366                 return str
367
368         conversions.append ((1,2,0), conv,
369                             'automaticMelismas -> automaticMelismata')
370
371 if 1:
372         def conv(lines):
373                 x =  re.sub ('dynamicDir', 'dynamicDirection', str)
374                         
375                 return str
376
377         conversions.append ((1,2,1), conv,
378                             'dynamicDir -> dynamicDirection')
379
380 ############################
381         
382
383 def get_conversions (from_version, to_version):
384         def version_b (v, f = from_version, t = to_version):
385                 return version_cmp (v[0], f) > 0 and version_cmp (v[0], t) <= 0
386         return filter (version_b, conversions)
387
388
389 def latest_version ():
390         return conversions[-1][0]
391
392 def do_conversion (infile, from_version, outfile, to_version):
393         
394         conv_list = get_conversions (from_version, to_version)
395
396         sys.stderr.write ('Applying conversions: ')
397         str = infile.read (-1)
398         last_conversion = ()
399         try:
400                 for x in conv_list:
401                         sys.stderr.write (tup_to_str (x[0])  + ', ')
402                         str = x[1] (str)
403                         last_conversion = x[0]
404
405         except FatalConversionError:
406                 sys.stderr.write ('Error while converting; I won\'t convert any further')
407
408         if last_conversion:
409                 sys.stderr.write ('\n')
410                 new_ver =  '\\\\version \"%s\"' % tup_to_str (last_conversion)
411                 if re.search (mudela_version_re_str):
412                         str = re.sub (mudela_version_re_str,new_ver , str)
413                 else:
414                         str = new_ver + '\n' + str
415
416                 outfile.write(str)
417
418 class UnknownVersion:
419         pass
420
421 def do_one_file (infile_name):
422         sys.stderr.write ('Processing `%s\' ... '% infile_name)
423         outfile_name = ''
424         if __main__.edit:
425                 outfile_name = infile_name + '.NEW'
426         elif __main__.outfile_name:
427                 outfile_name = __main__.outfile_name
428
429         if __main__.from_version:
430                 from_version = __main__.from_version
431         else:
432                 guess = guess_mudela_version (infile_name)
433                 if not guess:
434                         raise UnknownVersion()
435                 from_version = str_to_tuple (guess)
436
437         if __main__.to_version:
438                 to_version = __main__.to_version
439         else:
440                 to_version = latest_version ()
441
442
443         if infile_name:
444                 infile = open (infile_name,'r')
445         else:
446                 infile = sys.stdin
447
448         if outfile_name:
449                 outfile =  open (outfile_name, 'w')
450         else:
451                 outfile = sys.stdout
452
453         
454         do_conversion (infile, from_version, outfile, to_version)
455
456         if infile_name:
457                 infile.close ()
458
459         if outfile_name:
460                 outfile.close ()
461
462         if __main__.edit:
463                 try:
464                         os.remove(infile_name + '~')
465                 except:
466                         pass
467                 os.rename (infile_name, infile_name + '~')
468                 os.rename (infile_name + '.NEW', infile_name)
469
470         sys.stderr.write ('\n')
471         sys.stderr.flush ()
472
473 edit = 0
474 to_version = ()
475 from_version = ()
476 outfile_name = ''
477
478 (options, files) = getopt.getopt (
479         sys.argv[1:], 'o:f:t:seh', ['version', 'output', 'show-rules', 'help', 'edit', 'from=', 'to'])
480
481 for opt in options:
482         o = opt[0]
483         a = opt[1]
484         if o== '--help' or o == '-h':
485                 usage ()
486                 sys.exit (0)
487         if o == '--version' or o == '-v':
488                 print_version ()
489                 sys.exit (0)
490         elif o== '--from' or o=='-f':
491                 from_version = str_to_tuple (a)
492         elif o== '--to' or o=='-t':
493                 to_version = str_to_tuple (a)
494         elif o== '--edit' or o == '-e':
495                 edit = 1
496         elif o== '--show-rules' or o == '-s':
497                 show_rules (sys.stdout)
498                 sys.exit(0)
499         elif o == '--output' or o == '-o':
500                 outfile_name = a
501         else:
502                 print o
503                 raise getopt.error
504
505 identify ()
506 for f in files:
507         if f == '-':
508                 f = ''
509         try:
510                 do_one_file (f)
511         except UnknownVersion:
512                 pass