]> git.donarmstrong.com Git - lilypond.git/blob - scripts/convert-mudela.py
release: 1.1.43
[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
328 ############################
329         
330
331 def get_conversions (from_version, to_version):
332         def version_b (v, f = from_version, t = to_version):
333                 return version_cmp (v[0], f) > 0 and version_cmp (v[0], t) <= 0
334         return filter (version_b, conversions)
335
336
337 def latest_version ():
338         return conversions[-1][0]
339
340 def do_conversion (infile, from_version, outfile, to_version):
341         
342         conv_list = get_conversions (from_version, to_version)
343
344         sys.stderr.write ('Applying conversions: ')
345         lines = infile.readlines();
346         last_conversion = ()
347         try:
348                 for x in conv_list:
349                         sys.stderr.write (tup_to_str (x[0])  + ', ')
350                         lines = x[1] (lines)
351                         last_conversion = x[0]
352                         
353
354         except FatalConversionError:
355                 sys.stderr.write ('Error while converting; I won\'t convert any further')
356
357         for x in lines:
358                 if last_conversion:
359                         x = re.sub (mudela_version_re_str, '\\\\version \"%s\"' % tup_to_str (last_conversion), x)
360                 outfile.write(x)
361
362 class UnknownVersion:
363         pass
364
365 def do_one_file (infile_name):
366         sys.stderr.write ('Processing `%s\' ... '% infile_name)
367         outfile_name = ''
368         if __main__.edit:
369                 outfile_name = infile_name + '.NEW'
370         elif __main__.outfile_name:
371                 outfile_name = __main__.outfile_name
372
373         if __main__.from_version:
374                 from_version = __main__.from_version
375         else:
376                 guess = guess_mudela_version (infile_name)
377                 if not guess:
378                         raise UnknownVersion()
379                 from_version = str_to_tuple (guess)
380
381         if __main__.to_version:
382                 to_version = __main__.to_version
383         else:
384                 to_version = latest_version ()
385
386
387         if infile_name:
388                 infile = open (infile_name,'r')
389         else:
390                 infile = sys.stdin
391
392         if outfile_name:
393                 outfile =  open (outfile_name, 'w')
394         else:
395                 outfile = sys.stdout
396
397         
398         do_conversion (infile, from_version, outfile, to_version)
399
400         if infile_name:
401                 infile.close ()
402
403         if outfile_name:
404                 outfile.close ()
405
406         if __main__.edit:
407                 try:
408                         os.remove(infile_name + '~')
409                 except:
410                         pass
411                 os.rename (infile_name, infile_name + '~')
412                 os.rename (infile_name + '.NEW', infile_name)
413
414         sys.stderr.write ('\n')
415         sys.stderr.flush ()
416
417 edit = 0
418 to_version = ()
419 from_version = ()
420 outfile_name = ''
421
422 identify ()
423 (options, files) = getopt.getopt (
424         sys.argv[1:], 'f:t:seh', ['show-rules', 'help', 'edit', 'from', 'to'])
425
426 for opt in options:
427         o = opt[0]
428         a = opt[1]
429         if o== '--help' or o == '-h':
430                 help ()
431         elif o== '--from' or o=='-f':
432                 from_version = str_to_tuple (a)
433         elif o== '--to' or o=='-t':
434                 to_version = str_to_tuple (a)
435         elif o== '--edit' or o == '-e':
436                 edit = 1
437         elif o== '--show-rules' or o == '-s':
438                 show_rules (sys.stdout)
439                 sys.exit(0)
440         else:
441                 print o
442                 raise getopt.error
443
444
445 for f in files:
446         if f == '-':
447                 f = ''
448         try:
449                 do_one_file (f)
450         except UnknownVersion:
451                 pass