]> git.donarmstrong.com Git - lilypond.git/blob - scripts/convert-ly.py
*** empty log message ***
[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 import os
19 import sys
20 import __main__
21 import getopt
22 import  string
23 import re
24 import time
25
26 program_name = sys.argv[0]
27
28 version = '@TOPLEVEL_VERSION@'
29
30 # Did we ever have \mudela-version?  I doubt it.
31 # lilypond_version_re_str = '\\\\version *\"(.*)\"'
32 lilypond_version_re_str = '\\\\(mudela-)?version *\"([^"]+)\"'
33 lilypond_version_re = re.compile (lilypond_version_re_str)
34 add_version = 1
35
36
37 def program_id ():
38         return '%s (GNU LilyPond) %s' %(program_name,  version);
39
40 def identify ():
41         sys.stderr.write (program_id () + '\n')
42
43 def usage ():
44         sys.stdout.write (
45                 r"""Usage: %s [OPTIONS]... [FILE]...
46 Try to convert to newer lilypond-versions.  The version number of the
47 input is guessed by default from \version directive.
48
49 Options:
50   -h, --help             print this help
51   -e, --edit             edit in place
52   -f, --from=VERSION     start from version; overrides \version found in file
53   -s, --show-rules       print all rules
54   -t, --to=VERSION       show target version
55   -n, --no-version       don't add new version stamp
56       --version          print program version
57
58 Report bugs to bugs-gnu-music@gnu.org.
59
60 """ % program_name)
61         
62         
63         sys.exit (0)
64
65 def print_version ():
66         
67         sys.stdout.write (r"""%s
68
69 This is free software.  It is covered by the GNU General Public
70 License, and you are welcome to change it and/or distribute copies of
71 it under certain conditions.  invoke as `%s --warranty' for more
72 information.
73
74 """ % (program_id() , program_name))
75         
76 def gulp_file(f):
77         try:
78                 i = open(f)
79                 i.seek (0, 2)
80                 n = i.tell ()
81                 i.seek (0,0)
82         except:
83                 print 'can\'t open file: ' + f + '\n'
84                 return ''
85         s = i.read (n)
86         if len (s) <= 0:
87                 print 'gulped empty file: ' + f + '\n'
88         i.close ()
89         return s
90
91 def str_to_tuple (s):
92         return tuple (map (string.atoi, string.split (s,'.')))
93
94 def tup_to_str (t):
95         return string.join (map (lambda x: '%s' % x, list (t)), '.')
96
97 def version_cmp (t1, t2):
98         for x in [0,1,2]:
99                 if t1[x] - t2[x]:
100                         return t1[x] - t2[x]
101         return 0
102
103 def guess_lilypond_version (filename):
104         s = gulp_file (filename)
105         m = lilypond_version_re.search (s)
106         if m:
107                 return m.group (2)
108         else:
109                 return ''
110
111 class FatalConversionError:
112         pass
113
114 conversions = []
115
116 def show_rules (file):
117         for x in conversions:
118                 file.write  ('%s: %s\n' % (tup_to_str (x[0]), x[2]))
119
120 ############################
121                 
122 if 1:
123         def conv(str):
124                 if re.search ('\\\\multi', str):
125                         sys.stderr.write ('\nNot smart enough to convert \\multi')
126                 return str
127         
128         conversions.append (((0,1,9), conv, '\\header { key = concat + with + operator }'))
129
130 if 1:                                   # need new a namespace
131         def conv (str):
132                 if re.search ('\\\\octave', str):
133                         sys.stderr.write ('\nNot smart enough to convert \\octave')
134                 #       raise FatalConversionError()
135                 
136                 return str
137
138         conversions.append ((
139                 ((0,1,19), conv, 'deprecated \\octave; can\'t convert automatically')))
140
141
142 if 1:                                   # need new a namespace
143         def conv (str):
144                 str = re.sub ('\\\\textstyle([^;]+);',
145                                          '\\\\property Lyrics . textstyle = \\1', str)
146                 # harmful to current .lys
147                 # str = re.sub ('\\\\key([^;]+);', '\\\\accidentals \\1;', str)
148                         
149                 return str
150
151         conversions.append ((
152                 ((0,1,20), conv, 'deprecated \\textstyle, new \\key syntax')))
153
154
155 if 1:
156         def conv (str):
157                 str = re.sub ('\\\\musical_pitch', '\\\\musicalpitch',str)
158                 str = re.sub ('\\\\meter', '\\\\time',str)
159                         
160                 return str
161
162         conversions.append ((
163                 ((0,1,21), conv, '\\musical_pitch -> \\musicalpitch, '+
164                  '\\meter -> \\time')))
165
166 if 1:
167         def conv (str):
168                 return str
169
170         conversions.append ((
171                 ((1,0,0), conv, '0.1.21 -> 1.0.0 ')))
172
173
174 if 1:
175         def conv (str):
176                 str = re.sub ('\\\\accidentals', '\\\\keysignature',str)
177                 str = re.sub ('specialaccidentals *= *1', 'keyoctaviation = 0',str)
178                 str = re.sub ('specialaccidentals *= *0', 'keyoctaviation = 1',str)
179                         
180                 return str
181
182         conversions.append ((
183                 ((1,0,1), conv, '\\accidentals -> \\keysignature, ' +
184                  'specialaccidentals -> keyoctaviation')))
185
186 if 1:
187         def conv(str):
188                 if re.search ('\\\\header', str):
189                         sys.stderr.write ('\nNot smart enough to convert to new \\header format')
190                 return str
191         
192         conversions.append (((1,0,2), conv, '\\header { key = concat + with + operator }'))
193
194 if 1:
195         def conv(str):
196                 str =  re.sub ('\\\\melodic([^a-zA-Z])', '\\\\notes\\1',str)
197                 return str
198         
199         conversions.append (((1,0,3), conv, '\\melodic -> \\notes'))
200
201 if 1:
202         def conv(str):
203                 str =  re.sub ('default_paper *=', '',str)
204                 str =  re.sub ('default_midi *=', '',str)
205                 return str
206         
207         conversions.append (((1,0,4), conv, 'default_{paper,midi}'))
208
209 if 1:
210         def conv(str):
211                 str =  re.sub ('ChoireStaff', 'ChoirStaff',str)
212                 str =  re.sub ('\\\\output', 'output = ',str)
213                         
214                 return str
215         
216         conversions.append (((1,0,5), conv, 'ChoireStaff -> ChoirStaff'))
217
218 if 1:
219         def conv(str):
220                 if re.search ('[a-zA-Z]+ = *\\translator',str):
221                         sys.stderr.write ('\nNot smart enough to change \\translator syntax')
222                 #       raise FatalConversionError()
223                 return str
224         
225         conversions.append (((1,0,6), conv, 'foo = \\translator {\\type .. } ->\\translator {\\type ..; foo; }'))
226
227
228 if 1:
229         def conv(str):
230                 str =  re.sub ('\\\\lyrics*', '\\\\lyrics',str)
231                         
232                 return str
233         
234         conversions.append (((1,0,7), conv, '\\lyric -> \\lyrics'))
235
236 if 1:
237         def conv(str):
238                 str =  re.sub ('\\\\\\[/3+', '\\\\times 2/3 { ',str)
239                 str =  re.sub ('\\[/3+', '\\\\times 2/3 { [',str)
240                 str =  re.sub ('\\\\\\[([0-9/]+)', '\\\\times \\1 {',str)
241                 str =  re.sub ('\\[([0-9/]+)', '\\\\times \\1 { [',str)
242                 str =  re.sub ('\\\\\\]([0-9/]+)', '}', str)
243                 str =  re.sub ('\\\\\\]', '}',str)
244                 str =  re.sub ('\\]([0-9/]+)', '] }', str)
245                 return str
246         
247         conversions.append (((1,0,10), conv, '[2/3 ]1/1 -> \\times 2/3 '))
248
249 if 1:
250         def conv(str):
251                 return str
252         conversions.append (((1,0,12), conv, 'Chord syntax stuff'))
253
254
255 if 1:
256         def conv(str):
257                 
258                 
259                 str =  re.sub ('<([^>~]+)~([^>]*)>','<\\1 \\2> ~', str)
260                         
261                 return str
262         
263         conversions.append (((1,0,13), conv, '<a ~ b> c -> <a b> ~ c'))
264
265 if 1:
266         def conv(str):
267                 str =  re.sub ('<\\[','[<', str)
268                 str =  re.sub ('\\]>','>]', str)
269                         
270                 return str
271         
272         conversions.append (((1,0,14), conv, '<[a b> <a b]>c -> [<a b> <a b>]'))
273
274
275 if 1:
276         def conv(str):
277                 str =  re.sub ('\\\\type([^\n]*engraver)','\\\\TYPE\\1', str)
278                 str =  re.sub ('\\\\type([^\n]*performer)','\\\\TYPE\\1', str)
279                 str =  re.sub ('\\\\type','\\\\context', str)
280                 str =  re.sub ('\\\\TYPE','\\\\type', str)
281                 str =  re.sub ('textstyle','textStyle', str)
282                         
283                 return str
284         
285         conversions.append (((1,0,16), conv, '\\type -> \\context, textstyle -> textStyle'))
286
287
288 if 1:
289         def conv(str):
290                 if re.search ('\\\\repeat',str):
291                         sys.stderr.write ('\nNot smart enough to convert \\repeat')
292                 #       raise FatalConversionError()
293                 return str
294         
295         conversions.append (((1,0,18), conv,
296                 '\\repeat NUM Music Alternative -> \\repeat FOLDSTR Music Alternative'))
297
298 if 1:
299         def conv(str):
300                 str =  re.sub ('SkipBars','skipBars', str)
301                 str =  re.sub ('fontsize','fontSize', str)
302                 str =  re.sub ('midi_instrument','midiInstrument', str)                 
303                         
304                 return str
305
306         conversions.append (((1,0,19), conv,
307                 'fontsize -> fontSize, midi_instrument -> midiInstrument, SkipBars -> skipBars'))
308
309
310 if 1:
311         def conv(str):
312                 str =  re.sub ('tieydirection','tieVerticalDirection', str)
313                 str =  re.sub ('slurydirection','slurVerticalDirection', str)
314                 str =  re.sub ('ydirection','verticalDirection', str)                   
315                         
316                 return str
317
318         conversions.append (((1,0,20), conv,
319                 '{,tie,slur}ydirection -> {v,tieV,slurV}erticalDirection'))
320
321
322 if 1:
323         def conv(str):
324                 str =  re.sub ('hshift','horizontalNoteShift', str)
325                         
326                 return str
327
328         conversions.append (((1,0,21), conv,
329                 'hshift -> horizontalNoteShift'))
330
331
332 if 1:
333         def conv(str):
334                 str =  re.sub ('\\\\grouping[^;]*;','', str)
335                         
336                 return str
337
338         conversions.append (((1,1,52), conv,
339                 'deprecate \\grouping'))
340
341
342 if 1:
343         def conv(str):
344                 str =  re.sub ('\\\\wheel','\\\\coda', str)
345                         
346                 return str
347
348         conversions.append (((1,1,55), conv,
349                 '\\wheel -> \\coda'))
350
351 if 1:
352         def conv(str):
353                 str =  re.sub ('keyoctaviation','keyOctaviation', str)
354                 str =  re.sub ('slurdash','slurDash', str)
355                         
356                 return str
357
358         conversions.append (((1,1,65), conv,
359                 'slurdash -> slurDash, keyoctaviation -> keyOctaviation'))
360
361 if 1:
362         def conv(str):
363                 str =  re.sub ('\\\\repeat *\"?semi\"?','\\\\repeat "volta"', str)
364                         
365                 return str
366
367         conversions.append (((1,1,66), conv,
368                 'semi -> volta'))
369
370
371 if 1:
372         def conv(str):
373                 str =  re.sub ('\"?beamAuto\"? *= *\"?0?\"?','noAutoBeaming = "1"', str)
374                         
375                 return str
376
377         conversions.append (((1,1,67), conv,
378                 'beamAuto -> noAutoBeaming'))
379
380 if 1:
381         def conv(str):
382                 str =  re.sub ('automaticMelismas', 'automaticMelismata', str)
383                         
384                 return str
385
386         conversions.append (((1,2,0), conv,
387                 'automaticMelismas -> automaticMelismata'))
388
389 if 1:
390         def conv(str):
391                 str =  re.sub ('dynamicDir\\b', 'dynamicDirection', str)
392                         
393                 return str
394
395         conversions.append (((1,2,1), conv,
396                 'dynamicDir -> dynamicDirection'))
397
398 if 1:
399         def conv(str):
400                 str =  re.sub ('\\\\cadenza *0 *;', '\\\\cadenzaOff', str)
401                 str =  re.sub ('\\\\cadenza *1 *;', '\\\\cadenzaOn', str)               
402                         
403                 return str
404
405         conversions.append (((1,3,4), conv,
406                 '\\cadenza -> \\cadenza{On|Off}'))
407
408 if 1:
409         def conv (str):
410                 str = re.sub ('"?beamAuto([^"=]+)"? *= *"([0-9]+)/([0-9]+)" *;*',
411                               'beamAuto\\1 = #(make-moment \\2 \\3)',
412                               str)
413                 return str
414
415         conversions.append (((1,3,5), conv, 'beamAuto moment properties'))
416
417 if 1:
418         def conv (str):
419                 str = re.sub ('stemStyle',
420                               'flagStyle',
421                               str)
422                 return str
423
424         conversions.append (((1,3,17), conv, 'stemStyle -> flagStyle'))
425
426 if 1:
427         def conv (str):
428                 str = re.sub ('staffLineLeading',
429                               'staffSpace',
430                               str)
431                 return str
432
433         conversions.append (((1,3,18), conv, 'staffLineLeading -> staffSpace'))
434
435
436 if 1:
437         def conv(str):
438                 if re.search ('\\\\repetitions',str):
439                         sys.stderr.write ('\nNot smart enough to convert \\repetitions')
440                 #       raise FatalConversionError()
441                 return str
442         
443         conversions.append (((1,3,23), conv,
444                 '\\\\repetitions feature dropped'))
445
446
447 if 1:
448         def conv (str):
449                 str = re.sub ('textEmptyDimension *= *##t',
450                               'textNonEmpty = ##f',
451                               str)
452                 str = re.sub ('textEmptyDimension *= *##f',
453                               'textNonEmpty = ##t',
454                               str)
455                 return str
456
457         conversions.append (((1,3,35), conv, 'textEmptyDimension -> textNonEmpty'))
458
459 if 1:
460         def conv (str):
461                 str = re.sub ("([a-z]+)[ \t]*=[ \t]*\\\\musicalpitch *{([- 0-9]+)} *\n",
462                               "(\\1 . (\\2))\n", str)
463                 str = re.sub ("\\\\musicalpitch *{([0-9 -]+)}",
464                               "\\\\musicalpitch #'(\\1)", str)
465                 if re.search ('\\\\notenames',str):
466                         sys.stderr.write ('\nNot smart enough to convert to new \\notenames format')
467                 return str
468
469         conversions.append (((1,3,38), conv, '\musicalpitch { a b c } -> #\'(a b c)'))
470
471 if 1:
472         def conv (str):
473                 def replace (match):
474                         return '\\key %s;' % string.lower (match.group (1))
475                 
476                 str = re.sub ("\\\\key ([^;]+);",  replace, str)
477                 return str
478         
479         conversions.append (((1,3,39), conv, '\\key A ;  ->\\key a;'))
480
481 if 1:
482         def conv (str):
483                 if re.search ('\\[:',str):
484                         sys.stderr.write ('\nNot smart enough to convert to new tremolo format')
485                 return str
486
487         conversions.append (((1,3,41), conv,
488                 '[:16 c4 d4 ] -> \\repeat "tremolo" 2 { c16 d16 }'))
489
490 if 1:
491         def conv (str):
492                 str = re.sub ('Staff_margin_engraver' , 'Instrument_name_engraver', str)
493                 return str
494
495         conversions.append (((1,3,42), conv,
496                 'Staff_margin_engraver deprecated, use Instrument_name_engraver'))
497
498 if 1:
499         def conv (str):
500                 str = re.sub ('note[hH]eadStyle\\s*=\\s*"?(\\w+)"?' , "noteHeadStyle = #'\\1", str)
501                 return str
502
503         conversions.append (((1,3,49), conv,
504                 'noteHeadStyle value: string -> symbol'))
505
506 if 1:
507         def conv (str):
508                 if re.search ('\\\\keysignature', str):
509                         sys.stderr.write ('\nNot smart enough to convert to new tremolo format')
510                 return str
511
512
513         conversions.append (((1,3,58), conv,
514                 'noteHeadStyle value: string -> symbol'))
515
516 if 1:
517         def conv (str):
518                 str = re.sub (r"""\\key *([a-z]+) *;""", r"""\\key \1 \major;""",str);
519                 return str
520         conversions.append (((1,3,59), conv,
521                 '\key X ; -> \key X major; '))
522
523 if 1:
524         def conv (str):
525                 str = re.sub (r'latexheaders *= *"\\\\input ',
526                               'latexheaders = "',
527                               str)
528                 return str
529         conversions.append (((1,3,68), conv, 'latexheaders = "\\input global" -> latexheaders = "global"'))
530
531
532
533
534 # TODO: lots of other syntax change should be done here as well
535 if 1:
536         def conv (str):
537                 str = re.sub ('basicCollisionProperties', 'NoteCollision', str)
538                 str = re.sub ('basicVoltaSpannerProperties' , "VoltaBracket", str)
539                 str = re.sub ('basicKeyProperties' , "KeySignature", str)
540
541                 str = re.sub ('basicClefItemProperties' ,"Clef", str)
542
543
544                 str = re.sub ('basicLocalKeyProperties' ,"Accidentals", str)
545                 str = re.sub ('basicMarkProperties' ,"Accidentals", str)
546                 str = re.sub ('basic([A-Za-z_]+)Properties', '\\1', str)
547
548                 str = re.sub ('Repeat_engraver' ,'Volta_engraver', str)
549                 return str
550         
551         conversions.append (((1,3,92), conv, 'basicXXXProperties -> XXX, Repeat_engraver -> Volta_engraver'))
552
553 if 1:
554         def conv (str):
555                 # Ugh, but meaning of \stemup changed too
556                 # maybe we should do \stemup -> \stemUp\slurUp\tieUp ?
557                 str = re.sub ('\\\\stemup', '\\\\stemUp', str)
558                 str = re.sub ('\\\\stemdown', '\\\\stemDown', str)
559                 str = re.sub ('\\\\stemboth', '\\\\stemBoth', str)
560                 
561                 str = re.sub ('\\\\slurup', '\\\\slurUp', str)
562                 str = re.sub ('\\\\slurboth', '\\\\slurBoth', str)
563                 str = re.sub ('\\\\slurdown', '\\\\slurDown', str)
564                 str = re.sub ('\\\\slurdotted', '\\\\slurDotted', str)
565                 str = re.sub ('\\\\slurnormal', '\\\\slurNoDots', str)          
566                 
567                 str = re.sub ('\\\\shiftoff', '\\\\shiftOff', str)
568                 str = re.sub ('\\\\shifton', '\\\\shiftOn', str)
569                 str = re.sub ('\\\\shiftonn', '\\\\shiftOnn', str)
570                 str = re.sub ('\\\\shiftonnn', '\\\\shiftOnnn', str)
571
572                 str = re.sub ('\\\\onevoice', '\\\\oneVoice', str)
573                 str = re.sub ('\\\\voiceone', '\\\\voiceOne', str)
574                 str = re.sub ('\\\\voicetwo', '\\\\voiceTwo', str)
575                 str = re.sub ('\\\\voicethree', '\\\\voiceThree', str)
576                 str = re.sub ('\\\\voicefour', '\\\\voiceFour', str)
577
578                 # I don't know exactly when these happened...
579                 # ugh, we loose context setting here...
580                 str = re.sub ('\\\\property *[^ ]*verticalDirection[^=]*= *#?"?(1|(\\\\up))"?', '\\\\stemUp\\\\slurUp\\\\tieUp', str)
581                 str = re.sub ('\\\\property *[^ ]*verticalDirection[^=]*= *#?"?((-1)|(\\\\down))"?', '\\\\stemDown\\\\slurDown\\\\tieDown', str)
582                 str = re.sub ('\\\\property *[^ ]*verticalDirection[^=]*= *#?"?(0|(\\\\center))"?', '\\\\stemBoth\\\\slurBoth\\\\tieBoth', str)
583
584                 str = re.sub ('verticalDirection[^=]*= *#?"?(1|(\\\\up))"?', 'Stem \\\\override #\'direction = #0\nSlur \\\\override #\'direction = #0\n Tie \\\\override #\'direction = #1', str)
585                 str = re.sub ('verticalDirection[^=]*= *#?"?((-1)|(\\\\down))"?', 'Stem \\\\override #\'direction = #0\nSlur \\\\override #\'direction = #0\n Tie \\\\override #\'direction = #-1', str)
586                 str = re.sub ('verticalDirection[^=]*= *#?"?(0|(\\\\center))"?', 'Stem \\\\override #\'direction = #0\nSlur \\\\override #\'direction = #0\n Tie \\\\override #\'direction = #0', str)
587                 
588                 str = re.sub ('\\\\property *[^ .]*[.]?([a-z]+)VerticalDirection[^=]*= *#?"?(1|(\\\\up))"?', '\\\\\\1Up', str)
589                 str = re.sub ('\\\\property *[^ .]*[.]?([a-z]+)VerticalDirection[^=]*= *#?"?((-1)|(\\\\down))"?', '\\\\\\1Down', str)
590                 str = re.sub ('\\\\property *[^ .]*[.]?([a-z]+)VerticalDirection[^=]*= *#?"?(0|(\\\\center))"?', '\\\\\\1Both', str)
591
592                 # (lacks capitalisation slur -> Slur)
593                 str = re.sub ('([a-z]+)VerticalDirection[^=]*= *#?"?(1|(\\\\up))"?', '\\1 \\\\override #\'direction = #1', str)
594                 str = re.sub ('([a-z]+)VerticalDirection[^=]*= *#?"?((-1)|(\\\\down))"?', '\\1 \\override #\'direction = #-1', str)
595                 str = re.sub ('([a-z]+)VerticalDirection[^=]*= *#?"?(0|(\\\\center))"?', '\\1 \\\\override #\'direction = #0', str)
596
597                 ## dynamic..
598                 str = re.sub ('\\\\property *[^ .]*[.]?dynamicDirection[^=]*= *#?"?(1|(\\\\up))"?', '\\\\dynamicUp', str)
599                 str = re.sub ('\\\\property *[^ .]*[.]?dyn[^=]*= *#?"?((-1)|(\\\\down))"?', '\\\\dynamicDown', str)
600                 str = re.sub ('\\\\property *[^ .]*[.]?dyn[^=]*= *#?"?(0|(\\\\center))"?', '\\\\dynamicBoth', str)
601
602                 str = re.sub ('\\\\property *[^ .]*[.]?([a-z]+)Dash[^=]*= *#?"?(0|(""))"?', '\\\\\\1NoDots', str)
603                 str = re.sub ('\\\\property *[^ .]*[.]?([a-z]+)Dash[^=]*= *#?"?([1-9]+)"?', '\\\\\\1Dotted', str)
604
605                 str = re.sub ('\\\\property *[^ .]*[.]?noAutoBeaming[^=]*= *#?"?(0|(""))"?', '\\\\autoBeamOn', str)
606                 str = re.sub ('\\\\property *[^ .]*[.]?noAutoBeaming[^=]*= *#?"?([1-9]+)"?', '\\\\autoBeamOff', str)
607
608
609
610                 return str
611         
612         conversions.append (((1,3,93), conv,
613                 'property definiton case (eg. onevoice -> oneVoice)'))
614
615
616 if 1:
617         def conv (str):
618                 str = re.sub ('ChordNames*', 'ChordNames', str)
619                 if re.search ('\\\\textscript "[^"]* *"[^"]*"', str):
620                         sys.stderr.write ('\nNot smart enough to convert to new \\textscript markup text')
621
622                 str = re.sub ('\\textscript +("[^"]*")', '\\textscript #\\1', str)
623
624                 return str
625         
626         conversions.append (((1,3,97), conv, 'ChordName -> ChordNames'))
627
628
629 # TODO: add lots of these
630         
631 if 1:
632         def conv (str):
633                 str = re.sub ('\\\\property *"?Voice"? *[.] *"?textStyle"? *= *"([^"]*)"', '\\\\property Voice.TextScript \\\\set #\'font-style = #\'\\1', str)
634                 str = re.sub ('\\\\property *"?Lyrics"? *[.] *"?textStyle"? *= *"([^"]*)"', '\\\\property Lyrics.LyricText \\\\set #\'font-style = #\'\\1', str)
635
636                 str = re.sub ('\\\\property *"?([^.]+)"? *[.] *"?timeSignatureStyle"? *= *"([^"]*)"', '\\\\property \\1.TimeSignature \\\\override #\'style = #\'\\2', str)
637
638                 str = re.sub ('"?timeSignatureStyle"? *= *#?""', 'TimeSignature \\\\override #\'style = ##f', str)
639                 
640                 str = re.sub ('"?timeSignatureStyle"? *= *#?"([^"]*)"', 'TimeSignature \\\\override #\'style = #\'\\1', str)
641                 
642                 str = re.sub ('#\'style *= #*"([^"])"', '#\'style = #\'\\1', str)
643                 
644                 str = re.sub ('\\\\property *"?([^.]+)"? *[.] *"?horizontalNoteShift"? *= *"?#?([-0-9]+)"?', '\\\\property \\1.NoteColumn \\\\override #\'horizontal-shift = #\\2', str)
645
646                 # ugh
647                 str = re.sub ('\\\\property *"?([^.]+)"? *[.] *"?flagStyle"? *= *""', '\\\\property \\1.Stem \\\\override #\'flag-style = ##f', str)
648                 
649                 str = re.sub ('\\\\property *"?([^.]+)"? *[.] *"?flagStyle"? *= *"([^"]*)"', '\\\\property \\1.Stem \\\\override #\'flag-style = #\'\\2', str)
650                 return str
651         
652         conversions.append (((1,3,98), conv, 'CONTEXT.textStyle -> GROB.#font-style '))
653
654 if 1:
655         def conv (str):
656                 str = re.sub ('"?beamAutoEnd_([0-9]*)"? *= *(#\\([^)]*\\))', 'autoBeamSettings \\push #\'(end 1 \\1 * *) = \\2', str)
657                 str = re.sub ('"?beamAutoBegin_([0-9]*)"? *= *(#\\([^)]*\))', 'autoBeamSettings \\push #\'(begin 1 \\1 * *) = \\2', str)
658                 str = re.sub ('"?beamAutoEnd"? *= *(#\\([^)]*\\))', 'autoBeamSettings \\push #\'(end * * * *) = \\1', str)
659                 str = re.sub ('"?beamAutoBegin"? *= *(#\\([^)]*\\))', 'autoBeamSettings \\push #\'(begin * * * *) = \\1', str)
660
661
662                 return str
663         
664         conversions.append (((1,3,102), conv, 'beamAutoEnd -> autoBeamSettings \\push (end * * * *)'))
665
666
667 if 1:
668         def conv (str):
669                 str = re.sub ('\\\\push', '\\\\override', str)
670                 str = re.sub ('\\\\pop', '\\\\revert', str)
671
672                 return str
673         
674         conversions.append (((1,3,111), conv, '\\push -> \\override, \\pop -> \\revert'))
675
676 if 1:
677         def conv (str):
678                 str = re.sub ('LyricVoice', 'LyricsVoice', str)
679                 # old fix
680                 str = re.sub ('Chord[Nn]ames*.Chord[Nn]ames*', 'ChordNames.ChordName', str)
681                 str = re.sub ('Chord[Nn]ames([ \t\n]+\\\\override)', 'ChordName\\1', str)
682                 return str
683         
684         conversions.append (((1,3,113), conv, 'LyricVoice -> LyricsVoice'))
685
686 def regularize_id (str):
687         s = ''
688         lastx = ''
689         for x in str:
690                 if x == '_':
691                         lastx = x
692                         continue
693                 elif x in string.digits:
694                         x = chr(ord (x) - ord ('0')  +ord ('A'))
695                 elif x not in string.letters:
696                         x = 'x'
697                 elif x in string.lowercase and lastx == '_':
698                         x = string.upper (x)
699                 s = s + x
700                 lastx = x
701         return s
702
703 if 1:
704         def conv (str):
705                 
706                 def regularize_dollar_reference (match):
707                         return regularize_id (match.group (1))
708                 def regularize_assignment (match):
709                         return '\n' + regularize_id (match.group (1)) + ' = '
710                 str = re.sub ('\$([^\t\n ]+)', regularize_dollar_reference, str)
711                 str = re.sub ('\n([^ \t\n]+)[ \t]*= *', regularize_assignment, str)
712                 return str
713         
714         conversions.append (((1,3,117), conv, 'identifier names: $!foo_bar_123 -> xfooBarABC'))
715
716
717 if 1:
718         def conv (str):
719                 def regularize_paper (match):
720                         return regularize_id (match.group (1))
721                 
722                 str = re.sub ('(paper_[a-z]+)', regularize_paper, str)
723                 str = re.sub ('sustainup', 'sustainUp', str)
724                 str = re.sub ('nobreak', 'noBreak', str)
725                 str = re.sub ('sustaindown', 'sustainDown', str)
726                 str = re.sub ('sostenutoup', 'sostenutoUp', str)
727                 str = re.sub ('sostenutodown', 'sostenutoDown', str)
728                 str = re.sub ('unachorda', 'unaChorda', str)
729                 str = re.sub ('trechorde', 'treChorde', str)
730         
731                 return str
732         
733         conversions.append (((1,3,120), conv, 'paper_xxx -> paperXxxx, pedalup -> pedalUp.'))
734
735 if 1:
736         def conv (str):
737                 str = re.sub ('drarnChords', 'chordChanges', str)
738                 str = re.sub ('\\musicalpitch', '\\pitch', str)
739                 return str
740         
741         conversions.append (((1,3,122), conv, 'drarnChords -> chordChanges, \\musicalpitch -> \\pitch'))
742
743 if 1:
744         def conv (str):
745                 str = re.sub ('ly-([sg])et-elt-property', 'ly-\\1et-grob-property', str)
746                 return str
747         
748         conversions.append (((1,3,136), conv, 'ly-X-elt-property -> ly-X-grob-property'))
749
750 if 1:
751         def conv (str):
752                 str = re.sub ('point-and-click +#t', 'point-and-click line-column-location', str)
753                 return str
754         
755         conversions.append (((1,3,138), conv, 'point-and-click argument changed to procedure.'))
756
757 if 1:
758         def conv (str):
759                 str = re.sub ('followThread', 'followVoice', str)
760                 str = re.sub ('Thread.FollowThread', 'Voice.VoiceFollower', str)
761                 str = re.sub ('FollowThread', 'VoiceFollower', str)
762                 return str
763         
764         conversions.append (((1,3,138), conv, 'followThread -> followVoice.'))
765
766 if 1:
767         def conv (str):
768                 str = re.sub ('font-point-size', 'font-design-size', str)
769                 return str
770         
771         conversions.append (((1,3,139), conv, 'font-point-size -> font-design-size.'))
772
773 if 1:
774         def conv (str):
775                 str = re.sub ('([a-zA-Z]*)NoDots', '\\1Solid', str)
776                 return str
777         
778         conversions.append (((1,3,141), conv, 'xNoDots -> xSolid'))
779
780 if 1:
781         def conv (str):
782                 str = re.sub ('([Cc])hord([ea])', '\\1ord\\2', str)
783                 return str
784         
785         conversions.append (((1,3,144), conv, 'Chorda -> Corda'))
786
787
788 if 1:
789         def conv (str):
790                 str = re.sub ('([A-Za-z]+)MinimumVerticalExtent', 'MinimumV@rticalExtent', str)
791                 str = re.sub ('([A-Za-z]+)ExtraVerticalExtent', 'ExtraV@rticalExtent', str)
792                 str = re.sub ('([A-Za-z]+)VerticalExtent', 'VerticalExtent', str)
793                 str = re.sub ('ExtraV@rticalExtent', 'ExtraVerticalExtent', str)
794                 str = re.sub ('MinimumV@rticalExtent', 'MinimumVerticalExtent', str)            
795                 return str
796
797         conversions.append (((1,3,145), conv,
798         'ContextNameXxxxVerticalExtent -> XxxxVerticalExtent'))
799
800 if 1:
801         def conv (str):
802                 str = re.sub ('\\\\key[ \t]*;', '\\key \\default;', str)
803                 str = re.sub ('\\\\mark[ \t]*;', '\\mark \\default;', str)
804
805                 # Make sure groups of more than one ; have space before
806                 # them, so that non of them gets removed by next rule
807                 str = re.sub ("([^ \n\t;]);(;+)", "\\1 ;\\2", str)
808                 
809                 # Only remove ; that are not after spaces, # or ;
810                 # Otherwise  we interfere with Scheme comments,
811                 # which is badbadbad.
812                 str = re.sub ("([^ \t;#]);", "\\1", str)
813
814                 return str
815         conversions.append (((1,3,146), conv, 'semicolons removed'))
816
817 if 1:
818         def conv (str):
819                 str = re.sub ('default-neutral-direction', 'neutral-direction',str)
820                 return str
821         conversions.append (((1,3,147), conv, 'default-neutral-direction -> neutral-direction'))
822
823 if 1:
824         def conv (str):
825                 str = re.sub ('\(align', '(axis', str)
826                 str = re.sub ('\(rows', '(columns', str)
827                 return str
828         conversions.append (((1,3,148), conv, '"(align" -> "(axis", "(rows" -> "(columns"'))
829
830
831 if 1:
832         def conv (str):
833                 str = re.sub ('SystemStartDelimiter', 'systemStartDelimiter', str)
834                 return str
835         conversions.append (((1,5,33), conv, 'SystemStartDelimiter -> systemStartDelimiter'))
836
837 if 1:
838         def conv (str):
839                 str = re.sub ('arithmetic-multiplier', 'spacing-increment', str)
840                 str = re.sub ('arithmetic-basicspace', 'shortest-duration-space', str)          
841                 return str
842         
843         conversions.append (((1,5,38), conv, 'SystemStartDelimiter -> systemStartDelimiter'))
844
845
846 if 1:
847         def conv (str):
848         
849                 def func(match):
850                         break_dict = {
851                         "Instrument_name": "instrument-name",
852                         "Left_edge_item": "left-edge",
853                         "Span_bar": "span-bar",
854                         "Breathing_sign": "breathing-sign",
855                         "Staff_bar": "staff-bar",
856                         "Clef_item": "clef",
857                         "Key_item": "key-signature",
858                         "Time_signature": "time-signature",
859                         "Custos": "custos"
860                         }
861                         props =  match.group (1)
862                         for (k,v) in break_dict.items():
863                                 props = re.sub (k, v, props)
864                         return  "breakAlignOrder = #'(%s)" % props
865
866                 str = re.sub ("breakAlignOrder *= *#'\\(([a-z_\n\tA-Z ]+)\\)",
867                               func, str)
868                 return str
869
870         # 40 ?
871         conversions.append (((1,5,40), conv, 'breakAlignOrder property names'))
872         
873
874 if 1:
875         def conv (str):
876                 str = re.sub ('noAutoBeaming *= *##f', 'autoBeaming = ##t', str)
877                 str = re.sub ('noAutoBeaming *= *##t', 'autoBeaming = ##f', str)
878                 return str
879         
880         conversions.append (((1,5,49), conv, 'noAutoBeaming -> autoBeaming'))
881
882 if 1:
883         def conv (str):
884                 str = re.sub ('tuplet-bracket-visibility', 'bracket-visibility', str)
885                 str = re.sub ('tuplet-number-visibility', 'number-visibility', str)             
886                 return str
887         
888         conversions.append (((1,5,52), conv, 'tuplet-X-visibility -> X-visibility'))
889
890 if 1:
891         def conv (str):
892                 str = re.sub ('Pitch::transpose', 'ly-transpose-pitch', str)
893
894                 return str
895         
896         conversions.append (((1,5,56), conv, 'Pitch::transpose -> ly-transpose-pitch'))
897
898 if 1:
899         def conv (str):
900                 str = re.sub ('textNonEmpty *= *##t', "TextScript \\set #'no-spacing-rods = ##f", str)
901                 str = re.sub ('textNonEmpty *= *##f', "TextScript \\set #'no-spacing-rods = ##t", str)
902                 return str
903         
904         conversions.append (((1,5,58), conv, 'deprecate textNonEmpty'))
905
906
907 if 1:
908         def conv (str):
909                 str = re.sub ('MinimumVerticalExtent', 'minimumV@rticalExtent', str)
910                 str = re.sub ('minimumVerticalExtent', 'minimumV@rticalExtent', str)            
911                 str = re.sub ('ExtraVerticalExtent', 'extraV@rticalExtent', str)
912                 str = re.sub ('extraVerticalExtent', 'extraV@rticalExtent', str)                
913                 str = re.sub ('VerticalExtent', 'verticalExtent', str)
914                 str = re.sub ('extraV@rticalExtent', 'extraVerticalExtent', str)
915                 str = re.sub ('minimumV@rticalExtent', 'minimumVerticalExtent', str)            
916                 return str
917
918         conversions.append (((1,5,59), conv,
919         'XxxxVerticalExtent -> xxxVerticalExtent'))
920
921 if 1:
922         def conv (str):
923                 str = re.sub ('visibility-lambda', 'break-visibility', str)
924                 return str
925
926         conversions.append (((1,5,62), conv,
927         'visibility-lambda -> break-visibility'))
928         
929
930 if 1:
931         def conv (str):
932                 if re.search (r'\addlyrics',str) \
933                        and re.search ('automaticMelismata', str)  == None:
934                         sys.stderr.write  ('automaticMelismata is turned on by default since 1.5.67. Please fix this by hand.')
935                         raise FatalConversionError()
936                 return str
937
938         conversions.append (((1,5,67), conv,
939                              'automaticMelismata turned on by default'))
940
941 if 1:
942         def conv (str):
943                 str = re.sub ('ly-set-grob-property([^!])', 'ly-set-grob-property!\1', str)
944                 str = re.sub ('ly-set-mus-property([^!])', 'ly-set-mus-property!\1', str)               
945                 return str
946         
947         conversions.append (((1,5,68), conv, 'ly-set-X-property -> ly-set-X-property!'))
948
949 if 1:
950         def conv (str):
951                 str = re.sub ('extent-X', 'X-extent', str)
952                 str = re.sub ('extent-Y', 'Y-extent', str)              
953                 return str
954         
955         conversions.append (((1,5,71), conv, 'extent-[XY] -> [XY]-extent'))
956
957
958 if 1:
959         def conv (str):
960                 str = re.sub ("""#\(set! +point-and-click +line-column-location\)""",
961                               """#(set-point-and-click! \'line-column)""", str)
962                 str = re.sub ("""#\(set![ \t]+point-and-click +line-location\)""",
963                               '#(set-point-and-click! \'line)', str)
964                 str = re.sub ('#\(set! +point-and-click +#f\)',
965                               '#(set-point-and-click! \'none)', str)
966                 return str
967         
968         conversions.append (((1,5,72), conv, 'set! point-and-click -> set-point-and-click!'))
969
970
971 if 1:
972         def conv (str):
973                 str = re.sub ('flag-style', 'stroke-style', str)
974                 str = re.sub (r"""Stem([ ]+)\\override #'style""", r"""Stem \\override #'flag-style""", str);
975                 str = re.sub (r"""Stem([ ]+)\\set([ ]+)#'style""", r"""Stem \\set #'flag-style""", str);
976                 return str
977         
978         conversions.append (((1,6,5), conv, 'Stems: flag-style -> stroke-style; style -> flag-style'))
979
980
981 if 1:
982         def subst_req_name (match):
983                 return "(make-music-by-name \'%sEvent)" % regularize_id (match.group(1))
984
985         def conv (str):
986                 str = re.sub ('\\(ly-make-music *\"([A-Z][a-z_]+)_req\"\\)', subst_req_name, str)
987                 str = re.sub ('Request_chord', 'EventChord', str)
988                 return str
989         
990         conversions.append (((1,7,1), conv, 'ly-make-music foo_bar_req -> make-music-by-name FooBarEvent'))
991
992
993 if 1:
994         spanner_subst ={
995                 "text" : 'TextSpanEvent',
996                 "decrescendo" : 'DecrescendoEvent',
997                 "crescendo" : 'CrescendoEvent',
998                 "Sustain" : 'SustainPedalEvent',
999                 "slur" : 'SlurEvent',
1000                 "UnaCorda" : 'UnaCordaEvent',
1001                 "Sostenuto" : 'SostenutoEvent',
1002                 }
1003         def subst_ev_name (match):
1004                 stype = 'STOP'
1005                 if re.search ('start', match.group(1)):
1006                         stype= 'START'
1007
1008                 mtype = spanner_subst[match.group(2)]
1009                 return "(make-span-event '%s %s)" % (mtype , stype)
1010
1011         def subst_definition_ev_name(match):
1012                 return ' = #%s' % subst_ev_name (match)
1013         def subst_inline_ev_name (match):
1014                 s = subst_ev_name (match)
1015                 return '#(ly-export %s)' % s
1016         def subst_csp_definition (match):
1017                 return ' = #(make-event-chord (list %s))' % subst_ev_name (match)
1018         def subst_csp_inline (match):
1019                 return '#(ly-export (make-event-chord (list %s)))' % subst_ev_name (match)
1020                 
1021         def conv (str):
1022                 str = re.sub (r' *= *\\spanrequest *([^ ]+) *"([^"]+)"', subst_definition_ev_name, str)
1023                 str = re.sub (r'\\spanrequest *([^ ]+) *"([^"]+)"', subst_inline_ev_name, str)
1024                 str = re.sub (r' *= *\\commandspanrequest *([^ ]+) *"([^"]+)"', subst_csp_definition, str)
1025                 str = re.sub (r'\\commandspanrequest *([^ ]+) *"([^"]+)"', subst_csp_inline, str)
1026                 str = re.sub (r'ly-id ', 'ly-import ', str)
1027
1028                 str = re.sub (r' *= *\\script "([^"]+)"', ' = #(make-articulation "\\1")', str)
1029                 str = re.sub (r'\\script "([^"]+)"', '#(ly-export (make-articulation "\\1"))', str)
1030                 return str
1031
1032         conversions.append (((1,7,2), conv, '\\spanrequest -> #(make-span-event .. ), \script -> #(make-articulation .. )'))
1033
1034 if 1:
1035         def conv(str):
1036                 str = re.sub (r'\(ly-', '(ly:', str)
1037
1038                 changed = [
1039                         r'duration\?',
1040                         r'font-metric\?',
1041                         r'molecule\?',
1042                         r'moment\?',
1043                         r'music\?',
1044                         r'pitch\?',
1045                         'make-duration',
1046                         'music-duration-length',
1047                         'duration-log',
1048                         'duration-dotcount',
1049                         'intlog2',
1050                         'duration-factor',
1051                         'transpose-key-alist',
1052                         'get-system',
1053                         'get-broken-into',
1054                         'get-original',
1055                         'set-point-and-click!',
1056                         'make-moment',
1057                         'make-pitch',
1058                         'pitch-octave',
1059                         'pitch-alteration',
1060                         'pitch-notename',
1061                         'pitch-semitones',
1062                         r'pitch<\?',
1063                         r'dir\?',
1064                         'music-duration-compress',
1065                         'set-point-and-click!'
1066                         ]
1067
1068                 origre = r'\b(%s)' % string.join (changed, '|')
1069                 
1070                 str = re.sub (origre, r'ly:\1',str)
1071                 str = re.sub ('set-point-and-click!', 'set-point-and-click', str)
1072                 
1073                 return str
1074         
1075         conversions.append (((1,7,3), conv, 'ly- -> ly:'))
1076
1077 if 1:
1078         def conv(str):
1079                 if re.search ('new-chords-done',str):
1080                         return str
1081                 
1082                 str = re.sub (r'<<', '< <', str)
1083                 str = re.sub (r'>>', '> >', str)
1084                 return str
1085         
1086         conversions.append (((1,7,4), conv, '<< >> -> < <  > >'))
1087
1088 if 1:
1089         def conv(str):
1090                 str = re.sub (r"\\transpose", r"\\transpose c'", str)
1091                 str = re.sub (r"\\transpose c' *([a-z]+)'", r"\\transpose c \1", str)
1092                 return str
1093         conversions.append (((1,7,5), conv, '\\transpose TO -> \\transpose FROM  TO'))
1094
1095 if 1:
1096         def conv(str):
1097                 kws =   ['arpeggio',
1098                          'sustainDown',
1099                          'sustainUp',
1100                          'f',
1101                          'p',
1102                          'pp',
1103                          'ppp',
1104                          'fp',
1105                          'ff',
1106                          'mf',
1107                          'mp',
1108                          'sfz',
1109                          ]
1110
1111                 origstr = string.join (kws, '|')
1112                 str = re.sub (r'([^_^-])\\(%s)\b' % origstr, r'\1-\\\2', str)
1113                 return str
1114         conversions.append (((1,7,6), conv, 'note\\script -> note-\script'))
1115
1116
1117 if 1:
1118         def conv(str):
1119                 str = re.sub (r"\\property *ChordNames *\. *ChordName *\\(set|override) *#'style *= *#('[a-z]+)",
1120                               r"#(set-chord-name-style \2)", str)
1121                 str = re.sub (r"\\property *ChordNames *\. *ChordName *\\revert *#'style",
1122                               r"", str)
1123                 return str
1124         conversions.append (((1,7,10), conv, "\property ChordName #'style -> #(set-chord-name-style 'style)"))
1125         
1126
1127
1128 if 1:
1129         def conv(str):
1130                 str = re.sub (r"ly:transpose-pitch", "ly:pitch-transpose", str)
1131                 
1132                 return str
1133         conversions.append (((1,7,11), conv, "transpose-pitch -> pitch-transpose"))
1134
1135 if 1:
1136         def conv(str):
1137                 str = re.sub (r"ly:get-molecule-extent", "ly:molecule-get-extent", str)
1138                 str = re.sub (r"ly:set-molecule-extent!", "ly:molecule-set-extent!", str)
1139                 str = re.sub (r"ly:add-molecule", "ly:molecule-add", str)
1140                 str = re.sub (r"ly:combine-molecule-at-edge", "ly:molecule-combine-at-edge", str)
1141                 str = re.sub (r"ly:align-to!", "ly:molecule-align-to!", str)
1142                 
1143                 return str
1144         
1145         conversions.append (((1,7,13), conv, "ly:XX-molecule-YY -> ly:molecule-XX-YY")) 
1146
1147 if 1:
1148         def conv(str):
1149                 str = re.sub (r"linewidth *= *-[0-9.]+ *(\\mm|\\cm|\\in|\\pt)?", 'raggedright = ##t', str )
1150                 return str
1151         
1152         conversions.append (((1,7,15), conv, "linewidth = -1 -> raggedright = ##t"))    
1153
1154 if 1:
1155         def conv(str):
1156                 str = re.sub ("divisiomaior",
1157                               "divisioMaior", str)
1158                 str = re.sub ("divisiominima",
1159                               "divisioMinima", str)
1160                 str = re.sub ("divisiomaxima",
1161                               "divisioMaxima", str)
1162                 return str
1163         
1164         conversions.append (((1,7,16), conv, "divisiomaior -> divisioMaior"))
1165
1166 if 1:
1167         def conv(str):
1168                 str = re.sub ("Skip_req_swallow_translator",
1169                               "Skip_event_swallow_translator", str)
1170                 return str
1171         
1172         conversions.append (((1,7,17), conv, "Skip_req  -> Skip_event"))
1173
1174 if 1:
1175         def conv(str):
1176                 str = re.sub ("groupOpen",
1177                               "startGroup", str)
1178                 str = re.sub ("groupClose",
1179                               "stopGroup", str)
1180                 str = re.sub ("#'outer",
1181                               "#'enclose-bounds", str)
1182
1183                 return str
1184         
1185         conversions.append (((1,7,18), conv,
1186                              """groupOpen/Close  -> start/stopGroup,
1187                              #'outer  -> #'enclose-bounds
1188                              """))
1189
1190 if 1:
1191         def conv(str):
1192                 if re.search( r'\\GraceContext', str):
1193                         sys.stderr.write ("GraceContext has been removed")
1194                         sys.stderr.write ("please use #(add-to-grace-init .. )")
1195                         raise FatalConversionError()
1196
1197                 str = re.sub ('HaraKiriStaffContext', 'RemoveEmptyStaffContext', str)
1198                 return str
1199         
1200         conversions.append (((1,7,19), conv,"remove GraceContext"))
1201
1202
1203
1204 if 1:
1205         def conv(str):
1206                 str = re.sub (
1207                         r"(set|override|revert) *#'type",
1208                         r"\1 #'style",
1209                         str)
1210                 return str
1211         
1212         conversions.append (((1,7,22), conv,"#'type -> #'style"))
1213
1214 if 1:
1215         def conv(str):
1216                 str = re.sub (
1217                         "barNonAuto *= *##t",
1218                         "automaticBars = ##f",
1219                         str)
1220                 str = re.sub (
1221                         "barNonAuto *= *##f",
1222                         "automaticBars = ##t",
1223                         str)
1224                 return str
1225         
1226         conversions.append (((1,7,23), conv,"barNonAuto -> automaticBars"))
1227         
1228
1229 if 1:
1230         def conv(str):
1231                 if re.search( r'-(start|stop)Cluster', str):
1232                         sys.stderr.write ("""Cluster syntax has been changed.
1233 Please refer to the manual for details, and convert manually.
1234 """)
1235                         
1236                         raise FatalConversionError()
1237
1238                 return str
1239         
1240         conversions.append (((1,7,24), conv,"cluster syntax"))
1241
1242 if 1:
1243         def conv(str):
1244                 str = re.sub (r"\\property *Staff\.(Sustain|Sostenuto|UnaCorda)Pedal *\\(override|set) *#'pedal-type *",
1245                                 r"\property Staff.pedal\1Style ", str)
1246                 str = re.sub (r"\\property *Staff\.(Sustain|Sostenuto|UnaCorda)Pedal *\\revert *#'pedal-type", '', str)
1247                 return str
1248         
1249         conversions.append (((1,7,28), conv,"new Pedal style syntax"))
1250
1251
1252
1253 if 1:
1254
1255         def sub_chord (m):
1256                 str = m.group(1)
1257
1258                 origstr =  '<%s>' % str
1259                 if re.search (r'\\\\', str):
1260                         return origstr
1261
1262                 if re.search (r'\\property', str):
1263                         return origstr
1264
1265                 if re.match (r'^\s*\)?\s*\\[a-zA-Z]+', str):
1266                         return origstr
1267
1268                 durs = []
1269                 def sub_durs (m, durs = durs):
1270                         durs.append(m.group(2))
1271                         return m.group (1)
1272
1273                 str = re.sub (r"([a-z]+[,'!? ]*)([0-9]+\.*)", sub_durs, str)
1274                 dur_str = ''
1275
1276                 for d in durs:
1277                         if dur_str == '':
1278                                 dur_str = d
1279                         if dur_str <> d:
1280                                 return '<%s>' % m.group (1)
1281
1282                 pslur_strs = ['']
1283                 dyns = ['']
1284                 slur_strs = ['']
1285
1286                 last_str = ''
1287                 while last_str <> str:
1288                         last_str = str
1289
1290                         def sub_tremolos (m, slur_strs = slur_strs):
1291                                 tr = m.group (2)
1292                                 if tr not in slur_strs:
1293                                         slur_strs.append (tr)
1294                                 return  m.group (1)
1295                         
1296                         str = re.sub (r"([a-z]+[',!? ]*)(:[0-9]+)",
1297                                       sub_tremolos, str)
1298
1299                         def sub_dyn_end (m, dyns = dyns):
1300                                 dyns.append (' \!')
1301                                 return ' ' + m.group(2)
1302
1303                         str = re.sub (r'(\\!)\s*([a-z]+)', sub_dyn_end, str)
1304                         def sub_slurs(m, slur_strs = slur_strs):
1305                                 if '-)' not in slur_strs:
1306                                         slur_strs.append (')')
1307                                 return m.group(1)
1308                         
1309                         def sub_p_slurs(m, slur_strs = slur_strs):
1310                                 if '-\)' not in slur_strs:
1311                                         slur_strs.append ('\)')
1312                                 return m.group(1)
1313                         
1314                         str = re.sub (r"\)[ ]*([a-z]+)", sub_slurs, str)
1315                         str = re.sub (r"\\\)[ ]*([a-z]+)", sub_p_slurs, str)
1316                         def sub_begin_slurs(m, slur_strs = slur_strs):
1317                                 if '-(' not in slur_strs:
1318                                         slur_strs.append ('(')
1319                                 return m.group(1)
1320                         
1321                         str = re.sub (r"([a-z]+[,'!?0-9 ]*)\(",
1322                                       sub_begin_slurs, str)
1323                         def sub_begin_p_slurs(m, slur_strs = slur_strs):
1324                                 if '-\(' not in slur_strs:
1325                                         slur_strs.append ('\(')
1326                                 return m.group(1)
1327
1328                         str = re.sub (r"([a-z]+[,'!?0-9 ]*)\\\(",
1329                                 sub_begin_p_slurs, str)
1330
1331                         def sub_dyns (m, slur_strs = slur_strs):
1332                                 s = m.group(0)
1333                                 if s == '@STARTCRESC@':
1334                                         slur_strs.append ("\\<")
1335                                 elif s == '@STARTDECRESC@':
1336                                         slur_strs.append ("\\>")
1337                                 elif s == r'-?\\!':
1338                                         slur_strs.append ('\\!')
1339                                 return ''
1340
1341                         str = re.sub (r'@STARTCRESC@', sub_dyns, str)
1342                         str = re.sub (r'-?\\!', sub_dyns, str)
1343
1344                         def sub_articulations (m, slur_strs = slur_strs):
1345                                 a = m.group(1)
1346                                 if a not in slur_strs:
1347                                         slur_strs.append (a)
1348                                 return ''
1349
1350                         str = re.sub (r"([_^-]\@ACCENT\@)", sub_articulations,
1351                                       str)
1352                         str = re.sub (r"([_^-]\\[a-z]+)", sub_articulations,
1353                                       str)
1354                         str = re.sub (r"([_^-][>_.+|^-])", sub_articulations,
1355                                       str)
1356                         str = re.sub (r'([_^-]"[^"]+")', sub_articulations,
1357                                       str)
1358
1359                         def sub_pslurs(m, slur_strs = slur_strs):
1360                                 slur_strs.append (' \\)')
1361                                 return m.group(1)
1362                         str = re.sub (r"\\\)[ ]*([a-z]+)", sub_pslurs, str)
1363
1364                 ## end of while <>
1365
1366                 suffix = string.join (slur_strs, '') + string.join (pslur_strs,
1367                                                                     '') \
1368                          + string.join (dyns, '')
1369
1370                 return '@STARTCHORD@%s@ENDCHORD@%s%s' % (str , dur_str, suffix)
1371
1372
1373
1374         def sub_chords (str):
1375                 simend = '>'
1376                 simstart = '<'
1377                 chordstart = '<<'
1378                 chordend = '>>'
1379                 marker_str = '%% new-chords-done %%'
1380
1381                 if re.search (marker_str,str):
1382                         return str
1383                 str = re.sub ('<<', '@STARTCHORD@', str)
1384                 str = re.sub ('>>', '@ENDCHORD@', str)
1385                 
1386                 str = re.sub (r'\\<', '@STARTCRESC@', str)
1387                 str = re.sub (r'\\>', '@STARTDECRESC@', str)
1388                 str = re.sub (r'([_^-])>', r'\1@ACCENT@', str)
1389                 str = re.sub (r'<([^<>{}]+)>', sub_chord, str)
1390
1391                 # add dash: -[, so that [<<a b>> c d] becomes
1392                 #                      <<a b>>-[ c d]
1393                 # and gets skipped by articulation_substitute
1394                 str = re.sub (r'\[ *(@STARTCHORD@[^@]+@ENDCHORD@[0-9.]*)',
1395                               r'\1-[', str)
1396                 str = re.sub (r'\\! *(@STARTCHORD@[^@]+@ENDCHORD@[0-9.]*)',
1397                               r'\1-\\!', str)
1398                 
1399                 str = re.sub (r'<([^?])', r'%s\1' % simstart, str)
1400                 str = re.sub (r'>([^?])', r'%s\1' % simend,  str)
1401                 str = re.sub ('@STARTCRESC@', r'\\<', str)
1402                 str = re.sub ('@STARTDECRESC@', r'\\>' ,str)
1403                 str = re.sub (r'\\context *Voice *@STARTCHORD@',
1404                               '@STARTCHORD@', str)
1405                 str = re.sub ('@STARTCHORD@', chordstart, str)
1406                 str = re.sub ('@ENDCHORD@', chordend, str)
1407                 str = re.sub (r'@ACCENT@', '>', str)
1408                 return str
1409
1410         def text_markup (str):
1411                 str = re.sub (r"""([-_^]) *# *' *\( *music *(\"[^"]*\") *\)""",
1412                                 r"\1\\markup { \\musicglyph #\2 }", str)
1413                 str = re.sub (r"""([-_^]) *# *' *\( *([a-z]+) *([^()]*)\)""",
1414                                 r"\1\\markup { \\\2 \3 }", str)
1415                 str = re.sub (r"""\\mark *# *' *\( *music *(\"[^"]*\") *\)""",
1416                                 r"\\mark \\markup { \\musicglyph #\1 }", str)
1417                 str = re.sub (r"""\\mark *# *' *\( *([a-z]+) *([^()]*)\)""",
1418                                 r"\\mark \\markup { \\\1 \2 }", str)
1419                 return str      
1420
1421         def articulation_substitute (str):
1422                 str = re.sub (r"""([^-])\[ *([a-z]+[,']*[!?]?[0-9:]*\.*)""",
1423                               r"\1 \2[", str)
1424                 str = re.sub (r"""([^-])\\\) *([a-z]+[,']*[!?]?[0-9:]*\.*)""",
1425                               r"\1 \2\\)", str)
1426                 str = re.sub (r"""([^-\\])\) *([a-z]+[,']*[!?]?[0-9:]*\.*)""",
1427                               r"\1 \2)", str)
1428                 str = re.sub (r"""([^-])\\! *([a-z]+[,']*[!?]?[0-9:]*\.*)""",
1429                               r"\1 \2\\!", str)
1430                 return str
1431         
1432         def conv_relative(str):
1433                 if re.search (r"\\relative", str):
1434                         str= "#(ly:set-option 'old-relative)\n" + str
1435
1436                 return str
1437         
1438         def conv (str):
1439                 str = re.sub (r"#'\(\)", "@SCM_EOL@", str)
1440                 str =  conv_relative (str)
1441                 str = sub_chords (str)
1442
1443                 str = text_markup (str)
1444                 str = articulation_substitute (str)
1445                 str = re.sub ("@SCM_EOL@", "#'()", str)
1446                 
1447                 return str
1448         
1449         conversions.append (((1,9,0), conv, """New relative mode,
1450 Postfix articulations, new text markup syntax, new chord syntax."""))
1451
1452 if 1:
1453         def conv (str):
1454                 if re.search ("font-style",str):
1455                         sys.stderr.write ("font-style is deprecated. Please remove.")
1456                         raise FatalConversionError()
1457                         
1458                 str = re.sub (r'-\\markup', r'@\\markup', str)
1459                 str = re.sub (r'-\\', r'\\', str)
1460                 str = re.sub (r'-\)', ')', str)
1461                 str = re.sub (r'-\(', '(', str)
1462                 str = re.sub ('-\[', '[', str)
1463                 str = re.sub ('-\]', ']', str)
1464                 str = re.sub ('-~', '~', str)
1465                 str = re.sub (r'@\\markup', r'-\\markup', str)
1466                 return str
1467
1468         conversions.append (((1,9,1), conv, """Remove - before articulation"""))
1469 if 1:
1470         def conv (str):
1471                 str = re.sub ('ly:set-context-property',
1472                               'ly:set-context-property!', str)
1473                 str = re.sub ('\\\\newcontext', '\\\\new', str)
1474                 str = re.sub ('\\\\grace[\t\n ]*([^{ ]+)',
1475                               r'\\grace { \1 }', str)
1476                 str = re.sub ("\\\\grace[\t\n ]*{([^}]+)}",
1477                               r"""\\grace {
1478   \\property Voice.Stem \\override #'stroke-style = #"grace"
1479   \1
1480   \\property Voice.Stem \\revert #'stroke-style }
1481 """, str)
1482                 
1483                 return str
1484         
1485         conversions.append (((1,9,2), conv, """\\newcontext -> \\new"""))
1486
1487 if 1:
1488         def conv (str):
1489                 str = re.sub ('accacciatura',
1490                               'acciaccatura', str)
1491
1492                 if re.search ("context-spec-music", str):
1493                         sys.stderr.write ("context-spec-music takes a symbol for the context now. Update by hand.")
1494                                         
1495                         raise FatalConversionError()
1496                 
1497                 str = re.sub ('fingerHorizontalDirection *= *#(LEFT|-1)',
1498                               "fingeringOrientations = #'(up down left)", str)
1499                 str = re.sub ('fingerHorizontalDirection *= *#(RIGHT|1)',
1500                               "fingeringOrientations = #'(up down right)", str)
1501
1502                 return str
1503         
1504         conversions.append (((1,9,3), conv,
1505                              """\\acciaccatura misspelling, fingerHorizontalDirection -> fingeringOrientations"""))
1506
1507
1508 def conv (str):
1509         if re.search ('\\figures', str):
1510                 sys.stderr.write ("Warning: attempting automatic \\figures conversion.  Check results!");
1511                 
1512         
1513         def figures_replace (m):
1514                 s = m.group (1)
1515                 s = re.sub ('<', '@FIGOPEN@',s)
1516                 s = re.sub ('>', '@FIGCLOSE@',s)
1517                 return '\\figures { %s }' % s
1518         
1519         str = re.sub (r'\\figures[ \t\n]*{([^}]+)}', figures_replace, str)
1520         str = re.sub (r'\\<', '@STARTCRESC@', str)
1521         str = re.sub (r'\\>', '@STARTDECRESC@', str)
1522         str = re.sub (r'([-^_])>', r'\1@ACCENT@', str)
1523         str = re.sub (r'<<', '@STARTCHORD@', str)
1524         str = re.sub (r'>>', '@ENDCHORD@', str)
1525         str = re.sub (r'>', '@ENDSIMUL@', str)
1526         str = re.sub (r'<', '@STARTSIMUL@', str)
1527         str = re.sub ('@STARTDECRESC@', '\\>', str)
1528         str = re.sub ('@STARTCRESC@', '\\<', str)
1529         str = re.sub ('@ACCENT@', '>', str)
1530         str = re.sub ('@ENDCHORD@', '>', str)
1531         str = re.sub ('@STARTCHORD@', '<', str)
1532         str = re.sub ('@STARTSIMUL@', '<<', str)
1533         str = re.sub ('@ENDSIMUL@', '>>', str)
1534         str = re.sub ('@FIGOPEN@', '<', str)
1535         str = re.sub ('@FIGCLOSE@', '>', str)
1536
1537         return str
1538
1539 conversions.append (((1,9,4), conv, 'Swap < > and << >>'))
1540
1541
1542 def conv (str):
1543         str = re.sub ('HaraKiriVerticalGroup', 'RemoveEmptyVerticalGroup', str)
1544
1545         return str
1546
1547 conversions.append (((1,9,5), conv, 'HaraKiriVerticalGroup -> RemoveEmptyVerticalGroup'))
1548
1549 def conv (str):
1550         if re.search ("ly:get-font", str) :
1551                 sys.stderr.write (r"(ly:get-font foo ..)  has been replaced by" + \
1552                                   " (ly:paper-get-font (ly:grob-get-paper foo) .. ).\n" +\
1553                                   "please update manually.")
1554                 
1555                 raise FatalConversionError()
1556         
1557         if re.search ("\\pitch *#", str) :
1558                 sys.stderr.write (r"\\pitch has been deprecated. " +\
1559                                   " Use Scheme code to construct arbitrary note events.")
1560                 
1561                 raise FatalConversionError()
1562         
1563         return str
1564                 
1565
1566 conversions.append (((1,9,6), conv, 'ly:get-font deprecated.'))
1567
1568 def conv (str):
1569         def sub_alteration (m):
1570                 alt = m.group (3)
1571                 alt = {
1572                         '-1': 'FLAT',
1573                         '-2': 'DOUBLE-FLAT',
1574                         '0': 'NATURAL',
1575                         '1': 'SHARP',
1576                         '2': 'DOUBLE-SHARP',
1577                         }[alt]
1578                 
1579                 return '(ly:make-pitch %s %s %s)' % (m.group(1), m.group (2),
1580                                                      alt)
1581         
1582         str =re.sub ("\\(ly:make-pitch *([0-9-]+) *([0-9-]+) *([0-9-]+) *\\)",
1583                      sub_alteration, str)
1584
1585
1586         str = re.sub ("ly:verbose", "ly:get-option 'verbose", str)
1587
1588         m= re.search ("\\\\outputproperty #([^#]+)[\t\n ]*#'([^ ]+)", str)
1589         if m:
1590                 sys.stderr.write (\
1591                         r"""\outputproperty found,
1592 Please hand-edit, using
1593
1594   \applyoutput #(outputproperty-compatibility %s '%s <GROB PROPERTY VALUE>)
1595
1596 as a substitution text.""" % (m.group (1), m.group (2)) )
1597                 raise FatalConversionError ()
1598
1599         if re.search ("ly:(make-pitch|pitch-alteration)", str) \
1600                or re.search ("keySignature", str):
1601                 sys.stderr.write (
1602 """The alteration field of Scheme pitches was multiplied by 2
1603 to support quarter tone accidentals. You have to edit the following constructs by hand:
1604
1605 * calls of  ly:make-pitch and ly:pitch-alteration
1606 * keySignature settings made with \property
1607 """)
1608                 raise FatalConversionError ()
1609         
1610         return str
1611 conversions.append (((1,9,7), conv,
1612                      '''use symbolic constants for alterations,
1613 remove \\outputproperty, move ly:verbose into ly:get-option'''))
1614
1615
1616 def conv (str):
1617         if re.search ("dash-length",str):
1618                 sys.stderr.write ("""dash-length has been removed. Use dash-fraction instead.""")
1619                 raise FatalConversionError()
1620         return str
1621
1622 conversions.append (((1,9,8), conv, """dash-length -> dash-fraction"""))
1623
1624
1625 def conv (str):
1626         def func(match):
1627                 return "#'font-size = #%d" % (2*string.atoi (match.group (1))) 
1628                 
1629         str =re.sub (r"#'font-relative-size\s*=\s*#\+?([0-9-]+)", func, str)
1630         str =re.sub (r"#'font-family\s*=\s*#'ancient",
1631                      r"#'font-family = #'music", str)
1632         
1633         return str
1634
1635 conversions.append (((2,1,1), conv, """font-relative-size -> font-size"""))
1636
1637 def conv (str):
1638         str =re.sub (r"ly:get-music-length", "ly:music-length", str)
1639         return str
1640
1641 conversions.append (((2,1,2), conv, """ly:get-music-length -> ly:music-length"""))
1642
1643 def conv (str):
1644         str =re.sub (r"\.\s+stz=", ". instr ", str)
1645         return str
1646
1647 conversions.append (((2,1,3), conv, """stanza -> instrument"""))
1648
1649 def conv (str):
1650         def func (match):
1651                 c = match.group (1)
1652                 b = match.group (2)
1653                 
1654                 if b == 't':
1655                         if c == 'Score':
1656                                 return ''
1657                         else:
1658                                 return r" \property %s.melismaBusyProperties \unset"  % c
1659                 elif b == 'f':
1660                         return r"\property %s.melismaBusyProperties = #'(melismaBusy)"  % c
1661                 
1662         str =re.sub (r"\\property ([a-zA-Z]+)\s*\.\s*automaticMelismata\s*=\s*##([ft])", func, str)
1663         return str
1664
1665 conversions.append (((2,1,4), conv, """removal of automaticMelismata; use melismaBusyProperties instead."""))
1666
1667
1668
1669 def conv (str):
1670         str =re.sub (r"\\translator\s+([a-zA-Z]+)", r"\\change \1", str)
1671         return str
1672
1673 conversions.append (((2,1,7), conv, """\\translator Staff -> \\change Staff"""))
1674
1675 def conv (str):
1676         str =re.sub (r"\\newaddlyrics", r"\\lyricsto", str)
1677         return str
1678
1679 conversions.append (((2,1,10), conv, """\\newaddlyrics -> \\lyricsto"""))
1680
1681 def conv (str):
1682         str = re.sub (r'\\include\s*"paper([0-9]+)(-init)?.ly"',
1683                       r"#(set-staff-size \1)", str)
1684
1685         def sub_note (match):
1686                 dur = ''
1687                 log = string.atoi (match.group (1))
1688                 dots = string.atoi (match.group (2))
1689                 
1690                 if log >= 0:
1691                         dur = '%d' % (1 << log)
1692                 else:
1693                         dur = { -1 : 'breve',
1694                                 -2 : 'longa',
1695                                 -3 : 'maxima'}[log]
1696
1697                 dur += ('.' * dots)
1698                 
1699                 return r'\note #"%s" #%s' % (dur, match.group (3))
1700         
1701         str = re.sub (r'\\note\s+#([0-9-]+)\s+#([0-9]+)\s+#([0-9.-]+)',
1702                       sub_note, str)
1703         return str
1704
1705 conversions.append (((2,1,11), conv, """\\include "paper16.ly" -> #(set-staff-size 16)
1706 \\note #3 #1 #1 -> \\note #"8." #1
1707 """))
1708
1709
1710 def conv (str):
1711         str =re.sub (r"OttavaSpanner", r"OttavaBracket", str)
1712         return str
1713
1714 conversions.append (((2,1,12), conv, """OttavaSpanner -> OttavaBracket"""))
1715
1716
1717 def conv (str):
1718         str =re.sub (r"\(set-staff-size ", r"(set-global-staff-size ", str)
1719         return str
1720
1721 conversions.append (((2,1,13), conv, """set-staff-size -> set-global-staff-size"""))
1722
1723 def conv (str):
1724         str =re.sub (r"#'style\s*=\s*#'dotted-line",
1725                      r"#'dash-fraction = #0.0 ", str)
1726         return str
1727
1728 conversions.append (((2,1,14), conv, """style = dotted -> dash-fraction = 0"""))
1729
1730 def conv (str):
1731         str =re.sub (r'LyricsVoice\s*\.\s*instrument\s*=\s*("[^"]*")',
1732                      r'LyricsVoice . vocalName = \1', str)
1733         
1734         str =re.sub (r'LyricsVoice\s*\.\s*instr\s*=\s*("[^"]*")',
1735                      r'LyricsVoice . vocNam = \1', str)
1736         return str
1737
1738 conversions.append (((2,1,15), conv, """LyricsVoice . instr(ument) -> vocalName"""))
1739
1740 def conv (str):
1741         def sub_acc (m):
1742                 d = {
1743                 '4': 'doublesharp',
1744                 '3': 'threeqsharp',
1745                 '2': 'sharp',
1746                 '1': 'semisharp',
1747                 '0': 'natural',
1748                 '-1': 'semiflat',
1749                 '-2': 'flat',
1750                 '-3': 'threeqflat',
1751                 '-4': 'doubleflat'}
1752                 return '\\%s' %  d[m.group (1)]
1753                      
1754         str = re.sub (r'\\musicglyph\s*#"accidentals-([0-9-]+)"',
1755                       sub_acc, str)
1756         return str
1757
1758 conversions.append (((2,1,16), conv, """\\musicglyph #"accidentals-NUM" -> \\sharp/flat/etc."""))
1759
1760
1761 def conv (str):
1762
1763         if re.search (r'\\partcombine', str):
1764                 sys.stderr.write ('Warning: \\partcombine has been changed. '
1765                                   +'Check conversion manually!')
1766
1767                 raise FatalConversionError()
1768
1769         # this rule doesn't really work,
1770         # too lazy to figure out why.
1771         str = re.sub (r'\\context\s+Voice\s*=\s*one\s*\\partcombine\s+Voice\s*\\context\s+Thread\s*=\s*one(.*)\s*'
1772                       + r'\\context\s+Thread\s*=\s*two',
1773                       '\\\\newpartcombine\n\\1\n', str)
1774         
1775         
1776         return str
1777
1778 conversions.append (((2,1,17), conv, """\\partcombine syntax change to \\newpartcombine"""))
1779
1780
1781 def conv (str):
1782         str = re.sub (r'\\newpartcombine', r'\\partcombine', str)
1783         str = re.sub (r'\\autochange\s+Staff', r'\\autochange ', str)
1784         return str
1785
1786 conversions.append (((2,1,18), conv, """\\newpartcombine -> \\partcombine,
1787 \\autochange Staff -> \\autochange
1788 """))
1789
1790
1791
1792
1793 def conv (str):
1794         str = re.sub (r'\\include "drumpitch-init.ly"','', str)
1795         str = re.sub (r'\\pitchnames ','pitchnames = ', str)
1796         str = re.sub (r'\\chordmodifiers ','chordmodifiers = ', str)
1797         str = re.sub (r'\bdrums\b\s*=','drumContents = ', str)
1798         str = re.sub (r'\\drums\b','\\drumContents ', str)
1799         
1800
1801         if re.search ('drums->paper', str):
1802                 sys.stderr.write ("\nDrum notation found. Check file manually!")
1803                 
1804         str = re.sub (r"""\\apply\s+#\(drums->paper\s+'([a-z]+)\)""",
1805                       r"""\property DrumStaff.drumStyleTable = #\1-style""",
1806                       str)
1807
1808         if re.search ('Thread', str):
1809                 sys.stderr.write ("\nThread found. Check file manually!\n");
1810
1811         str = re.sub (r"""(\\once\s*)?\\property\s+Thread\s*\.\s*NoteHead\s*"""
1812                       + r"""\\(set|override)\s*#'style\s*=\s*#'harmonic"""
1813                       + r"""\s+([a-z]+[,'=]*)([0-9]*\.*)"""                   
1814                       ,r"""<\3\\harmonic>\4""", str)
1815
1816         str = re.sub (r"""\\new Thread""", """\context Voice""", str)
1817         str = re.sub (r"""Thread""", """Voice""", str)
1818
1819         if re.search ('\bLyrics\b', str):
1820                 sys.stderr.write ("\nLyrics found. Check file manually!\n");
1821
1822         str = re.sub (r"""LyricsVoice""", r"""L@ricsVoice""", str)
1823         str = re.sub (r"""\bLyrics\b""", r"""LyricsVoice""", str)
1824         str = re.sub (r"""LyricsContext""", r"""LyricsVoiceContext""", str)
1825         str = re.sub (r"""L@ricsVoice""", r"""LyricsVoice""",str)
1826         
1827         
1828         return str
1829
1830 conversions.append (((2,1,19), conv, """Drum notation changes, Removing \\chordmodifiers, \\notenames.
1831 Harmonic notes. Thread context removed. Lyrics context removed."""))
1832
1833 def conv (str):
1834         str = re.sub (r'nonevent-skip', 'skip-music', str)
1835         return str
1836
1837 conversions.append (((2,1,20), conv, """nonevent-skip -> skip-music""" ))
1838
1839 def conv (str):
1840         str = re.sub (r'molecule-callback', 'print-function', str)
1841         str = re.sub (r'brew_molecule', 'print', str)
1842         str = re.sub (r'brew-new-markup-molecule', 'Text_item::print', str)
1843         str = re.sub (r'LyricsVoice', 'Lyrics', str)
1844         str = re.sub (r'tupletInvisible',
1845                       r"TupletBracket \\set #'transparent", str)
1846 #       str = re.sub (r'molecule', 'collage', str)
1847 #molecule -> collage
1848         str = re.sub (r"\\property\s+[a-zA-Z]+\s*\.\s*[a-zA-Z]+\s*"
1849                       + r"\\set\s*#'X-extent-callback\s*=\s*#Grob::preset_extent",
1850                       "", str)
1851
1852         return str
1853
1854 conversions.append (((2,1,21), conv, """molecule-callback -> print-function,
1855 brew_molecule -> print
1856 brew-new-markup-molecule -> Text_item::print
1857 LyricsVoice -> Lyrics
1858 tupletInvisible -> TupletBracket \set #'transparent
1859 Grob::preset_extent removed.
1860 """ ))
1861
1862
1863 def conv (str):
1864         str = re.sub (r'\\property\s+([^. ]+)\s*\.\s*([^\\=]+)\s*\\(set|override)',
1865                       r"\\overrid@ \1.\2 ", str)
1866         str = re.sub (r'\\property\s+([^. ]+)\s*\.\s*([^\\= ]+)\s*=\s*',
1867                       r'\\s@t \1.\2 = ', str)
1868         str = re.sub (r'\\property\s+([^. ]+)\s*\.\s*([^\\= ]+)\s*\\unset',
1869                       r'\\uns@t \1.\2 ', str)
1870         str = re.sub (r'\\property\s+([^. ]+)\s*\.\s*([^\\= ]+)\s*\\revert'
1871                       + r"\s*#'([-a-z0-9_]+)",
1872                       r"\\rev@rt \1.\2 #'\3", str)
1873         str = re.sub (r'Voice\.', '', str)
1874         str = re.sub (r'Lyrics\.', '', str)
1875         str = re.sub (r'ChordNames\.', '', str)
1876         
1877         str = re.sub ('rev@rt', 'revert',str)
1878         str = re.sub ('s@t', 'set',str)
1879         str = re.sub ('overrid@', 'override',str)
1880
1881         str = re.sub ('molecule', 'stencil', str)
1882         str = re.sub ('Molecule', 'Stencil', str)
1883         return str
1884
1885 conversions.append (((2,1,22), conv, """new syntax for property settings:
1886         \\set A.B = #C , \\unset A.B
1887         \\override A.B #C = #D, \\revert A.B #C
1888
1889 """))
1890
1891 def conv (str):
1892         def subst_in_trans (match):
1893                 s = match.group (0)
1894                 s = re.sub (r'\s([a-zA-Z]+)\s*\\override',
1895                               r' \\override \1', s)
1896                 s = re.sub (r'\s([a-zA-Z]+)\s*\\set',
1897                               r' \\override \1', s)
1898                 s = re.sub (r'\s([a-zA-Z]+)\s*\\revert',
1899                               r' \\revert \1', s)
1900                 return s
1901         str = re.sub (r'\\(translator|with)\s*{[^}]+}',  subst_in_trans, str)
1902
1903         def sub_abs (m):
1904                 
1905                 context = m.group ('context')
1906                 d = m.groupdict ()
1907                 if context:
1908                         context = " '%s" % context[:-1] # -1: remove . 
1909                 else:
1910                         context = ''
1911
1912                 d['context'] = context
1913                 
1914                 return r"""#(override-auto-beam-setting %(prop)s %(num)s %(den)s%(context)s)""" % d
1915
1916         str = re.sub (r"""\\override\s*(?P<context>[a-zA-Z]+\s*\.\s*)?autoBeamSettings"""
1917                       +r"""\s*#(?P<prop>[^=]+)\s*=\s*#\(ly:make-moment\s+(?P<num>\d+)\s+(?P<den>\d)\s*\)""",
1918                       sub_abs, str)
1919         
1920         return str
1921         
1922 conversions.append (((2,1,23), conv, """Property setting syntax in \\translator{ }"""))
1923 def conv (str):
1924         str = re.sub (r'music-list\?', 'ly:music-list?', str)
1925         str = re.sub (r'\|\s*~', '~ |', str)   
1926         return str
1927
1928 conversions.append (((2,1,24), conv, """music-list? -> ly:music-list?"""))
1929
1930 def conv (str):
1931         str = re.sub (r'ly:get-spanner-bound', 'ly:spanner-get-bound', str)
1932         str = re.sub (r'ly:get-extent', 'ly:grob-extent', str)
1933         str = re.sub (r'ly:get-system', 'ly:grob-system', str)
1934         str = re.sub (r'ly:get-original', 'ly:grob-original', str)
1935         str = re.sub (r'ly:get-parent', 'ly:grob-parent', str)
1936         str = re.sub (r'ly:get-broken-into', 'ly:spanner-broken-into', str)
1937         str = re.sub (r'Melisma_engraver', 'Melisma_translator', str)
1938         if re.search ("ly:get-paper-variable", str):
1939                 sys.stderr.write ('use (ly:paper-lookup (ly:grob-paper ))')
1940                 raise FatalConversionError()
1941
1942         str = re.sub (r'\\defaultAccidentals', "#(set-accidental-style 'default)", str)
1943         str = re.sub (r'\\voiceAccidentals', "#(set-accidental-style 'voice)", str)
1944         str = re.sub (r'\\modernAccidentals', "#(set-accidental-style 'modern)", str)
1945         str = re.sub (r'\\modernCautionaries', "#(set-accidental-style 'modern-cautionary)", str)
1946         str = re.sub (r'\\modernVoiceAccidental', "#(set-accidental-style 'modern-voice)", str)
1947         str = re.sub (r'\\modernVoiceCautionaries', "#(set-accidental-style 'modern-voice-cautionary)", str)
1948         str = re.sub (r'\\pianoAccidentals', "#(set-accidental-style 'piano)", str)
1949         str = re.sub (r'\\pianoCautionaries', "#(set-accidental-style 'piano-cautionary)", str)
1950         str = re.sub (r'\\forgetAccidentals', "#(set-accidental-style 'forget)", str)
1951         str = re.sub (r'\\noResetKey', "#(set-accidental-style 'no-reset)", str)
1952         
1953         return str
1954
1955 conversions.append (((2,1,25), conv, """Scheme grob function renaming"""))
1956
1957
1958 def conv (str):
1959         str = re.sub ('ly:set-grob-property!', 'ly:grob-set-property!',str)
1960         str = re.sub ('ly:set-mus-property!', 'ly:music-set-property!',str)     
1961         str = re.sub ('ly:set-context-property!', 'ly:context-set-property!', str)      
1962         str = re.sub ('ly:get-grob-property', 'ly:grob-property',str)
1963         str = re.sub ('ly:get-mus-property', 'ly:music-property',str)
1964         str = re.sub ('ly:get-context-property', 'ly:context-property',str)
1965         
1966         return str
1967
1968 conversions.append (((2,1,26), conv, """More Scheme function renaming"""))
1969
1970 def conv (str):
1971         def subst (m):
1972                 g = string.atoi (m.group (2))
1973                 o = g / 12
1974                 g -= o * 12
1975                 if g <  0:
1976                         g += 12
1977                         o -= 1
1978
1979
1980                 lower_pitches = filter (lambda x : x <= g, [0, 2, 4, 5, 7, 9, 11, 12])
1981                 s = len (lower_pitches) -1 
1982                 a = g - lower_pitches [-1]
1983
1984
1985                 print s , lower_pitches, g, a, s 
1986                 str = 'cdefgab' [s]
1987                 str += ['eses', 'es', '', 'is', 'isis'][a + 2]
1988                 if o < 0:
1989                         str += ',' * (-o - 1)
1990                 elif o >= 0:
1991                         str += "'" * (o + 1)
1992                         
1993                 return '\\transposition %s ' % str
1994
1995         
1996         str = re.sub (r"\\set ([A-Za-z]+\s*\.\s*)?transposing\s*=\s*#([-0-9]+)",
1997                       subst, str)
1998         return str
1999
2000 conversions.append (((2,1,27), conv, """property transposing -> tuning"""))
2001
2002 def conv (str):
2003         str = re.sub (r'make-music-by-name', 'make-music', str)
2004         str = re.sub (r"\\override\s+.*Arpeggio\s+#.print-function\s+=\s+\\arpeggioBracket", r"\\arpeggioBracket", str)
2005         return str
2006
2007 conversions.append (((2,1,28), conv,
2008                      """make-music-by-name -> make-music,
2009 new syntax for setting \\arpeggioBracket"""))
2010
2011 def conv (str):
2012         str = re.sub (r'\\center([^-])', '\\center-align\\1', str)
2013         str = re.sub (r'\\translator', '\\context', str)
2014         return str
2015
2016 conversions.append (((2,1,29), conv,
2017                      '\\center -> \\center-align, \\translator -> \\context'))
2018
2019
2020 def conv (str):
2021         str = re.sub (r'\\threeq(flat|sharp)', r'\\sesqui\1', str)
2022         str = re.sub (r'ly:stencil-get-extent',
2023                       'ly:stencil-extent', str)
2024         str = re.sub (r'ly:translator-find',
2025                       'ly:context-find', str)
2026         str = re.sub ('ly:unset-context-property','ly:context-unset-property',
2027                       str)
2028                      
2029         str = re.sub (r'ly:get-mutable-properties',
2030                       'ly:mutable-music-properties',str)
2031         str = re.sub (r'centralCPosition',
2032                       'middleCPosition',str)
2033         return str
2034
2035 conversions.append (((2,1,30), conv,
2036                      '''\\threeq{flat,sharp} -> \\sesqui{flat,sharp}
2037 ly:get-mutable-properties -> ly:mutable-music-properties
2038 centralCPosition -> middleCPosition
2039 ly:unset-context-property -> ly:context-unset-property
2040 ly:translator-find -> ly:context-find
2041 ly:get-stencil-extent -> ly:stencil-extent
2042 '''))
2043
2044
2045 def conv (str):
2046         str = re.sub (r'\\alias\s*"?Timing"?', '', str)
2047         return str
2048
2049 conversions.append (((2,1,31), conv,
2050                      '''remove \\alias Timing'''))
2051
2052 def conv (str):
2053         str = re.sub (r"(\\set\s+)?(?P<context>(Score\.)?)breakAlignOrder\s*=\s*#'(?P<list>[^\)]+)",
2054                       r"\n\\override \g<context>BreakAlignment #'break-align-orders = "
2055                       + "#(make-vector 3 '\g<list>)", str)
2056                       
2057         return str
2058
2059 conversions.append (((2,1,33), conv,
2060                      '''breakAlignOrder -> break-align-orders.'''))
2061
2062 def conv (str):
2063         str = re.sub (r"\(set-paper-size",
2064                       "(set-default-paper-size",str)
2065         return str
2066
2067 conversions.append (((2,1,34), conv,
2068                      '''set-paper-size -> set-default-paper-size.'''))
2069
2070 def conv (str):
2071         str = re.sub (r"ly:mutable-music-properties",
2072                       "ly:music-mutable-properties", str)
2073         return str
2074
2075 conversions.append (((2,1, 36), conv,
2076                      '''ly:mutable-music-properties -> ly:music-mutable-properties'''))
2077
2078
2079
2080 def conv (str):
2081         return str
2082
2083 conversions.append (((2,2, 0), conv,
2084                      '''clean up version. '''))
2085
2086 def conv (str):
2087         return re.sub (r'\\apply\b', r'\\applymusic', str)
2088
2089 conversions.append (((2, 3, 1), conv,
2090                      '''\\apply -> \\applymusic'''))
2091
2092 def conv (str):
2093         str = re.sub (r'\\OrchestralScoreContext', '\\Score', str)
2094         def func(m):
2095                 if m.group(1) not in ['RemoveEmptyStaff',
2096                                       'AncientRemoveEmptyStaffContext',
2097                                       'EasyNotation']:
2098                         return '\\' + m.group (1)
2099                 else:
2100                         return m.group (0)
2101                 
2102                 
2103         str = re.sub (r'\\([a-zA-Z]+)Context\b', func, str)
2104
2105         str = re.sub ('ly:paper-lookup', 'ly:output-def-lookup', str)
2106         return str
2107
2108 conversions.append (((2, 3, 2), conv,
2109                      '''\\FooContext -> \\Foo'''))
2110
2111 def conv (str):
2112         str = re.sub (r'\\notes\b', '', str)
2113         
2114         return str
2115
2116 conversions.append (((2, 3, 4), conv,
2117                      '''remove \\notes'''))
2118
2119
2120
2121 def conv (str):
2122         str = re.sub (r'\\consistsend', '\\consists', str)
2123         str = re.sub (r'\\lyricsto\s+("?[a-zA-Z]+"?)(\s*\\new Lyrics\s*)?\\lyrics',
2124                       r'\\lyricsto \1 \2', str)
2125         return str
2126
2127 conversions.append (((2, 3, 8), conv,
2128                      '''remove \\consistsend, strip \\lyrics from \\lyricsto.'''))
2129
2130 def conv (str):
2131         str = re.sub (r'neo_mensural', 'neomensural', str)
2132         str = re.sub (r'if-text-padding', 'bound-padding', str)
2133         return str
2134
2135 conversions.append (((2, 3, 9), conv,
2136                      '''neo_mensural -> neomensural, if-text-padding -> bound-padding'''))
2137
2138
2139
2140 def conv (str):
2141         str = re.sub (r'\\addlyrics', r'\\oldaddlyrics', str)
2142         str = re.sub (r'\\newlyrics', r'\\addlyrics', str)
2143         return str
2144
2145 conversions.append (((2, 3, 10), conv,
2146                      '''\\addlyrics -> \\oldaddlyrics, \\newlyrics -> \\addlyrics'''))
2147
2148 def conv (str):
2149         str = re.sub (r'\\setMmRestFermata\s+(R[0-9.*/]*)',
2150                       r'\1^\\fermataMarkup', str)
2151         return str
2152
2153 conversions.append (((2, 3, 11), conv,
2154                      '''\\setMmRestFermata -> ^\\fermataMarkup'''))
2155
2156 def conv (str):
2157         str = re.sub (r'\\newpage', r'\\pageBreak', str)
2158         str = re.sub (r'\\scriptUp', r"""{
2159   \\override TextScript  #'direction = #1
2160   \\override Script  #'direction = #1
2161 }""", str)
2162         str = re.sub (r'\\scriptDown', r"""{
2163   \\override TextScript  #'direction = #-1
2164   \\override Script  #'direction = #-1
2165 }""", str)
2166         str = re.sub (r'\\scriptBoth', r"""{
2167   \\revert TextScript  #'direction
2168   \\revert Script  #'direction
2169 }""", str)
2170         str = re.sub ('soloADue', 'printPartCombineTexts', str)
2171         str = re.sub (r'\\applymusic\s*#notes-to-clusters',
2172                       '\\makeClusters', str)
2173         return str
2174
2175 conversions.append (((2, 3, 12), conv,
2176                      '''\\newpage -> \\pageBreak, junk \\script{up,down,both},
2177 soloADue -> printPartCombineTexts, #notes-to-clusters -> \\makeClusters
2178 '''))
2179
2180
2181 def conv (str):
2182         str = re.sub (r'\\chords\b', r'\\chordmode', str)
2183         str = re.sub (r'\\lyrics\b', r'\\lyricmode', str)
2184         str = re.sub (r'\\figures\b', r'\\figuremode', str)
2185         str = re.sub (r'\\notes\b', r'\\notemode', str)
2186         str = re.sub (r'\\drums\b', r'\\drummode', str)
2187         str = re.sub (r'\\chordmode\s*\\new ChordNames', r'\\chords', str)
2188         str = re.sub (r'\\new ChordNames\s*\\chordmode', r'\\chords', str)
2189         str = re.sub (r'\\new FiguredBass\s*\\figuremode', r'\\figures', str)
2190         str = re.sub (r'\\figuremode\s*\new FiguredBass', r'\\figures', str)
2191         str = re.sub (r'\\new DrumStaff\s*\\drummode', r'\\drums', str)
2192         str = re.sub (r'\\drummode\s*\\new DrumStaff', r'\\drums', str)
2193
2194         return str
2195
2196 conversions.append (((2, 3, 16), conv,
2197                      '''\foo -> \foomode (for chords, notes, etc.)
2198 fold \new FooContext \foomode into \foo.'''))
2199
2200 def conv (str):
2201         str = re.sub (r'(slur|stem|phrasingSlur|tie|dynamic|dots|tuplet|arpeggio|)Both', r'\1Neutral', str)
2202         str = re.sub (r"\\applymusic\s*#\(remove-tag\s*'([a-z-0-9]+)\)",
2203                       r"\\removeWithTag #'\1", str)
2204         return str
2205
2206 conversions.append (((2, 3, 17), conv,
2207                      '''\foo -> \foomode (for chords, notes, etc.)
2208 fold \new FooContext \foomode into \foo.'''))
2209
2210
2211 def conv (str):
2212         str = re.sub (r'Text_item', 'Text_interface', str)
2213         return str
2214
2215 conversions.append (((2, 3, 18),
2216                      conv,
2217                      '''Text_item -> Text_interface''' ))
2218
2219 ################################
2220 #       END OF CONVERSIONS      
2221 ################################
2222
2223 def get_conversions (from_version, to_version):
2224         def version_b (v, f = from_version, t = to_version):
2225                 return version_cmp (v[0], f) > 0 and version_cmp (v[0], t) <= 0
2226         return filter (version_b, conversions)
2227
2228
2229 def latest_version ():
2230         return conversions[-1][0]
2231
2232 def do_conversion (infile, from_version, outfile, to_version):
2233         conv_list = get_conversions (from_version, to_version)
2234
2235         sys.stderr.write ('Applying conversions: ')
2236         str = infile.read ()
2237         last_conversion = ()
2238         try:
2239                 for x in conv_list:
2240                         sys.stderr.write (tup_to_str (x[0])  + ', ')
2241                         str = x[1] (str)
2242                         last_conversion = x[0]
2243
2244         except FatalConversionError:
2245                 sys.stderr.write ('Error while converting; I won\'t convert any further')
2246
2247         if last_conversion:
2248                 sys.stderr.write ('\n')
2249                 new_ver =  '\\version \"%s\"' % tup_to_str (last_conversion)
2250
2251                 if re.search (lilypond_version_re_str, str):
2252                         str = re.sub (lilypond_version_re_str,'\\'+new_ver , str)
2253                 elif add_version:
2254                         str = new_ver + '\n' + str
2255
2256                 outfile.write(str)
2257
2258         return last_conversion
2259         
2260 class UnknownVersion:
2261         pass
2262
2263 def do_one_file (infile_name):
2264         sys.stderr.write ('Processing `%s\' ... '% infile_name)
2265         outfile_name = ''
2266         if __main__.edit:
2267                 outfile_name = infile_name + '.NEW'
2268         elif __main__.outfile_name:
2269                 outfile_name = __main__.outfile_name
2270
2271         if __main__.from_version:
2272                 from_version = __main__.from_version
2273         else:
2274                 guess = guess_lilypond_version (infile_name)
2275                 if not guess:
2276                         raise UnknownVersion()
2277                 from_version = str_to_tuple (guess)
2278
2279         if __main__.to_version:
2280                 to_version = __main__.to_version
2281         else:
2282                 to_version = latest_version ()
2283
2284
2285         if infile_name:
2286                 infile = open (infile_name,'r')
2287         else:
2288                 infile = sys.stdin
2289
2290         if outfile_name:
2291                 outfile =  open (outfile_name, 'w')
2292         else:
2293                 outfile = sys.stdout
2294
2295         touched = do_conversion (infile, from_version, outfile, to_version)
2296
2297         if infile_name:
2298                 infile.close ()
2299
2300         if outfile_name:
2301                 outfile.close ()
2302
2303         if __main__.edit and touched:
2304                 try:
2305                         os.remove(infile_name + '~')
2306                 except:
2307                         pass
2308                 os.rename (infile_name, infile_name + '~')
2309                 os.rename (infile_name + '.NEW', infile_name)
2310
2311         sys.stderr.write ('\n')
2312         sys.stderr.flush ()
2313
2314 edit = 0
2315 assume_old = 0
2316 to_version = ()
2317 from_version = ()
2318 outfile_name = ''
2319
2320 (options, files) = getopt.getopt (
2321         sys.argv[1:], 'ao:f:t:senh', ['no-version', 'version', 'output', 'show-rules', 'help', 'edit', 'from=', 'to='])
2322
2323 for opt in options:
2324         o = opt[0]
2325         a = opt[1]
2326         if o== '--help' or o == '-h':
2327                 usage ()
2328                 sys.exit (0)
2329         if o == '--version' or o == '-v':
2330                 print_version ()
2331                 sys.exit (0)
2332         elif o== '--from' or o=='-f':
2333                 from_version = str_to_tuple (a)
2334         elif o== '--to' or o=='-t':
2335                 to_version = str_to_tuple (a)
2336         elif o== '--edit' or o == '-e':
2337                 edit = 1
2338         elif o== '--show-rules' or o == '-s':
2339                 show_rules (sys.stdout)
2340                 sys.exit(0)
2341         elif o == '--output' or o == '-o':
2342                 outfile_name = a
2343         elif o == '--no-version' or o == '-n':
2344                 add_version = 0
2345         else:
2346                 print o
2347                 raise getopt.error
2348
2349 identify ()
2350 for f in files:
2351         if f == '-':
2352                 f = ''
2353         elif not os.path.isfile (f):
2354                 continue
2355         try:
2356                 do_one_file (f)
2357         except UnknownVersion:
2358                 sys.stderr.write ('\n')
2359                 sys.stderr.write ("%s: can't determine version for `%s'" % (program_name, f))
2360                 sys.stderr.write ('\n')
2361                 if assume_old:
2362                         fv = from_version
2363                         from_version = (0,0,0)
2364                         do_one_file (f)
2365                         from_version = fv
2366                 else:
2367                         sys.stderr.write ("%s: skipping: `%s' " % (program_name,  f))
2368                 pass
2369
2370 sys.stderr.write ('\n')