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