]> git.donarmstrong.com Git - lilypond.git/blob - scripts/convert-ly.py
($(outdir)/%.1): build man
[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 [OPTIONS]... [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             edit in place
51   -f, --from=VERSION     start from version; overrides \version found in file
52   -s, --show-rules       print all rules
53   -t, --to=VERSION       show 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 if 1:
1174         def conv(str):
1175                 str = re.sub ("groupOpen",
1176                               "startGroup", str)
1177                 str = re.sub ("groupClose",
1178                               "stopGroup", str)
1179                 str = re.sub ("#'outer",
1180                               "#'enclose-bounds", str)
1181
1182                 return str
1183         
1184         conversions.append (((1,7,18), conv,
1185                              """groupOpen/Close  -> start/stopGroup,
1186                              #'outer  -> #'enclose-bounds
1187                              """))
1188
1189 if 1:
1190         def conv(str):
1191                 if re.search( r'\\GraceContext', str):
1192                         sys.stderr.write ("GraceContext has been removed")
1193                         sys.stderr.write ("please use #(add-to-grace-init .. )")
1194                         raise FatalConversionError()
1195
1196                 str = re.sub ('HaraKiriStaffContext', 'RemoveEmptyStaffContext', str)
1197                 return str
1198         
1199         conversions.append (((1,7,19), conv,"remove GraceContext"))
1200
1201
1202
1203 if 1:
1204         def conv(str):
1205                 str = re.sub (
1206                         r"(set|override|revert) *#'type",
1207                         r"\1 #'style",
1208                         str)
1209                 return str
1210         
1211         conversions.append (((1,7,22), conv,"#'type -> #'style"))
1212
1213 if 1:
1214         def conv(str):
1215                 str = re.sub (
1216                         "barNonAuto *= *##t",
1217                         "automaticBars = ##f",
1218                         str)
1219                 str = re.sub (
1220                         "barNonAuto *= *##f",
1221                         "automaticBars = ##t",
1222                         str)
1223                 return str
1224         
1225         conversions.append (((1,7,23), conv,"barNonAuto -> automaticBars"))
1226         
1227
1228 if 1:
1229         def conv(str):
1230                 if re.search( r'-(start|stop)Cluster', str):
1231                         sys.stderr.write ("""Cluster syntax has been changed.
1232 Please refer to the manual for details, and convert manually.
1233 """)
1234                         
1235                         raise FatalConversionError()
1236
1237                 return str
1238         
1239         conversions.append (((1,7,24), conv,"cluster syntax"))
1240
1241 if 1:
1242         def conv(str):
1243                 str = re.sub (r"\\property *Staff\.(Sustain|Sostenuto|UnaCorda)Pedal *\\(override|set) *#'pedal-type *",
1244                                 r"\property Staff.pedal\1Style ", str)
1245                 str = re.sub (r"\\property *Staff\.(Sustain|Sostenuto|UnaCorda)Pedal *\\revert *#'pedal-type", '', str)
1246                 return str
1247         
1248         conversions.append (((1,7,28), conv,"new Pedal style syntax"))
1249
1250
1251
1252 if 1:
1253
1254         def sub_chord (m):
1255                 str = m.group(1)
1256
1257                 origstr =  '<%s>' % str
1258                 if re.search (r'\\\\', str):
1259                         return origstr
1260
1261                 if re.search (r'\\property', str):
1262                         return origstr
1263
1264                 if re.match (r'^\s*\)?\s*\\[a-zA-Z]+', str):
1265                         return origstr
1266
1267                 durs = []
1268                 def sub_durs (m):
1269                         durs.append(m.group(2))
1270                         return m.group (1)
1271
1272                 str = re.sub ("([a-z]+[,'!? ]*)([0-9.]+)", sub_durs, str)
1273                 dur_str = ''
1274
1275                 for d in durs:
1276                         if dur_str == '':
1277                                 dur_str = d
1278                         if dur_str <> d:
1279                                 return '<%s>' % m.group (1)
1280
1281                 pslur_strs = ['']
1282                 dyns = ['']
1283                 slur_strs = ['']
1284
1285                 last_str = ''
1286                 while last_str <> str:
1287                   last_str = str
1288                   def sub_dyn_end (m):
1289                           dyns.append (' \!')
1290                           return ' ' + m.group(2)
1291
1292                   str = re.sub (r'(\\!)\s*([a-z]+)', sub_dyn_end, str)
1293                   def sub_slurs(m):
1294                           if '-)' not in slur_strs:
1295                                   slur_strs.append ( ')')
1296                           return m.group(1)
1297                   def sub_p_slurs(m):
1298                           if '-\)' not in slur_strs:
1299                                   slur_strs.append ( '\)')
1300                           return m.group(1)
1301                   str = re.sub (r"\)[ ]*([a-z]+)", sub_slurs, str)
1302                   str = re.sub (r"\\\)[ ]*([a-z]+)", sub_p_slurs, str)
1303                   def sub_begin_slurs(m):
1304                           if '-(' not in slur_strs:
1305                                   slur_strs.append ( '(')
1306                           return m.group(1)
1307                   str = re.sub (r"([a-z]+[,'!?0-9 ]*)\(", sub_begin_slurs, str)
1308                   def sub_begin_p_slurs(m):
1309                           if '-\(' not in slur_strs:
1310                                   slur_strs.append ( '\(')
1311                           return m.group(1)
1312
1313                   str = re.sub (r"([a-z]+[,'!?0-9 ]*)\\\(", sub_begin_p_slurs, str)
1314
1315                   def sub_dyns (m):
1316                           s = m.group(0)
1317                           if s == '@STARTCRESC@':
1318                                   slur_strs.append ("\\<")
1319                           elif s == '@STARTDECRESC@':
1320                                   slur_strs.append ("\\>")
1321                           elif s == r'-?\\!':
1322                                   slur_strs.append ('\\!')
1323                           return ''
1324
1325                   str = re.sub (r'@STARTCRESC@', sub_dyns, str)
1326                   str = re.sub (r'-?\\!', sub_dyns, str)
1327
1328                   def sub_articulations (m):
1329                           a = m.group(1)
1330                           if a not in slur_strs:
1331                                   slur_strs.append (a)
1332                           return ''
1333
1334                   str = re.sub (r"([_^-]\@ACCENT\@)", sub_articulations, str)
1335                   str = re.sub (r"([_^-]\\[a-z]+)", sub_articulations, str)
1336                   str = re.sub (r"([_^-][>_.+|^-])", sub_articulations, str)
1337
1338                   def sub_pslurs(m):
1339                           slur_strs.append ( ' \\)')
1340                           return m.group(1)
1341                   str = re.sub (r"\\\)[ ]*([a-z]+)", sub_pslurs, str)
1342
1343                 suffix = string.join (slur_strs, '') + string.join (pslur_strs, '') \
1344                          + string.join (dyns, '')
1345
1346                 return '@STARTCHORD@%s@ENDCHORD@%s%s' % (str , dur_str, suffix)
1347
1348
1349
1350
1351
1352         def sub_chords (str):
1353                 simend = '>'
1354                 simstart = "<" 
1355                 chordstart = '<<'
1356                 chordend = '>>'
1357                 marker_str = '%% new-chords-done %%'
1358
1359                 if re.search (marker_str,str):
1360                         return str
1361                 str= re.sub (r'\\<', '@STARTCRESC@', str)
1362                 str= re.sub (r'\\>', '@STARTDECRESC@', str)
1363                 str= re.sub (r'([_^-])>', r'\1@ACCENT@', str)
1364                 str = re.sub ('<([^<>{}]+)>', sub_chord, str)
1365
1366                 str = re.sub (r'\[ *(@STARTCHORD@[^@]+@ENDCHORD@[0-9.]*)',
1367                               r'\1[',
1368                               str)
1369                 str = re.sub (r'\\! *(@STARTCHORD@[^@]+@ENDCHORD@[0-9.]*)',
1370                               r'\1\\!',
1371                               str)
1372                 str = re.sub ('<([^?])', r'%s\1' % simstart, str)
1373                 str = re.sub ('>([^?])', r'%s\1' % simend,  str)
1374                 str = re.sub ('@STARTCRESC@', r'\\<', str)
1375                 str = re.sub ('@STARTDECRESC@', r'\\>' ,str)
1376                 str = re.sub (r'\\context *Voice *@STARTCHORD@', '@STARTCHORD@', str)
1377                 str = re.sub ('@STARTCHORD@', chordstart, str)
1378                 str = re.sub ('@ENDCHORD@', chordend, str)
1379                 str = re.sub (r'@ACCENT@', '>', str)
1380                 return str
1381
1382         def articulation_substitute (str):
1383                 str = re.sub (r"""([^-])\[ *([a-z]+[,']*[!?]?[0-9:]*\.*)""",
1384                               r" \1 \2[", str)
1385                 str = re.sub (r"""([^-])\) *([a-z]+[,']*[!?]?[0-9:]*\.*)""",
1386                               r"\1 \2)", str)
1387                 str = re.sub (r"""([^-])\\! *([a-z]+[,']*[!?]?[0-9:]*\.*)""",
1388                               r"\1 \2\\!", str)
1389                 return str
1390         
1391         def conv_relative(str):
1392                 if re.search (r"\\relative", str):
1393                         str= "#(ly:set-option 'old-relative)\n" + str
1394
1395                 return str
1396         
1397         def conv (str):
1398                 str =  conv_relative (str)
1399                 str = sub_chords (str)
1400
1401                 str = articulation_substitute (str)
1402                 
1403                 return str
1404         
1405         conversions.append (((1,9,0), conv, """New relative mode,
1406 Postfix articulations, new chord syntax."""))
1407
1408 if 1:
1409         def conv (str):
1410                 if re.search ("font-style",str):
1411                         sys.stderr.write ("font-style is deprecated. Please remove.")
1412                         raise FatalConversionError()
1413                         
1414                 str = re.sub (r'-\\markup', r'@\\markup', str)
1415                 str = re.sub (r'-\\', r'\\', str)
1416                 str = re.sub (r'-\)', ')', str)
1417                 str = re.sub (r'-\(', '(', str)
1418                 str = re.sub ('-\[', '[', str)
1419                 str = re.sub ('-\]', ']', str)
1420                 str = re.sub ('-~', '~', str)
1421                 str = re.sub (r'@\\markup', r'-\\markup', str)
1422                 return str
1423
1424         conversions.append (((1,9,1), conv, """Remove - before articulation"""))
1425 if 1:
1426         def conv (str):
1427                 str = re.sub ('ly:set-context-property',
1428                               'ly:set-context-property!', str)
1429                 str = re.sub ('\\\\newcontext', '\\\\new', str)
1430                 str = re.sub ('\\\\grace[\t\n ]*([^{ ]+)',
1431                               r'\\grace { \1 }', str) 
1432                 str = re.sub ("\\\\grace[\t\n ]*{([^}]+)}",
1433                               r"""\\grace {
1434   \\property Voice.Stem \\override #'stroke-style = #"grace"
1435   \1
1436   \\property Voice.Stem \\revert #'stroke-style }
1437 """, str)
1438                 
1439                 return str
1440         
1441         conversions.append (((1,9,2), conv, """\newcontext -> \new"""))
1442
1443 if 1:
1444         def conv (str):
1445                 str = re.sub ('accacciatura',
1446                               'acciaccatura', str)
1447
1448                 if re.search ("context-spec-music"):
1449                         sys.stderr.write ("context-spec-music takes a symbol for the context now. Update by hand.")
1450                                           
1451                         raise FatalConversionError()
1452                 
1453                 str = re.sub ('fingerHorizontalDirection *= *#(LEFT|-1)',
1454                               "fingeringOrientations = #'(up down left)", str)
1455                 str = re.sub ('fingerHorizontalDirection *= *#(RIGHT|1)',
1456                               "fingeringOrientations = #'(up down right)", str)
1457
1458                 return str
1459         
1460         conversions.append (((1,9,3), conv,
1461                              """\acciaccatura misspelling, fingerHorizontalDirection -> fingeringOrientations"""))
1462
1463
1464                         
1465
1466 ################################
1467 #       END OF CONVERSIONS      
1468 ################################
1469
1470 def get_conversions (from_version, to_version):
1471         def version_b (v, f = from_version, t = to_version):
1472                 return version_cmp (v[0], f) > 0 and version_cmp (v[0], t) <= 0
1473         return filter (version_b, conversions)
1474
1475
1476 def latest_version ():
1477         return conversions[-1][0]
1478
1479 def do_conversion (infile, from_version, outfile, to_version):
1480         conv_list = get_conversions (from_version, to_version)
1481
1482         sys.stderr.write ('Applying conversions: ')
1483         str = infile.read ()
1484         last_conversion = ()
1485         try:
1486                 for x in conv_list:
1487                         sys.stderr.write (tup_to_str (x[0])  + ', ')
1488                         str = x[1] (str)
1489                         last_conversion = x[0]
1490
1491         except FatalConversionError:
1492                 sys.stderr.write ('Error while converting; I won\'t convert any further')
1493
1494         if last_conversion:
1495                 sys.stderr.write ('\n')
1496                 new_ver =  '\\version \"%s\"' % tup_to_str (last_conversion)
1497
1498                 if re.search (lilypond_version_re_str, str):
1499                         str = re.sub (lilypond_version_re_str,'\\'+new_ver , str)
1500                 elif add_version:
1501                         str = new_ver + '\n' + str
1502
1503                 outfile.write(str)
1504
1505         return last_conversion
1506         
1507 class UnknownVersion:
1508         pass
1509
1510 def do_one_file (infile_name):
1511         sys.stderr.write ('Processing `%s\' ... '% infile_name)
1512         outfile_name = ''
1513         if __main__.edit:
1514                 outfile_name = infile_name + '.NEW'
1515         elif __main__.outfile_name:
1516                 outfile_name = __main__.outfile_name
1517
1518         if __main__.from_version:
1519                 from_version = __main__.from_version
1520         else:
1521                 guess = guess_lilypond_version (infile_name)
1522                 if not guess:
1523                         raise UnknownVersion()
1524                 from_version = str_to_tuple (guess)
1525
1526         if __main__.to_version:
1527                 to_version = __main__.to_version
1528         else:
1529                 to_version = latest_version ()
1530
1531
1532         if infile_name:
1533                 infile = open (infile_name,'r')
1534         else:
1535                 infile = sys.stdin
1536
1537         if outfile_name:
1538                 outfile =  open (outfile_name, 'w')
1539         else:
1540                 outfile = sys.stdout
1541
1542         touched = do_conversion (infile, from_version, outfile, to_version)
1543
1544         if infile_name:
1545                 infile.close ()
1546
1547         if outfile_name:
1548                 outfile.close ()
1549
1550         if __main__.edit and touched:
1551                 try:
1552                         os.remove(infile_name + '~')
1553                 except:
1554                         pass
1555                 os.rename (infile_name, infile_name + '~')
1556                 os.rename (infile_name + '.NEW', infile_name)
1557
1558         sys.stderr.write ('\n')
1559         sys.stderr.flush ()
1560
1561 edit = 0
1562 assume_old = 0
1563 to_version = ()
1564 from_version = ()
1565 outfile_name = ''
1566
1567 (options, files) = getopt.getopt (
1568         sys.argv[1:], 'ao:f:t:senh', ['no-version', 'version', 'output', 'show-rules', 'help', 'edit', 'from=', 'to='])
1569
1570 for opt in options:
1571         o = opt[0]
1572         a = opt[1]
1573         if o== '--help' or o == '-h':
1574                 usage ()
1575                 sys.exit (0)
1576         if o == '--version' or o == '-v':
1577                 print_version ()
1578                 sys.exit (0)
1579         elif o== '--from' or o=='-f':
1580                 from_version = str_to_tuple (a)
1581         elif o== '--to' or o=='-t':
1582                 to_version = str_to_tuple (a)
1583         elif o== '--edit' or o == '-e':
1584                 edit = 1
1585         elif o== '--show-rules' or o == '-s':
1586                 show_rules (sys.stdout)
1587                 sys.exit(0)
1588         elif o == '--output' or o == '-o':
1589                 outfile_name = a
1590         elif o == '--no-version' or o == '-n':
1591                 add_version = 0
1592         else:
1593                 print o
1594                 raise getopt.error
1595
1596 identify ()
1597 for f in files:
1598         if f == '-':
1599                 f = ''
1600         if not os.path.isfile (f):
1601                 continue
1602         try:
1603                 do_one_file (f)
1604         except UnknownVersion:
1605                 sys.stderr.write ('\n')
1606                 sys.stderr.write ("%s: can't determine version for `%s'" % (program_name, f))
1607                 sys.stderr.write ('\n')
1608                 if assume_old:
1609                         fv = from_version
1610                         from_version = (0,0,0)
1611                         do_one_file (f)
1612                         from_version = fv
1613                 else:
1614                         sys.stderr.write ("%s: skipping: `%s' " % (program_name,  f))
1615                 pass
1616
1617 sys.stderr.write ('\n')