]> git.donarmstrong.com Git - lilypond.git/blob - scripts/convert-ly.py
* Another grand 2003 update.
[lilypond.git] / scripts / convert-ly.py
1 #!@PYTHON@
2 #
3 # convert-ly.py -- Update old LilyPond input files (fix name?)
4
5 # source file of the GNU LilyPond music typesetter
6
7 # (c)  1998--2003  Han-Wen Nienhuys <hanwen@cs.uu.nl>
8 #                 Jan Nieuwenhuizen <janneke@gnu.org>
9
10
11 # TODO
12 #   use -f and -t for -s output
13
14 # NEWS
15 # 0.2
16 #  - rewrite in python
17
18 program_name = 'convert-ly'
19 version = '@TOPLEVEL_VERSION@'
20
21 import os
22 import sys
23 import __main__
24 import getopt
25 import  string
26 import re
27 import time
28
29 # Did we ever have \mudela-version?  I doubt it.
30 # lilypond_version_re_str = '\\\\version *\"(.*)\"'
31 lilypond_version_re_str = '\\\\(mudela-)?version *\"(.*)\"'
32 lilypond_version_re = re.compile (lilypond_version_re_str)
33 add_version = 1
34
35
36 def program_id ():
37         return '%s (GNU LilyPond) %s' %(program_name,  version);
38
39 def identify ():
40         sys.stderr.write (program_id () + '\n')
41
42 def usage ():
43         sys.stdout.write (
44                 r"""Usage: %s [OPTION]... [FILE]... 
45 Try to convert to newer lilypond-versions.  The version number of the
46 input is guessed by default from \version directive
47
48 Options:
49   -h, --help             print this help
50   -e, --edit             in place edit
51   -f, --from=VERSION     start from version. Overrides \version found in file.
52   -s, --show-rules       print all rules.
53   -t, --to=VERSION       target version
54   -n, --no-version       don't add new version stamp.
55       --version          print program version
56
57 Report bugs to bugs-gnu-music@gnu.org
58
59 """ % program_name)
60         
61         
62         sys.exit (0)
63
64 def print_version ():
65         
66         sys.stdout.write (r"""%s
67
68 This is free software.  It is covered by the GNU General Public
69 License, and you are welcome to change it and/or distribute copies of
70 it under certain conditions.  invoke as `%s --warranty' for more
71 information.
72
73 """ % (program_id() , program_name))
74         
75 def gulp_file(f):
76         try:
77                 i = open(f)
78                 i.seek (0, 2)
79                 n = i.tell ()
80                 i.seek (0,0)
81         except:
82                 print 'can\'t open file: ' + f + '\n'
83                 return ''
84         s = i.read (n)
85         if len (s) <= 0:
86                 print 'gulped empty file: ' + f + '\n'
87         i.close ()
88         return s
89
90 def str_to_tuple (s):
91         return tuple (map (string.atoi, string.split (s,'.')))
92
93 def tup_to_str (t):
94         return string.join (map (lambda x: '%s' % x, list (t)), '.')
95
96 def version_cmp (t1, t2):
97         for x in [0,1,2]:
98                 if t1[x] - t2[x]:
99                         return t1[x] - t2[x]
100         return 0
101
102 def guess_lilypond_version (filename):
103         s = gulp_file (filename)
104         m = lilypond_version_re.search (s)
105         if m:
106                 return m.group (2)
107         else:
108                 return ''
109
110 class FatalConversionError:
111         pass
112
113 conversions = []
114
115 def show_rules (file):
116         for x in conversions:
117                 file.write  ('%s: %s\n' % (tup_to_str (x[0]), x[2]))
118
119 ############################
120                 
121 if 1:
122         def conv(str):
123                 if re.search ('\\\\multi', str):
124                         sys.stderr.write ('\nNot smart enough to convert \\multi')
125                 return str
126         
127         conversions.append (((0,1,9), conv, '\\header { key = concat + with + operator }'))
128
129 if 1:                                   # need new a namespace
130         def conv (str):
131                 if re.search ('\\\\octave', str):
132                         sys.stderr.write ('\nNot smart enough to convert \\octave')
133                 #       raise FatalConversionError()
134                 
135                 return str
136
137         conversions.append ((
138                 ((0,1,19), conv, 'deprecated \\octave; can\'t convert automatically')))
139
140
141 if 1:                                   # need new a namespace
142         def conv (str):
143                 str = re.sub ('\\\\textstyle([^;]+);',
144                                          '\\\\property Lyrics . textstyle = \\1', str)
145                 # harmful to current .lys
146                 # str = re.sub ('\\\\key([^;]+);', '\\\\accidentals \\1;', str)
147                         
148                 return str
149
150         conversions.append ((
151                 ((0,1,20), conv, 'deprecated \\textstyle, new \key syntax')))
152
153
154 if 1:
155         def conv (str):
156                 str = re.sub ('\\\\musical_pitch', '\\\\musicalpitch',str)
157                 str = re.sub ('\\\\meter', '\\\\time',str)
158                         
159                 return str
160
161         conversions.append ((
162                 ((0,1,21), conv, '\\musical_pitch -> \\musicalpitch, '+
163                  '\\meter -> \\time')))
164
165 if 1:
166         def conv (str):
167                 return str
168
169         conversions.append ((
170                 ((1,0,0), conv, '0.1.21 -> 1.0.0 ')))
171
172
173 if 1:
174         def conv (str):
175                 str = re.sub ('\\\\accidentals', '\\\\keysignature',str)
176                 str = re.sub ('specialaccidentals *= *1', 'keyoctaviation = 0',str)
177                 str = re.sub ('specialaccidentals *= *0', 'keyoctaviation = 1',str)
178                         
179                 return str
180
181         conversions.append ((
182                 ((1,0,1), conv, '\\accidentals -> \\keysignature, ' +
183                  'specialaccidentals -> keyoctaviation')))
184
185 if 1:
186         def conv(str):
187                 if re.search ('\\\\header', str):
188                         sys.stderr.write ('\nNot smart enough to convert to new \\header format')
189                 return str
190         
191         conversions.append (((1,0,2), conv, '\\header { key = concat + with + operator }'))
192
193 if 1:
194         def conv(str):
195                 str =  re.sub ('\\\\melodic([^a-zA-Z])', '\\\\notes\\1',str)
196                 return str
197         
198         conversions.append (((1,0,3), conv, '\\melodic -> \\notes'))
199
200 if 1:
201         def conv(str):
202                 str =  re.sub ('default_paper *=', '',str)
203                 str =  re.sub ('default_midi *=', '',str)
204                 return str
205         
206         conversions.append (((1,0,4), conv, 'default_{paper,midi}'))
207
208 if 1:
209         def conv(str):
210                 str =  re.sub ('ChoireStaff', 'ChoirStaff',str)
211                 str =  re.sub ('\\\\output', 'output = ',str)
212                         
213                 return str
214         
215         conversions.append (((1,0,5), conv, 'ChoireStaff -> ChoirStaff'))
216
217 if 1:
218         def conv(str):
219                 if re.search ('[a-zA-Z]+ = *\\translator',str):
220                         sys.stderr.write ('\nNot smart enough to change \\translator syntax')
221                 #       raise FatalConversionError()
222                 return str
223         
224         conversions.append (((1,0,6), conv, 'foo = \\translator {\\type .. } ->\\translator {\\type ..; foo; }'))
225
226
227 if 1:
228         def conv(str):
229                 str =  re.sub ('\\\\lyrics*', '\\\\lyrics',str)
230                         
231                 return str
232         
233         conversions.append (((1,0,7), conv, '\\lyric -> \\lyrics'))
234
235 if 1:
236         def conv(str):
237                 str =  re.sub ('\\\\\\[/3+', '\\\\times 2/3 { ',str)
238                 str =  re.sub ('\\[/3+', '\\\\times 2/3 { [',str)
239                 str =  re.sub ('\\\\\\[([0-9/]+)', '\\\\times \\1 {',str)
240                 str =  re.sub ('\\[([0-9/]+)', '\\\\times \\1 { [',str)
241                 str =  re.sub ('\\\\\\]([0-9/]+)', '}', str)
242                 str =  re.sub ('\\\\\\]', '}',str)
243                 str =  re.sub ('\\]([0-9/]+)', '] }', str)
244                 return str
245         
246         conversions.append (((1,0,10), conv, '[2/3 ]1/1 -> \\times 2/3 '))
247
248 if 1:
249         def conv(str):
250                 return str
251         conversions.append (((1,0,12), conv, 'Chord syntax stuff'))
252
253
254 if 1:
255         def conv(str):
256                 
257                 
258                 str =  re.sub ('<([^>~]+)~([^>]*)>','<\\1 \\2> ~', str)
259                         
260                 return str
261         
262         conversions.append (((1,0,13), conv, '<a ~ b> c -> <a b> ~ c'))
263
264 if 1:
265         def conv(str):
266                 str =  re.sub ('<\\[','[<', str)
267                 str =  re.sub ('\\]>','>]', str)
268                         
269                 return str
270         
271         conversions.append (((1,0,14), conv, '<[a b> <a b]>c -> [<a b> <a b>]'))
272
273
274 if 1:
275         def conv(str):
276                 str =  re.sub ('\\\\type([^\n]*engraver)','\\\\TYPE\\1', str)
277                 str =  re.sub ('\\\\type([^\n]*performer)','\\\\TYPE\\1', str)
278                 str =  re.sub ('\\\\type','\\\\context', str)
279                 str =  re.sub ('\\\\TYPE','\\\\type', str)
280                 str =  re.sub ('textstyle','textStyle', str)
281                         
282                 return str
283         
284         conversions.append (((1,0,16), conv, '\\type -> \\context, textstyle -> textStyle'))
285
286
287 if 1:
288         def conv(str):
289                 if re.search ('\\\\repeat',str):
290                         sys.stderr.write ('\nNot smart enough to convert \\repeat')
291                 #       raise FatalConversionError()
292                 return str
293         
294         conversions.append (((1,0,18), conv,
295                 '\\repeat NUM Music Alternative -> \\repeat FOLDSTR Music Alternative'))
296
297 if 1:
298         def conv(str):
299                 str =  re.sub ('SkipBars','skipBars', str)
300                 str =  re.sub ('fontsize','fontSize', str)
301                 str =  re.sub ('midi_instrument','midiInstrument', str)                 
302                         
303                 return str
304
305         conversions.append (((1,0,19), conv,
306                 'fontsize -> fontSize, midi_instrument -> midiInstrument, SkipBars -> skipBars'))
307
308
309 if 1:
310         def conv(str):
311                 str =  re.sub ('tieydirection','tieVerticalDirection', str)
312                 str =  re.sub ('slurydirection','slurVerticalDirection', str)
313                 str =  re.sub ('ydirection','verticalDirection', str)                   
314                         
315                 return str
316
317         conversions.append (((1,0,20), conv,
318                 '{,tie,slur}ydirection -> {v,tieV,slurV}erticalDirection'))
319
320
321 if 1:
322         def conv(str):
323                 str =  re.sub ('hshift','horizontalNoteShift', str)
324                         
325                 return str
326
327         conversions.append (((1,0,21), conv,
328                 'hshift -> horizontalNoteShift'))
329
330
331 if 1:
332         def conv(str):
333                 str =  re.sub ('\\\\grouping[^;]*;','', str)
334                         
335                 return str
336
337         conversions.append (((1,1,52), conv,
338                 'deprecate \\grouping'))
339
340
341 if 1:
342         def conv(str):
343                 str =  re.sub ('\\\\wheel','\\\\coda', str)
344                         
345                 return str
346
347         conversions.append (((1,1,55), conv,
348                 '\\wheel -> \\coda'))
349
350 if 1:
351         def conv(str):
352                 str =  re.sub ('keyoctaviation','keyOctaviation', str)
353                 str =  re.sub ('slurdash','slurDash', str)
354                         
355                 return str
356
357         conversions.append (((1,1,65), conv,
358                 'slurdash -> slurDash, keyoctaviation -> keyOctaviation'))
359
360 if 1:
361         def conv(str):
362                 str =  re.sub ('\\\\repeat *\"?semi\"?','\\\\repeat "volta"', str)
363                         
364                 return str
365
366         conversions.append (((1,1,66), conv,
367                 'semi -> volta'))
368
369
370 if 1:
371         def conv(str):
372                 str =  re.sub ('\"?beamAuto\"? *= *\"?0?\"?','noAutoBeaming = "1"', str)
373                         
374                 return str
375
376         conversions.append (((1,1,67), conv,
377                 'beamAuto -> noAutoBeaming'))
378
379 if 1:
380         def conv(str):
381                 str =  re.sub ('automaticMelismas', 'automaticMelismata', str)
382                         
383                 return str
384
385         conversions.append (((1,2,0), conv,
386                 'automaticMelismas -> automaticMelismata'))
387
388 if 1:
389         def conv(str):
390                 str =  re.sub ('dynamicDir\\b', 'dynamicDirection', str)
391                         
392                 return str
393
394         conversions.append (((1,2,1), conv,
395                 'dynamicDir -> dynamicDirection'))
396
397 if 1:
398         def conv(str):
399                 str =  re.sub ('\\\\cadenza *0 *;', '\\\\cadenzaOff', str)
400                 str =  re.sub ('\\\\cadenza *1 *;', '\\\\cadenzaOn', str)               
401                         
402                 return str
403
404         conversions.append (((1,3,4), conv,
405                 '\\cadenza -> \cadenza{On|Off}'))
406
407 if 1:
408         def conv (str):
409                 str = re.sub ('"?beamAuto([^"=]+)"? *= *"([0-9]+)/([0-9]+)" *;*',
410                               'beamAuto\\1 = #(make-moment \\2 \\3)',
411                               str)
412                 return str
413
414         conversions.append (((1,3,5), conv, 'beamAuto moment properties'))
415
416 if 1:
417         def conv (str):
418                 str = re.sub ('stemStyle',
419                               'flagStyle',
420                               str)
421                 return str
422
423         conversions.append (((1,3,17), conv, 'stemStyle -> flagStyle'))
424
425 if 1:
426         def conv (str):
427                 str = re.sub ('staffLineLeading',
428                               'staffSpace',
429                               str)
430                 return str
431
432         conversions.append (((1,3,18), conv, 'staffLineLeading -> staffSpace'))
433
434
435 if 1:
436         def conv(str):
437                 if re.search ('\\\\repetitions',str):
438                         sys.stderr.write ('\nNot smart enough to convert \\repetitions')
439                 #       raise FatalConversionError()
440                 return str
441         
442         conversions.append (((1,3,23), conv,
443                 '\\\\repetitions feature dropped'))
444
445
446 if 1:
447         def conv (str):
448                 str = re.sub ('textEmptyDimension *= *##t',
449                               'textNonEmpty = ##f',
450                               str)
451                 str = re.sub ('textEmptyDimension *= *##f',
452                               'textNonEmpty = ##t',
453                               str)
454                 return str
455
456         conversions.append (((1,3,35), conv, 'textEmptyDimension -> textNonEmpty'))
457
458 if 1:
459         def conv (str):
460                 str = re.sub ("([a-z]+)[ \t]*=[ \t]*\\\\musicalpitch *{([- 0-9]+)} *\n",
461                               "(\\1 . (\\2))\n", str)
462                 str = re.sub ("\\\\musicalpitch *{([0-9 -]+)}",
463                               "\\\\musicalpitch #'(\\1)", str)
464                 if re.search ('\\\\notenames',str):
465                         sys.stderr.write ('\nNot smart enough to convert to new \\notenames format')
466                 return str
467
468         conversions.append (((1,3,38), conv, '\musicalpitch { a b c } -> #\'(a b c)'))
469
470 if 1:
471         def conv (str):
472                 def replace (match):
473                         return '\\key %s;' % string.lower (match.group (1))
474                 
475                 str = re.sub ("\\\\key ([^;]+);",  replace, str)
476                 return str
477         
478         conversions.append (((1,3,39), conv, '\\key A ;  ->\\key a;'))
479
480 if 1:
481         def conv (str):
482                 if re.search ('\\[:',str):
483                         sys.stderr.write ('\nNot smart enough to convert to new tremolo format')
484                 return str
485
486         conversions.append (((1,3,41), conv,
487                 '[:16 c4 d4 ] -> \\repeat "tremolo" 2 { c16 d16 }'))
488
489 if 1:
490         def conv (str):
491                 str = re.sub ('Staff_margin_engraver' , 'Instrument_name_engraver', str)
492                 return str
493
494         conversions.append (((1,3,42), conv,
495                 'Staff_margin_engraver deprecated, use Instrument_name_engraver'))
496
497 if 1:
498         def conv (str):
499                 str = re.sub ('note[hH]eadStyle\\s*=\\s*"?(\\w+)"?' , "noteHeadStyle = #'\\1", str)
500                 return str
501
502         conversions.append (((1,3,49), conv,
503                 'noteHeadStyle value: string -> symbol'))
504
505 if 1:
506         def conv (str):
507                 if re.search ('\\\\keysignature', str):
508                         sys.stderr.write ('\nNot smart enough to convert to new tremolo format')
509                 return str
510
511
512         conversions.append (((1,3,58), conv,
513                 'noteHeadStyle value: string -> symbol'))
514
515 if 1:
516         def conv (str):
517                 str = re.sub (r"""\\key *([a-z]+) *;""", r"""\\key \1 \major;""",str);
518                 return str
519         conversions.append (((1,3,59), conv,
520                 '\key X ; -> \key X major; ')) 
521
522 if 1:
523         def conv (str):
524                 str = re.sub (r'latexheaders *= *"\\\\input ',
525                               'latexheaders = "',
526                               str)
527                 return str
528         conversions.append (((1,3,68), conv, 'latexheaders = "\\input global" -> latexheaders = "global"'))
529
530
531
532
533 # TODO: lots of other syntax change should be done here as well
534 if 1:
535         def conv (str):
536                 str = re.sub ('basicCollisionProperties', 'NoteCollision', str)
537                 str = re.sub ('basicVoltaSpannerProperties' , "VoltaBracket", str)
538                 str = re.sub ('basicKeyProperties' , "KeySignature", str)
539
540                 str = re.sub ('basicClefItemProperties' ,"Clef", str)
541
542
543                 str = re.sub ('basicLocalKeyProperties' ,"Accidentals", str)
544                 str = re.sub ('basicMarkProperties' ,"Accidentals", str)
545                 str = re.sub ('basic([A-Za-z_]+)Properties', '\\1', str)
546
547                 str = re.sub ('Repeat_engraver' ,'Volta_engraver', str)
548                 return str
549         
550         conversions.append (((1,3,92), conv, 'basicXXXProperties -> XXX, Repeat_engraver -> Volta_engraver'))
551
552 if 1:
553         def conv (str):
554                 # Ugh, but meaning of \stemup changed too
555                 # maybe we should do \stemup -> \stemUp\slurUp\tieUp ?
556                 str = re.sub ('\\\\stemup', '\\\\stemUp', str)
557                 str = re.sub ('\\\\stemdown', '\\\\stemDown', str)
558                 str = re.sub ('\\\\stemboth', '\\\\stemBoth', str)
559                 
560                 str = re.sub ('\\\\slurup', '\\\\slurUp', str)
561                 str = re.sub ('\\\\slurboth', '\\\\slurBoth', str)
562                 str = re.sub ('\\\\slurdown', '\\\\slurDown', str)
563                 str = re.sub ('\\\\slurdotted', '\\\\slurDotted', str)
564                 str = re.sub ('\\\\slurnormal', '\\\\slurNoDots', str)          
565                 
566                 str = re.sub ('\\\\shiftoff', '\\\\shiftOff', str)
567                 str = re.sub ('\\\\shifton', '\\\\shiftOn', str)
568                 str = re.sub ('\\\\shiftonn', '\\\\shiftOnn', str)
569                 str = re.sub ('\\\\shiftonnn', '\\\\shiftOnnn', str)
570
571                 str = re.sub ('\\\\onevoice', '\\\\oneVoice', str)
572                 str = re.sub ('\\\\voiceone', '\\\\voiceOne', str)
573                 str = re.sub ('\\\\voicetwo', '\\\\voiceTwo', str)
574                 str = re.sub ('\\\\voicethree', '\\\\voiceThree', str)
575                 str = re.sub ('\\\\voicefour', '\\\\voiceFour', str)
576
577                 # I don't know exactly when these happened...
578                 # ugh, we loose context setting here...
579                 str = re.sub ('\\\\property *[^ ]*verticalDirection[^=]*= *#?"?(1|(\\\\up))"?', '\\\\stemUp\\\\slurUp\\\\tieUp', str)
580                 str = re.sub ('\\\\property *[^ ]*verticalDirection[^=]*= *#?"?((-1)|(\\\\down))"?', '\\\\stemDown\\\\slurDown\\\\tieDown', str)
581                 str = re.sub ('\\\\property *[^ ]*verticalDirection[^=]*= *#?"?(0|(\\\\center))"?', '\\\\stemBoth\\\\slurBoth\\\\tieBoth', str)
582
583                 str = re.sub ('verticalDirection[^=]*= *#?"?(1|(\\\\up))"?', 'Stem \\\\override #\'direction = #0\nSlur \\\\override #\'direction = #0\n Tie \\\\override #\'direction = #1', str)
584                 str = re.sub ('verticalDirection[^=]*= *#?"?((-1)|(\\\\down))"?', 'Stem \\\\override #\'direction = #0\nSlur \\\\override #\'direction = #0\n Tie \\\\override #\'direction = #-1', str)
585                 str = re.sub ('verticalDirection[^=]*= *#?"?(0|(\\\\center))"?', 'Stem \\\\override #\'direction = #0\nSlur \\\\override #\'direction = #0\n Tie \\\\override #\'direction = #0', str)
586                 
587                 str = re.sub ('\\\\property *[^ .]*[.]?([a-z]+)VerticalDirection[^=]*= *#?"?(1|(\\\\up))"?', '\\\\\\1Up', str)
588                 str = re.sub ('\\\\property *[^ .]*[.]?([a-z]+)VerticalDirection[^=]*= *#?"?((-1)|(\\\\down))"?', '\\\\\\1Down', str)
589                 str = re.sub ('\\\\property *[^ .]*[.]?([a-z]+)VerticalDirection[^=]*= *#?"?(0|(\\\\center))"?', '\\\\\\1Both', str)
590
591                 # (lacks capitalisation slur -> Slur)
592                 str = re.sub ('([a-z]+)VerticalDirection[^=]*= *#?"?(1|(\\\\up))"?', '\\1 \\\\override #\'direction = #1', str)
593                 str = re.sub ('([a-z]+)VerticalDirection[^=]*= *#?"?((-1)|(\\\\down))"?', '\\1 \\override #\'direction = #-1', str)
594                 str = re.sub ('([a-z]+)VerticalDirection[^=]*= *#?"?(0|(\\\\center))"?', '\\1 \\\\override #\'direction = #0', str)
595
596                 ## dynamic..
597                 str = re.sub ('\\\\property *[^ .]*[.]?dynamicDirection[^=]*= *#?"?(1|(\\\\up))"?', '\\\\dynamicUp', str)
598                 str = re.sub ('\\\\property *[^ .]*[.]?dyn[^=]*= *#?"?((-1)|(\\\\down))"?', '\\\\dynamicDown', str)
599                 str = re.sub ('\\\\property *[^ .]*[.]?dyn[^=]*= *#?"?(0|(\\\\center))"?', '\\\\dynamicBoth', str)
600
601                 str = re.sub ('\\\\property *[^ .]*[.]?([a-z]+)Dash[^=]*= *#?"?(0|(""))"?', '\\\\\\1NoDots', str)
602                 str = re.sub ('\\\\property *[^ .]*[.]?([a-z]+)Dash[^=]*= *#?"?([1-9]+)"?', '\\\\\\1Dotted', str)
603
604                 str = re.sub ('\\\\property *[^ .]*[.]?noAutoBeaming[^=]*= *#?"?(0|(""))"?', '\\\\autoBeamOn', str)
605                 str = re.sub ('\\\\property *[^ .]*[.]?noAutoBeaming[^=]*= *#?"?([1-9]+)"?', '\\\\autoBeamOff', str)
606
607
608
609                 return str
610         
611         conversions.append (((1,3,93), conv,
612                 'property definiton case (eg. onevoice -> oneVoice)'))
613
614
615 if 1:
616         def conv (str):
617                 str = re.sub ('ChordNames*', 'ChordNames', str)
618                 if re.search ('\\\\textscript "[^"]* *"[^"]*"', str):
619                         sys.stderr.write ('\nNot smart enough to convert to new \\textscript markup text')
620
621                 str = re.sub ('\\textscript +("[^"]*")', '\\textscript #\\1', str)
622
623                 return str
624         
625         conversions.append (((1,3,97), conv, 'ChordName -> ChordNames'))
626
627
628 # TODO: add lots of these
629         
630 if 1:
631         def conv (str):
632                 str = re.sub ('\\\\property *"?Voice"? *[.] *"?textStyle"? *= *"([^"]*)"', '\\\\property Voice.TextScript \\\\set #\'font-style = #\'\\1', str)
633                 str = re.sub ('\\\\property *"?Lyrics"? *[.] *"?textStyle"? *= *"([^"]*)"', '\\\\property Lyrics.LyricText \\\\set #\'font-style = #\'\\1', str)
634
635                 str = re.sub ('\\\\property *"?([^.]+)"? *[.] *"?timeSignatureStyle"? *= *"([^"]*)"', '\\\\property \\1.TimeSignature \\\\override #\'style = #\'\\2', str) 
636
637                 str = re.sub ('"?timeSignatureStyle"? *= *#?""', 'TimeSignature \\\\override #\'style = ##f', str)
638                 
639                 str = re.sub ('"?timeSignatureStyle"? *= *#?"([^"]*)"', 'TimeSignature \\\\override #\'style = #\'\\1', str)
640                 
641                 str = re.sub ('#\'style *= #*"([^"])"', '#\'style = #\'\\1', str)
642                 
643                 str = re.sub ('\\\\property *"?([^.]+)"? *[.] *"?horizontalNoteShift"? *= *"?#?([-0-9]+)"?', '\\\\property \\1.NoteColumn \\\\override #\'horizontal-shift = #\\2', str) 
644
645                 # ugh
646                 str = re.sub ('\\\\property *"?([^.]+)"? *[.] *"?flagStyle"? *= *""', '\\\\property \\1.Stem \\\\override #\'flag-style = ##f', str)
647                 
648                 str = re.sub ('\\\\property *"?([^.]+)"? *[.] *"?flagStyle"? *= *"([^"]*)"', '\\\\property \\1.Stem \\\\override #\'flag-style = #\'\\2', str) 
649                 return str
650         
651         conversions.append (((1,3,98), conv, 'CONTEXT.textStyle -> GROB.#font-style '))
652
653 if 1:
654         def conv (str):
655                 str = re.sub ('"?beamAutoEnd_([0-9]*)"? *= *(#\\([^)]*\\))', 'autoBeamSettings \\push #\'(end 1 \\1 * *) = \\2', str)
656                 str = re.sub ('"?beamAutoBegin_([0-9]*)"? *= *(#\\([^)]*\))', 'autoBeamSettings \\push #\'(begin 1 \\1 * *) = \\2', str)
657                 str = re.sub ('"?beamAutoEnd"? *= *(#\\([^)]*\\))', 'autoBeamSettings \\push #\'(end * * * *) = \\1', str)
658                 str = re.sub ('"?beamAutoBegin"? *= *(#\\([^)]*\\))', 'autoBeamSettings \\push #\'(begin * * * *) = \\1', str)
659
660
661                 return str
662         
663         conversions.append (((1,3,102), conv, 'beamAutoEnd -> autoBeamSettings \\push (end * * * *)'))
664
665
666 if 1:
667         def conv (str):
668                 str = re.sub ('\\\\push', '\\\\override', str)
669                 str = re.sub ('\\\\pop', '\\\\revert', str)
670
671                 return str
672         
673         conversions.append (((1,3,111), conv, '\\push -> \\override, \\pop -> \\revert'))
674
675 if 1:
676         def conv (str):
677                 str = re.sub ('LyricVoice', 'LyricsVoice', str)
678                 # old fix
679                 str = re.sub ('Chord[Nn]ames*.Chord[Nn]ames*', 'ChordNames.ChordName', str)
680                 str = re.sub ('Chord[Nn]ames([ \t\n]+\\\\override)', 'ChordName\\1', str)
681                 return str
682         
683         conversions.append (((1,3,113), conv, 'LyricVoice -> LyricsVoice'))
684
685 def regularize_id (str):
686         s = ''
687         lastx = ''
688         for x in str:
689                 if x == '_':
690                         lastx = x
691                         continue
692                 elif x in string.digits:
693                         x = chr(ord (x) - ord ('0')  +ord ('A'))
694                 elif x not in string.letters:
695                         x = 'x'
696                 elif x in string.lowercase and lastx == '_':
697                         x = string.upper (x)
698                 s = s + x
699                 lastx = x
700         return s
701
702 if 1:
703         def conv (str):
704                 
705                 def regularize_dollar_reference (match):
706                         return regularize_id (match.group (1))
707                 def regularize_assignment (match):
708                         return '\n' + regularize_id (match.group (1)) + ' = '
709                 str = re.sub ('\$([^\t\n ]+)', regularize_dollar_reference, str)
710                 str = re.sub ('\n([^ \t\n]+)[ \t]*= *', regularize_assignment, str)
711                 return str
712         
713         conversions.append (((1,3,117), conv, 'identifier names: $!foo_bar_123 -> xfooBarABC'))
714
715
716 if 1:
717         def conv (str):
718                 def regularize_paper (match):
719                         return regularize_id (match.group (1))
720                 
721                 str = re.sub ('(paper_[a-z]+)', regularize_paper, str)
722                 str = re.sub ('sustainup', 'sustainUp', str)
723                 str = re.sub ('nobreak', 'noBreak', str)
724                 str = re.sub ('sustaindown', 'sustainDown', str)
725                 str = re.sub ('sostenutoup', 'sostenutoUp', str)
726                 str = re.sub ('sostenutodown', 'sostenutoDown', str)
727                 str = re.sub ('unachorda', 'unaChorda', str)
728                 str = re.sub ('trechorde', 'treChorde', str)
729         
730                 return str
731         
732         conversions.append (((1,3,120), conv, 'paper_xxx -> paperXxxx, pedalup -> pedalUp.'))
733
734 if 1:
735         def conv (str):
736                 str = re.sub ('drarnChords', 'chordChanges', str)
737                 str = re.sub ('\\musicalpitch', '\\pitch', str)
738                 return str
739         
740         conversions.append (((1,3,122), conv, 'drarnChords -> chordChanges, \\musicalpitch -> \\pitch'))
741
742 if 1:
743         def conv (str):
744                 str = re.sub ('ly-([sg])et-elt-property', 'ly-\\1et-grob-property', str)
745                 return str
746         
747         conversions.append (((1,3,136), conv, 'ly-X-elt-property -> ly-X-grob-property'))
748
749 if 1:
750         def conv (str):
751                 str = re.sub ('point-and-click +#t', 'point-and-click line-column-location', str)
752                 return str
753         
754         conversions.append (((1,3,138), conv, 'point-and-click argument changed to procedure.'))
755
756 if 1:
757         def conv (str):
758                 str = re.sub ('followThread', 'followVoice', str)
759                 str = re.sub ('Thread.FollowThread', 'Voice.VoiceFollower', str)
760                 str = re.sub ('FollowThread', 'VoiceFollower', str)
761                 return str
762         
763         conversions.append (((1,3,138), conv, 'followThread -> followVoice.'))
764
765 if 1:
766         def conv (str):
767                 str = re.sub ('font-point-size', 'font-design-size', str)
768                 return str
769         
770         conversions.append (((1,3,139), conv, 'font-point-size -> font-design-size.'))
771
772 if 1:
773         def conv (str):
774                 str = re.sub ('([a-zA-Z]*)NoDots', '\\1Solid', str)
775                 return str
776         
777         conversions.append (((1,3,141), conv, 'xNoDots -> xSolid'))
778
779 if 1:
780         def conv (str):
781                 str = re.sub ('([Cc])hord([ea])', '\\1ord\\2', str)
782                 return str
783         
784         conversions.append (((1,3,144), conv, 'Chorda -> Corda'))
785
786
787 if 1:
788         def conv (str):
789                 str = re.sub ('([A-Za-z]+)MinimumVerticalExtent', 'MinimumV@rticalExtent', str)
790                 str = re.sub ('([A-Za-z]+)ExtraVerticalExtent', 'ExtraV@rticalExtent', str)
791                 str = re.sub ('([A-Za-z]+)VerticalExtent', 'VerticalExtent', str)
792                 str = re.sub ('ExtraV@rticalExtent', 'ExtraVerticalExtent', str)
793                 str = re.sub ('MinimumV@rticalExtent', 'MinimumVerticalExtent', str)            
794                 return str
795
796         conversions.append (((1,3,145), conv,
797         'ContextNameXxxxVerticalExtent -> XxxxVerticalExtent'))
798
799 if 1:
800         def conv (str):
801                 str = re.sub ('\\\\key[ \t]*;', '\\key \\default;', str)
802                 str = re.sub ('\\\\mark[ \t]*;', '\\mark \\default;', str)
803
804                 # Make sure groups of more than one ; have space before
805                 # them, so that non of them gets removed by next rule
806                 str = re.sub ("([^ \n\t;]);(;+)", "\\1 ;\\2", str)
807                 
808                 # Only remove ; that are not after spaces, # or ;
809                 # Otherwise  we interfere with Scheme comments,
810                 # which is badbadbad.
811                 str = re.sub ("([^ \t;#]);", "\\1", str)
812
813                 return str
814         conversions.append (((1,3,146), conv, 'semicolons removed'))
815
816 if 1:
817         def conv (str):
818                 str = re.sub ('default-neutral-direction', 'neutral-direction',str)
819                 return str
820         conversions.append (((1,3,147), conv, 'default-neutral-direction -> neutral-direction'))
821
822 if 1:
823         def conv (str):
824                 str = re.sub ('\(align', '(axis', str)
825                 str = re.sub ('\(rows', '(columns', str)
826                 return str
827         conversions.append (((1,3,148), conv, '"(align" -> "(axis", "(rows" -> "(columns"'))
828
829
830 if 1:
831         def conv (str):
832                 str = re.sub ('SystemStartDelimiter', 'systemStartDelimiter', str)
833                 return str
834         conversions.append (((1,5,33), conv, 'SystemStartDelimiter -> systemStartDelimiter'))
835
836 if 1:
837         def conv (str):
838                 str = re.sub ('arithmetic-multiplier', 'spacing-increment', str)
839                 str = re.sub ('arithmetic-basicspace', 'shortest-duration-space', str)          
840                 return str
841         
842         conversions.append (((1,5,38), conv, 'SystemStartDelimiter -> systemStartDelimiter'))
843
844
845 if 1:
846         def conv (str):
847         
848                 def func(match):
849                         break_dict = {
850                         "Instrument_name": "instrument-name",
851                         "Left_edge_item": "left-edge",
852                         "Span_bar": "span-bar",
853                         "Breathing_sign": "breathing-sign",
854                         "Staff_bar": "staff-bar",
855                         "Clef_item": "clef",
856                         "Key_item": "key-signature",
857                         "Time_signature": "time-signature",
858                         "Custos": "custos"
859                         }
860                         props =  match.group (1)
861                         for (k,v) in break_dict.items():
862                                 props = re.sub (k, v, props)
863                         return  "breakAlignOrder = #'(%s)" % props
864
865                 str = re.sub ("breakAlignOrder *= *#'\\(([a-z_\n\tA-Z ]+)\\)",
866                               func, str)
867                 return str
868
869         # 40 ? 
870         conversions.append (((1,5,40), conv, 'breakAlignOrder property names'))
871         
872
873 if 1:
874         def conv (str):
875                 str = re.sub ('noAutoBeaming *= *##f', 'autoBeaming = ##t', str)
876                 str = re.sub ('noAutoBeaming *= *##t', 'autoBeaming = ##f', str)
877                 return str
878         
879         conversions.append (((1,5,49), conv, 'noAutoBeaming -> autoBeaming'))
880
881 if 1:
882         def conv (str):
883                 str = re.sub ('tuplet-bracket-visibility', 'bracket-visibility', str)
884                 str = re.sub ('tuplet-number-visibility', 'number-visibility', str)             
885                 return str
886         
887         conversions.append (((1,5,52), conv, 'tuplet-X-visibility -> X-visibility'))
888
889 if 1:
890         def conv (str):
891                 str = re.sub ('Pitch::transpose', 'ly-transpose-pitch', str)
892
893                 return str
894         
895         conversions.append (((1,5,56), conv, 'Pitch::transpose -> ly-transpose-pitch'))
896
897 if 1:
898         def conv (str):
899                 str = re.sub ('textNonEmpty *= *##t', "TextScript \\set #'no-spacing-rods = ##f", str)
900                 str = re.sub ('textNonEmpty *= *##f', "TextScript \\set #'no-spacing-rods = ##t", str)
901                 return str
902         
903         conversions.append (((1,5,58), conv, 'deprecate textNonEmpty'))
904
905
906 if 1:
907         def conv (str):
908                 str = re.sub ('MinimumVerticalExtent', 'minimumV@rticalExtent', str)
909                 str = re.sub ('minimumVerticalExtent', 'minimumV@rticalExtent', str)            
910                 str = re.sub ('ExtraVerticalExtent', 'extraV@rticalExtent', str)
911                 str = re.sub ('extraVerticalExtent', 'extraV@rticalExtent', str)                
912                 str = re.sub ('VerticalExtent', 'verticalExtent', str)
913                 str = re.sub ('extraV@rticalExtent', 'extraVerticalExtent', str)
914                 str = re.sub ('minimumV@rticalExtent', 'minimumVerticalExtent', str)            
915                 return str
916
917         conversions.append (((1,5,59), conv,
918         'XxxxVerticalExtent -> xxxVerticalExtent'))
919
920 if 1:
921         def conv (str):
922                 str = re.sub ('visibility-lambda', 'break-visibility', str)
923                 return str
924
925         conversions.append (((1,5,62), conv,
926         'visibility-lambda -> break-visibility'))
927         
928
929 if 1:
930         def conv (str):
931                 if re.search (r'\addlyrics',str) \
932                        and re.search ('automaticMelismata', str)  == None:
933                         sys.stderr.write  ('automaticMelismata is turned on by default since 1.5.67. Please fix this by hand.')
934                         raise FatalConversionError()
935                 return str
936
937         conversions.append (((1,5,67), conv,
938                              'automaticMelismata turned on by default'))
939
940 if 1:
941         def conv (str):
942                 str = re.sub ('ly-set-grob-property([^!])', 'ly-set-grob-property!\1', str)
943                 str = re.sub ('ly-set-mus-property([^!])', 'ly-set-mus-property!\1', str)               
944                 return str
945         
946         conversions.append (((1,5,68), conv, 'ly-set-X-property -> ly-set-X-property!'))
947
948 if 1:
949         def conv (str):
950                 str = re.sub ('extent-X', 'X-extent', str)
951                 str = re.sub ('extent-Y', 'Y-extent', str)              
952                 return str
953         
954         conversions.append (((1,5,71), conv, 'extent-[XY] -> [XY]-extent'))
955
956
957 if 1:
958         def conv (str):
959                 str = re.sub ("""#\(set! +point-and-click +line-column-location\)""",
960                               """#(set-point-and-click! \'line-column)""", str)
961                 str = re.sub ("""#\(set![ \t]+point-and-click +line-location\)""",
962                               '#(set-point-and-click! \'line)', str)
963                 str = re.sub ('#\(set! +point-and-click +#f\)',
964                               '#(set-point-and-click! \'none)', str)
965                 return str
966         
967         conversions.append (((1,5,72), conv, 'set! point-and-click -> set-point-and-click!'))
968
969
970 if 1:
971         def conv (str):
972                 str = re.sub ('flag-style', 'stroke-style', str)
973                 str = re.sub (r"""Stem([ ]+)\\override #'style""", r"""Stem \\override #'flag-style""", str);
974                 str = re.sub (r"""Stem([ ]+)\\set([ ]+)#'style""", r"""Stem \\set #'flag-style""", str);
975                 return str
976         
977         conversions.append (((1,6,5), conv, 'Stems: flag-style -> stroke-style; style -> flag-style'))
978
979
980 if 1:
981         def subst_req_name (match):
982                 return "(make-music-by-name \'%sEvent)" % regularize_id (match.group(1))
983
984         def conv (str):
985                 str = re.sub ('\\(ly-make-music *\"([A-Z][a-z_]+)_req\"\\)', subst_req_name, str)
986                 str = re.sub ('Request_chord', 'EventChord', str)
987                 return str
988         
989         conversions.append (((1,7,1), conv, 'ly-make-music foo_bar_req -> make-music-by-name FooBarEvent'))
990
991
992 if 1:
993         spanner_subst ={
994                 "text" : 'TextSpanEvent',
995                 "decrescendo" : 'DecrescendoEvent',
996                 "crescendo" : 'CrescendoEvent',
997                 "Sustain" : 'SustainPedalEvent',
998                 "slur" : 'SlurEvent',
999                 "UnaCorda" : 'UnaCordaEvent',
1000                 "Sostenuto" : 'SostenutoEvent',
1001                 }
1002         def subst_ev_name (match):
1003                 stype = 'STOP'
1004                 if re.search ('start', match.group(1)):
1005                         stype= 'START'
1006
1007                 mtype = spanner_subst[match.group(2)]
1008                 return "(make-span-event '%s %s)" % (mtype , stype)
1009
1010         def subst_definition_ev_name(match):
1011                 return ' = #%s' % subst_ev_name (match) 
1012         def subst_inline_ev_name (match):
1013                 s = subst_ev_name (match)
1014                 return '#(ly-export %s)' % s
1015         def subst_csp_definition (match):
1016                 return ' = #(make-event-chord (list %s))' % subst_ev_name (match)
1017         def subst_csp_inline (match):
1018                 return '#(ly-export (make-event-chord (list %s)))' % subst_ev_name (match)
1019                 
1020         def conv (str):
1021                 str = re.sub (r' *= *\\spanrequest *([^ ]+) *"([^"]+)"', subst_definition_ev_name, str)
1022                 str = re.sub (r'\\spanrequest *([^ ]+) *"([^"]+)"', subst_inline_ev_name, str)
1023                 str = re.sub (r' *= *\\commandspanrequest *([^ ]+) *"([^"]+)"', subst_csp_definition, str)
1024                 str = re.sub (r'\\commandspanrequest *([^ ]+) *"([^"]+)"', subst_csp_inline, str)
1025                 str = re.sub (r'ly-id ', 'ly-import ', str)
1026
1027                 str = re.sub (r' *= *\\script "([^"]+)"', ' = #(make-articulation "\\1")', str)
1028                 str = re.sub (r'\\script "([^"]+)"', '#(ly-export (make-articulation "\\1"))', str)
1029                 return str
1030
1031         conversions.append (((1,7,2), conv, '\\spanrequest -> #(make-span-event .. ), \script -> #(make-articulation .. )'))
1032
1033 if 1:
1034         def conv(str):
1035                 str = re.sub (r'\(ly-', '(ly:', str)
1036
1037                 changed = [
1038                         r'duration\?',
1039                         r'font-metric\?',
1040                         r'molecule\?',
1041                         r'moment\?',
1042                         r'music\?',
1043                         r'pitch\?',
1044                         'make-duration',
1045                         'music-duration-length',
1046                         'duration-log',
1047                         'duration-dotcount',
1048                         'intlog2',
1049                         'duration-factor',
1050                         'transpose-key-alist',
1051                         'get-system',
1052                         'get-broken-into',
1053                         'get-original',
1054                         'set-point-and-click!',
1055                         'make-moment',
1056                         'make-pitch',
1057                         'pitch-octave',
1058                         'pitch-alteration',
1059                         'pitch-notename',
1060                         'pitch-semitones',
1061                         r'pitch<\?',
1062                         r'dir\?',
1063                         'music-duration-compress',
1064                         'set-point-and-click!'
1065                         ]
1066
1067                 origre = r'\b(%s)' % string.join (changed, '|')
1068                 
1069                 str = re.sub (origre, r'ly:\1',str)
1070                 str = re.sub ('set-point-and-click!', 'set-point-and-click', str)
1071                 
1072                 return str
1073         
1074         conversions.append (((1,7,3), conv, 'ly- -> ly:'))
1075
1076 if 1:
1077         def conv(str):
1078                 if re.search ('new-chords-done',str):
1079                         return str
1080                 
1081                 str = re.sub (r'<<', '< <', str)
1082                 str = re.sub (r'>>', '> >', str)
1083                 return str
1084         
1085         conversions.append (((1,7,4), conv, '<< >> -> < <  > >'))
1086
1087 if 1:
1088         def conv(str):
1089                 str = re.sub (r"\\transpose", r"\\transpose c'", str)
1090                 str = re.sub (r"\\transpose c' *([a-z]+)'", r"\\transpose c \1", str)
1091                 return str
1092         conversions.append (((1,7,5), conv, '\\transpose TO -> \\transpose FROM  TO'))
1093
1094 if 1:
1095         def conv(str):
1096                 kws =   ['arpeggio',
1097                          'sustainDown',
1098                          'sustainUp',
1099                          'f',
1100                          'p',
1101                          'pp',
1102                          'ppp',
1103                          'fp',
1104                          'ff',
1105                          'mf',
1106                          'mp',
1107                          'sfz',
1108                          ]
1109
1110                 origstr = string.join (kws, '|')
1111                 str = re.sub (r'([^_^-])\\(%s)\b' % origstr, r'\1-\\\2', str)
1112                 return str
1113         conversions.append (((1,7,6), conv, 'note\\script -> note-\script'))
1114
1115
1116 if 1:
1117         def conv(str):
1118                 str = re.sub (r"\\property *ChordNames *\. *ChordName *\\(set|override) *#'style *= *#('[a-z]+)",
1119                               r"#(set-chord-name-style \2)", str)
1120                 str = re.sub (r"\\property *ChordNames *\. *ChordName *\\revert *#'style",
1121                               r"", str)
1122                 return str
1123         conversions.append (((1,7,10), conv, "\property ChordName #'style -> #(set-chord-name-style 'style)"))
1124         
1125
1126
1127 if 1:
1128         def conv(str):
1129                 str = re.sub (r"ly:transpose-pitch", "ly:pitch-transpose", str)
1130                 
1131                 return str
1132         conversions.append (((1,7,11), conv, "transpose-pitch -> pitch-transpose"))
1133
1134 if 1:
1135         def conv(str):
1136                 str = re.sub (r"ly:get-molecule-extent", "ly:molecule-get-extent", str)
1137                 str = re.sub (r"ly:set-molecule-extent!", "ly:molecule-set-extent!", str)
1138                 str = re.sub (r"ly:add-molecule", "ly:molecule-add", str)
1139                 str = re.sub (r"ly:combine-molecule-at-edge", "ly:molecule-combine-at-edge", str)
1140                 str = re.sub (r"ly:align-to!", "ly:molecule-align-to!", str)
1141                 
1142                 return str
1143         
1144         conversions.append (((1,7,13), conv, "ly:XX-molecule-YY -> ly:molecule-XX-YY")) 
1145
1146 if 1:
1147         def conv(str):
1148                 str = re.sub (r"linewidth *= *-[0-9.]+ *(\\mm|\\cm|\\in|\\pt)?", 'raggedright = ##t', str )
1149                 return str
1150         
1151         conversions.append (((1,7,15), conv, "linewidth = -1 -> raggedright = ##t"))    
1152
1153 if 1:
1154         def conv(str):
1155                 str = re.sub ("divisiomaior",
1156                               "divisioMaior", str)
1157                 str = re.sub ("divisiominima",
1158                               "divisioMinima", str)
1159                 str = re.sub ("divisiomaxima",
1160                               "divisioMaxima", str)
1161                 return str
1162         
1163         conversions.append (((1,7,16), conv, "divisiomaior -> divisioMaior"))
1164
1165 if 1:
1166         def conv(str):
1167                 str = re.sub ("Skip_req_swallow_translator",
1168                               "Skip_event_swallow_translator", str)
1169                 return str
1170         
1171         conversions.append (((1,7,17), conv, "Skip_req  -> Skip_event"))
1172
1173
1174 ################################
1175 #       END OF CONVERSIONS      
1176 ################################
1177
1178 def get_conversions (from_version, to_version):
1179         def version_b (v, f = from_version, t = to_version):
1180                 return version_cmp (v[0], f) > 0 and version_cmp (v[0], t) <= 0
1181         return filter (version_b, conversions)
1182
1183
1184 def latest_version ():
1185         return conversions[-1][0]
1186
1187 def do_conversion (infile, from_version, outfile, to_version):
1188         conv_list = get_conversions (from_version, to_version)
1189
1190         sys.stderr.write ('Applying conversions: ')
1191         str = infile.read ()
1192         last_conversion = ()
1193         try:
1194                 for x in conv_list:
1195                         sys.stderr.write (tup_to_str (x[0])  + ', ')
1196                         str = x[1] (str)
1197                         last_conversion = x[0]
1198
1199         except FatalConversionError:
1200                 sys.stderr.write ('Error while converting; I won\'t convert any further')
1201
1202         if last_conversion:
1203                 sys.stderr.write ('\n')
1204                 new_ver =  '\\version \"%s\"' % tup_to_str (last_conversion)
1205
1206                 if re.search (lilypond_version_re_str, str):
1207                         str = re.sub (lilypond_version_re_str,'\\'+new_ver , str)
1208                 elif add_version:
1209                         str = new_ver + '\n' + str
1210
1211                 outfile.write(str)
1212
1213         return last_conversion
1214         
1215 class UnknownVersion:
1216         pass
1217
1218 def do_one_file (infile_name):
1219         sys.stderr.write ('Processing `%s\' ... '% infile_name)
1220         outfile_name = ''
1221         if __main__.edit:
1222                 outfile_name = infile_name + '.NEW'
1223         elif __main__.outfile_name:
1224                 outfile_name = __main__.outfile_name
1225
1226         if __main__.from_version:
1227                 from_version = __main__.from_version
1228         else:
1229                 guess = guess_lilypond_version (infile_name)
1230                 if not guess:
1231                         raise UnknownVersion()
1232                 from_version = str_to_tuple (guess)
1233
1234         if __main__.to_version:
1235                 to_version = __main__.to_version
1236         else:
1237                 to_version = latest_version ()
1238
1239
1240         if infile_name:
1241                 infile = open (infile_name,'r')
1242         else:
1243                 infile = sys.stdin
1244
1245         if outfile_name:
1246                 outfile =  open (outfile_name, 'w')
1247         else:
1248                 outfile = sys.stdout
1249
1250         touched = do_conversion (infile, from_version, outfile, to_version)
1251
1252         if infile_name:
1253                 infile.close ()
1254
1255         if outfile_name:
1256                 outfile.close ()
1257
1258         if __main__.edit and touched:
1259                 try:
1260                         os.remove(infile_name + '~')
1261                 except:
1262                         pass
1263                 os.rename (infile_name, infile_name + '~')
1264                 os.rename (infile_name + '.NEW', infile_name)
1265
1266         sys.stderr.write ('\n')
1267         sys.stderr.flush ()
1268
1269 edit = 0
1270 assume_old = 0
1271 to_version = ()
1272 from_version = ()
1273 outfile_name = ''
1274
1275 (options, files) = getopt.getopt (
1276         sys.argv[1:], 'ao:f:t:senh', ['no-version', 'version', 'output', 'show-rules', 'help', 'edit', 'from=', 'to='])
1277
1278 for opt in options:
1279         o = opt[0]
1280         a = opt[1]
1281         if o== '--help' or o == '-h':
1282                 usage ()
1283                 sys.exit (0)
1284         if o == '--version' or o == '-v':
1285                 print_version ()
1286                 sys.exit (0)
1287         elif o== '--from' or o=='-f':
1288                 from_version = str_to_tuple (a)
1289         elif o== '--to' or o=='-t':
1290                 to_version = str_to_tuple (a)
1291         elif o== '--edit' or o == '-e':
1292                 edit = 1
1293         elif o== '--show-rules' or o == '-s':
1294                 show_rules (sys.stdout)
1295                 sys.exit(0)
1296         elif o == '--output' or o == '-o':
1297                 outfile_name = a
1298         elif o == '--no-version' or o == '-n':
1299                 add_version = 0
1300         else:
1301                 print o
1302                 raise getopt.error
1303
1304 identify ()
1305 for f in files:
1306         if f == '-':
1307                 f = ''
1308         if not os.path.isfile (f):
1309                 continue
1310         try:
1311                 do_one_file (f)
1312         except UnknownVersion:
1313                 sys.stderr.write ('\n')
1314                 sys.stderr.write ("%s: can't determine version for `%s'" % (program_name, f))
1315                 sys.stderr.write ('\n')
1316                 if assume_old:
1317                         fv = from_version
1318                         from_version = (0,0,0)
1319                         do_one_file (f)
1320                         from_version = fv
1321                 else:
1322                         sys.stderr.write ("%s: skipping: `%s' " % (program_name,  f))
1323                 pass
1324 sys.stderr.write ('\n')