]> git.donarmstrong.com Git - lilypond.git/blob - scripts/convert-ly.py
($(outdir)/%.pdf): add DVIPS_FLAGS. This will
[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--2004  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, durs = durs):
1269                         durs.append(m.group(2))
1270                         return m.group (1)
1271
1272                 str = re.sub (r"([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
1289                         def sub_tremolos (m, slur_strs = slur_strs):
1290                                 tr = m.group (2)
1291                                 if tr not in slur_strs:
1292                                         slur_strs.append (tr)
1293                                 return  m.group (1)
1294                         
1295                         str = re.sub (r"([a-z]+[',!? ]*)(:[0-9]+)",
1296                                       sub_tremolos, str)
1297
1298                         def sub_dyn_end (m, dyns = dyns):
1299                                 dyns.append (' \!')
1300                                 return ' ' + m.group(2)
1301
1302                         str = re.sub (r'(\\!)\s*([a-z]+)', sub_dyn_end, str)
1303                         def sub_slurs(m, slur_strs = slur_strs):
1304                                 if '-)' not in slur_strs:
1305                                         slur_strs.append (')')
1306                                 return m.group(1)
1307                         
1308                         def sub_p_slurs(m, slur_strs = slur_strs):
1309                                 if '-\)' not in slur_strs:
1310                                         slur_strs.append ('\)')
1311                                 return m.group(1)
1312                         
1313                         str = re.sub (r"\)[ ]*([a-z]+)", sub_slurs, str)
1314                         str = re.sub (r"\\\)[ ]*([a-z]+)", sub_p_slurs, str)
1315                         def sub_begin_slurs(m, slur_strs = slur_strs):
1316                                 if '-(' not in slur_strs:
1317                                         slur_strs.append ('(')
1318                                 return m.group(1)
1319                         
1320                         str = re.sub (r"([a-z]+[,'!?0-9 ]*)\(",
1321                                       sub_begin_slurs, str)
1322                         def sub_begin_p_slurs(m, slur_strs = slur_strs):
1323                                 if '-\(' not in slur_strs:
1324                                         slur_strs.append ('\(')
1325                                 return m.group(1)
1326
1327                         str = re.sub (r"([a-z]+[,'!?0-9 ]*)\\\(",
1328                                 sub_begin_p_slurs, str)
1329
1330                         def sub_dyns (m, slur_strs = slur_strs):
1331                                 s = m.group(0)
1332                                 if s == '@STARTCRESC@':
1333                                         slur_strs.append ("\\<")
1334                                 elif s == '@STARTDECRESC@':
1335                                         slur_strs.append ("\\>")
1336                                 elif s == r'-?\\!':
1337                                         slur_strs.append ('\\!')
1338                                 return ''
1339
1340                         str = re.sub (r'@STARTCRESC@', sub_dyns, str)
1341                         str = re.sub (r'-?\\!', sub_dyns, str)
1342
1343                         def sub_articulations (m, slur_strs = slur_strs):
1344                                 a = m.group(1)
1345                                 if a not in slur_strs:
1346                                         slur_strs.append (a)
1347                                 return ''
1348
1349                         str = re.sub (r"([_^-]\@ACCENT\@)", sub_articulations,
1350                                       str)
1351                         str = re.sub (r"([_^-]\\[a-z]+)", sub_articulations,
1352                                       str)
1353                         str = re.sub (r"([_^-][>_.+|^-])", sub_articulations,
1354                                       str)
1355                         str = re.sub (r'([_^-]"[^"]+")', sub_articulations,
1356                                       str)
1357
1358                         def sub_pslurs(m, slur_strs = slur_strs):
1359                                 slur_strs.append (' \\)')
1360                                 return m.group(1)
1361                         str = re.sub (r"\\\)[ ]*([a-z]+)", sub_pslurs, str)
1362
1363                 ## end of while <>
1364
1365                 suffix = string.join (slur_strs, '') + string.join (pslur_strs,
1366                                                                     '') \
1367                          + string.join (dyns, '')
1368
1369                 return '@STARTCHORD@%s@ENDCHORD@%s%s' % (str , dur_str, suffix)
1370
1371
1372
1373         def sub_chords (str):
1374                 simend = '>'
1375                 simstart = '<'
1376                 chordstart = '<<'
1377                 chordend = '>>'
1378                 marker_str = '%% new-chords-done %%'
1379
1380                 if re.search (marker_str,str):
1381                         return str
1382                 str = re.sub ('<<', '@STARTCHORD@', str)
1383                 str = re.sub ('>>', '@ENDCHORD@', str)
1384                 
1385                 str = re.sub (r'\\<', '@STARTCRESC@', str)
1386                 str = re.sub (r'\\>', '@STARTDECRESC@', str)
1387                 str = re.sub (r'([_^-])>', r'\1@ACCENT@', str)
1388                 str = re.sub (r'<([^<>{}]+)>', sub_chord, str)
1389
1390                 # add dash: -[, so that [<<a b>> c d] becomes
1391                 #                      <<a b>>-[ c d]
1392                 # and gets skipped by articulation_substitute
1393                 str = re.sub (r'\[ *(@STARTCHORD@[^@]+@ENDCHORD@[0-9.]*)',
1394                               r'\1-[', str)
1395                 str = re.sub (r'\\! *(@STARTCHORD@[^@]+@ENDCHORD@[0-9.]*)',
1396                               r'\1-\\!', str)
1397                 
1398                 str = re.sub (r'<([^?])', r'%s\1' % simstart, str)
1399                 str = re.sub (r'>([^?])', r'%s\1' % simend,  str)
1400                 str = re.sub ('@STARTCRESC@', r'\\<', str)
1401                 str = re.sub ('@STARTDECRESC@', r'\\>' ,str)
1402                 str = re.sub (r'\\context *Voice *@STARTCHORD@',
1403                               '@STARTCHORD@', str)
1404                 str = re.sub ('@STARTCHORD@', chordstart, str)
1405                 str = re.sub ('@ENDCHORD@', chordend, str)
1406                 str = re.sub (r'@ACCENT@', '>', str)
1407                 return str
1408
1409         def articulation_substitute (str):
1410                 str = re.sub (r"""([^-])\[ *([a-z]+[,']*[!?]?[0-9:]*\.*)""",
1411                               r"\1 \2[", str)
1412                 str = re.sub (r"""([^-])\\\) *([a-z]+[,']*[!?]?[0-9:]*\.*)""",
1413                               r"\1 \2\\)", str)
1414                 str = re.sub (r"""([^-\\])\) *([a-z]+[,']*[!?]?[0-9:]*\.*)""",
1415                               r"\1 \2)", str)
1416                 str = re.sub (r"""([^-])\\! *([a-z]+[,']*[!?]?[0-9:]*\.*)""",
1417                               r"\1 \2\\!", str)
1418                 return str
1419         
1420         def conv_relative(str):
1421                 if re.search (r"\\relative", str):
1422                         str= "#(ly:set-option 'old-relative)\n" + str
1423
1424                 return str
1425         
1426         def conv (str):
1427                 str =  conv_relative (str)
1428                 str = sub_chords (str)
1429
1430                 str = articulation_substitute (str)
1431                 
1432                 return str
1433         
1434         conversions.append (((1,9,0), conv, """New relative mode,
1435 Postfix articulations, new chord syntax."""))
1436
1437 if 1:
1438         def conv (str):
1439                 if re.search ("font-style",str):
1440                         sys.stderr.write ("font-style is deprecated. Please remove.")
1441                         raise FatalConversionError()
1442                         
1443                 str = re.sub (r'-\\markup', r'@\\markup', str)
1444                 str = re.sub (r'-\\', r'\\', str)
1445                 str = re.sub (r'-\)', ')', str)
1446                 str = re.sub (r'-\(', '(', str)
1447                 str = re.sub ('-\[', '[', str)
1448                 str = re.sub ('-\]', ']', str)
1449                 str = re.sub ('-~', '~', str)
1450                 str = re.sub (r'@\\markup', r'-\\markup', str)
1451                 return str
1452
1453         conversions.append (((1,9,1), conv, """Remove - before articulation"""))
1454 if 1:
1455         def conv (str):
1456                 str = re.sub ('ly:set-context-property',
1457                               'ly:set-context-property!', str)
1458                 str = re.sub ('\\\\newcontext', '\\\\new', str)
1459                 str = re.sub ('\\\\grace[\t\n ]*([^{ ]+)',
1460                               r'\\grace { \1 }', str)
1461                 str = re.sub ("\\\\grace[\t\n ]*{([^}]+)}",
1462                               r"""\\grace {
1463   \\property Voice.Stem \\override #'stroke-style = #"grace"
1464   \1
1465   \\property Voice.Stem \\revert #'stroke-style }
1466 """, str)
1467                 
1468                 return str
1469         
1470         conversions.append (((1,9,2), conv, """\newcontext -> \new"""))
1471
1472 if 1:
1473         def conv (str):
1474                 str = re.sub ('accacciatura',
1475                               'acciaccatura', str)
1476
1477                 if re.search ("context-spec-music", str):
1478                         sys.stderr.write ("context-spec-music takes a symbol for the context now. Update by hand.")
1479                                         
1480                         raise FatalConversionError()
1481                 
1482                 str = re.sub ('fingerHorizontalDirection *= *#(LEFT|-1)',
1483                               "fingeringOrientations = #'(up down left)", str)
1484                 str = re.sub ('fingerHorizontalDirection *= *#(RIGHT|1)',
1485                               "fingeringOrientations = #'(up down right)", str)
1486
1487                 return str
1488         
1489         conversions.append (((1,9,3), conv,
1490                              """\acciaccatura misspelling, fingerHorizontalDirection -> fingeringOrientations"""))
1491
1492
1493 def conv (str):
1494         if re.search ('\\figures', str):
1495                 sys.stderr.write ("Warning: attempting automatic \\figures conversion.  Check results!");
1496                 
1497         
1498         def figures_replace (m):
1499                 s = m.group (1)
1500                 s = re.sub ('<', '@FIGOPEN@',s)
1501                 s = re.sub ('>', '@FIGCLOSE@',s)
1502                 return '\\figures { %s }' % s
1503         
1504         str = re.sub (r'\\figures[ \t\n]*{([^}]+)}', figures_replace, str)
1505         str = re.sub (r'\\<', '@STARTCRESC@', str)
1506         str = re.sub (r'\\>', '@STARTDECRESC@', str)
1507         str = re.sub (r'([-^_])>', r'\1@ACCENT@', str)
1508         str = re.sub (r'<<', '@STARTCHORD@', str)
1509         str = re.sub (r'>>', '@ENDCHORD@', str)
1510         str = re.sub (r'>', '@ENDSIMUL@', str)
1511         str = re.sub (r'<', '@STARTSIMUL@', str)
1512         str = re.sub ('@STARTDECRESC@', '\\>', str)
1513         str = re.sub ('@STARTCRESC@', '\\<', str)
1514         str = re.sub ('@ACCENT@', '>', str)
1515         str = re.sub ('@ENDCHORD@', '>', str)
1516         str = re.sub ('@STARTCHORD@', '<', str)
1517         str = re.sub ('@STARTSIMUL@', '<<', str)
1518         str = re.sub ('@ENDSIMUL@', '>>', str)
1519         str = re.sub ('@FIGOPEN@', '<', str)
1520         str = re.sub ('@FIGCLOSE@', '>', str)
1521
1522         return str
1523
1524 conversions.append (((1,9,4), conv, 'Swap < > and << >>'))
1525
1526
1527 def conv (str):
1528         str = re.sub ('HaraKiriVerticalGroup', 'RemoveEmptyVerticalGroup', str)
1529
1530         return str
1531
1532 conversions.append (((1,9,5), conv, 'HaraKiriVerticalGroup -> RemoveEmptyVerticalGroup'))
1533
1534 def conv (str):
1535         if re.search ("ly:get-font", str) :
1536                 sys.stderr.write (r"(ly:get-font foo ..)  has been replaced by" + \
1537                                   " (ly:paper-get-font (ly:grob-get-paper foo) .. ).\n" +\
1538                                   "please update manually.")
1539                 
1540                 raise FatalConversionError()
1541         
1542         if re.search ("\\pitch *#", str) :
1543                 sys.stderr.write (r"\\pitch has been deprecated. " +\
1544                                   " Use Scheme code to construct arbitrary note events.")
1545                 
1546                 raise FatalConversionError()
1547         
1548         return str
1549                 
1550
1551 conversions.append (((1,9,6), conv, 'ly:get-font deprecated.'))
1552
1553 def conv (str):
1554         def sub_alteration (m):
1555                 alt = m.group (3)
1556                 alt = {
1557                         '-1': 'FLAT',
1558                         '-2': 'DOUBLE-FLAT',
1559                         '0': 'NATURAL',
1560                         '1': 'SHARP',
1561                         '2': 'DOUBLE-SHARP',
1562                         }[alt]
1563                 
1564                 return '(ly:make-pitch %s %s %s)' % (m.group(1), m.group (2),
1565                                                      alt)
1566         
1567         str =re.sub ("\\(ly:make-pitch *([0-9-]+) *([0-9-]+) *([0-9-]+) *\\)",
1568                      sub_alteration, str)
1569
1570
1571         str = re.sub ("ly:verbose", "ly:get-option 'verbose", str)
1572
1573         m= re.search ("\\\\outputproperty #([^#]+)[\t\n ]*#'([^ ]+)", str)
1574         if m:
1575                 sys.stderr.write (\
1576                         r"""\outputproperty found,
1577 Please hand-edit, using
1578
1579   \applyoutput #(outputproperty-compatibility %s '%s <GROB PROPERTY VALUE>)
1580
1581 as a substitution text.""" % (m.group (1), m.group (2)) )
1582                 raise FatalConversionError ()
1583
1584         if re.search ("ly:(make-pitch|pitch-alteration)", str) \
1585                or re.search ("keySignature", str):
1586                 sys.stderr.write (
1587 """The alteration field of Scheme pitches was multiplied by 2
1588 to support quarter tone accidentals. You have to edit the following constructs by hand:
1589
1590 * calls of  ly:make-pitch and ly:pitch-alteration
1591 * keySignature settings made with \property
1592 """)
1593                 raise FatalConversionError ()
1594         
1595         return str
1596 conversions.append (((1,9,7), conv,
1597                      '''use symbolic constants for alterations,
1598 remove \\outputproperty, move ly:verbose into ly:get-option'''))
1599
1600
1601 def conv (str):
1602         if re.search ("dash-length",str):
1603                 sys.stderr.write ("""dash-length has been removed. Use dash-fraction instead.""")
1604                 raise FatalConversionError()
1605         return str
1606
1607 conversions.append (((1,9,8), conv, """dash-length -> dash-fraction"""))
1608
1609
1610 def conv (str):
1611         def func(match):
1612                 return "#'font-size = #%d" % (2*string.atoi (match.group (1))) 
1613                 
1614         str =re.sub (r"#'font-relative-size\s*=\s*#([0-9-]+)", func, str)
1615         str =re.sub (r"#'font-family\s*=\s*#'ancient",
1616                      r"#'font-family = #'music", str)
1617         
1618         return str
1619
1620 conversions.append (((2,1,1), conv, """font-relative-size -> font-size"""))
1621
1622 def conv (str):
1623         str =re.sub (r"ly:get-music-length", "ly:music-length", str)
1624         return str
1625
1626 conversions.append (((2,1,2), conv, """ly:get-music-length -> ly:music-length"""))
1627
1628 def conv (str):
1629         str =re.sub (r"\.\s+stz=", ". instr ", str)
1630         return str
1631
1632 conversions.append (((2,1,3), conv, """stanza -> instrument"""))
1633
1634 def conv (str):
1635         def func (match):
1636                 c = match.group (1)
1637                 b = match.group (2)
1638                 
1639                 if b == 't':
1640                         if c == 'Score':
1641                                 return ''
1642                         else:
1643                                 return r" \property %s.melismaBusyProperties \unset"  % c
1644                 elif b == 'f':
1645                         return r"\property %s.melismaBusyProperties = #'(melismaBusy)"  % c
1646                 
1647         str =re.sub (r"\\property ([a-zA-Z]+)\s*\.\s*automaticMelismata\s*=\s*##([ft])", func, str)
1648         return str
1649
1650 conversions.append (((2,1,4), conv, """removal of automaticMelismata; use melismaBusyProperties instead."""))
1651
1652
1653
1654 def conv (str):
1655         str =re.sub (r"\\translator\s+([a-zA-Z]+)", r"\\change \1", str)
1656         return str
1657
1658 conversions.append (((2,1,7), conv, """\\translator Staff -> \\change Staff"""))
1659
1660 def conv (str):
1661         str =re.sub (r"\\newaddlyrics", r"\\lyricsto", str)
1662         return str
1663
1664 conversions.append (((2,1,10), conv, """\\newaddlyrics -> \\lyricsto"""))
1665
1666 def conv (str):
1667         str = re.sub (r'\\include\s*"paper([0-9]+)(-init)?.ly"',
1668                       r"#(set-staff-size \1)", str)
1669
1670         def sub_note (match):
1671                 dur = ''
1672                 log = string.atoi (match.group (1))
1673                 dots = string.atoi (match.group (2))
1674                 
1675                 if log >= 0:
1676                         dur = '%d' % (1 << log)
1677                 else:
1678                         dur = { -1 : 'breve',
1679                                 -2 : 'longa',
1680                                 -3 : 'maxima'}[log]
1681
1682                 dur += ('.' * dots)
1683                 
1684                 return r'\note #"%s" #%s' % (dur, match.group (3))
1685         
1686         str = re.sub (r'\\note\s+#([0-9-]+)\s+#([0-9]+)\s+#([0-9.-]+)',
1687                       sub_note, str)
1688         return str
1689
1690 conversions.append (((2,1,11), conv, """\\include "paper16.ly" -> #(set-staff-size 16)
1691 \note #3 #1 #1 -> \note #"8." #1
1692 """))
1693
1694
1695 def conv (str):
1696         str =re.sub (r"OttavaSpanner", r"OttavaBracket", str)
1697         return str
1698
1699 conversions.append (((2,1,12), conv, """OttavaSpanner -> OttavaBracket"""))
1700
1701
1702 def conv (str):
1703         str =re.sub (r"\(set-staff-size ", r"(set-global-staff-size ", str)
1704         return str
1705
1706 conversions.append (((2,1,13), conv, """set-staff-size -> set-global-staff-size"""))
1707
1708 def conv (str):
1709         str =re.sub (r"#'style\s*=\s*#'dotted-line",
1710                      r"#'dash-fraction = #0.0 ", str)
1711         return str
1712
1713 conversions.append (((2,1,14), conv, """style = dotted -> dash-fraction = 0"""))
1714
1715 def conv (str):
1716         str =re.sub (r'LyricsVoice\s*\.\s*instrument\s*=\s*("[^"]*")',
1717                      r'LyricsVoice . vocalName = \1', str)
1718         
1719         str =re.sub (r'LyricsVoice\s*\.\s*instr\s*=\s*("[^"]*")',
1720                      r'LyricsVoice . vocNam = \1', str)
1721         return str
1722
1723 conversions.append (((2,1,15), conv, """LyricsVoice . instr(ument) -> vocalName"""))
1724
1725 def conv (str):
1726         def sub_acc (m):
1727                 d = {
1728                 '4': 'doublesharp',
1729                 '3': 'threeqsharp',
1730                 '2': 'sharp',
1731                 '1': 'semisharp',
1732                 '0': 'natural',
1733                 '-1': 'semiflat',
1734                 '-2': 'flat',
1735                 '-3': 'threeqflat',
1736                 '-4': 'doubleflat'}
1737                 return '\\%s' %  d[m.group (1)]
1738                      
1739         str = re.sub (r'\\musicglyph\s*#"accidentals-([0-9-]+)"',
1740                       sub_acc, str)
1741         return str
1742
1743 conversions.append (((2,1,16), conv, """\\musicglyph #"accidentals-NUM" -> \\sharp/flat/etc."""))
1744
1745
1746 def conv (str):
1747
1748         if re.search (r'\\partcombine', str):
1749                 sys.stderr.write ('Warning: \\partcombine has been changed. '
1750                                   +'Check conversion manually!')
1751
1752                 raise FatalConversionError()
1753
1754         # this rule doesn't really work,
1755         # too lazy to figure out why.
1756         str = re.sub (r'\\context\s+Voice\s*=\s*one\s*\\partcombine\s+Voice\s*\\context\s+Thread\s*=\s*one(.*)\s*'
1757                       + r'\\context\s+Thread\s*=\s*two',
1758                       '\\\\newpartcombine\n\\1\n', str)
1759         
1760         
1761         return str
1762
1763 conversions.append (((2,1,17), conv, """\\partcombine syntax change to \\newpartcombine"""))
1764
1765
1766 def conv (str):
1767         str = re.sub (r'\\newpartcombine', r'\\partcombine', str)
1768         str = re.sub (r'\\autochange\s+Staff', r'\\autochange ', str)
1769         return str
1770
1771 conversions.append (((2,1,18), conv, """\\newpartcombine -> \\partcombine,
1772 \\autochange Staff -> \\autochange
1773 """))
1774
1775
1776
1777
1778 def conv (str):
1779         str = re.sub (r'\\include "drumpitch-init.ly"','', str)
1780         str = re.sub (r'\\pitchnames ','pitchnames = ', str)
1781         str = re.sub (r'\\chordmodifiers ','chordmodifiers = ', str)
1782         str = re.sub (r'\bdrums\b\s*=','drumContents = ', str)
1783         str = re.sub (r'\\drums\b','\\drumContents ', str)
1784         
1785
1786         if re.search ('drums->paper', str):
1787                 sys.stderr.write ("\nDrum notation found. Check file manually!")
1788                 
1789         str = re.sub (r"""\\apply\s+#\(drums->paper\s+'([a-z]+)\)""",
1790                       r"""\property DrumStaff.drumStyleTable = #\1-style""",
1791                       str)
1792
1793         if re.search ('Thread', str):
1794                 sys.stderr.write ("\nThread found. Check file manually!\n");
1795
1796         str = re.sub (r"""(\\once\s*)?\\property\s+Thread\s*\.\s*NoteHead\s*"""
1797                       + r"""\\(set|override)\s*#'style\s*=\s*#'harmonic"""
1798                       + r"""\s+([a-z]+[,'=]*)([0-9]*\.*)"""                   
1799                       ,r"""<\3\\harmonic>\4""", str)
1800
1801         str = re.sub (r"""\\new Thread""", """\context Voice""", str)
1802         str = re.sub (r"""Thread""", """Voice""", str)
1803
1804         if re.search ('\bLyrics\b', str):
1805                 sys.stderr.write ("\nLyrics found. Check file manually!\n");
1806
1807         str = re.sub (r"""LyricsVoice""", r"""L@ricsVoice""", str)
1808         str = re.sub (r"""\bLyrics\b""", r"""LyricsVoice""", str)
1809         str = re.sub (r"""LyricsContext""", r"""LyricsVoiceContext""", str)
1810         str = re.sub (r"""L@ricsVoice""", r"""LyricsVoice""",str)
1811         
1812         
1813         return str
1814
1815 conversions.append (((2,1,19), conv, """Drum notation changes, Removing \chordmodifiers, \notenames.
1816 Harmonic notes. Thread context removed. Lyrics context removed."""))
1817
1818 def conv (str):
1819         str = re.sub (r'nonevent-skip', 'skip-music', str)
1820         return str
1821
1822 conversions.append (((2,1,20), conv, """nonevent-skip -> skip-music""" ))
1823
1824 def conv (str):
1825         str = re.sub (r'molecule-callback', 'print-function', str)
1826         str = re.sub (r'brew_molecule', 'print', str)
1827         str = re.sub (r'brew-new-markup-molecule', 'Text_item::print', str)
1828         str = re.sub (r'LyricsVoice', 'Lyrics', str)
1829         str = re.sub (r'tupletInvisible',
1830                       r"TupletBracket \\set #'transparent", str)
1831 #       str = re.sub (r'molecule', 'collage', str)
1832 #molecule -> collage
1833         str = re.sub (r"\\property\s+[a-zA-Z]+\s*\.\s*[a-zA-Z]+\s*"
1834                       + r"\\set\s*#'X-extent-callback\s*=\s*#Grob::preset_extent",
1835                       "", str)
1836
1837         return str
1838
1839 conversions.append (((2,1,21), conv, """molecule-callback -> print-function,
1840 brew_molecule -> print
1841 brew-new-markup-molecule -> Text_item::print
1842 LyricsVoice -> Lyrics
1843 tupletInvisible -> TupletBracket \set #'transparent
1844 Grob::preset_extent removed.
1845 """ ))
1846
1847
1848 def conv (str):
1849         str = re.sub (r'\\property\s+([^.]+)\s*\.\s*([^\\=]+)\s*\\(set|override)',
1850                       r"\\overrid@ \1.\2 ", str)
1851         str = re.sub (r'\\property\s+([^. ]+)\s*\.\s*([^\\= ]+)\s*=',
1852                       r'\\s@t \1.\2 = ', str)
1853         str = re.sub (r'\\property\s+([^. ]+)\s*\.\s*([^\\= ]+)\s*\\unset',
1854                       r'\\uns@t \1.\2 ', str)
1855         str = re.sub (r'\\property\s+([^. ]+)\s*\.\s*([^\\= ]+)\s*\\revert'
1856                       + r"\s*#'([-a-z0-9_]+)",
1857                       r"\\rev@rt \1.\2 #'\3", str)
1858         str = re.sub (r'Voice\.', '', str)
1859         str = re.sub (r'Lyrics\.', '', str)
1860         str = re.sub (r'ChordNames\.', '', str)
1861         
1862         str = re.sub ('rev@rt', 'revert',str)
1863         str = re.sub ('s@t', 'set',str)
1864         str = re.sub ('overrid@', 'override',str)
1865
1866         str = re.sub ('molecule', 'stencil', str)
1867         str = re.sub ('Molecule', 'Stencil', str)
1868         return str
1869
1870 conversions.append (((2,1,22), conv, """new syntax for property settings:
1871         \set A.B = #C , \unset A.B
1872         \override A.B #C = #D, \revert A.B #C
1873
1874 """))
1875
1876
1877 ################################
1878 #       END OF CONVERSIONS      
1879 ################################
1880
1881 def get_conversions (from_version, to_version):
1882         def version_b (v, f = from_version, t = to_version):
1883                 return version_cmp (v[0], f) > 0 and version_cmp (v[0], t) <= 0
1884         return filter (version_b, conversions)
1885
1886
1887 def latest_version ():
1888         return conversions[-1][0]
1889
1890 def do_conversion (infile, from_version, outfile, to_version):
1891         conv_list = get_conversions (from_version, to_version)
1892
1893         sys.stderr.write ('Applying conversions: ')
1894         str = infile.read ()
1895         last_conversion = ()
1896         try:
1897                 for x in conv_list:
1898                         sys.stderr.write (tup_to_str (x[0])  + ', ')
1899                         str = x[1] (str)
1900                         last_conversion = x[0]
1901
1902         except FatalConversionError:
1903                 sys.stderr.write ('Error while converting; I won\'t convert any further')
1904
1905         if last_conversion:
1906                 sys.stderr.write ('\n')
1907                 new_ver =  '\\version \"%s\"' % tup_to_str (last_conversion)
1908
1909                 if re.search (lilypond_version_re_str, str):
1910                         str = re.sub (lilypond_version_re_str,'\\'+new_ver , str)
1911                 elif add_version:
1912                         str = new_ver + '\n' + str
1913
1914                 outfile.write(str)
1915
1916         return last_conversion
1917         
1918 class UnknownVersion:
1919         pass
1920
1921 def do_one_file (infile_name):
1922         sys.stderr.write ('Processing `%s\' ... '% infile_name)
1923         outfile_name = ''
1924         if __main__.edit:
1925                 outfile_name = infile_name + '.NEW'
1926         elif __main__.outfile_name:
1927                 outfile_name = __main__.outfile_name
1928
1929         if __main__.from_version:
1930                 from_version = __main__.from_version
1931         else:
1932                 guess = guess_lilypond_version (infile_name)
1933                 if not guess:
1934                         raise UnknownVersion()
1935                 from_version = str_to_tuple (guess)
1936
1937         if __main__.to_version:
1938                 to_version = __main__.to_version
1939         else:
1940                 to_version = latest_version ()
1941
1942
1943         if infile_name:
1944                 infile = open (infile_name,'r')
1945         else:
1946                 infile = sys.stdin
1947
1948         if outfile_name:
1949                 outfile =  open (outfile_name, 'w')
1950         else:
1951                 outfile = sys.stdout
1952
1953         touched = do_conversion (infile, from_version, outfile, to_version)
1954
1955         if infile_name:
1956                 infile.close ()
1957
1958         if outfile_name:
1959                 outfile.close ()
1960
1961         if __main__.edit and touched:
1962                 try:
1963                         os.remove(infile_name + '~')
1964                 except:
1965                         pass
1966                 os.rename (infile_name, infile_name + '~')
1967                 os.rename (infile_name + '.NEW', infile_name)
1968
1969         sys.stderr.write ('\n')
1970         sys.stderr.flush ()
1971
1972 edit = 0
1973 assume_old = 0
1974 to_version = ()
1975 from_version = ()
1976 outfile_name = ''
1977
1978 (options, files) = getopt.getopt (
1979         sys.argv[1:], 'ao:f:t:senh', ['no-version', 'version', 'output', 'show-rules', 'help', 'edit', 'from=', 'to='])
1980
1981 for opt in options:
1982         o = opt[0]
1983         a = opt[1]
1984         if o== '--help' or o == '-h':
1985                 usage ()
1986                 sys.exit (0)
1987         if o == '--version' or o == '-v':
1988                 print_version ()
1989                 sys.exit (0)
1990         elif o== '--from' or o=='-f':
1991                 from_version = str_to_tuple (a)
1992         elif o== '--to' or o=='-t':
1993                 to_version = str_to_tuple (a)
1994         elif o== '--edit' or o == '-e':
1995                 edit = 1
1996         elif o== '--show-rules' or o == '-s':
1997                 show_rules (sys.stdout)
1998                 sys.exit(0)
1999         elif o == '--output' or o == '-o':
2000                 outfile_name = a
2001         elif o == '--no-version' or o == '-n':
2002                 add_version = 0
2003         else:
2004                 print o
2005                 raise getopt.error
2006
2007 identify ()
2008 for f in files:
2009         if f == '-':
2010                 f = ''
2011         elif not os.path.isfile (f):
2012                 continue
2013         try:
2014                 do_one_file (f)
2015         except UnknownVersion:
2016                 sys.stderr.write ('\n')
2017                 sys.stderr.write ("%s: can't determine version for `%s'" % (program_name, f))
2018                 sys.stderr.write ('\n')
2019                 if assume_old:
2020                         fv = from_version
2021                         from_version = (0,0,0)
2022                         do_one_file (f)
2023                         from_version = fv
2024                 else:
2025                         sys.stderr.write ("%s: skipping: `%s' " % (program_name,  f))
2026                 pass
2027
2028 sys.stderr.write ('\n')