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