]> git.donarmstrong.com Git - lilypond.git/blob - bin/convert-mudela.py
ee6d05a22938dffc670d2335678df600fe3fda2d
[lilypond.git] / bin / 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.3'
18
19
20 import os
21 import sys
22 import __main__
23 import getopt
24 from string import *
25 import re
26
27 import time
28 mudela_version_re_str = '\\\\version *\"(.*)\"'
29 mudela_version_re = re.compile(mudela_version_re_str)
30
31 def program_id ():
32         return '%s version %s' %(program_name,  version);
33
34 def identify ():
35         sys.stderr.write (program_id () + '\n')
36
37 def gulp_file(f):
38         try:
39                 i = open(f)
40                 i.seek (0, 2)
41                 n = i.tell ()
42                 i.seek (0,0)
43         except:
44                 print 'can\'t open file: ' + f + '\n'
45                 return ''
46         s = i.read (n)
47         if len (s) <= 0:
48                 print 'gulped empty file: ' + f + '\n'
49         i.close ()
50         return s
51
52
53 def str_to_tuple (s):
54         return tuple (map (atoi, split (s,'.')))
55
56 def tup_to_str (t):
57         return join (map (lambda x: '%s' % x, list (t)), '.')
58
59 def version_cmp (t1, t2):
60         for x in [0,1,2]:
61                 if t1[x] - t2[x]:
62                         return t1[x] - t2[x]
63         return 0
64                 
65
66 def guess_mudela_version(filename):
67         s = gulp_file (filename)
68         m = mudela_version_re.search (s)
69         if m:
70                 return m.group(1)
71         else:
72                 return ''
73
74 def help ():
75         sys.stdout.write (
76                 ("Usage: %s [OPTION]... [FILE]...\n" 
77                 + "Try to convert to newer mudela-versions\n"
78                 + "Options:\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)
84         sys.exit (0)
85
86 class FatalConversionError:
87         pass
88
89 conversions = []
90
91 def show_rules (file):
92         for x in conversions:
93                 file.write  ('%s: %s\n' % (tup_to_str (x[0]), x[2]))
94
95 ############################
96                 
97 if 1:                                   # need new a namespace
98         def conv (lines):
99                 found =0
100                 for x in lines:
101                         if re.search ('\\\\octave', x):
102                                 found = 1
103                                 break
104                 if found:
105                         sys.stderr.write ('\nNot smart enough to convert \\octave')
106                         raise FatalConversionError()
107                 return lines
108                 
109
110         conversions.append (
111                 ((0,1,19), conv, 'deprecated \\octave; can\'t convert automatically'))
112
113
114 if 1:                                   # need new a namespace
115         def conv (lines):
116                 newlines = []
117                 for x in lines:
118                         x = re.sub ('\\\\textstyle([^;]+);',
119                                          '\\\\property Lyrics . textstyle = \\1', x)
120                         x = re.sub ('\\\\key([^;]+);', '\\\\accidentals \\1;', x)
121                         newlines.append (x)
122                 return newlines
123                 
124
125         conversions.append (
126                 ((0,1,20), conv, 'deprecated \\textstyle, new \key syntax'))
127
128
129 if 1:                                   # need new a namespace
130         def conv (lines):
131                 newlines = []
132                 for x in lines:
133                         x = re.sub ('\\\\musical_pitch',
134                                          '\\\\musicalpitch',x)
135                         x = re.sub ('\\\\meter',
136                                          '\\\\time',x)
137                         newlines.append (x)
138                 return newlines
139                 
140
141         conversions.append (
142                 ((0,1,21), conv, '\\musical_pitch -> \\musicalpitch, '+
143                  '\\meter -> \\time'))
144
145 if 1:                                   # need new a namespace
146         def conv (lines):
147                 return lines
148
149         conversions.append (
150                 ((1,0,0), conv, '0.1.21 -> 1.0.0 '))
151
152
153 if 1:                                   # need new a namespace
154         def conv (lines):
155                 newlines = []
156                 for x in lines:
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)
163                         newlines.append (x)
164                 return newlines
165                 
166
167         conversions.append (
168                 ((1,0,1), conv, '\\accidentals -> \\keysignature, ' +
169                  'specialaccidentals -> keyoctaviation'))
170
171 if 1:
172         def conv(lines):
173                 found = 0
174                 for x in lines:
175                         if re.search ('\\\\header', x):
176                                 found = 1
177                                 break
178                 if found:
179                         sys.stderr.write ('\nNot smart enough to convert to new \\header format')
180                 return lines
181         
182         conversions.append ((1,0,2), conv, '\\header { key = concat + with + operator }')
183
184 if 1:
185         def conv(lines):
186                 newlines =[]
187                 for x in lines:
188                         x =  re.sub ('\\\\melodic', '\\\\notes',x)
189                         newlines.append (x)
190                 return newlines
191         
192         conversions.append ((1,0,3), conv, '\\melodic -> \\notes')
193
194 if 1:
195         def conv(lines):
196                 newlines =[]
197                 for x in lines:
198                         x =  re.sub ('default_paper *=', '',x)
199                         x =  re.sub ('default_midi *=', '',x)                   
200                         newlines.append (x)
201                 return newlines
202         
203         conversions.append ((1,0,4), conv, 'default_{paper,midi}')
204
205 if 1:
206         def conv(lines):
207                 newlines =[]
208                 for x in lines:
209                         x =  re.sub ('ChoireStaff', 'ChoirStaff',x)
210                         x =  re.sub ('\\output', 'output = ',x)
211                         newlines.append (x)
212                 return newlines
213         
214         conversions.append ((1,0,5), conv, 'ChoireStaff -> ChoirStaff')
215
216 if 1:
217         def conv(lines):
218                 newlines =[]
219                 found = None
220                 for x in lines:
221                         found = re.search ('[a-zA-Z]+ = *\\translator',x)
222                         newlines.append (x)
223                         if found: break
224                 if found:
225                         sys.stderr.write ('\nNot smart enough to \\translator syntax')
226                         raise FatalConversionError()
227                 return newlines
228         
229         conversions.append ((1,0,6), conv, 'foo = \\translator {\\type .. } ->\\translator {\\type ..; foo; }')
230
231
232 if 1:
233         def conv(lines):
234                 newlines =[]
235                 for x in lines:
236                         x =  re.sub ('\\\\lyric', '\\\\lyrics',x)
237                         newlines.append (x)
238                 return newlines
239         
240         conversions.append ((1,0,7), conv, '\\lyric -> \\lyrics')
241
242
243 ############################
244         
245
246 def get_conversions (from_version, to_version):
247         def version_b (v, f = from_version, t = to_version):
248                 return version_cmp (v[0], f) > 0 and version_cmp (v[0], t) <= 0
249         return filter (version_b, conversions)
250
251
252 def latest_version ():
253         return conversions[-1][0]
254
255 def do_conversion (infile, from_version, outfile, to_version):
256         
257         conv_list = get_conversions (from_version, to_version)
258
259         sys.stderr.write ('Applying conversions: ')
260         lines = infile.readlines();
261         last_conversion = ()
262         try:
263                 for x in conv_list:
264                         sys.stderr.write (tup_to_str (x[0])  + ', ')
265                         lines = x[1] (lines)
266                         last_conversion = x[0]
267                         
268
269         except FatalConversionError:
270                 sys.stderr.write ('Error while converting; I won\'t convert any further')
271
272         for x in lines:
273                 if last_conversion:
274                         x = re.sub (mudela_version_re_str, '\\\\version \"%s\"' % tup_to_str (last_conversion), x)
275                 outfile.write(x)
276
277 class UnknownVersion:
278         pass
279
280 def do_one_file (infile_name):
281         sys.stderr.write ('Processing `%s\' ... '% infile_name)
282         outfile_name = ''
283         if __main__.edit:
284                 outfile_name = infile_name + '.NEW'
285         elif __main__.outfile_name:
286                 outfile_name = __main__.outfile_name
287
288         if __main__.from_version:
289                 from_version = __main__.from_version
290         else:
291                 guess = guess_mudela_version (infile_name)
292                 if not guess:
293                         raise UnknownVersion()
294                 from_version = str_to_tuple (guess)
295
296         if __main__.to_version:
297                 to_version = __main__.to_version
298         else:
299                 to_version = latest_version ()
300
301
302         if infile_name:
303                 infile = open (infile_name,'r')
304         else:
305                 infile = sys.stdin
306
307         if outfile_name:
308                 outfile =  open (outfile_name, 'w')
309         else:
310                 outfile = sys.stdout
311
312         
313         do_conversion (infile, from_version, outfile, to_version)
314
315         if infile_name:
316                 infile.close ()
317
318         if outfile_name:
319                 outfile.close ()
320
321         if __main__.edit:
322                 os.rename (infile_name, infile_name + '~')
323                 os.rename (infile_name + '.NEW', infile_name)
324
325         sys.stderr.write ('\n')
326         sys.stderr.flush ()
327
328 edit = 0
329 to_version = ()
330 from_version = ()
331 outfile_name = ''
332
333 identify ()
334 (options, files) = getopt.getopt (
335         sys.argv[1:], 'f:t:seh', ['show-rules', 'help', 'edit', 'from', 'to'])
336
337 for opt in options:
338         o = opt[0]
339         a = opt[1]
340         if o== '--help' or o == '-h':
341                 help ()
342         elif o== '--from' or o=='-f':
343                 from_version = str_to_tuple (a)
344         elif o== '--to' or o=='-t':
345                 to_version = str_to_tuple (a)
346         elif o== '--edit' or o == '-e':
347                 edit = 1
348         elif o== '--show-rules' or o == '-s':
349                 show_rules (sys.stdout)
350                 sys.exit(0)
351         else:
352                 print o
353                 raise getopt.error
354
355
356 for f in files:
357         if f == '-':
358                 f = ''
359         try:
360                 do_one_file (f)
361         except UnknownVersion:
362                 pass