]> git.donarmstrong.com Git - lilypond.git/blob - python/convertrules.py
Merge branch 'master' into lilypond/translation
[lilypond.git] / python / convertrules.py
1 # (setq py-indent-offset 4)
2
3
4 import string
5 import re
6 import sys
7 import lilylib
8
9 _ = lilylib._
10
11
12 NOT_SMART = _ ("Not smart enough to convert %s")
13 UPDATE_MANUALLY = _ ("Please refer to the manual for details, and update manually.")
14 FROM_TO = _ ( "%s has been replaced by %s")
15
16
17 class FatalConversionError:
18     pass
19
20 conversions = []
21 stderr_write = lilylib.stderr_write
22
23 def warning (str):
24     stderr_write (_ ("warning: %s") % str)
25
26 # Decorator to make rule syntax simpler
27 def rule (version, message):
28     """
29     version: a LilyPond version tuple like (2, 11, 50)
30     message: the message that describes the conversion.
31
32     This decorator adds its function together with the version and the
33     message to the global conversions list.  (It doesn't need to return
34     the function as it isn't used directly anyway.)
35
36     A conversion rule using this decorator looks like this:
37
38     @rule ((1, 2, 3), "convert foo to bar")
39     def conv(str):
40         str = str.replace('foo', 'bar')
41         return str
42
43     """
44     def dec(f):
45         conversions.append ((version, f, message))
46     return dec
47
48
49 @rule ((0, 1, 9), _ ('\\header { key = concat + with + operator }'))
50 def conv(str):
51     if re.search ('\\\\multi', str):
52         stderr_write ('\n')
53         stderr_write (NOT_SMART % "\\multi")
54         stderr_write ('\n')
55     return str
56
57
58 @rule ((0, 1, 19), _ ('deprecated %s') % '\\octave')
59 def conv (str):
60     if re.search ('\\\\octave', str):
61         stderr_write ('\n')
62         stderr_write (NOT_SMART % "\\octave")
63         stderr_write ('\n')
64         stderr_write (UPDATE_MANUALLY)
65         stderr_write ('\n')
66     #   raise FatalConversionError ()
67     return str
68
69
70 @rule ((0, 1, 20), _ ('deprecated \\textstyle, new \\key syntax'))
71 def conv (str):
72     str = re.sub ('\\\\textstyle([^;]+);',
73                              '\\\\property Lyrics . textstyle = \\1', str)
74     # harmful to current .lys
75     # str = re.sub ('\\\\key([^;]+);', '\\\\accidentals \\1;', str)
76     return str
77
78
79 @rule ((0, 1, 21), '\\musical_pitch -> \\musicalpitch, \\meter -> \\time')
80 def conv (str):
81     str = re.sub ('\\\\musical_pitch', '\\\\musicalpitch',str)
82     str = re.sub ('\\\\meter', '\\\\time',str)
83     return str
84
85
86 @rule ((1, 0, 0), _ ("bump version for release"))
87 def conv (str):
88     return str
89
90
91 @rule ((1, 0, 1), '\\accidentals -> \\keysignature, specialaccidentals -> keyoctaviation')
92 def conv (str):
93     str = re.sub ('\\\\accidentals', '\\\\keysignature',str)
94     str = re.sub ('specialaccidentals *= *1', 'keyoctaviation = 0',str)
95     str = re.sub ('specialaccidentals *= *0', 'keyoctaviation = 1',str)
96     return str
97
98
99 @rule ((1, 0, 2), _ ('\\header { key = concat + with + operator }'))
100 def conv(str):
101     if re.search ('\\\\header', str):
102         stderr_write ('\n')
103         stderr_write (NOT_SMART % _ ("new \\header format"))
104         stderr_write ('\n')
105     return str
106
107
108 @rule ((1, 0, 3), '\\melodic -> \\notes')
109 def conv(str):
110     str =  re.sub ('\\\\melodic([^a-zA-Z])', '\\\\notes\\1',str)
111     return str
112
113
114 @rule ((1, 0, 4), 'default_{paper,midi}')
115 def conv(str):
116     str =  re.sub ('default_paper *=', '',str)
117     str =  re.sub ('default_midi *=', '',str)
118     return str
119
120
121 @rule ((1, 0, 5), 'ChoireStaff -> ChoirStaff')
122 def conv(str):
123     str =  re.sub ('ChoireStaff', 'ChoirStaff',str)
124     str =  re.sub ('\\\\output', 'output = ',str)
125     return str
126
127
128 @rule ((1, 0, 6), 'foo = \\translator {\\type .. } ->\\translator {\\type ..; foo; }')
129 def conv(str):
130     if re.search ('[a-zA-Z]+ = *\\translator',str):
131         stderr_write ('\n')
132         stderr_write (NOT_SMART % _ ("\\translator syntax"))
133         stderr_write ('\n')
134     #   raise FatalConversionError ()
135     return str
136
137
138 @rule ((1, 0, 7), '\\lyric -> \\lyrics')
139 def conv(str):
140     str =  re.sub ('\\\\lyrics*', '\\\\lyrics',str)
141     return str
142
143
144 @rule ((1, 0, 10), '[2/3 ]1/1 -> \\times 2/3 ')
145 def conv(str):
146     str =  re.sub ('\\\\\\[/3+', '\\\\times 2/3 { ',str)
147     str =  re.sub ('\\[/3+', '\\\\times 2/3 { [',str)
148     str =  re.sub ('\\\\\\[([0-9/]+)', '\\\\times \\1 {',str)
149     str =  re.sub ('\\[([0-9/]+)', '\\\\times \\1 { [',str)
150     str =  re.sub ('\\\\\\]([0-9/]+)', '}', str)
151     str =  re.sub ('\\\\\\]', '}',str)
152     str =  re.sub ('\\]([0-9/]+)', '] }', str)
153     return str
154
155
156 @rule ((1, 0, 12), 'Chord syntax stuff')
157 def conv(str):
158     return str
159
160
161 @rule ((1, 0, 13), '<a ~ b> c -> <a b> ~ c')
162 def conv(str):
163     str =  re.sub ('<([^>~]+)~([^>]*)>','<\\1 \\2> ~', str)
164     return str
165
166
167 @rule ((1, 0, 14), '<[a b> <a b]>c -> [<a b> <a b>]')
168 def conv(str):
169     str =  re.sub ('<\\[','[<', str)
170     str =  re.sub ('\\]>','>]', str)
171     return str
172
173
174 @rule ((1, 0, 16), '\\type -> \\context, textstyle -> textStyle')
175 def conv(str):
176     str =  re.sub ('\\\\type([^\n]*engraver)','\\\\TYPE\\1', str)
177     str =  re.sub ('\\\\type([^\n]*performer)','\\\\TYPE\\1', str)
178     str =  re.sub ('\\\\type','\\\\context', str)
179     str =  re.sub ('\\\\TYPE','\\\\type', str)
180     str =  re.sub ('textstyle','textStyle', str)
181     return str
182
183
184 @rule ((1, 0, 18), _ ('\\repeat NUM Music Alternative -> \\repeat FOLDSTR Music Alternative'))
185 def conv(str):
186     if re.search ('\\\\repeat',str):
187         stderr_write ('\n')
188         stderr_write (NOT_SMART % "\\repeat")
189         stderr_write ('\n')
190     #   raise FatalConversionError ()
191     return str
192
193
194 @rule ((1, 0, 19), 'fontsize -> fontSize, midi_instrument -> midiInstrument, SkipBars -> skipBars')
195 def conv(str):
196     str =  re.sub ('SkipBars','skipBars', str)
197     str =  re.sub ('fontsize','fontSize', str)
198     str =  re.sub ('midi_instrument','midiInstrument', str)
199     return str
200
201
202 @rule ((1, 0, 20), '{,tie,slur}ydirection -> {v,tieV,slurV}erticalDirection')
203 def conv(str):
204     str =  re.sub ('tieydirection','tieVerticalDirection', str)
205     str =  re.sub ('slurydirection','slurVerticalDirection', str)
206     str =  re.sub ('ydirection','verticalDirection', str)
207     return str
208
209
210 @rule ((1, 0, 21), 'hshift -> horizontalNoteShift')
211 def conv(str):
212     str =  re.sub ('hshift','horizontalNoteShift', str)
213     return str
214
215
216 @rule ((1, 1, 52), _ ('deprecate %s') % '\\grouping')
217 def conv(str):
218     str =  re.sub ('\\\\grouping[^;]*;','', str)
219     return str
220
221
222 @rule ((1, 1, 55), '\\wheel -> \\coda')
223 def conv(str):
224     str =  re.sub ('\\\\wheel','\\\\coda', str)
225     return str
226
227
228 @rule ((1, 1, 65), 'slurdash -> slurDash, keyoctaviation -> keyOctaviation')
229 def conv(str):
230     str =  re.sub ('keyoctaviation','keyOctaviation', str)
231     str =  re.sub ('slurdash','slurDash', str)
232     return str
233
234
235 @rule ((1, 1, 66), 'semi -> volta')
236 def conv(str):
237     str =  re.sub ('\\\\repeat *\"?semi\"?','\\\\repeat "volta"', str)
238     return str
239
240
241 @rule ((1, 1, 67), 'beamAuto -> noAutoBeaming')
242 def conv(str):
243     str =  re.sub ('\"?beamAuto\"? *= *\"?0?\"?','noAutoBeaming = "1"', str)
244     return str
245
246
247 @rule ((1, 2, 0), 'automaticMelismas -> automaticMelismata')
248 def conv(str):
249     str =  re.sub ('automaticMelismas', 'automaticMelismata', str)
250     return str
251
252
253 @rule ((1, 2, 1), 'dynamicDir -> dynamicDirection')
254 def conv(str):
255     str =  re.sub ('dynamicDir\\b', 'dynamicDirection', str)
256     return str
257
258
259 @rule ((1, 3, 4), '\\cadenza -> \\cadenza{On|Off}')
260 def conv(str):
261     str =  re.sub ('\\\\cadenza *0 *;', '\\\\cadenzaOff', str)
262     str =  re.sub ('\\\\cadenza *1 *;', '\\\\cadenzaOn', str)
263     return str
264
265
266 @rule ((1, 3, 5), 'beamAuto moment properties')
267 def conv (str):
268     str = re.sub ('"?beamAuto([^"=]+)"? *= *"([0-9]+)/([0-9]+)" *;*',
269                   'beamAuto\\1 = #(make-moment \\2 \\3)',
270                   str)
271     return str
272
273
274 @rule ((1, 3, 17), 'stemStyle -> flagStyle')
275 def conv (str):
276     str = re.sub ('stemStyle',
277                   'flagStyle',
278                   str)
279     return str
280
281
282 @rule ((1, 3, 18), 'staffLineLeading -> staffSpace')
283 def conv (str):
284     str = re.sub ('staffLineLeading',
285                   'staffSpace',
286                   str)
287     return str
288
289
290 @rule ((1, 3, 23), _ ('deprecate %s ') % '\\repetitions')
291 def conv(str):
292     if re.search ('\\\\repetitions',str):
293         stderr_write ('\n')
294         stderr_write (NOT_SMART % "\\repetitions")
295         stderr_write ('\n')
296     #   raise FatalConversionError ()
297     return str
298
299
300 @rule ((1, 3, 35), 'textEmptyDimension -> textNonEmpty')
301 def conv (str):
302     str = re.sub ('textEmptyDimension *= *##t',
303                   'textNonEmpty = ##f',
304                   str)
305     str = re.sub ('textEmptyDimension *= *##f',
306                   'textNonEmpty = ##t',
307                   str)
308     return str
309
310
311 @rule ((1, 3, 38), '\musicalpitch { a b c } -> #\'(a b c)')
312 def conv (str):
313     str = re.sub ("([a-z]+)[ \t]*=[ \t]*\\\\musicalpitch *{([- 0-9]+)} *\n",
314                   "(\\1 . (\\2))\n", str)
315     str = re.sub ("\\\\musicalpitch *{([0-9 -]+)}",
316                   "\\\\musicalpitch #'(\\1)", str)
317     if re.search ('\\\\notenames',str):
318         stderr_write ('\n')
319         stderr_write (NOT_SMART % _ ("new \\notenames format"))
320         stderr_write ('\n')
321     return str
322
323
324 @rule ((1, 3, 39), '\\key A ;  ->\\key a;')
325 def conv (str):
326     def replace (match):
327         return '\\key %s;' % match.group (1).lower ()
328
329     str = re.sub ("\\\\key ([^;]+);",  replace, str)
330     return str
331
332
333 @rule ((1, 3, 41), '[:16 c4 d4 ] -> \\repeat "tremolo" 2 { c16 d16 }')
334 def conv (str):
335     if re.search ('\\[:',str):
336         stderr_write ('\n')
337         stderr_write (NOT_SMART % _ ("new tremolo format"))
338         stderr_write ('\n')
339     return str
340
341
342 @rule ((1, 3, 42), _ ('Staff_margin_engraver deprecated, use Instrument_name_engraver'))
343 def conv (str):
344     str = re.sub ('Staff_margin_engraver' , 'Instrument_name_engraver', str)
345     return str
346
347
348 @rule ((1, 3, 49), 'noteHeadStyle value: string -> symbol')
349 def conv (str):
350     str = re.sub ('note[hH]eadStyle\\s*=\\s*"?(\\w+)"?' , "noteHeadStyle = #'\\1", str)
351     return str
352
353
354 @rule ((1, 3, 58), 'noteHeadStyle value: string -> symbol')
355 def conv (str):
356     if re.search ('\\\\keysignature', str):
357         stderr_write ('\n')
358         stderr_write (NOT_SMART % '\\keysignature')
359         stderr_write ('\n')
360     return str
361
362
363 @rule ((1, 3, 59), '\key X ; -> \key X major; ')
364 def conv (str):
365     str = re.sub (r"""\\key *([a-z]+) *;""", r"""\\key \1 \major;""",str);
366     return str
367
368
369 @rule ((1, 3, 68), 'latexheaders = "\\input global" -> latexheaders = "global"')
370 def conv (str):
371     str = re.sub (r'latexheaders *= *"\\\\input ',
372                   'latexheaders = "',
373                   str)
374     return str
375
376
377 # TODO: lots of other syntax changes should be done here as well
378 @rule ((1, 3, 92), 'basicXXXProperties -> XXX, Repeat_engraver -> Volta_engraver')
379 def conv (str):
380     str = re.sub ('basicCollisionProperties', 'NoteCollision', str)
381     str = re.sub ('basicVoltaSpannerProperties' , "VoltaBracket", str)
382     str = re.sub ('basicKeyProperties' , "KeySignature", str)
383
384     str = re.sub ('basicClefItemProperties' ,"Clef", str)
385
386
387     str = re.sub ('basicLocalKeyProperties' ,"Accidentals", str)
388     str = re.sub ('basicMarkProperties' ,"Accidentals", str)
389     str = re.sub ('basic([A-Za-z_]+)Properties', '\\1', str)
390
391     str = re.sub ('Repeat_engraver' ,'Volta_engraver', str)
392     return str
393
394
395 @rule ((1, 3, 93), _ ('change property definiton case (eg. onevoice -> oneVoice)'))
396 def conv (str):
397     # Ugh, but meaning of \stemup changed too
398     # maybe we should do \stemup -> \stemUp\slurUp\tieUp ?
399     str = re.sub ('\\\\stemup', '\\\\stemUp', str)
400     str = re.sub ('\\\\stemdown', '\\\\stemDown', str)
401     str = re.sub ('\\\\stemboth', '\\\\stemBoth', str)
402
403     str = re.sub ('\\\\slurup', '\\\\slurUp', str)
404     str = re.sub ('\\\\slurboth', '\\\\slurBoth', str)
405     str = re.sub ('\\\\slurdown', '\\\\slurDown', str)
406     str = re.sub ('\\\\slurdotted', '\\\\slurDotted', str)
407     str = re.sub ('\\\\slurnormal', '\\\\slurNoDots', str)
408
409     str = re.sub ('\\\\shiftoff', '\\\\shiftOff', str)
410     str = re.sub ('\\\\shifton', '\\\\shiftOn', str)
411     str = re.sub ('\\\\shiftonn', '\\\\shiftOnn', str)
412     str = re.sub ('\\\\shiftonnn', '\\\\shiftOnnn', str)
413
414     str = re.sub ('\\\\onevoice', '\\\\oneVoice', str)
415     str = re.sub ('\\\\voiceone', '\\\\voiceOne', str)
416     str = re.sub ('\\\\voicetwo', '\\\\voiceTwo', str)
417     str = re.sub ('\\\\voicethree', '\\\\voiceThree', str)
418     str = re.sub ('\\\\voicefour', '\\\\voiceFour', str)
419
420     # I don't know exactly when these happened...
421     # ugh, we lose context setting here...
422     str = re.sub ('\\\\property *[^ ]*verticalDirection[^=]*= *#?"?(1|(\\\\up))"?', '\\\\stemUp\\\\slurUp\\\\tieUp', str)
423     str = re.sub ('\\\\property *[^ ]*verticalDirection[^=]*= *#?"?((-1)|(\\\\down))"?', '\\\\stemDown\\\\slurDown\\\\tieDown', str)
424     str = re.sub ('\\\\property *[^ ]*verticalDirection[^=]*= *#?"?(0|(\\\\center))"?', '\\\\stemBoth\\\\slurBoth\\\\tieBoth', str)
425
426     str = re.sub ('verticalDirection[^=]*= *#?"?(1|(\\\\up))"?', 'Stem \\\\override #\'direction = #0\nSlur \\\\override #\'direction = #0\n Tie \\\\override #\'direction = #1', str)
427     str = re.sub ('verticalDirection[^=]*= *#?"?((-1)|(\\\\down))"?', 'Stem \\\\override #\'direction = #0\nSlur \\\\override #\'direction = #0\n Tie \\\\override #\'direction = #-1', str)
428     str = re.sub ('verticalDirection[^=]*= *#?"?(0|(\\\\center))"?', 'Stem \\\\override #\'direction = #0\nSlur \\\\override #\'direction = #0\n Tie \\\\override #\'direction = #0', str)
429
430     str = re.sub ('\\\\property *[^ .]*[.]?([a-z]+)VerticalDirection[^=]*= *#?"?(1|(\\\\up))"?', '\\\\\\1Up', str)
431     str = re.sub ('\\\\property *[^ .]*[.]?([a-z]+)VerticalDirection[^=]*= *#?"?((-1)|(\\\\down))"?', '\\\\\\1Down', str)
432     str = re.sub ('\\\\property *[^ .]*[.]?([a-z]+)VerticalDirection[^=]*= *#?"?(0|(\\\\center))"?', '\\\\\\1Both', str)
433
434     # (lacks capitalization slur -> Slur)
435     str = re.sub ('([a-z]+)VerticalDirection[^=]*= *#?"?(1|(\\\\up))"?', '\\1 \\\\override #\'direction = #1', str)
436     str = re.sub ('([a-z]+)VerticalDirection[^=]*= *#?"?((-1)|(\\\\down))"?', '\\1 \\override #\'direction = #-1', str)
437     str = re.sub ('([a-z]+)VerticalDirection[^=]*= *#?"?(0|(\\\\center))"?', '\\1 \\\\override #\'direction = #0', str)
438
439     ## dynamic..
440     str = re.sub ('\\\\property *[^ .]*[.]?dynamicDirection[^=]*= *#?"?(1|(\\\\up))"?', '\\\\dynamicUp', str)
441     str = re.sub ('\\\\property *[^ .]*[.]?dyn[^=]*= *#?"?((-1)|(\\\\down))"?', '\\\\dynamicDown', str)
442     str = re.sub ('\\\\property *[^ .]*[.]?dyn[^=]*= *#?"?(0|(\\\\center))"?', '\\\\dynamicBoth', str)
443
444     str = re.sub ('\\\\property *[^ .]*[.]?([a-z]+)Dash[^=]*= *#?"?(0|(""))"?', '\\\\\\1NoDots', str)
445     str = re.sub ('\\\\property *[^ .]*[.]?([a-z]+)Dash[^=]*= *#?"?([1-9]+)"?', '\\\\\\1Dotted', str)
446
447     str = re.sub ('\\\\property *[^ .]*[.]?noAutoBeaming[^=]*= *#?"?(0|(""))"?', '\\\\autoBeamOn', str)
448     str = re.sub ('\\\\property *[^ .]*[.]?noAutoBeaming[^=]*= *#?"?([1-9]+)"?', '\\\\autoBeamOff', str)
449     return str
450
451
452 @rule ((1, 3, 97), 'ChordName -> ChordNames')
453 def conv (str):
454     str = re.sub ('ChordNames*', 'ChordNames', str)
455     if re.search ('\\\\textscript "[^"]* *"[^"]*"', str):
456         stderr_write ('\n')
457         stderr_write (NOT_SMART % _ ("new \\textscript markup text"))
458         stderr_write ('\n')
459
460     str = re.sub ('\\textscript +("[^"]*")', '\\textscript #\\1', str)
461     return str
462
463 # TODO: add lots of these
464
465 @rule ((1, 3, 98), 'CONTEXT.textStyle -> GROB.#font-style ')
466 def conv (str):
467     str = re.sub ('\\\\property *"?Voice"? *[.] *"?textStyle"? *= *"([^"]*)"', '\\\\property Voice.TextScript \\\\set #\'font-style = #\'\\1', str)
468     str = re.sub ('\\\\property *"?Lyrics"? *[.] *"?textStyle"? *= *"([^"]*)"', '\\\\property Lyrics.LyricText \\\\set #\'font-style = #\'\\1', str)
469
470     str = re.sub ('\\\\property *"?([^.]+)"? *[.] *"?timeSignatureStyle"? *= *"([^"]*)"', '\\\\property \\1.TimeSignature \\\\override #\'style = #\'\\2', str)
471
472     str = re.sub ('"?timeSignatureStyle"? *= *#?""', 'TimeSignature \\\\override #\'style = ##f', str)
473
474     str = re.sub ('"?timeSignatureStyle"? *= *#?"([^"]*)"', 'TimeSignature \\\\override #\'style = #\'\\1', str)
475
476     str = re.sub ('#\'style *= #*"([^"])"', '#\'style = #\'\\1', str)
477
478     str = re.sub ('\\\\property *"?([^.]+)"? *[.] *"?horizontalNoteShift"? *= *"?#?([-0-9]+)"?', '\\\\property \\1.NoteColumn \\\\override #\'horizontal-shift = #\\2', str)
479
480     # ugh
481     str = re.sub ('\\\\property *"?([^.]+)"? *[.] *"?flagStyle"? *= *""', '\\\\property \\1.Stem \\\\override #\'flag-style = ##f', str)
482
483     str = re.sub ('\\\\property *"?([^.]+)"? *[.] *"?flagStyle"? *= *"([^"]*)"', '\\\\property \\1.Stem \\\\override #\'flag-style = #\'\\2', str)
484     return str
485
486
487 @rule ((1, 3, 102), 'beamAutoEnd -> autoBeamSettings \\push (end * * * *)')
488 def conv (str):
489     str = re.sub ('"?beamAutoEnd_([0-9]*)"? *= *(#\\([^)]*\\))', 'autoBeamSettings \\push #\'(end 1 \\1 * *) = \\2', str)
490     str = re.sub ('"?beamAutoBegin_([0-9]*)"? *= *(#\\([^)]*\))', 'autoBeamSettings \\push #\'(begin 1 \\1 * *) = \\2', str)
491     str = re.sub ('"?beamAutoEnd"? *= *(#\\([^)]*\\))', 'autoBeamSettings \\push #\'(end * * * *) = \\1', str)
492     str = re.sub ('"?beamAutoBegin"? *= *(#\\([^)]*\\))', 'autoBeamSettings \\push #\'(begin * * * *) = \\1', str)
493     return str
494
495
496 @rule ((1, 3, 111), '\\push -> \\override, \\pop -> \\revert')
497 def conv (str):
498     str = re.sub ('\\\\push', '\\\\override', str)
499     str = re.sub ('\\\\pop', '\\\\revert', str)
500     return str
501
502
503 @rule ((1, 3, 113), 'LyricVoice -> LyricsVoice')
504 def conv (str):
505     str = re.sub ('LyricVoice', 'LyricsVoice', str)
506     # old fix
507     str = re.sub ('Chord[Nn]ames*.Chord[Nn]ames*', 'ChordNames.ChordName', str)
508     str = re.sub ('Chord[Nn]ames([ \t\n]+\\\\override)', 'ChordName\\1', str)
509     return str
510
511
512 def regularize_id (str):
513     s = ''
514     lastx = ''
515     for x in str:
516         if x == '_':
517             lastx = x
518             continue
519         elif x in string.digits:
520             x = chr(ord (x) - ord ('0')  +ord ('A'))
521         elif x not in string.letters:
522             x = 'x'
523         elif x in string.lowercase and lastx == '_':
524             x = x.upper ()
525         s = s + x
526         lastx = x
527     return s
528
529
530 @rule ((1, 3, 117), _ ('identifier names: %s') % '$!foo_bar_123 -> xfooBarABC')
531 def conv (str):
532     def regularize_dollar_reference (match):
533         return regularize_id (match.group (1))
534     def regularize_assignment (match):
535         return '\n' + regularize_id (match.group (1)) + ' = '
536     str = re.sub ('\$([^\t\n ]+)', regularize_dollar_reference, str)
537     str = re.sub ('\n([^ \t\n]+)[ \t]*= *', regularize_assignment, str)
538     return str
539
540
541 @rule ((1, 3, 120), 'paper_xxx -> paperXxxx, pedalup -> pedalUp.')
542 def conv (str):
543     def regularize_paper (match):
544         return regularize_id (match.group (1))
545     str = re.sub ('(paper_[a-z]+)', regularize_paper, str)
546     str = re.sub ('sustainup', 'sustainUp', str)
547     str = re.sub ('nobreak', 'noBreak', str)
548     str = re.sub ('sustaindown', 'sustainDown', str)
549     str = re.sub ('sostenutoup', 'sostenutoUp', str)
550     str = re.sub ('sostenutodown', 'sostenutoDown', str)
551     str = re.sub ('unachorda', 'unaChorda', str)
552     str = re.sub ('trechorde', 'treChorde', str)
553     return str
554
555
556 @rule ((1, 3, 122), 'drarnChords -> chordChanges, \\musicalpitch -> \\pitch')
557 def conv (str):
558     str = re.sub ('drarnChords', 'chordChanges', str)
559     str = re.sub ('\\musicalpitch', '\\pitch', str)
560     return str
561
562
563 @rule ((1, 3, 136), 'ly-X-elt-property -> ly-X-grob-property')
564 def conv (str):
565     str = re.sub ('ly-([sg])et-elt-property', 'ly-\\1et-grob-property', str)
566     return str
567
568
569 @rule ((1, 3, 138), _ ('point-and-click argument changed to procedure.'))
570 def conv (str):
571     str = re.sub ('point-and-click +#t', 'point-and-click line-column-location', str)
572     return str
573
574
575 @rule ((1, 3, 138), 'followThread -> followVoice.')
576 def conv (str):
577     str = re.sub ('followThread', 'followVoice', str)
578     str = re.sub ('Thread.FollowThread', 'Voice.VoiceFollower', str)
579     str = re.sub ('FollowThread', 'VoiceFollower', str)
580     return str
581
582
583 @rule ((1, 3, 139), 'font-point-size -> font-design-size.')
584 def conv (str):
585     str = re.sub ('font-point-size', 'font-design-size', str)
586     return str
587
588
589 @rule ((1, 3, 141), 'xNoDots -> xSolid')
590 def conv (str):
591     str = re.sub ('([a-zA-Z]*)NoDots', '\\1Solid', str)
592     return str
593
594
595 @rule ((1, 3, 144), 'Chorda -> Corda')
596 def conv (str):
597     str = re.sub ('([Cc])hord([ea])', '\\1ord\\2', str)
598     return str
599
600
601 @rule ((1, 3, 145), 'ContextNameXxxxVerticalExtent -> XxxxVerticalExtent')
602 def conv (str):
603     str = re.sub ('([A-Za-z]+)MinimumVerticalExtent', 'MinimumV@rticalExtent', str)
604     str = re.sub ('([A-Za-z]+)ExtraVerticalExtent', 'ExtraV@rticalExtent', str)
605     str = re.sub ('([A-Za-z]+)VerticalExtent', 'VerticalExtent', str)
606     str = re.sub ('ExtraV@rticalExtent', 'ExtraVerticalExtent', str)
607     str = re.sub ('MinimumV@rticalExtent', 'MinimumVerticalExtent', str)
608     return str
609
610
611 @rule ((1, 3, 146), _('semicolons removed'))
612 def conv (str):
613     str = re.sub ('\\\\key[ \t]*;', '\\key \\default;', str)
614     str = re.sub ('\\\\mark[ \t]*;', '\\mark \\default;', str)
615
616     # Make sure groups of more than one ; have space before
617     # them, so that non of them gets removed by next rule
618     str = re.sub ("([^ \n\t;]);(;+)", "\\1 ;\\2", str)
619
620     # Only remove ; that are not after spaces, # or ;
621     # Otherwise  we interfere with Scheme comments,
622     # which is badbadbad.
623     str = re.sub ("([^ \t;#]);", "\\1", str)
624     return str
625
626
627 @rule ((1, 3, 147), 'default-neutral-direction -> neutral-direction')
628 def conv (str):
629     str = re.sub ('default-neutral-direction', 'neutral-direction',str)
630     return str
631
632
633 @rule ((1, 3, 148), '"(align" -> "(axis", "(rows" -> "(columns"')
634 def conv (str):
635     str = re.sub ('\(align', '(axis', str)
636     str = re.sub ('\(rows', '(columns', str)
637     return str
638
639
640 @rule ((1, 5, 33), 'SystemStartDelimiter -> systemStartDelimiter')
641 def conv (str):
642     str = re.sub ('SystemStartDelimiter', 'systemStartDelimiter', str)
643     return str
644
645
646 @rule ((1, 5, 38), 'arithmetic... -> spacing...')
647 def conv (str):
648     str = re.sub ('arithmetic-multiplier', 'spacing-increment', str)
649     str = re.sub ('arithmetic-basicspace', 'shortest-duration-space', str)
650     return str
651
652
653 # 40 ?
654 @rule ((1, 5, 40), _ ('%s property names') % 'breakAlignOrder')
655 def conv (str):
656
657     def func(match):
658         break_dict = {
659         "Instrument_name": "instrument-name",
660         "Left_edge_item": "left-edge",
661         "Span_bar": "span-bar",
662         "Breathing_sign": "breathing-sign",
663         "Staff_bar": "staff-bar",
664         "Clef_item": "clef",
665         "Key_item": "key-signature",
666         "Time_signature": "time-signature",
667         "Custos": "custos"
668         }
669         props =  match.group (1)
670         for (k,v) in break_dict.items():
671             props = re.sub (k, v, props)
672         return  "breakAlignOrder = #'(%s)" % props
673
674     str = re.sub ("breakAlignOrder *= *#'\\(([a-z_\n\tA-Z ]+)\\)",
675                   func, str)
676     return str
677
678
679 @rule ((1, 5, 49), 'noAutoBeaming -> autoBeaming')
680 def conv (str):
681     str = re.sub ('noAutoBeaming *= *##f', 'autoBeaming = ##t', str)
682     str = re.sub ('noAutoBeaming *= *##t', 'autoBeaming = ##f', str)
683     return str
684
685
686 @rule ((1, 5, 52), 'tuplet-X-visibility -> X-visibility')
687 def conv (str):
688     str = re.sub ('tuplet-bracket-visibility', 'bracket-visibility', str)
689     str = re.sub ('tuplet-number-visibility', 'number-visibility', str)
690     return str
691
692
693 @rule ((1, 5, 56), 'Pitch::transpose -> ly-transpose-pitch')
694 def conv (str):
695     str = re.sub ('Pitch::transpose', 'ly-transpose-pitch', str)
696     return str
697
698
699 @rule ((1, 5, 58), _ ('deprecate %s') % 'textNonEmpty')
700 def conv (str):
701     str = re.sub ('textNonEmpty *= *##t', "TextScript \\set #'no-spacing-rods = ##f", str)
702     str = re.sub ('textNonEmpty *= *##f', "TextScript \\set #'no-spacing-rods = ##t", str)
703     return str
704
705
706 @rule ((1, 5, 59), 'XxxxVerticalExtent -> xxxVerticalExtent')
707 def conv (str):
708     str = re.sub ('MinimumVerticalExtent', 'minimumV@rticalExtent', str)
709     str = re.sub ('minimumVerticalExtent', 'minimumV@rticalExtent', str)
710     str = re.sub ('ExtraVerticalExtent', 'extraV@rticalExtent', str)
711     str = re.sub ('extraVerticalExtent', 'extraV@rticalExtent', str)
712     str = re.sub ('VerticalExtent', 'verticalExtent', str)
713     str = re.sub ('extraV@rticalExtent', 'extraVerticalExtent', str)
714     str = re.sub ('minimumV@rticalExtent', 'minimumVerticalExtent', str)
715     return str
716
717
718 @rule ((1, 5, 62), 'visibility-lambda -> break-visibility')
719 def conv (str):
720     str = re.sub ('visibility-lambda', 'break-visibility', str)
721     return str
722
723
724 @rule ((1, 5, 67), _ ('automaticMelismata turned on by default'))
725 def conv (str):
726     if re.search (r'\addlyrics',str) \
727            and re.search ('automaticMelismata', str)  == None:
728         stderr_write ('\n')
729         stderr_write (NOT_SMART % "automaticMelismata; turned on by default since 1.5.67.")
730         stderr_write ('\n')
731         raise FatalConversionError ()
732     return str
733
734
735 @rule ((1, 5, 68), 'ly-set-X-property -> ly-set-X-property!')
736 def conv (str):
737     str = re.sub ('ly-set-grob-property([^!])', 'ly-set-grob-property!\1', str)
738     str = re.sub ('ly-set-mus-property([^!])', 'ly-set-mus-property!\1', str)
739     return str
740
741
742 @rule ((1, 5, 71), 'extent-[XY] -> [XY]-extent')
743 def conv (str):
744     str = re.sub ('extent-X', 'X-extent', str)
745     str = re.sub ('extent-Y', 'Y-extent', str)
746     return str
747
748
749 @rule ((1, 5, 72), 'set! point-and-click -> set-point-and-click!')
750 def conv (str):
751     str = re.sub ("""#\(set! +point-and-click +line-column-location\)""",
752                   """#(set-point-and-click! \'line-column)""", str)
753     str = re.sub ("""#\(set![ \t]+point-and-click +line-location\)""",
754                   '#(set-point-and-click! \'line)', str)
755     str = re.sub ('#\(set! +point-and-click +#f\)',
756                   '#(set-point-and-click! \'none)', str)
757     return str
758
759
760 @rule ((1, 6, 5), 'Stems: flag-style -> stroke-style; style -> flag-style')
761 def conv (str):
762     str = re.sub ('flag-style', 'stroke-style', str)
763     str = re.sub (r"""Stem([ ]+)\\override #'style""", r"""Stem \\override #'flag-style""", str);
764     str = re.sub (r"""Stem([ ]+)\\set([ ]+)#'style""", r"""Stem \\set #'flag-style""", str);
765     return str
766
767
768 def subst_req_name (match):
769     return "(make-music-by-name \'%sEvent)" % regularize_id (match.group(1))
770
771
772 @rule ((1, 7, 1), 'ly-make-music foo_bar_req -> make-music-by-name FooBarEvent')
773 def conv (str):
774     str = re.sub ('\\(ly-make-music *\"([A-Z][a-z_]+)_req\"\\)', subst_req_name, str)
775     str = re.sub ('Request_chord', 'EventChord', str)
776     return str
777
778
779 spanner_subst ={
780         "text" : 'TextSpanEvent',
781         "decrescendo" : 'DecrescendoEvent',
782         "crescendo" : 'CrescendoEvent',
783         "Sustain" : 'SustainPedalEvent',
784         "slur" : 'SlurEvent',
785         "UnaCorda" : 'UnaCordaEvent',
786         "Sostenuto" : 'SostenutoEvent',
787         }
788
789 def subst_ev_name (match):
790     stype = 'STOP'
791     if re.search ('start', match.group(1)):
792         stype= 'START'
793     mtype = spanner_subst[match.group(2)]
794     return "(make-span-event '%s %s)" % (mtype , stype)
795
796 def subst_definition_ev_name(match):
797     return ' = #%s' % subst_ev_name (match)
798
799 def subst_inline_ev_name (match):
800     s = subst_ev_name (match)
801     return '#(ly-export %s)' % s
802
803 def subst_csp_definition (match):
804     return ' = #(make-event-chord (list %s))' % subst_ev_name (match)
805
806 def subst_csp_inline (match):
807     return '#(ly-export (make-event-chord (list %s)))' % subst_ev_name (match)
808
809
810 @rule ((1, 7, 2), '\\spanrequest -> #(make-span-event .. ), \script -> #(make-articulation .. )')
811 def conv (str):
812     str = re.sub (r' *= *\\spanrequest *([^ ]+) *"([^"]+)"', subst_definition_ev_name, str)
813     str = re.sub (r'\\spanrequest *([^ ]+) *"([^"]+)"', subst_inline_ev_name, str)
814     str = re.sub (r' *= *\\commandspanrequest *([^ ]+) *"([^"]+)"', subst_csp_definition, str)
815     str = re.sub (r'\\commandspanrequest *([^ ]+) *"([^"]+)"', subst_csp_inline, str)
816     str = re.sub (r'ly-id ', 'ly-import ', str)
817
818     str = re.sub (r' *= *\\script "([^"]+)"', ' = #(make-articulation "\\1")', str)
819     str = re.sub (r'\\script "([^"]+)"', '#(ly-export (make-articulation "\\1"))', str)
820     return str
821
822
823 @rule ((1, 7, 3), 'ly- -> ly:')
824 def conv(str):
825     str = re.sub (r'\(ly-', '(ly:', str)
826
827     changed = [
828             r'duration\?',
829             r'font-metric\?',
830             r'molecule\?',
831             r'moment\?',
832             r'music\?',
833             r'pitch\?',
834             'make-duration',
835             'music-duration-length',
836             'duration-log',
837             'duration-dotcount',
838             'intlog2',
839             'duration-factor',
840             'transpose-key-alist',
841             'get-system',
842             'get-broken-into',
843             'get-original',
844             'set-point-and-click!',
845             'make-moment',
846             'make-pitch',
847             'pitch-octave',
848             'pitch-alteration',
849             'pitch-notename',
850             'pitch-semitones',
851             r'pitch<\?',
852             r'dir\?',
853             'music-duration-compress',
854             'set-point-and-click!'
855             ]
856
857     origre = r'\b(%s)' % '|'.join (changed)
858
859     str = re.sub (origre, r'ly:\1',str)
860     str = re.sub ('set-point-and-click!', 'set-point-and-click', str)
861     return str
862
863
864 @rule ((1, 7, 4), '<< >> -> < <  > >')
865 def conv(str):
866     if re.search ('new-chords-done',str):
867         return str
868
869     str = re.sub (r'<<', '< <', str)
870     str = re.sub (r'>>', '> >', str)
871     return str
872
873
874 @rule ((1, 7, 5), '\\transpose TO -> \\transpose FROM  TO')
875 def conv(str):
876     str = re.sub (r"\\transpose", r"\\transpose c'", str)
877     str = re.sub (r"\\transpose c' *([a-z]+)'", r"\\transpose c \1", str)
878     return str
879
880
881 @rule ((1, 7, 6), 'note\\script -> note-\script')
882 def conv(str):
883     kws =   ['arpeggio',
884              'sustainDown',
885              'sustainUp',
886              'f',
887              'p',
888              'pp',
889              'ppp',
890              'fp',
891              'ff',
892              'mf',
893              'mp',
894              'sfz',
895              ]
896
897     origstr = '|'.join (kws)
898     str = re.sub (r'([^_^-])\\(%s)\b' % origstr, r'\1-\\\2', str)
899     return str
900
901
902 @rule ((1, 7, 10), "\property ChordName #'style -> #(set-chord-name-style 'style)")
903 def conv(str):
904     str = re.sub (r"\\property *ChordNames *\. *ChordName *\\(set|override) *#'style *= *#('[a-z]+)",
905                   r"#(set-chord-name-style \2)", str)
906     str = re.sub (r"\\property *ChordNames *\. *ChordName *\\revert *#'style",
907                   r"", str)
908     return str
909
910
911 @rule ((1, 7, 11), "transpose-pitch -> pitch-transpose")
912 def conv(str):
913     str = re.sub (r"ly:transpose-pitch", "ly:pitch-transpose", str)
914     return str
915
916
917 @rule ((1, 7, 13), "ly:XX-molecule-YY -> ly:molecule-XX-YY")
918 def conv(str):
919     str = re.sub (r"ly:get-molecule-extent", "ly:molecule-get-extent", str)
920     str = re.sub (r"ly:set-molecule-extent!", "ly:molecule-set-extent!", str)
921     str = re.sub (r"ly:add-molecule", "ly:molecule-add", str)
922     str = re.sub (r"ly:combine-molecule-at-edge", "ly:molecule-combine-at-edge", str)
923     str = re.sub (r"ly:align-to!", "ly:molecule-align-to!", str)
924     return str
925
926
927 @rule ((1, 7, 15), "linewidth = -1 -> raggedright = ##t")
928 def conv(str):
929     str = re.sub (r"linewidth *= *-[0-9.]+ *(\\mm|\\cm|\\in|\\pt)?", 'raggedright = ##t', str )
930     return str
931
932
933 @rule ((1, 7, 16), "divisiomaior -> divisioMaior")
934 def conv(str):
935     str = re.sub ("divisiomaior",
936                   "divisioMaior", str)
937     str = re.sub ("divisiominima",
938                   "divisioMinima", str)
939     str = re.sub ("divisiomaxima",
940                   "divisioMaxima", str)
941     return str
942
943
944 @rule ((1, 7, 17), "Skip_req  -> Skip_event")
945 def conv(str):
946     str = re.sub ("Skip_req_swallow_translator",
947                   "Skip_event_swallow_translator", str)
948     return str
949
950
951 @rule ((1, 7, 18), "groupOpen/Close  -> start/stopGroup, #'outer  -> #'enclose-bounds")
952 def conv(str):
953     str = re.sub ("groupOpen",
954                   "startGroup", str)
955     str = re.sub ("groupClose",
956                   "stopGroup", str)
957     str = re.sub ("#'outer",
958                   "#'enclose-bounds", str)
959
960     return str
961
962
963 @rule ((1, 7, 19), _ ("remove %s") % "GraceContext")
964 def conv(str):
965     if re.search( r'\\GraceContext', str):
966         stderr_write ('\n')
967         stderr_write (NOT_SMART % "GraceContext")
968         stderr_write (FROM_TO \
969                           % ("GraceContext", "#(add-to-grace-init .. )"))
970         stderr_write ('\n')
971         stderr_write (UPDATE_MANUALLY)
972         stderr_write ('\n')
973         raise FatalConversionError ()
974
975     str = re.sub ('HaraKiriStaffContext', 'RemoveEmptyStaffContext', str)
976     return str
977
978
979 @rule ((1, 7, 22), "#'type -> #'style")
980 def conv(str):
981     str = re.sub (
982             r"(set|override|revert) *#'type",
983             r"\1 #'style",
984             str)
985     return str
986
987
988 @rule ((1, 7, 23), "barNonAuto -> automaticBars")
989 def conv(str):
990     str = re.sub (
991             "barNonAuto *= *##t",
992             "automaticBars = ##f",
993             str)
994     str = re.sub (
995             "barNonAuto *= *##f",
996             "automaticBars = ##t",
997             str)
998     return str
999
1000
1001 @rule ((1, 7, 24), _ ("cluster syntax"))
1002 def conv(str):
1003     if re.search( r'-(start|stop)Cluster', str):
1004         stderr_write ('\n')
1005         stderr_write (NOT_SMART % _ ("cluster syntax"))
1006         stderr_write ('\n')
1007         stderr_write (UPDATE_MANUALLY)
1008         stderr_write ('\n')
1009
1010         raise FatalConversionError ()
1011     return str
1012
1013
1014 @rule ((1, 7, 28), _ ("new Pedal style syntax"))
1015 def conv(str):
1016     str = re.sub (r"\\property *Staff\.(Sustain|Sostenuto|UnaCorda)Pedal *\\(override|set) *#'pedal-type *",
1017                     r"\property Staff.pedal\1Style ", str)
1018     str = re.sub (r"\\property *Staff\.(Sustain|Sostenuto|UnaCorda)Pedal *\\revert *#'pedal-type", '', str)
1019     return str
1020
1021
1022 def sub_chord (m):
1023     str = m.group(1)
1024
1025     origstr =  '<%s>' % str
1026     if re.search (r'\\\\', str):
1027         return origstr
1028
1029     if re.search (r'\\property', str):
1030         return origstr
1031
1032     if re.match (r'^\s*\)?\s*\\[a-zA-Z]+', str):
1033         return origstr
1034
1035     durs = []
1036     def sub_durs (m, durs = durs):
1037         durs.append(m.group(2))
1038         return m.group (1)
1039
1040     str = re.sub (r"([a-z]+[,'!? ]*)([0-9]+\.*)", sub_durs, str)
1041     dur_str = ''
1042
1043     for d in durs:
1044         if dur_str == '':
1045             dur_str = d
1046         if dur_str <> d:
1047             return '<%s>' % m.group (1)
1048
1049     pslur_strs = ['']
1050     dyns = ['']
1051     slur_strs = ['']
1052
1053     last_str = ''
1054     while last_str <> str:
1055         last_str = str
1056
1057         def sub_tremolos (m, slur_strs = slur_strs):
1058             tr = m.group (2)
1059             if tr not in slur_strs:
1060                 slur_strs.append (tr)
1061             return  m.group (1)
1062
1063         str = re.sub (r"([a-z]+[',!? ]*)(:[0-9]+)",
1064                       sub_tremolos, str)
1065
1066         def sub_dyn_end (m, dyns = dyns):
1067             dyns.append (' \!')
1068             return ' ' + m.group(2)
1069
1070         str = re.sub (r'(\\!)\s*([a-z]+)', sub_dyn_end, str)
1071         def sub_slurs(m, slur_strs = slur_strs):
1072             if '-)' not in slur_strs:
1073                 slur_strs.append (')')
1074             return m.group(1)
1075
1076         def sub_p_slurs(m, slur_strs = slur_strs):
1077             if '-\)' not in slur_strs:
1078                 slur_strs.append ('\)')
1079             return m.group(1)
1080
1081         str = re.sub (r"\)[ ]*([a-z]+)", sub_slurs, str)
1082         str = re.sub (r"\\\)[ ]*([a-z]+)", sub_p_slurs, str)
1083         def sub_begin_slurs(m, slur_strs = slur_strs):
1084             if '-(' not in slur_strs:
1085                 slur_strs.append ('(')
1086             return m.group(1)
1087
1088         str = re.sub (r"([a-z]+[,'!?0-9 ]*)\(",
1089                       sub_begin_slurs, str)
1090         def sub_begin_p_slurs(m, slur_strs = slur_strs):
1091             if '-\(' not in slur_strs:
1092                 slur_strs.append ('\(')
1093             return m.group(1)
1094
1095         str = re.sub (r"([a-z]+[,'!?0-9 ]*)\\\(",
1096                 sub_begin_p_slurs, str)
1097
1098         def sub_dyns (m, slur_strs = slur_strs):
1099             s = m.group(0)
1100             if s == '@STARTCRESC@':
1101                 slur_strs.append ("\\<")
1102             elif s == '@STARTDECRESC@':
1103                 slur_strs.append ("\\>")
1104             elif s == r'-?\\!':
1105                 slur_strs.append ('\\!')
1106             return ''
1107
1108         str = re.sub (r'@STARTCRESC@', sub_dyns, str)
1109         str = re.sub (r'-?\\!', sub_dyns, str)
1110
1111         def sub_articulations (m, slur_strs = slur_strs):
1112             a = m.group(1)
1113             if a not in slur_strs:
1114                 slur_strs.append (a)
1115             return ''
1116
1117         str = re.sub (r"([_^-]\@ACCENT\@)", sub_articulations,
1118                       str)
1119         str = re.sub (r"([_^-]\\[a-z]+)", sub_articulations,
1120                       str)
1121         str = re.sub (r"([_^-][>_.+|^-])", sub_articulations,
1122                       str)
1123         str = re.sub (r'([_^-]"[^"]+")', sub_articulations,
1124                       str)
1125
1126         def sub_pslurs(m, slur_strs = slur_strs):
1127             slur_strs.append (' \\)')
1128             return m.group(1)
1129         str = re.sub (r"\\\)[ ]*([a-z]+)", sub_pslurs, str)
1130
1131     ## end of while <>
1132
1133     suffix = ''.join (slur_strs) + ''.join (pslur_strs) \
1134              + ''.join (dyns)
1135
1136     return '@STARTCHORD@%s@ENDCHORD@%s%s' % (str , dur_str, suffix)
1137
1138
1139
1140 def sub_chords (str):
1141     simend = '>'
1142     simstart = '<'
1143     chordstart = '<<'
1144     chordend = '>>'
1145     marker_str = '%% new-chords-done %%'
1146
1147     if re.search (marker_str,str):
1148         return str
1149     str = re.sub ('<<', '@STARTCHORD@', str)
1150     str = re.sub ('>>', '@ENDCHORD@', str)
1151
1152     str = re.sub (r'\\<', '@STARTCRESC@', str)
1153     str = re.sub (r'\\>', '@STARTDECRESC@', str)
1154     str = re.sub (r'([_^-])>', r'\1@ACCENT@', str)
1155     str = re.sub (r'<([^<>{}]+)>', sub_chord, str)
1156
1157     # add dash: -[, so that [<<a b>> c d] becomes
1158     #                      <<a b>>-[ c d]
1159     # and gets skipped by articulation_substitute
1160     str = re.sub (r'\[ *(@STARTCHORD@[^@]+@ENDCHORD@[0-9.]*)',
1161                   r'\1-[', str)
1162     str = re.sub (r'\\! *(@STARTCHORD@[^@]+@ENDCHORD@[0-9.]*)',
1163                   r'\1-\\!', str)
1164
1165     str = re.sub (r'<([^?])', r'%s\1' % simstart, str)
1166     str = re.sub (r'>([^?])', r'%s\1' % simend,  str)
1167     str = re.sub ('@STARTCRESC@', r'\\<', str)
1168     str = re.sub ('@STARTDECRESC@', r'\\>' ,str)
1169     str = re.sub (r'\\context *Voice *@STARTCHORD@',
1170                   '@STARTCHORD@', str)
1171     str = re.sub ('@STARTCHORD@', chordstart, str)
1172     str = re.sub ('@ENDCHORD@', chordend, str)
1173     str = re.sub (r'@ACCENT@', '>', str)
1174     return str
1175
1176 markup_start = re.compile(r"([-^_]|\\mark)\s*(#\s*'\s*)\(")
1177 musicglyph = re.compile(r"\(\s*music\b")
1178 columns = re.compile(r"\(\s*columns\b")
1179 submarkup_start = re.compile(r"\(\s*([a-zA-Z]+)")
1180 leftpar = re.compile(r"\(")
1181 rightpar = re.compile(r"\)")
1182
1183 def text_markup (str):
1184     result = ''
1185     # Find the beginning of each markup:
1186     match = markup_start.search (str)
1187     while match:
1188         result = result + str[:match.end (1)] + " \markup"
1189         str = str[match.end( 2):]
1190         # Count matching parentheses to find the end of the 
1191         # current markup:
1192         nesting_level = 0
1193         pars = re.finditer(r"[()]",str)
1194         for par in pars:
1195             if par.group () == '(':
1196                 nesting_level = nesting_level + 1
1197             else:
1198                 nesting_level = nesting_level - 1
1199             if nesting_level == 0:
1200                 markup_end = par.end ()
1201                 break
1202         # The full markup in old syntax:
1203         markup = str[:markup_end]
1204         # Modify to new syntax:
1205         markup = musicglyph.sub (r"{\\musicglyph", markup)
1206         markup = columns.sub (r"{", markup)
1207         markup = submarkup_start.sub (r"{\\\1", markup)
1208         markup = leftpar.sub ("{", markup)
1209         markup = rightpar.sub ("}", markup)
1210
1211         result = result + markup
1212         # Find next markup
1213         str = str[markup_end:]
1214         match = markup_start.search(str)
1215     result = result + str
1216     return result
1217
1218 def articulation_substitute (str):
1219     str = re.sub (r"""([^-])\[ *(\\?\)?[a-z]+[,']*[!?]?[0-9:]*\.*)""",
1220                   r"\1 \2[", str)
1221     str = re.sub (r"""([^-])\\\) *([a-z]+[,']*[!?]?[0-9:]*\.*)""",
1222                   r"\1 \2\\)", str)
1223     str = re.sub (r"""([^-\\])\) *([a-z]+[,']*[!?]?[0-9:]*\.*)""",
1224                   r"\1 \2)", str)
1225     str = re.sub (r"""([^-])\\! *([a-z]+[,']*[!?]?[0-9:]*\.*)""",
1226                   r"\1 \2\\!", str)
1227     return str
1228
1229 string_or_scheme = re.compile ('("(?:[^"\\\\]|\\\\.)*")|(#\\s*\'?\\s*\\()')
1230
1231 # Only apply articulation_substitute () outside strings and 
1232 # Scheme expressions:
1233 def smarter_articulation_subst (str):
1234     result = ''
1235     # Find the beginning of next string or Scheme expr.:
1236     match = string_or_scheme.search (str)
1237     while match:
1238         # Convert the preceding LilyPond code:
1239         previous_chunk = str[:match.start()]
1240         result = result + articulation_substitute (previous_chunk)
1241         if match.group (1): # Found a string
1242             # Copy the string to output:
1243             result = result + match.group (1)
1244             str = str[match.end(1):]
1245         else: # Found a Scheme expression. Count 
1246             # matching parentheses to find its end
1247             str = str[match.start ():]
1248             nesting_level = 0
1249             pars = re.finditer(r"[()]",str)
1250             for par in pars:
1251                 if par.group () == '(':
1252                     nesting_level = nesting_level + 1
1253                 else:
1254                     nesting_level = nesting_level - 1
1255                 if nesting_level == 0:
1256                     scheme_end = par.end ()
1257                     break
1258             # Copy the Scheme expression to output:
1259             result = result + str[:scheme_end]
1260             str = str[scheme_end:]
1261         # Find next string or Scheme expression:
1262         match = string_or_scheme.search (str)
1263     # Convert the remainder of the file
1264     result = result + articulation_substitute (str)
1265     return result
1266
1267 def conv_relative(str):
1268     if re.search (r"\\relative", str):
1269         str= "#(ly:set-option 'old-relative)\n" + str
1270
1271     return str
1272
1273 @rule ((1, 9, 0), _ ("""New relative mode,
1274 Postfix articulations, new text markup syntax, new chord syntax."""))
1275 def conv (str):
1276     str = re.sub (r"#'\(\)", "@SCM_EOL@", str)
1277     str =  conv_relative (str)
1278     str = sub_chords (str)
1279
1280     str = text_markup (str)
1281     str = smarter_articulation_subst (str)
1282     str = re.sub ("@SCM_EOL@", "#'()", str)
1283     return str
1284
1285
1286 @rule ((1, 9, 1), _ ("Remove - before articulation"))
1287 def conv (str):
1288     if re.search ("font-style",str):
1289         stderr_write ('\n')
1290         stderr_write (NOT_SMART % "font-style")
1291         stderr_write ('\n')
1292         stderr_write (UPDATE_MANUALLY)
1293         stderr_write ('\n')
1294
1295         raise FatalConversionError ()
1296
1297     str = re.sub (r'-\\markup', r'@\\markup', str)
1298     str = re.sub (r'-\\', r'\\', str)
1299     str = re.sub (r'-\)', ')', str)
1300     str = re.sub (r'-\(', '(', str)
1301     str = re.sub ('-\[', '[', str)
1302     str = re.sub ('-\]', ']', str)
1303     str = re.sub ('-~', '~', str)
1304     str = re.sub (r'@\\markup', r'-\\markup', str)
1305     return str
1306
1307
1308 @rule ((1, 9, 2), "\\newcontext -> \\new")
1309 def conv (str):
1310     str = re.sub ('ly:set-context-property',
1311                   'ly:set-context-property!', str)
1312     str = re.sub ('\\\\newcontext', '\\\\new', str)
1313     str = re.sub ('\\\\grace[\t\n ]*([^{ ]+)',
1314                   r'\\grace { \1 }', str)
1315     str = re.sub ("\\\\grace[\t\n ]*{([^}]+)}",
1316                   r"""\\grace {
1317 \\property Voice.Stem \\override #'stroke-style = #"grace"
1318   \1
1319   \\property Voice.Stem \\revert #'stroke-style }
1320 """, str)
1321     return str
1322
1323
1324 @rule ((1, 9, 3), (_ ("%s misspelling") % "\\acciaccatura") + 
1325                          ", fingerHorizontalDirection -> fingeringOrientations")
1326 def conv (str):
1327     str = re.sub ('accacciatura',
1328                   'acciaccatura', str)
1329
1330     if re.search ("context-spec-music", str):
1331         stderr_write ('\n')
1332         stderr_write (NOT_SMART % "context-spec-music")
1333         stderr_write ('\n')
1334         stderr_write (UPDATE_MANUALLY)
1335         stderr_write ('\n')
1336
1337         raise FatalConversionError ()
1338
1339     str = re.sub ('fingerHorizontalDirection *= *#(LEFT|-1)',
1340                   "fingeringOrientations = #'(up down left)", str)
1341     str = re.sub ('fingerHorizontalDirection *= *#(RIGHT|1)',
1342                   "fingeringOrientations = #'(up down right)", str)
1343     return str
1344
1345
1346 @rule ((1, 9, 4), _ ('Swap < > and << >>'))
1347 def conv (str):
1348     if re.search ('\\figures', str):
1349         warning (_ ("attempting automatic \\figures conversion.  Check results!"));
1350
1351     def figures_replace (m):
1352         s = m.group (1)
1353         s = re.sub ('<', '@FIGOPEN@',s)
1354         s = re.sub ('>', '@FIGCLOSE@',s)
1355         return '\\figures { %s }' % s
1356
1357     str = re.sub (r'\\figures[ \t\n]*{([^}]+)}', figures_replace, str)
1358     str = re.sub (r'\\<', '@STARTCRESC@', str)
1359     str = re.sub (r'\\>', '@STARTDECRESC@', str)
1360     str = re.sub (r'([-^_])>', r'\1@ACCENT@', str)
1361     str = re.sub (r'<<', '@STARTCHORD@', str)
1362     str = re.sub (r'>>', '@ENDCHORD@', str)
1363     str = re.sub (r'>', '@ENDSIMUL@', str)
1364     str = re.sub (r'<', '@STARTSIMUL@', str)
1365     str = re.sub ('@STARTDECRESC@', '\\>', str)
1366     str = re.sub ('@STARTCRESC@', '\\<', str)
1367     str = re.sub ('@ACCENT@', '>', str)
1368     str = re.sub ('@ENDCHORD@', '>', str)
1369     str = re.sub ('@STARTCHORD@', '<', str)
1370     str = re.sub ('@STARTSIMUL@', '<<', str)
1371     str = re.sub ('@ENDSIMUL@', '>>', str)
1372     str = re.sub ('@FIGOPEN@', '<', str)
1373     str = re.sub ('@FIGCLOSE@', '>', str)
1374     return str
1375
1376
1377 @rule ((1, 9, 5), 'HaraKiriVerticalGroup -> RemoveEmptyVerticalGroup')
1378 def conv (str):
1379     str = re.sub ('HaraKiriVerticalGroup', 'RemoveEmptyVerticalGroup', str)
1380     return str
1381
1382
1383 @rule ((1, 9, 6), _ ('deprecate %s') % 'ly:get-font')
1384 def conv (str):
1385     if re.search ("ly:get-font", str) :
1386         stderr_write ('\n')
1387         stderr_write (NOT_SMART % "(ly:-get-font")
1388         stderr_write ('\n')
1389         stderr_write (FROM_TO \
1390                           % ("(ly:paper-get-font (ly:grob-get-paper foo) .. )",
1391                              "(ly:paper-get-font (ly:grob-get-paper foo) .. )"))
1392         stderr_write (UPDATE_MANUALLY)
1393         stderr_write ('\n')
1394         raise FatalConversionError ()
1395
1396     if re.search ("\\pitch *#", str) :
1397         stderr_write ('\n')
1398         stderr_write (NOT_SMART % "\\pitch")
1399         stderr_write ('\n')
1400         stderr_write (_ ("Use Scheme code to construct arbitrary note events."))
1401         stderr_write ('\n')
1402
1403         raise FatalConversionError ()
1404     return str
1405
1406
1407 @rule ((1, 9, 7), _ ('''use symbolic constants for alterations,
1408 remove \\outputproperty, move ly:verbose into ly:get-option'''))
1409 def conv (str):
1410     def sub_alteration (m):
1411         alt = m.group (3)
1412         alt = {
1413                 '-1': 'FLAT',
1414                 '-2': 'DOUBLE-FLAT',
1415                 '0': 'NATURAL',
1416                 '1': 'SHARP',
1417                 '2': 'DOUBLE-SHARP',
1418                 }[alt]
1419
1420         return '(ly:make-pitch %s %s %s)' % (m.group(1), m.group (2),
1421                                              alt)
1422
1423     str =re.sub ("\\(ly:make-pitch *([0-9-]+) *([0-9-]+) *([0-9-]+) *\\)",
1424                  sub_alteration, str)
1425
1426
1427     str = re.sub ("ly:verbose", "ly:get-option 'verbose", str)
1428
1429     m= re.search ("\\\\outputproperty #([^#]+)[\t\n ]*#'([^ ]+)", str)
1430     if m:
1431         stderr_write (_ (\
1432                 r"""\outputproperty found,
1433 Please hand-edit, using
1434
1435   \applyoutput #(outputproperty-compatibility %s '%s <GROB PROPERTY VALUE>)
1436
1437 as a substitution text.""") % (m.group (1), m.group (2)) )
1438         raise FatalConversionError ()
1439
1440     if re.search ("ly:(make-pitch|pitch-alteration)", str) \
1441            or re.search ("keySignature", str):
1442         stderr_write ('\n')
1443         stderr_write (NOT_SMART % "pitches")
1444         stderr_write ('\n')
1445         stderr_write (
1446             _ ("""The alteration field of Scheme pitches was multiplied by 2
1447 to support quarter tone accidentals.  You must update the following constructs manually:
1448
1449 * calls of ly:make-pitch and ly:pitch-alteration
1450 * keySignature settings made with \property
1451 """))
1452         raise FatalConversionError ()
1453     return str
1454
1455
1456 @rule ((1, 9, 8), "dash-length -> dash-fraction")
1457 def conv (str):
1458     if re.search ("dash-length",str):
1459         stderr_write ('\n')
1460         stderr_write (NOT_SMART % "dash-length")
1461         stderr_write ('\n')
1462         stderr_write (FROM_TO % ("dash-length", "dash-fraction"))
1463         stderr_write ('\n')
1464         stderr_write (UPDATE_MANUALLY)
1465         stderr_write ('\n')
1466         raise FatalConversionError ()
1467     return str
1468
1469
1470 @rule ((2, 1, 1), "font-relative-size -> font-size")
1471 def conv (str):
1472     def func(match):
1473         return "#'font-size = #%d" % (2*int (match.group (1)))
1474
1475     str =re.sub (r"#'font-relative-size\s*=\s*#\+?([0-9-]+)", func, str)
1476     str =re.sub (r"#'font-family\s*=\s*#'ancient",
1477                  r"#'font-family = #'music", str)
1478     return str
1479
1480
1481 @rule ((2, 1, 2), "ly:get-music-length -> ly:music-length")
1482 def conv (str):
1483     str =re.sub (r"ly:get-music-length", "ly:music-length", str)
1484     return str
1485
1486
1487 @rule ((2, 1, 3), "stanza -> instrument")
1488 def conv (str):
1489     str =re.sub (r"\.\s+stz=", ". instr ", str)
1490     return str
1491
1492
1493 @rule ((2, 1, 4), _ ("removal of automaticMelismata; use melismaBusyProperties instead."))
1494 def conv (str):
1495     def func (match):
1496         c = match.group (1)
1497         b = match.group (2)
1498
1499         if b == 't':
1500             if c == 'Score':
1501                 return ''
1502             else:
1503                 return r" \property %s.melismaBusyProperties \unset"  % c
1504         elif b == 'f':
1505             return r"\property %s.melismaBusyProperties = #'(melismaBusy)"  % c
1506
1507     str = re.sub (r"\\property ([a-zA-Z]+)\s*\.\s*automaticMelismata\s*=\s*##([ft])", func, str)
1508     return str
1509
1510
1511 @rule ((2, 1, 7), "\\translator Staff -> \\change Staff")
1512 def conv (str):
1513     str =re.sub (r"\\translator\s+([a-zA-Z]+)", r"\\change \1", str)
1514     return str
1515
1516
1517 @rule ((2, 1, 10), "\\newaddlyrics -> \\lyricsto")
1518 def conv (str):
1519     str =re.sub (r"\\newaddlyrics", r"\\lyricsto", str)
1520     return str
1521
1522
1523 @rule ((2, 1, 11), """\\include "paper16.ly" -> #(set-staff-size 16)
1524 \\note #3 #1 #1 -> \\note #"8." #1
1525 """)
1526 def conv (str):
1527     str = re.sub (r'\\include\s*"paper([0-9]+)(-init)?.ly"',
1528                   r"#(set-staff-size \1)", str)
1529
1530     def sub_note (match):
1531         dur = ''
1532         log = int (match.group (1))
1533         dots = int (match.group (2))
1534
1535         if log >= 0:
1536             dur = '%d' % (1 << log)
1537         else:
1538             dur = { -1 : 'breve',
1539                     -2 : 'longa',
1540                     -3 : 'maxima'}[log]
1541
1542         dur += ('.' * dots)
1543
1544         return r'\note #"%s" #%s' % (dur, match.group (3))
1545
1546     str = re.sub (r'\\note\s+#([0-9-]+)\s+#([0-9]+)\s+#([0-9.-]+)',
1547                   sub_note, str)
1548     return str
1549
1550
1551 @rule ((2, 1, 12), "OttavaSpanner -> OttavaBracket")
1552 def conv (str):
1553     str = re.sub (r"OttavaSpanner", r"OttavaBracket", str)
1554     return str
1555
1556
1557 @rule ((2, 1, 13), "set-staff-size -> set-global-staff-size")
1558 def conv (str):
1559     str = re.sub (r"\(set-staff-size ", r"(set-global-staff-size ", str)
1560     return str
1561
1562
1563 @rule ((2, 1, 14), "style = dotted -> dash-fraction = 0")
1564 def conv (str):
1565     str = re.sub (r"#'style\s*=\s*#'dotted-line",
1566                  r"#'dash-fraction = #0.0 ", str)
1567     return str
1568
1569
1570 @rule ((2, 1, 15), "LyricsVoice . instr(ument) -> vocalName")
1571 def conv (str):
1572     str = re.sub (r'LyricsVoice\s*\.\s*instrument\s*=\s*("[^"]*")',
1573                  r'LyricsVoice . vocalName = \1', str)
1574
1575     str = re.sub (r'LyricsVoice\s*\.\s*instr\s*=\s*("[^"]*")',
1576                  r'LyricsVoice . vocNam = \1', str)
1577     return str
1578
1579
1580 @rule ((2, 1, 16), '\\musicglyph #"accidentals-NUM" -> \\sharp/flat/etc.')
1581 def conv (str):
1582     def sub_acc (m):
1583         d = {
1584         '4': 'doublesharp',
1585         '3': 'threeqsharp',
1586         '2': 'sharp',
1587         '1': 'semisharp',
1588         '0': 'natural',
1589         '-1': 'semiflat',
1590         '-2': 'flat',
1591         '-3': 'threeqflat',
1592         '-4': 'doubleflat'}
1593         return '\\%s' %  d[m.group (1)]
1594
1595     str = re.sub (r'\\musicglyph\s*#"accidentals-([0-9-]+)"',
1596                   sub_acc, str)
1597     return str
1598
1599
1600 @rule ((2, 1, 17), _ ("\\partcombine syntax change to \\newpartcombine"))
1601 def conv (str):
1602
1603     if re.search (r'\\partcombine', str):
1604         stderr_write ('\n')
1605         stderr_write (NOT_SMART % "\\partcombine")
1606         stderr_write ('\n')
1607         stderr_write (UPDATE_MANUALLY)
1608         stderr_write ('\n')
1609         raise FatalConversionError ()
1610
1611     # this rule doesn't really work,
1612     # too lazy to figure out why.
1613     str = re.sub (r'\\context\s+Voice\s*=\s*one\s*\\partcombine\s+Voice\s*\\context\s+Thread\s*=\s*one(.*)\s*'
1614                   + r'\\context\s+Thread\s*=\s*two',
1615                   '\\\\newpartcombine\n\\1\n', str)
1616     return str
1617
1618
1619 @rule ((2, 1, 18), """\\newpartcombine -> \\partcombine,
1620 \\autochange Staff -> \\autochange
1621 """)
1622 def conv (str):
1623     str = re.sub (r'\\newpartcombine', r'\\partcombine', str)
1624     str = re.sub (r'\\autochange\s+Staff', r'\\autochange ', str)
1625     return str
1626
1627
1628 @rule ((2, 1, 19), _ ("""Drum notation changes, Removing \\chordmodifiers, \\notenames.
1629 Harmonic notes. Thread context removed. Lyrics context removed."""))
1630 def conv (str):
1631     if re.search ('include "drumpitch', str):
1632         stderr_write (_ ("Drums found. Enclose drum notes in \\drummode"))
1633
1634     str = re.sub (r'\\include "drumpitch-init.ly"','', str)
1635
1636     str = re.sub (r'\\pitchnames ','pitchnames = ', str)
1637     str = re.sub (r'\\chordmodifiers ','chordmodifiers = ', str)
1638     str = re.sub (r'\bdrums\b\s*=','drumContents = ', str)
1639     str = re.sub (r'\\drums\b','\\drumContents ', str)
1640
1641
1642     if re.search ('drums->paper', str):
1643         stderr_write (_ ("\n%s found. Check file manually!\n") % _("Drum notation"))
1644
1645     str = re.sub (r"""\\apply\s+#\(drums->paper\s+'([a-z]+)\)""",
1646                   r"""\property DrumStaff.drumStyleTable = #\1-style""",
1647                   str)
1648
1649     if re.search ('Thread', str):
1650         stderr_write (_ ("\n%s found. Check file manually!\n") % "Thread");
1651
1652     str = re.sub (r"""(\\once\s*)?\\property\s+Thread\s*\.\s*NoteHead\s*"""
1653                   + r"""\\(set|override)\s*#'style\s*=\s*#'harmonic"""
1654                   + r"""\s+([a-z]+[,'=]*)([0-9]*\.*)"""
1655                   ,r"""<\3\\harmonic>\4""", str)
1656
1657     str = re.sub (r"""\\new Thread""", """\context Voice""", str)
1658     str = re.sub (r"""Thread""", """Voice""", str)
1659
1660     if re.search ('\bLyrics\b', str):
1661         stderr_write (_ ("\n%s found. Check file manually!\n") % "Lyrics");
1662
1663     str = re.sub (r"""LyricsVoice""", r"""L@ricsVoice""", str)
1664     str = re.sub (r"""\bLyrics\b""", r"""LyricsVoice""", str)
1665     str = re.sub (r"""LyricsContext""", r"""LyricsVoiceContext""", str)
1666     str = re.sub (r"""L@ricsVoice""", r"""LyricsVoice""",str)
1667     return str
1668
1669
1670 @rule ((2, 1, 20), "nonevent-skip -> skip-music")
1671 def conv (str):
1672     str = re.sub (r'nonevent-skip', 'skip-music', str)
1673     return str
1674
1675
1676 @rule ((2, 1, 21), """molecule-callback -> print-function,
1677 brew_molecule -> print
1678 brew-new-markup-molecule -> Text_item::print
1679 LyricsVoice -> Lyrics
1680 tupletInvisible -> TupletBracket \set #'transparent
1681 %s.
1682 """ % (_ ("remove %s") % "Grob::preset_extent"))
1683 def conv (str):
1684     str = re.sub (r'molecule-callback', 'print-function', str)
1685     str = re.sub (r'brew_molecule', 'print', str)
1686     str = re.sub (r'brew-new-markup-molecule', 'Text_item::print', str)
1687     str = re.sub (r'LyricsVoice', 'Lyrics', str)
1688     str = re.sub (r'tupletInvisible',
1689                   r"TupletBracket \\set #'transparent", str)
1690 #       str = re.sub (r'molecule', 'collage', str)
1691 #molecule -> collage
1692     str = re.sub (r"\\property\s+[a-zA-Z]+\s*\.\s*[a-zA-Z]+\s*"
1693                   + r"\\set\s*#'X-extent-callback\s*=\s*#Grob::preset_extent",
1694                   "", str)
1695     return str
1696
1697
1698 @rule ((2, 1, 22), """%s
1699         \\set A.B = #C , \\unset A.B
1700         \\override A.B #C = #D, \\revert A.B #C
1701
1702 """ % _ ("new syntax for property settings:"))
1703 def conv (str):
1704     str = re.sub (r'(\\property[^=]+)=\s*([-0-9]+)',
1705                   r'\1= #\2', str)
1706     str = re.sub (r'\\property\s+([^. ]+)\s*\.\s*([^\\=]+)\s*\\(set|override)',
1707                   r"\\overrid@ \1.\2 ", str)
1708     str = re.sub (r'\\property\s+([^. ]+)\s*\.\s*([^\\= ]+)\s*=\s*',
1709                   r'\\s@t \1.\2 = ', str)
1710     str = re.sub (r'\\property\s+([^. ]+)\s*\.\s*([^\\= ]+)\s*\\unset',
1711                   r'\\uns@t \1.\2 ', str)
1712     str = re.sub (r'\\property\s+([^. ]+)\s*\.\s*([^\\= ]+)\s*\\revert'
1713                   + r"\s*#'([-a-z0-9_]+)",
1714                   r"\\rev@rt \1.\2 #'\3", str)
1715     str = re.sub (r'Voice\.', '', str)
1716     str = re.sub (r'Lyrics\.', '', str)
1717     str = re.sub (r'ChordNames\.', '', str)
1718
1719     str = re.sub ('rev@rt', 'revert',str)
1720     str = re.sub ('s@t', 'set',str)
1721     str = re.sub ('overrid@', 'override',str)
1722
1723     str = re.sub ('molecule', 'stencil', str)
1724     str = re.sub ('Molecule', 'Stencil', str)
1725     return str
1726
1727
1728 @rule ((2, 1, 23), _ ("Property setting syntax in \\translator{ }"))
1729 def conv (str):
1730     def subst_in_trans (match):
1731         s = match.group (0)
1732         s = re.sub (r'\s([a-zA-Z]+)\s*\\override',
1733                       r' \\override \1', s)
1734         s = re.sub (r'\s([a-zA-Z]+)\s*\\set',
1735                       r' \\override \1', s)
1736         s = re.sub (r'\s([a-zA-Z]+)\s*\\revert',
1737                       r' \\revert \1', s)
1738         return s
1739     str = re.sub (r'\\(translator|with)\s*{[^}]+}',  subst_in_trans, str)
1740
1741     def sub_abs (m):
1742
1743         context = m.group ('context')
1744         d = m.groupdict ()
1745         if context:
1746             context = " '%s" % context[:-1] # -1: remove .
1747         else:
1748             context = ''
1749
1750         d['context'] = context
1751
1752         return r"""#(override-auto-beam-setting %(prop)s %(num)s %(den)s%(context)s)""" % d
1753
1754     str = re.sub (r"""\\override\s*(?P<context>[a-zA-Z]+\s*\.\s*)?autoBeamSettings"""
1755                   +r"""\s*#(?P<prop>[^=]+)\s*=\s*#\(ly:make-moment\s+(?P<num>\d+)\s+(?P<den>\d)\s*\)""",
1756                   sub_abs, str)
1757     return str
1758
1759
1760 @rule ((2, 1, 24), "music-list? -> ly:music-list?")
1761 def conv (str):
1762     str = re.sub (r'music-list\?', 'ly:music-list?', str)
1763     str = re.sub (r'\|\s*~', '~ |', str)
1764     return str
1765
1766
1767 @rule ((2, 1, 25), _ ("Scheme grob function renaming"))
1768 def conv (str):
1769     str = re.sub (r'ly:get-spanner-bound', 'ly:spanner-get-bound', str)
1770     str = re.sub (r'ly:get-extent', 'ly:grob-extent', str)
1771     str = re.sub (r'ly:get-system', 'ly:grob-system', str)
1772     str = re.sub (r'ly:get-original', 'ly:grob-original', str)
1773     str = re.sub (r'ly:get-parent', 'ly:grob-parent', str)
1774     str = re.sub (r'ly:get-broken-into', 'ly:spanner-broken-into', str)
1775     str = re.sub (r'Melisma_engraver', 'Melisma_translator', str)
1776     if re.search ("ly:get-paper-variable", str):
1777         stderr_write ('\n')
1778         stderr_write (NOT_SMART % "ly:paper-get-variable")
1779         stderr_write ('\n')
1780         stderr_write (_ ('use %s') % '(ly:paper-lookup (ly:grob-paper ))')
1781         stderr_write ('\n')
1782         raise FatalConversionError ()
1783
1784     str = re.sub (r'\\defaultAccidentals', "#(set-accidental-style 'default)", str)
1785     str = re.sub (r'\\voiceAccidentals', "#(set-accidental-style 'voice)", str)
1786     str = re.sub (r'\\modernAccidentals', "#(set-accidental-style 'modern)", str)
1787     str = re.sub (r'\\modernCautionaries', "#(set-accidental-style 'modern-cautionary)", str)
1788     str = re.sub (r'\\modernVoiceAccidental', "#(set-accidental-style 'modern-voice)", str)
1789     str = re.sub (r'\\modernVoiceCautionaries', "#(set-accidental-style 'modern-voice-cautionary)", str)
1790     str = re.sub (r'\\pianoAccidentals', "#(set-accidental-style 'piano)", str)
1791     str = re.sub (r'\\pianoCautionaries', "#(set-accidental-style 'piano-cautionary)", str)
1792     str = re.sub (r'\\forgetAccidentals', "#(set-accidental-style 'forget)", str)
1793     str = re.sub (r'\\noResetKey', "#(set-accidental-style 'no-reset)", str)
1794     return str
1795
1796
1797 @rule ((2, 1, 26), _ ("More Scheme function renaming"))
1798 def conv (str):
1799     str = re.sub ('ly:set-grob-property!', 'ly:grob-set-property!',str)
1800     str = re.sub ('ly:set-mus-property!', 'ly:music-set-property!',str)
1801     str = re.sub ('ly:set-context-property!', 'ly:context-set-property!', str)
1802     str = re.sub ('ly:get-grob-property', 'ly:grob-property',str)
1803     str = re.sub ('ly:get-mus-property', 'ly:music-property',str)
1804     str = re.sub ('ly:get-context-property', 'ly:context-property',str)
1805     return str
1806
1807
1808 @rule ((2, 1, 27), "property transposing -> tuning")
1809 def conv (str):
1810     def subst (m):
1811         g = int (m.group (2))
1812         o = g / 12
1813         g -= o * 12
1814         if g <  0:
1815             g += 12
1816             o -= 1
1817
1818
1819         lower_pitches = filter (lambda x : x <= g, [0, 2, 4, 5, 7, 9, 11, 12])
1820         s = len (lower_pitches) -1
1821         a = g - lower_pitches [-1]
1822
1823
1824         str = 'cdefgab' [s]
1825         str += ['eses', 'es', '', 'is', 'isis'][a + 2]
1826         if o < 0:
1827             str += ',' * (-o - 1)
1828         elif o >= 0:
1829             str += "'" * (o + 1)
1830
1831         return '\\transposition %s ' % str
1832
1833
1834     str = re.sub (r"\\set ([A-Za-z]+\s*\.\s*)?transposing\s*=\s*#([-0-9]+)",
1835                   subst, str)
1836     return str
1837
1838
1839 @rule ((2, 1, 28), """make-music-by-name -> make-music,
1840 new syntax for setting \\arpeggioBracket""")
1841 def conv (str):
1842     str = re.sub (r'make-music-by-name', 'make-music', str)
1843     str = re.sub (r"\\override\s+.*Arpeggio\s+#.print-function\s+=\s+\\arpeggioBracket", r"\\arpeggioBracket", str)
1844     return str
1845
1846
1847 @rule ((2, 1, 29), '\\center -> \\center-align, \\translator -> \\context')
1848 def conv (str):
1849     str = re.sub (r'\\center([^-])', '\\center-align\\1', str)
1850     str = re.sub (r'\\translator', '\\context', str)
1851     return str
1852
1853
1854 @rule ((2, 1, 30), '''\\threeq{flat,sharp} -> \\sesqui{flat,sharp}
1855 ly:get-mutable-properties -> ly:mutable-music-properties
1856 centralCPosition -> middleCPosition
1857 ly:unset-context-property -> ly:context-unset-property
1858 ly:translator-find -> ly:context-find
1859 ly:get-stencil-extent -> ly:stencil-extent
1860 ''')
1861 def conv (str):
1862     str = re.sub (r'\\threeq(flat|sharp)', r'\\sesqui\1', str)
1863     str = re.sub (r'ly:stencil-get-extent',
1864                   'ly:stencil-extent', str)
1865     str = re.sub (r'ly:translator-find',
1866                   'ly:context-find', str)
1867     str = re.sub ('ly:unset-context-property','ly:context-unset-property',
1868                   str)
1869
1870     str = re.sub (r'ly:get-mutable-properties',
1871                   'ly:mutable-music-properties',str)
1872     str = re.sub (r'centralCPosition',
1873                   'middleCPosition',str)
1874     return str
1875
1876
1877 @rule ((2, 1, 31), 'remove \\alias Timing')
1878 def conv (str):
1879     str = re.sub (r'\\alias\s*"?Timing"?', '', str)
1880     return str
1881
1882
1883 @rule ((2, 1, 33), 'breakAlignOrder -> break-align-orders.')
1884 def conv (str):
1885     str = re.sub (r"(\\set\s+)?(?P<context>(Score\.)?)breakAlignOrder\s*=\s*#'(?P<list>[^\)]+)",
1886                   r"\n\\override \g<context>BreakAlignment #'break-align-orders = "
1887                   + "#(make-vector 3 '\g<list>)", str)
1888     return str
1889
1890
1891 @rule ((2, 1, 34), 'set-paper-size -> set-default-paper-size.')
1892 def conv (str):
1893     str = re.sub (r"\(set-paper-size",
1894                   "(set-default-paper-size",str)
1895     return str
1896
1897
1898 @rule ((2, 1, 36), 'ly:mutable-music-properties -> ly:music-mutable-properties')
1899 def conv (str):
1900     str = re.sub (r"ly:mutable-music-properties",
1901                   "ly:music-mutable-properties", str)
1902     return str
1903
1904
1905 @rule ((2, 2, 0), _ ("bump version for release"))
1906 def conv (str):
1907     return str
1908
1909
1910 @rule ((2, 3, 1), '\\apply -> \\applymusic')
1911 def conv (str):
1912     return re.sub (r'\\apply\b', r'\\applymusic', str)
1913
1914
1915 @rule ((2, 3, 2), '\\FooContext -> \\Foo')
1916 def conv (str):
1917     if re.search ('textheight', str):
1918         stderr_write ('\n')
1919         stderr_write (NOT_SMART % "textheight")
1920         stderr_write ('\n')
1921         stderr_write (UPDATE_MANUALLY)
1922         stderr_write ('\n')
1923         stderr_write (
1924 _ ("""Page layout has been changed, using paper size and margins.
1925 textheight is no longer used.
1926 """))
1927     str = re.sub (r'\\OrchestralScoreContext', '\\Score', str)
1928     def func(m):
1929         if m.group(1) not in ['RemoveEmptyStaff',
1930                               'AncientRemoveEmptyStaffContext',
1931                               'EasyNotation']:
1932             return '\\' + m.group (1)
1933         else:
1934             return m.group (0)
1935
1936
1937     str = re.sub (r'\\([a-zA-Z]+)Context\b', func, str)
1938     str = re.sub ('ly:paper-lookup', 'ly:output-def-lookup', str)
1939     return str
1940
1941
1942 @rule ((2, 3, 4), _ ('remove %s') % '\\notes')
1943 def conv (str):
1944     str = re.sub (r'\\notes\b', '', str)
1945     return str
1946
1947
1948 @rule ((2, 3, 6), 'lastpagefill -> raggedlastbottom')
1949 def conv (str):
1950     str = re.sub (r'lastpagefill\s*=\s*"?1"', 'raggedlastbottom = ##t', str)
1951     return str
1952
1953
1954 @rule ((2, 3, 8), 'remove \\consistsend, strip \\lyrics from \\lyricsto.')
1955 def conv (str):
1956     str = re.sub (r'\\consistsend', '\\consists', str)
1957     str = re.sub (r'\\lyricsto\s+("?[a-zA-Z]+"?)(\s*\\new Lyrics\s*)?\\lyrics',
1958                   r'\\lyricsto \1 \2', str)
1959     return str
1960
1961
1962 @rule ((2, 3, 9), 'neo_mensural -> neomensural, if-text-padding -> bound-padding')
1963 def conv (str):
1964     str = re.sub (r'neo_mensural', 'neomensural', str)
1965     str = re.sub (r'if-text-padding', 'bound-padding', str)
1966     return str
1967
1968
1969 @rule ((2, 3, 10), '\\addlyrics -> \\oldaddlyrics, \\newlyrics -> \\addlyrics')
1970 def conv (str):
1971     str = re.sub (r'\\addlyrics', r'\\oldaddlyrics', str)
1972     str = re.sub (r'\\newlyrics', r'\\addlyrics', str)
1973     if re.search (r"\\override\s*TextSpanner", str):
1974         stderr_write ("\nWarning: TextSpanner has been split into DynamicTextSpanner and TextSpanner\n")
1975     return str
1976
1977
1978 @rule ((2, 3, 11), '\\setMmRestFermata -> ^\\fermataMarkup')
1979 def conv (str):
1980     str = re.sub (r'\\setMmRestFermata\s+(R[0-9.*/]*)',
1981                   r'\1^\\fermataMarkup', str)
1982     return str
1983
1984
1985 @rule ((2, 3, 12), '''\\newpage -> \\pageBreak, junk \\script{up,down,both},
1986 soloADue -> printPartCombineTexts, #notes-to-clusters -> \\makeClusters
1987 ''')
1988 def conv (str):
1989     str = re.sub (r'\\newpage', r'\\pageBreak', str)
1990     str = re.sub (r'\\scriptUp', r"""{
1991 \\override TextScript  #'direction = #1
1992 \\override Script  #'direction = #1
1993 }""", str)
1994     str = re.sub (r'\\scriptDown', r"""{
1995   \\override TextScript  #'direction = #-1
1996   \\override Script  #'direction = #-1
1997 }""", str)
1998     str = re.sub (r'\\scriptBoth', r"""{
1999   \\revert TextScript  #'direction
2000   \\revert Script  #'direction
2001 }""", str)
2002     str = re.sub ('soloADue', 'printPartCombineTexts', str)
2003     str = re.sub (r'\\applymusic\s*#notes-to-clusters',
2004                       '\\makeClusters', str)
2005     
2006     str = re.sub (r'pagenumber\s*=', 'firstpagenumber = ', str)
2007     return str
2008
2009
2010 @rule ((2, 3, 16), _ ('''\\foo -> \\foomode (for chords, notes, etc.)
2011 fold \\new FooContext \\foomode into \\foo.'''))
2012 def conv (str):
2013     str = re.sub (r'\\chords\b', r'\\chordmode', str)
2014     str = re.sub (r'\\lyrics\b', r'\\lyricmode', str)
2015     str = re.sub (r'\\figures\b', r'\\figuremode', str)
2016     str = re.sub (r'\\notes\b', r'\\notemode', str)
2017     str = re.sub (r'\\drums\b', r'\\drummode', str)
2018     str = re.sub (r'\\chordmode\s*\\new ChordNames', r'\\chords', str)
2019     str = re.sub (r'\\new ChordNames\s*\\chordmode', r'\\chords', str)
2020     str = re.sub (r'\\new FiguredBass\s*\\figuremode', r'\\figures', str)
2021     str = re.sub (r'\\figuremode\s*\new FiguredBass', r'\\figures', str)
2022     str = re.sub (r'\\new DrumStaff\s*\\drummode', r'\\drums', str)
2023     str = re.sub (r'\\drummode\s*\\new DrumStaff', r'\\drums', str)
2024
2025     return str
2026
2027
2028 @rule ((2, 3, 17), '''slurBoth -> slurNeutral, stemBoth -> stemNeutral, etc.
2029 \\applymusic #(remove-tag 'foo) -> \\removeWithTag 'foo''')
2030 def conv (str):
2031     str = re.sub (r'(slur|stem|phrasingSlur|tie|dynamic|dots|tuplet|arpeggio|)Both', r'\1Neutral', str)
2032     str = re.sub (r"\\applymusic\s*#\(remove-tag\s*'([a-z-0-9]+)\)",
2033                   r"\\removeWithTag #'\1", str)
2034     return str
2035
2036
2037 @rule ((2, 3, 18), 'Text_item -> Text_interface')
2038 def conv (str):
2039     str = re.sub (r'Text_item', 'Text_interface', str)
2040     return str
2041
2042
2043 @rule ((2, 3, 22), 'paper -> layout, bookpaper -> paper')
2044 def conv (str):
2045     str = re.sub (r'\\paper', r'\\layout', str)
2046     str = re.sub (r'\\bookpaper', r'\\paper', str)
2047     if re.search ('paper-set-staff-size', str):
2048         warning (_ ('''staff size should be changed at top-level
2049 with
2050
2051   #(set-global-staff-size <STAFF-HEIGHT-IN-POINT>)
2052
2053 '''))
2054
2055
2056     str = re.sub (r'#\(paper-set-staff-size', '%Use set-global-staff-size at toplevel\n% #(layout-set-staff-size', str)
2057     return str
2058     
2059
2060 @rule ((2, 3, 23), r'\context Foo = NOTENAME -> \context Foo = "NOTENAME"')
2061 def conv (str):
2062     str = re.sub (r'\\context\s+([a-zA-Z]+)\s*=\s*([a-z]+)\s',
2063                   r'\\context \1 = "\2" ',
2064                   str )
2065     return str
2066
2067
2068 @rule ((2, 3, 24), _ ('''regularize other identifiers'''))
2069 def conv (str):
2070     def sub(m):
2071         return regularize_id (m.group (1))
2072     str = re.sub (r'(maintainer_email|maintainer_web|midi_stuff|gourlay_maxmeasures)',
2073                   sub, str)
2074     return str
2075
2076
2077 @rule ((2, 3, 25), 'petrucci_c1 -> petrucci-c1, 1style -> single-digit')
2078 def conv (str):
2079     str = re.sub ('petrucci_c1', 'petrucci-c1', str)
2080     str = re.sub ('1style', 'single-digit', str)
2081     return str
2082
2083
2084 @rule ((2, 4, 0), _ ("bump version for release"))
2085 def conv (str):
2086     return str
2087
2088
2089 @rule ((2, 5, 0), '\\quote -> \\quoteDuring')
2090 def conv (str):
2091     str = re.sub (r'\\quote\s+"?([a-zA-Z0-9]+)"?\s+([0-9.*/]+)',
2092                   r'\\quoteDuring #"\1" { \skip \2 }',
2093                   str)
2094     return str
2095
2096
2097 @rule ((2, 5, 1), 'ly:import-module -> ly:module-copy')
2098 def conv (str):
2099     str = re.sub (r'ly:import-module',
2100                   r'ly:module-copy', str)
2101     return str
2102
2103
2104 @rule ((2, 5, 2), '\markup .. < .. > .. -> \markup .. { .. } ..')
2105 def conv (str):
2106     str = re.sub (r'\\(column|fill-line|dir-column|center-align|right-align|left-align|bracketed-y-column)\s*<(([^>]|<[^>]*>)*)>',
2107                   r'\\\1 {\2}', str)
2108     str = re.sub (r'\\(column|fill-line|dir-column|center-align|right-align|left-align|bracketed-y-column)\s*<(([^>]|<[^>]*>)*)>',
2109                   r'\\\1 {\2}', str)
2110     str = re.sub (r'\\(column|fill-line|dir-column|center-align|right-align|left-align|bracketed-y-column)\s*<(([^>]|<[^>]*>)*)>',
2111                   r'\\\1 {\2}', str)
2112     def get_markup (m):
2113         s = m.group (0)
2114         s = re.sub (r'''((\\"|})\s*){''', '\2 \\line {', s)
2115         return s
2116     str = re.sub (r'\\markup\s*{([^}]|{[^}]*})*}', get_markup, str)
2117     return str
2118
2119
2120 @rule ((2, 5, 3), 'ly:find-glyph-by-name -> ly:font-get-glyph, remove - from glyphnames.')
2121 def conv (str):
2122     str = re.sub ('ly:find-glyph-by-name', 'ly:font-get-glyph', str)
2123     str = re.sub ('"(scripts|clefs|accidentals)-', r'"\1.', str)
2124     str = re.sub ("'hufnagel-do-fa", "'hufnagel.do.fa", str)
2125     str = re.sub ("'(vaticana|hufnagel|medicaea|petrucci|neomensural|mensural)-", r"'\1.", str)
2126     return str
2127
2128
2129 @rule ((2, 5, 12), '\set Slur #\'dashed = #X -> \slurDashed')
2130 def conv (str):
2131     str = re.sub (r"\\override\s+(Voice\.)?Slur #'dashed\s*=\s*#\d*(\.\d+)?",
2132                   r"\\slurDashed", str)
2133     return str
2134
2135
2136 @rule ((2, 5, 13), _ ('\\encoding: smart recode latin1..utf-8. Remove ly:point-and-click'))
2137 def conv (str):
2138     input_encoding = 'latin1'
2139     def func (match):
2140         encoding = match.group (1)
2141
2142         # FIXME: automatic recoding of other than latin1?
2143         if encoding == 'latin1':
2144             return match.group (2)
2145
2146         stderr_write ('\n')
2147         stderr_write (NOT_SMART % ("\\encoding: %s" % encoding))
2148         stderr_write ('\n')
2149         stderr_write (_ ("LilyPond source must be UTF-8"))
2150         stderr_write ('\n')
2151         if encoding == 'TeX':
2152             stderr_write (_ ("Try the texstrings backend"))
2153             stderr_write ('\n')
2154         else:
2155             stderr_write ( _("Do something like: %s") % \
2156                                ("recode %s..utf-8 FILE" % encoding))
2157             stderr_write ('\n')
2158         stderr_write (_ ("Or save as UTF-8 in your editor"))
2159         stderr_write ('\n')
2160         raise FatalConversionError ()
2161
2162         return match.group (0)
2163
2164     str = re.sub (r'\\encoding\s+"?([a-zA-Z0-9]+)"?(\s+)', func, str)
2165
2166     import codecs
2167     de_ascii = codecs.getdecoder ('ascii')
2168     de_utf_8 = codecs.getdecoder ('utf_8')
2169     de_input = codecs.getdecoder (input_encoding)
2170     en_utf_8 = codecs.getencoder ('utf_8')
2171     try:
2172         de_ascii (str)
2173     # only in python >= 2.3
2174     # except UnicodeDecodeError:
2175     except UnicodeError:
2176         # do not re-recode UTF-8 input
2177         try:
2178             de_utf_8 (str)
2179         #except UnicodeDecodeError:
2180         except UnicodeError:
2181             str = en_utf_8 (de_input (str)[0])[0]
2182
2183
2184
2185     str = re.sub (r"#\(ly:set-point-and-click '[a-z-]+\)", '', str)
2186     return str
2187
2188
2189 @rule ((2, 5, 17), _ ('remove %s') % 'ly:stencil-set-extent!')
2190 def conv (str):
2191     if re.search ("ly:stencil-set-extent!", str):
2192         stderr_write ('\n')
2193         stderr_write (NOT_SMART % "ly:stencil-set-extent!")
2194         stderr_write ('\n')
2195         stderr_write ('use (set! VAR (ly:make-stencil (ly:stencil-expr VAR) X-EXT Y-EXT))\n')
2196         raise FatalConversionError ()
2197     if re.search ("ly:stencil-align-to!", str):
2198         stderr_write ('\n')
2199         stderr_write (NOT_SMART % "ly:stencil-align-to!")
2200         stderr_write ('\n')
2201         stderr_write ('use (set! VAR (ly:stencil-aligned-to VAR AXIS DIR))\n')
2202         raise FatalConversionError ()
2203     return str
2204
2205
2206 @rule ((2, 5, 18), 'ly:warn -> ly:warning')
2207 def conv (str):
2208     str = re.sub (r"ly:warn\b", 'ly:warning', str)
2209     return str
2210
2211
2212 @rule ((2, 5, 21), _ ('warn about auto beam settings'))
2213 def conv (str):
2214     if re.search ("(override-|revert-)auto-beam-setting", str)\
2215        or re.search ("autoBeamSettings", str):
2216         stderr_write ('\n')
2217         stderr_write (NOT_SMART % _ ("auto beam settings"))
2218         stderr_write ('\n')
2219         stderr_write (_ ('''
2220 Auto beam settings must now specify each interesting moment in a measure
2221 explicitly; 1/4 is no longer multiplied to cover moments 1/2 and 3/4 too.
2222 '''))
2223         stderr_write (UPDATE_MANUALLY)
2224         stderr_write ('\n')
2225         raise FatalConversionError ()
2226     return str
2227
2228
2229 @rule ((2, 5, 25), 'unfoldrepeats -> unfoldRepeats, compressmusic -> compressMusic')
2230 def conv (str):
2231     str = re.sub (r"unfoldrepeats", 'unfoldRepeats', str)
2232     str = re.sub (r"compressmusic", 'compressMusic', str)
2233     return str
2234
2235
2236 @rule ((2, 6, 0), _ ("bump version for release"))
2237 def conv (str):
2238     return str
2239
2240
2241 @rule ((2, 7, 0), 'ly:get-default-font -> ly:grob-default-font')
2242 def conv (str):
2243     return re.sub('ly:get-default-font', 'ly:grob-default-font', str) 
2244
2245
2246 @rule ((2, 7, 1), '''ly:parser-define -> ly:parser-define!
2247 excentricity -> eccentricity
2248 Timing_engraver -> Timing_translator + Default_bar_line_engraver
2249 ''')
2250 def conv (str):
2251     str = re.sub('ly:parser-define', 'ly:parser-define!', str)
2252     str = re.sub('excentricity', 'eccentricity', str)
2253     str = re.sub(r'\\(consists|remove) *"?Timing_engraver"?',
2254                  r'\\\1 "Timing_translator" \\\1 "Default_bar_line_engraver"',
2255                  str)
2256     return str
2257
2258
2259 @rule ((2, 7, 2), 'ly:X-moment -> ly:moment-X')
2260 def conv (str):
2261     str = re.sub('ly:(add|mul|mod|div)-moment', r'ly:moment-\1', str)
2262     return str
2263
2264
2265 @rule ((2, 7, 4), 'keyAccidentalOrder -> keyAlterationOrder')
2266 def conv (str):
2267     str = re.sub('keyAccidentalOrder', 'keyAlterationOrder', str)
2268     return str
2269
2270
2271 @rule ((2, 7, 6), '''Performer_group_performer -> Performer_group, Engraver_group_engraver -> Engraver_group,
2272 inside-slur -> avoid-slur''')
2273 def conv (str):
2274     str = re.sub('Performer_group_performer', 'Performer_group', str)
2275     str = re.sub('Engraver_group_engraver', 'Engraver_group', str)
2276     str = re.sub (r"#'inside-slur\s*=\s*##t *",
2277                   r"#'avoid-slur = #'inside ", str)
2278     str = re.sub (r"#'inside-slur\s*=\s*##f *",
2279                   r"#'avoid-slur = #'around ", str)
2280     str = re.sub (r"#'inside-slur",
2281                   r"#'avoid-slur", str)
2282     return str
2283
2284
2285 @rule ((2, 7, 10), '\\applyxxx -> \\applyXxx')
2286 def conv (str):
2287     str = re.sub(r'\\applyoutput', r'\\applyOutput', str)
2288     str = re.sub(r'\\applycontext', r'\\applyContext', str)
2289     str = re.sub(r'\\applymusic',  r'\\applyMusic', str)
2290     str = re.sub(r'ly:grob-suicide', 'ly:grob-suicide!', str)
2291     return str
2292
2293
2294 @rule ((2, 7, 11), '"tabloid" -> "11x17"')
2295 def conv (str):
2296     str = re.sub(r'\"tabloid\"', '"11x17"', str)
2297     return str
2298
2299
2300 @rule ((2, 7, 12), 'outputProperty -> overrideProperty')
2301 def conv (str):
2302     str = re.sub(r'outputProperty' , 'overrideProperty', str)
2303     return str
2304
2305
2306 @rule ((2, 7, 13), 'layout engine refactoring [FIXME]')
2307 def conv (str):
2308     def subber (match):
2309         newkey = {'spacing-procedure': 'springs-and-rods',
2310                   'after-line-breaking-callback' : 'after-line-breaking',
2311                   'before-line-breaking-callback' : 'before-line-breaking',
2312                   'print-function' : 'stencil'} [match.group(3)]
2313         what = match.group (1)
2314         grob = match.group (2)
2315
2316         if what == 'revert':
2317             return "revert %s #'callbacks %% %s\n" % (grob, newkey)
2318         elif what == 'override':
2319             return "override %s #'callbacks #'%s" % (grob, newkey)
2320         else:
2321             raise 'urg'
2322             return ''
2323
2324     str = re.sub(r"(override|revert)\s*([a-zA-Z.]+)\s*#'(spacing-procedure|after-line-breaking-callback"
2325                 + r"|before-line-breaking-callback|print-function)",
2326                 subber, str)
2327
2328     if re.search ('bar-size-procedure', str):
2329         stderr_write (NOT_SMART % "bar-size-procedure")
2330     if re.search ('space-function', str):
2331         stderr_write (NOT_SMART % "space-function")
2332     if re.search ('verticalAlignmentChildCallback', str):
2333         stderr_write (_ ('verticalAlignmentChildCallback has been deprecated'))
2334     return str
2335
2336
2337 @rule ((2, 7, 14), _ ('Remove callbacks property, deprecate XY-extent-callback.'))
2338 def conv (str):
2339     str = re.sub (r"\\override +([A-Z.a-z]+) #'callbacks",
2340                   r"\\override \1", str)
2341     str = re.sub (r"\\revert ([A-Z.a-z]+) #'callbacks % ([a-zA-Z]+)",
2342                   r"\\revert \1 #'\2", str)
2343     str = re.sub (r"([XY]-extent)-callback", r'\1', str)
2344     str = re.sub (r"RemoveEmptyVerticalGroup", "VerticalAxisGroup", str)
2345     str = re.sub (r"\\set ([a-zA-Z]*\.?)minimumVerticalExtent",
2346                   r"\\override \1VerticalAxisGroup #'minimum-Y-extent",
2347                   str)
2348     str = re.sub (r"minimumVerticalExtent",
2349                   r"\\override VerticalAxisGroup #'minimum-Y-extent",
2350                   str)
2351     str = re.sub (r"\\set ([a-zA-Z]*\.?)extraVerticalExtent",
2352                   r"\\override \1VerticalAxisGroup #'extra-Y-extent", str)
2353     str = re.sub (r"\\set ([a-zA-Z]*\.?)verticalExtent",
2354                   r"\\override \1VerticalAxisGroup #'Y-extent", str)
2355     return str
2356
2357
2358 @rule ((2, 7, 15), _ ('Use grob closures iso. XY-offset-callbacks.'))
2359 def conv (str):
2360     if re.search ('[XY]-offset-callbacks', str):
2361         stderr_write (NOT_SMART % "[XY]-offset-callbacks")
2362     if re.search ('position-callbacks', str):
2363         stderr_write (NOT_SMART % "position-callbacks")
2364     return str
2365
2366
2367 @rule ((2, 7, 22), r"\tag #'(a b) -> \tag #'a \tag #'b")
2368 def conv (str):
2369     def sub_syms (m):
2370         syms =  m.group (1).split ()
2371         tags = ["\\tag #'%s" % s for s in syms]
2372         return ' '.join (tags)
2373
2374     str = re.sub (r"\\tag #'\(([^)]+)\)",  sub_syms, str)
2375     return str
2376
2377
2378 @rule ((2, 7, 24), _ ('deprecate %s') % 'number-visibility')
2379 def conv (str):
2380     str = re.sub (r"#'number-visibility",
2381                   "#'number-visibility % number-visibility is deprecated. Tune the TupletNumber instead\n",
2382                   str)
2383     return str
2384
2385
2386 @rule ((2, 7, 28), "ly:spanner-get-bound -> ly:spanner-bound")
2387 def conv (str):
2388     str = re.sub (r"ly:spanner-get-bound", "ly:spanner-bound", str)
2389     return str
2390
2391
2392 @rule ((2, 7, 29), "override Stem #'beamed-* -> #'details #'beamed-*")
2393 def conv (str):
2394     for a in ['beamed-lengths', 'beamed-minimum-free-lengths',
2395               'lengths',
2396               'beamed-extreme-minimum-free-lengths']:
2397         str = re.sub (r"\\override\s+Stem\s+#'%s" % a,
2398                       r"\\override Stem #'details #'%s" % a,
2399                       str)
2400     return str
2401
2402
2403 @rule ((2, 7, 30), "\\epsfile")
2404 def conv (str):
2405     str = re.sub (r'\\epsfile *#"', r'\\epsfile #X #10 #"', str)
2406     return str
2407
2408
2409 @rule ((2, 7, 31), "Foo_bar::bla_bla -> ly:foo-bar::bla-bla")
2410 def conv (str):
2411     def sub_cxx_id (m):
2412         str = m.group(1)
2413         return 'ly:' + str.lower ().replace ('_','-')
2414
2415     str = re.sub (r'([A-Z][a-z_0-9]+::[a-z_0-9]+)',
2416                   sub_cxx_id, str)
2417     return str
2418
2419
2420 @rule ((2, 7, 32), _ ("foobar -> foo-bar for \paper, \layout"))
2421 def conv (str):
2422     identifier_subs = [
2423             ('inputencoding', 'input-encoding'),
2424             ('printpagenumber', 'print-page-number'),
2425             ('outputscale', 'output-scale'),
2426             ('betweensystemspace', 'between-system-space'),
2427             ('betweensystempadding', 'between-system-padding'),
2428             ('pagetopspace', 'page-top-space'),
2429             ('raggedlastbottom', 'ragged-last-bottom'),
2430             ('raggedright', 'ragged-right'),
2431             ('raggedlast', 'ragged-last'),
2432             ('raggedbottom', 'ragged-bottom'),
2433             ('aftertitlespace', 'after-title-space'),
2434             ('beforetitlespace', 'before-title-space'),
2435             ('betweentitlespace', 'between-title-space'),
2436             ('topmargin', 'top-margin'),
2437             ('bottommargin', 'bottom-margin'),
2438             ('headsep', 'head-separation'),
2439             ('footsep', 'foot-separation'),
2440             ('rightmargin', 'right-margin'),
2441             ('leftmargin', 'left-margin'),
2442             ('printfirstpagenumber', 'print-first-page-number'),
2443             ('firstpagenumber', 'first-page-number'),
2444             ('hsize', 'paper-width'),
2445             ('vsize', 'paper-height'),
2446             ('horizontalshift', 'horizontal-shift'),
2447             ('staffspace', 'staff-space'),
2448             ('linethickness', 'line-thickness'),
2449             ('ledgerlinethickness', 'ledger-line-thickness'),
2450             ('blotdiameter', 'blot-diameter'),
2451             ('staffheight', 'staff-height'),
2452             ('linewidth', 'line-width'),
2453             ('annotatespacing', 'annotate-spacing')
2454             ]
2455
2456     for (a,b)  in identifier_subs:
2457         ### for C++:
2458         ## str = re.sub ('"%s"' % a, '"%s"' b, str)
2459
2460         str = re.sub (a, b, str)
2461     return str
2462
2463
2464 @rule ((2, 7, 32), "debug-beam-quanting -> debug-beam-scoring")
2465 def conv (str):
2466     str = re.sub ('debug-beam-quanting', 'debug-beam-scoring', str)
2467     return str
2468
2469
2470 @rule ((2, 7, 36), "def-(music-function|markup-command) -> define-(music-function|markup-command)")
2471 def conv (str):
2472     str = re.sub ('def-music-function', 'define-music-function', str)
2473     str = re.sub ('def-markup-command', 'define-markup-command', str)
2474     return str
2475
2476
2477 @rule ((2, 7, 40), "rehearsalMarkAlignSymbol/barNumberAlignSymbol -> break-align-symbol")
2478 def conv (str):
2479     str = re.sub (r'\\set\s+Score\s*\.\s*barNumberAlignSymbol\s*=',
2480                   r"\\override Score.BarNumber #'break-align-symbol = ", str)
2481     str = re.sub (r'\\set\s*Score\s*\.\s*rehearsalMarkAlignSymbol\s*=',
2482                   r"\\override Score.RehearsalMark #'break-align-symbol = ", str)
2483     return str
2484
2485
2486 @rule ((2, 9, 4), "(page-)penalty -> (page-)break-penalty")
2487 def conv (str):
2488     str = re.sub ('page-penalty', 'page-break-penalty', str)
2489     str = re.sub ('([^-])penalty', '\1break-penalty', str)
2490     return str
2491
2492
2493 @rule ((2, 9, 6), "\\context Foo \\applyOutput #bla -> \\applyOutput #'Foo #bla ")
2494 def conv (str):
2495     str = re.sub (r'\\context\s+\"?([a-zA-Z]+)\"?\s*\\applyOutput', r"\\applyOutput #'\1", str)
2496     return str
2497
2498
2499 @rule ((2, 9, 9), "annotatefoo -> annotate-foo")
2500 def conv (str):
2501     str = re.sub ('annotatepage', 'annotate-page', str)
2502     str = re.sub ('annotateheaders', 'annotate-headers', str)
2503     str = re.sub ('annotatesystems', 'annotate-systems', str)
2504     return str
2505
2506
2507 @rule ((2, 9, 11), "\\set tupletNumberFormatFunction -> \\override #'text = ")
2508 def conv (str):
2509     str = re.sub (r"""(\\set\s)?(?P<context>[a-zA-Z]*.?)tupletNumberFormatFunction\s*=\s*#denominator-tuplet-formatter""",
2510                   r"""\\override \g<context>TupletNumber #'text = #tuplet-number::calc-denominator-text""", str)
2511
2512     str = re.sub (r"""(\\set\s+)?(?P<context>[a-zA-Z]*.?)tupletNumberFormatFunction\s*=\s*#fraction-tuplet-formatter""",
2513                   r"""\\override \g<context>TupletNumber #'text = #tuplet-number::calc-fraction-text""", str)
2514
2515     if re.search ('tupletNumberFormatFunction', str):
2516         stderr_write ("\n")
2517         stderr_write ("tupletNumberFormatFunction has been removed. Use #'text property on TupletNumber")
2518         stderr_write ("\n")
2519     return str
2520
2521
2522 @rule ((2, 9, 13), "instrument -> instrumentName, instr -> shortInstrumentName, vocNam -> shortVocalName")
2523 def conv (str):
2524     str = re.sub ('vocNam', 'shortVocalName', str)
2525     str = re.sub (r'\.instr\s*=', r'.shortInstrumentName =', str)
2526     str = re.sub (r'\.instrument\s*=', r'.instrumentName =', str)
2527     return str
2528
2529
2530 @rule ((2, 9, 16), _ ("deprecate \\tempo in \\midi"))
2531 def conv (str):
2532
2533     def sub_tempo (m):
2534         dur = int (m.group (1))
2535         dots = len (m.group (2))
2536         count = int (m.group (3))
2537
2538         log2 = 0
2539         while dur > 1 :
2540             dur /= 2
2541             log2 += 1
2542         
2543         den = (1 << dots) * (1 << log2)
2544         num = ((1 << (dots+1))  - 1)
2545
2546         return  """
2547   \midi {
2548     \context {
2549       \Score
2550       tempoWholesPerMinute = #(ly:make-moment %d %d)
2551       }
2552     }
2553
2554 """ % (num*count, den)
2555     
2556     str = re.sub (r'\\midi\s*{\s*\\tempo ([0-9]+)\s*([.]*)\s*=\s*([0-9]+)\s*}', sub_tempo, str)
2557     return str
2558
2559
2560 @rule ((2, 9, 19), "printfirst-page-number -> print-first-page-number")
2561 def conv (str):
2562     str = re.sub ('printfirst-page-number', 'print-first-page-number', str)
2563     return str
2564
2565
2566 @rule ((2, 10, 0), _ ("bump version for release"))
2567 def conv (str):
2568     return str
2569
2570
2571 @rule ((2, 11, 2), "ly:clone-parser -> ly:parser-clone")
2572 def conv (str):
2573     return re.sub ('ly:clone-parser',
2574                    'ly:parser-clone', str)
2575
2576 @rule ((2, 11, 3), "no-spacing-rods -> extra-spacing-width")
2577 def conv (str):
2578     str = re.sub (r"no-spacing-rods\s+=\s+##t", r"extra-spacing-width = #'(+inf.0 . -inf.0)", str)
2579     str = re.sub (r"no-spacing-rods\s+=\s+##f", r"extra-spacing-width = #'(0 . 0)", str)
2580     return str
2581
2582
2583 @rule ((2, 11, 5), _ ("deprecate cautionary-style. Use AccidentalCautionary properties"))
2584 def conv (str):
2585     str = re.sub ("Accidental\s*#'cautionary-style\s*=\s*#'smaller",
2586                    "AccidentalCautionary #'font-size = #-2", str)
2587     str = re.sub ("Accidental\s*#'cautionary-style\s*=\s*#'parentheses",
2588                    "AccidentalCautionary #'parenthesized = ##t", str)
2589     str = re.sub ("([A-Za-z]+)\s*#'cautionary-style\s*=\s*#'parentheses",
2590                    r"\1 #'parenthesized = ##t", str)
2591     str = re.sub ("([A-Za-z]+)\s*#'cautionary-style\s*=\s*#'smaller",
2592                    r"\1 #'font-size = #-2", str)
2593     return str
2594
2595
2596 @rule ((2, 11, 6), _ ("Rename accidental glyphs, use glyph-name-alist."))
2597 def conv (str):
2598     
2599     def sub_acc_name (m):
2600         idx = int (m.group (1).replace ('M','-'))
2601         
2602         return ["accidentals.doublesharp",
2603                 "accidentals.sharp.slashslash.stemstemstem",
2604                 "accidentals.sharp",
2605                 "accidentals.sharp.slashslash.stem",
2606                 "accidentals.natural",
2607                 "accidentals.mirroredflat",
2608                 "accidentals.flat",
2609                 "accidentals.mirroredflat.flat",
2610                 "accidentals.flatflat"][4-idx]
2611
2612     str = re.sub (r"accidentals[.](M?[-0-9]+)",
2613                   sub_acc_name, str) 
2614     str = re.sub (r"(KeySignature|Accidental[A-Za-z]*)\s*#'style\s*=\s*#'([a-z]+)",
2615                   r"\1 #'glyph-name-alist = #alteration-\2-glyph-name-alist", str)
2616     ## FIXME: standard vs default, alteration-FOO vs FOO-alteration
2617     str = str.replace ('alteration-default-glyph-name-alist',
2618                        'standard-alteration-glyph-name-alist')
2619     return str
2620
2621
2622 @rule ((2, 11, 10), """allowBeamBreak -> Beam #'breakable = ##t
2623 addquote -> addQuote
2624 """)
2625 def conv (str):
2626     str = re.sub (r'(\\set\s+)?([A-Z][a-zA-Z]+\s*\.\s*)allowBeamBreak',
2627                   r"\override \2Beam #'breakable", str)
2628     str = re.sub (r'(\\set\s+)?allowBeamBreak',
2629                   r"\override Beam #'breakable", str)
2630     str = re.sub (r'addquote', 'addQuote', str)
2631     if re.search ("Span_dynamic_performer", str):
2632         stderr_write ("Span_dynamic_performer has been merged into Dynamic_performer")
2633
2634     return str
2635
2636
2637 @rule ((2, 11, 11), "layout-set-staff-size -> layout-set-absolute-staff-size")
2638 def conv (str):
2639     str = re.sub (r'\(layout-set-staff-size \(\*\s*([0-9.]+)\s*(pt|mm|cm)\)\)',
2640                   r'(layout-set-absolute-staff-size (* \1 \2))', str)
2641     return str
2642
2643
2644 @rule ((2, 11, 13), "#'arrow = ##t -> #'bound-details #'right #'arrow = ##t")
2645 def conv (str):
2646     str = re.sub (r"\\override\s*([a-zA-Z.]+)\s*#'arrow\s*=\s*##t",
2647                   r"\\override \1 #'bound-details #'right #'arrow = ##t",
2648                   str)
2649
2650     if re.search ('edge-text', str):
2651         stderr_write (NOT_SMART % _ ("edge-text settings for TextSpanner."))
2652         stderr_write (_ ("Use\n\n%s") %
2653                           "\t\\override TextSpanner #'bound-details #'right #'text = <right-text>\n"
2654                           "\t\\override TextSpanner #'bound-details #'left #'text = <left-text>\n")
2655     return str
2656
2657
2658 @rule ((2, 11, 15), "TextSpanner #'edge-height -> #'bound-details #'right/left #'text = ...")
2659 def conv (str):
2660     def sub_edge_height (m):
2661         s = ''
2662         for (var, h) in [('left', m.group (3)),
2663                          ('right', m.group (4))]:
2664
2665             if h and float (h):
2666                 once = m.group (1)
2667                 if not once:
2668                     once = ''
2669                 context = m.group (2)
2670                 if not context:
2671                     context = ''
2672                     
2673                 s += (r"%s \override %sTextSpanner #'bound-details #'%s #'text = \markup { \draw-line #'(0 . %s) }"
2674                       % (once, context, var, h))
2675
2676                 s += '\n'
2677             
2678         return s
2679     
2680                   
2681     str = re.sub (r"(\\once)?\s*\\override\s*([a-zA-Z]+\s*[.]\s*)?TextSpanner\s*#'edge-height\s*=\s*#'\(\s*([0-9.-]+)\s+[.]\s+([0-9.-]+)\s*\)", sub_edge_height, str)
2682     return str
2683
2684
2685 @rule ((2, 11, 23), "#'break-align-symbol -> #'break-align-symbols")
2686 def conv (str):
2687     str = re.sub (r"\\override\s*([a-zA-Z.]+)\s*#'break-align-symbol\s*=\s*#'([a-z-]+)",
2688                   r"\\override \1 #'break-align-symbols = #'(\2)", str)
2689     return str
2690
2691
2692 @rule ((2, 11, 35), """scripts.caesura -> scripts.caesura.curved.
2693 """ + _ ("Use #'style not #'dash-fraction to select solid/dashed lines."))
2694 def conv (str):
2695     str = re.sub (r"scripts\.caesura",
2696                   r"scripts.caesura.curved", str)
2697
2698     if re.search ('dash-fraction', str):
2699         stderr_write (NOT_SMART % _ ("all settings related to dashed lines.\n"))
2700         stderr_write (_ ("Use \\override ... #'style = #'line for solid lines and\n"))
2701         stderr_write (_ ("\t\\override ... #'style = #'dashed-line for dashed lines."))
2702     return str
2703
2704
2705 @rule ((2, 11, 38), """\\setEasyHeads -> \\easyHeadsOn, \\fatText -> \\textLengthOn,
2706 \\emptyText -> \\textLengthOff""")
2707 def conv (str):
2708     str = re.sub (r"setEasyHeads", r"easyHeadsOn", str)
2709     str = re.sub (r"fatText", r"textLengthOn", str)
2710     str = re.sub (r"emptyText", r"textLengthOff", str)
2711     return str
2712
2713
2714 @rule ((2, 11, 46), "\\set hairpinToBarline -> \\override Hairpin #'to-barline")
2715 def conv (str):
2716     str = re.sub (r"\\set\s+([a-zA-Z]+)\s*.\s*hairpinToBarline\s*=\s*##([tf]+)",
2717                   r"\\override \1.Hairpin #'to-barline = ##\2", str)
2718     str = re.sub (r"\\set\s+hairpinToBarline\s*=\s*##([tf]+)",
2719                   r"\\override Hairpin #'to-barline = ##\1", str)
2720     str = re.sub (r"\\unset\s+([a-zA-Z]+)\s*.\s*hairpinToBarline",
2721                   r"\\revert \1.Hairpin #'to-barline", str)
2722     str = re.sub (r"\\unset\s+hairpinToBarline",
2723                   r"\\revert Hairpin #'to-barline", str)
2724     str = re.sub (r"hairpinToBarline\s*=\s*##([tf]+)",
2725                   r"\\override Hairpin #'to-barline = ##\1", str)
2726     str = re.sub (r"\\set (de|)crescendoSpanner = #'dashed-line",
2727                   r"\\set \1crescendoSpanner = #'text", str)
2728     return str
2729
2730
2731 @rule ((2, 11, 48), "\\compressMusic -> \\scaleDurations")
2732 def conv (str):
2733     str = re.sub (r"compressMusic", r"scaleDurations", str)
2734     return str
2735
2736
2737 @rule ((2, 11, 50), _ ("metronomeMarkFormatter uses text markup as second argument,\n\
2738 fret diagram properties moved to fret-diagram-details."))
2739 def conv (str):
2740     ## warning 1/2: metronomeMarkFormatter uses text markup as second argument
2741     if re.search ('metronomeMarkFormatter', str):
2742         stderr_write (NOT_SMART % _ ("metronomeMarkFormatter got an additional text argument.\n"))
2743         stderr_write (_ ("The function assigned to Score.metronomeMarkFunction now uses the signature\n%s") %
2744                           "\t(format-metronome-markup text dur count context)\n")
2745
2746     ## warning 2/2: fret diagram properties moved to fret-diagram-details
2747     fret_props = ['barre-type', 
2748                 'dot-color', 
2749                 'dot-radius',
2750                 'finger-code',
2751                 'fret-count',
2752                 'label-dir',
2753                 'number-type',
2754                 'string-count',
2755                 'xo-font-magnification',
2756                 'mute-string',
2757                 'open-string',
2758                 'orientation']
2759     for prop in fret_props:
2760       if re.search (prop, str):
2761           stderr_write (NOT_SMART %
2762             prop + " in fret-diagram properties. Use fret-diagram-details.")
2763           stderr_write ('\n')
2764     return str
2765
2766 @rule ((2, 11, 51), "\\octave -> \\octaveCheck, \\arpeggioUp -> \\arpeggioArrowUp,\n\
2767 \\arpeggioDown -> \\arpeggioArrowDown, \\arpeggioNeutral -> \\arpeggioNormal,\n\
2768 \\setTextCresc -> \\crescTextCresc, \\setTextDecresc -> \\dimTextDecresc,\n\
2769 \\setTextDecr -> \\dimTextDecr, \\setTextDim -> \\dimTextDim,\n\
2770 \\setHairpinCresc -> \\crescHairpin, \\setHairpinDecresc -> \\dimHairpin,\n\
2771 \\sustainUp -> \\sustainOff, \\sustainDown -> \\sustainOn\n\
2772 \\sostenutoDown -> \\sostenutoOn, \\sostenutoUp -> \\sostenutoOff")
2773 def conv (str):
2774     str = re.sub (r"\\octave(?![a-zA-Z])", r"\\octaveCheck", str)
2775     str = re.sub (r"arpeggioUp", r"arpeggioArrowUp", str)
2776     str = re.sub (r"arpeggioDown", r"arpeggioArrowDown", str)
2777     str = re.sub (r"arpeggioNeutral", r"arpeggioNormal", str)
2778     str = re.sub (r"setTextCresc", r"crescTextCresc", str)
2779     str = re.sub (r"setTextDecresc", r"dimTextDecresc", str)
2780     str = re.sub (r"setTextDecr", r"dimTextDecr", str)
2781     str = re.sub (r"setTextDim", r"dimTextDim", str)
2782     str = re.sub (r"setHairpinCresc", r"crescHairpin", str)
2783     str = re.sub (r"setHairpinDecresc", r"dimHairpin", str)
2784     str = re.sub (r"sustainUp", r"sustainOff", str)
2785     str = re.sub (r"sustainDown", r"sustainOn", str)
2786     str = re.sub (r"sostenutoDown", r"sostenutoOn", str)
2787     str = re.sub (r"sostenutoUp", r"sostenutoOff", str)
2788     return str
2789
2790 @rule ((2, 11, 52), "\\setHairpinDim -> \\dimHairpin")
2791 def conv (str):
2792     str = str.replace ("setHairpinDim", "dimHairpin")
2793     return str
2794
2795 @rule ((2, 11, 53), "infinite-spacing-height -> extra-spacing-height")
2796 def conv (str):
2797     str = re.sub (r"infinite-spacing-height\s+=\s+##t", r"extra-spacing-height = #'(-inf.0 . +inf.0)", str)
2798     str = re.sub (r"infinite-spacing-height\s+=\s+##f", r"extra-spacing-height = #'(0 . 0)", str)
2799     return str
2800
2801 @rule ((2, 11, 55), "#(set-octavation oct) -> \\ottava #oct,\n\
2802 \\put-adjacent markup axis dir markup -> \\put-adjacent axis dir markup markup")
2803 def conv (str):    
2804     str = re.sub (r"#\(set-octavation (-*[0-9]+)\)", r"\\ottava #\1", str)
2805     if re.search ('put-adjacent', str):
2806         stderr_write (NOT_SMART % _ ("\\put-adjacent argument order.\n"))
2807         stderr_write (_ ("Axis and direction now come before markups:\n"))
2808         stderr_write (_ ("\\put-adjacent axis dir markup markup."))
2809     return str
2810
2811 @rule ((2, 11, 57), "\\center-align -> \\center-column, \\hcenter -> \\center-align")
2812 def conv (str):
2813     str = re.sub (r"([\\:]+)center-align", r"\1center-column", str)
2814     str = re.sub (r"hcenter(\s+)", r"center-align\1", str)
2815     return str
2816
2817 @rule ((2, 11, 60), "printallheaders -> print-all-headers")
2818 def conv (str):
2819     str = re.sub (r"printallheaders", r"print-all-headers", str)
2820     return str
2821
2822 @rule ((2, 11, 61), "gregorian-init.ly -> gregorian.ly")
2823 def conv (str):
2824     str = re.sub (r'\\include(\s+)"gregorian-init.ly"', r'\\include\1"gregorian.ly"', str)
2825     return str
2826
2827 @rule ((2, 11, 62), "makam-init.ly -> makam.ly, \\bigger -> \\larger")
2828 def conv (str):
2829     str = re.sub (r'\\include(\s+)"makam-init.ly"', r'\\include\1"makam.ly"', str)
2830     str = re.sub (r"([\\:])bigger", r"\1larger", str)
2831     return str
2832
2833 @rule ((2, 11, 64), "systemSeparatorMarkup -> system-separator-markup,\n\
2834 InnerStaffGroup -> StaffGroup, InnerChoirStaff -> ChoirStaff")
2835 def conv (str):
2836     str = re.sub (r'systemSeparatorMarkup', r'system-separator-markup', str)
2837     if re.search (r'\\InnerStaffGroup', str):
2838         stderr_write ("\n")
2839         stderr_write (NOT_SMART % _("re-definition of InnerStaffGroup.\n"))
2840         stderr_write (FROM_TO % ("InnerStaffGroup", "StaffGroup.\n"))
2841         stderr_write (UPDATE_MANUALLY)
2842         raise FatalConversionError ()
2843     if re.search (r'\\InnerChoirStaff', str):
2844         stderr_write ("\n")
2845         stderr_write (NOT_SMART % _("re-definition of InnerChoirStaff.\n"))
2846         stderr_write (FROM_TO % ("InnerChoirStaff", "ChoirStaff.\n"))
2847         stderr_write (UPDATE_MANUALLY)
2848         raise FatalConversionError ()
2849     else:
2850         str = re.sub ('InnerStaffGroup', 'StaffGroup', str)
2851         str = re.sub ('InnerChoirStaff', 'ChoirStaff', str)
2852     return str
2853
2854 @rule ((2, 12, 0),
2855        _ ("Syntax changes for \\addChordShape and \\chord-shape") + "\n" + \
2856        _ ("bump version for release"))
2857 def conv(str):
2858     if re.search(r'\\addChordShape', str):
2859         stderr_write ("\n")
2860         stderr_write (NOT_SMART % _("stringTuning must be added to \
2861 addChordShape call.\n"))
2862         stderr_write (UPDATE_MANUALLY)
2863         raise FatalConversionError ()
2864     if re.search (r'\\chord-shape', str):
2865         stderr_write ("\n")
2866         stderr_write (NOT_SMART % _("stringTuning must be added to \
2867 chord-shape call.\n"))
2868         stderr_write (UPDATE_MANUALLY)
2869         raise FatalConversionError ()
2870     return str
2871
2872 @rule ((2,12,3),
2873     _ ("Remove oldaddlyrics"))
2874 def conv(str):
2875     if re.search(r'\\oldaddlyrics', str):
2876         stderr_write ("\n")
2877         stderr_write (NOT_SMART % _("oldaddlyrics is no longer supported. \n \
2878         Use addlyrics or lyrsicsto instead.\n"))
2879         stderr_write (UPDATE_MANUALLY)
2880         raise FatalConversionError ()
2881     return str
2882
2883 @rule ((2, 13, 0), _ ("keySignature property not reversed any more\n\
2884 MIDI 47: orchestral strings -> orchestral harp"))
2885 def conv(str):
2886     if re.search(r'\set Staff.keySignature', str):
2887         stderr_write ("\n")
2888         stderr_write (NOT_SMART % _("The alist for Staff.keySignature is no \
2889 longer in reversed order.\n"))
2890     str = str.replace('"orchestral strings"', '"orchestral harp"')
2891     return str
2892
2893 @rule ((2, 13, 1),
2894        _ ("\\bar \".\" now produces a thick barline\n\
2895 ly:hairpin::after-line-breaking -> ly:spanner::kill-zero-spanned-time\n\
2896 Dash parameters for slurs and ties are now in dash-definition"))
2897 def conv(str):
2898     if re.search(r'\\bar\s*"."', str):
2899         stderr_write ("\n")
2900         stderr_write (NOT_SMART % _("\\bar \".\" now produces a thick barline.\n"))
2901         stderr_write (UPDATE_MANUALLY)
2902     str = re.sub (r'ly:hairpin::after-line-breaking', r'ly:spanner::kill-zero-spanned-time', str)
2903     if re.search("(Slur|Tie)\w+#\'dash-fraction", str) \
2904         or re.search("(Slur|Tie)\w+#\'dash-period", str):
2905         stderr_write ("\n")
2906         stderr_write (NOT_SMART % _("Dash parameters for slurs and ties are now in \'dash-details.\n"))
2907         stderr_write (UPDATE_MANUALLY)
2908     return str
2909
2910 # Guidelines to write rules (please keep this at the end of this file)
2911 #
2912 # - keep at most one rule per version; if several conversions should be done,
2913 # concatenate them into a single "conv" function;
2914 #
2915 # - enclose strings to be localized with `_(' and  `)';
2916 #
2917 # - write rule for bumping major stable version with
2918 #
2919 #     _ ("bump version for release")
2920 #  
2921 # as exact description.