]> git.donarmstrong.com Git - lilypond.git/blob - python/convertrules.py
Docs: Fix fixed IR compilation (copy @q and @qq from macros.itely)
[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 change 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 loose 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 capitalisation 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         print s , lower_pitches, g, a, s
1825         str = 'cdefgab' [s]
1826         str += ['eses', 'es', '', 'is', 'isis'][a + 2]
1827         if o < 0:
1828             str += ',' * (-o - 1)
1829         elif o >= 0:
1830             str += "'" * (o + 1)
1831
1832         return '\\transposition %s ' % str
1833
1834
1835     str = re.sub (r"\\set ([A-Za-z]+\s*\.\s*)?transposing\s*=\s*#([-0-9]+)",
1836                   subst, str)
1837     return str
1838
1839
1840 @rule ((2, 1, 28), """make-music-by-name -> make-music,
1841 new syntax for setting \\arpeggioBracket""")
1842 def conv (str):
1843     str = re.sub (r'make-music-by-name', 'make-music', str)
1844     str = re.sub (r"\\override\s+.*Arpeggio\s+#.print-function\s+=\s+\\arpeggioBracket", r"\\arpeggioBracket", str)
1845     return str
1846
1847
1848 @rule ((2, 1, 29), '\\center -> \\center-align, \\translator -> \\context')
1849 def conv (str):
1850     str = re.sub (r'\\center([^-])', '\\center-align\\1', str)
1851     str = re.sub (r'\\translator', '\\context', str)
1852     return str
1853
1854
1855 @rule ((2, 1, 30), '''\\threeq{flat,sharp} -> \\sesqui{flat,sharp}
1856 ly:get-mutable-properties -> ly:mutable-music-properties
1857 centralCPosition -> middleCPosition
1858 ly:unset-context-property -> ly:context-unset-property
1859 ly:translator-find -> ly:context-find
1860 ly:get-stencil-extent -> ly:stencil-extent
1861 ''')
1862 def conv (str):
1863     str = re.sub (r'\\threeq(flat|sharp)', r'\\sesqui\1', str)
1864     str = re.sub (r'ly:stencil-get-extent',
1865                   'ly:stencil-extent', str)
1866     str = re.sub (r'ly:translator-find',
1867                   'ly:context-find', str)
1868     str = re.sub ('ly:unset-context-property','ly:context-unset-property',
1869                   str)
1870
1871     str = re.sub (r'ly:get-mutable-properties',
1872                   'ly:mutable-music-properties',str)
1873     str = re.sub (r'centralCPosition',
1874                   'middleCPosition',str)
1875     return str
1876
1877
1878 @rule ((2, 1, 31), 'remove \\alias Timing')
1879 def conv (str):
1880     str = re.sub (r'\\alias\s*"?Timing"?', '', str)
1881     return str
1882
1883
1884 @rule ((2, 1, 33), 'breakAlignOrder -> break-align-orders.')
1885 def conv (str):
1886     str = re.sub (r"(\\set\s+)?(?P<context>(Score\.)?)breakAlignOrder\s*=\s*#'(?P<list>[^\)]+)",
1887                   r"\n\\override \g<context>BreakAlignment #'break-align-orders = "
1888                   + "#(make-vector 3 '\g<list>)", str)
1889     return str
1890
1891
1892 @rule ((2, 1, 34), 'set-paper-size -> set-default-paper-size.')
1893 def conv (str):
1894     str = re.sub (r"\(set-paper-size",
1895                   "(set-default-paper-size",str)
1896     return str
1897
1898
1899 @rule ((2, 1, 36), 'ly:mutable-music-properties -> ly:music-mutable-properties')
1900 def conv (str):
1901     str = re.sub (r"ly:mutable-music-properties",
1902                   "ly:music-mutable-properties", str)
1903     return str
1904
1905
1906 @rule ((2, 2, 0), _ ("bump version for release"))
1907 def conv (str):
1908     return str
1909
1910
1911 @rule ((2, 3, 1), '\\apply -> \\applymusic')
1912 def conv (str):
1913     return re.sub (r'\\apply\b', r'\\applymusic', str)
1914
1915
1916 @rule ((2, 3, 2), '\\FooContext -> \\Foo')
1917 def conv (str):
1918     if re.search ('textheight', str):
1919         stderr_write ('\n')
1920         stderr_write (NOT_SMART % "textheight")
1921         stderr_write ('\n')
1922         stderr_write (UPDATE_MANUALLY)
1923         stderr_write ('\n')
1924         stderr_write (
1925 _ ("""Page layout has been changed, using paper size and margins.
1926 textheight is no longer used.
1927 """))
1928     str = re.sub (r'\\OrchestralScoreContext', '\\Score', str)
1929     def func(m):
1930         if m.group(1) not in ['RemoveEmptyStaff',
1931                               'AncientRemoveEmptyStaffContext',
1932                               'EasyNotation']:
1933             return '\\' + m.group (1)
1934         else:
1935             return m.group (0)
1936
1937
1938     str = re.sub (r'\\([a-zA-Z]+)Context\b', func, str)
1939     str = re.sub ('ly:paper-lookup', 'ly:output-def-lookup', str)
1940     return str
1941
1942
1943 @rule ((2, 3, 4), _ ('remove %s') % '\\notes')
1944 def conv (str):
1945     str = re.sub (r'\\notes\b', '', str)
1946     return str
1947
1948
1949 @rule ((2, 3, 6), 'lastpagefill -> raggedlastbottom')
1950 def conv (str):
1951     str = re.sub (r'lastpagefill\s*=\s*"?1"', 'raggedlastbottom = ##t', str)
1952     return str
1953
1954
1955 @rule ((2, 3, 8), 'remove \\consistsend, strip \\lyrics from \\lyricsto.')
1956 def conv (str):
1957     str = re.sub (r'\\consistsend', '\\consists', str)
1958     str = re.sub (r'\\lyricsto\s+("?[a-zA-Z]+"?)(\s*\\new Lyrics\s*)?\\lyrics',
1959                   r'\\lyricsto \1 \2', str)
1960     return str
1961
1962
1963 @rule ((2, 3, 9), 'neo_mensural -> neomensural, if-text-padding -> bound-padding')
1964 def conv (str):
1965     str = re.sub (r'neo_mensural', 'neomensural', str)
1966     str = re.sub (r'if-text-padding', 'bound-padding', str)
1967     return str
1968
1969
1970 @rule ((2, 3, 10), '\\addlyrics -> \\oldaddlyrics, \\newlyrics -> \\addlyrics')
1971 def conv (str):
1972     str = re.sub (r'\\addlyrics', r'\\oldaddlyrics', str)
1973     str = re.sub (r'\\newlyrics', r'\\addlyrics', str)
1974     if re.search (r"\\override\s*TextSpanner", str):
1975         stderr_write ("\nWarning: TextSpanner has been split into DynamicTextSpanner and TextSpanner\n")
1976     return str
1977
1978
1979 @rule ((2, 3, 11), '\\setMmRestFermata -> ^\\fermataMarkup')
1980 def conv (str):
1981     str = re.sub (r'\\setMmRestFermata\s+(R[0-9.*/]*)',
1982                   r'\1^\\fermataMarkup', str)
1983     return str
1984
1985
1986 @rule ((2, 3, 12), '''\\newpage -> \\pageBreak, junk \\script{up,down,both},
1987 soloADue -> printPartCombineTexts, #notes-to-clusters -> \\makeClusters
1988 ''')
1989 def conv (str):
1990     str = re.sub (r'\\newpage', r'\\pageBreak', str)
1991     str = re.sub (r'\\scriptUp', r"""{
1992 \\override TextScript  #'direction = #1
1993 \\override Script  #'direction = #1
1994 }""", str)
1995     str = re.sub (r'\\scriptDown', r"""{
1996   \\override TextScript  #'direction = #-1
1997   \\override Script  #'direction = #-1
1998 }""", str)
1999     str = re.sub (r'\\scriptBoth', r"""{
2000   \\revert TextScript  #'direction
2001   \\revert Script  #'direction
2002 }""", str)
2003     str = re.sub ('soloADue', 'printPartCombineTexts', str)
2004     str = re.sub (r'\\applymusic\s*#notes-to-clusters',
2005                       '\\makeClusters', str)
2006     
2007     str = re.sub (r'pagenumber\s*=', 'firstpagenumber = ', str)
2008     return str
2009
2010
2011 @rule ((2, 3, 16), _ ('''\\foo -> \\foomode (for chords, notes, etc.)
2012 fold \\new FooContext \\foomode into \\foo.'''))
2013 def conv (str):
2014     str = re.sub (r'\\chords\b', r'\\chordmode', str)
2015     str = re.sub (r'\\lyrics\b', r'\\lyricmode', str)
2016     str = re.sub (r'\\figures\b', r'\\figuremode', str)
2017     str = re.sub (r'\\notes\b', r'\\notemode', str)
2018     str = re.sub (r'\\drums\b', r'\\drummode', str)
2019     str = re.sub (r'\\chordmode\s*\\new ChordNames', r'\\chords', str)
2020     str = re.sub (r'\\new ChordNames\s*\\chordmode', r'\\chords', str)
2021     str = re.sub (r'\\new FiguredBass\s*\\figuremode', r'\\figures', str)
2022     str = re.sub (r'\\figuremode\s*\new FiguredBass', r'\\figures', str)
2023     str = re.sub (r'\\new DrumStaff\s*\\drummode', r'\\drums', str)
2024     str = re.sub (r'\\drummode\s*\\new DrumStaff', r'\\drums', str)
2025
2026     return str
2027
2028
2029 @rule ((2, 3, 17), '''slurBoth -> slurNeutral, stemBoth -> stemNeutral, etc.
2030 \\applymusic #(remove-tag 'foo) -> \\removeWithTag 'foo''')
2031 def conv (str):
2032     str = re.sub (r'(slur|stem|phrasingSlur|tie|dynamic|dots|tuplet|arpeggio|)Both', r'\1Neutral', str)
2033     str = re.sub (r"\\applymusic\s*#\(remove-tag\s*'([a-z-0-9]+)\)",
2034                   r"\\removeWithTag #'\1", str)
2035     return str
2036
2037
2038 @rule ((2, 3, 18), 'Text_item -> Text_interface')
2039 def conv (str):
2040     str = re.sub (r'Text_item', 'Text_interface', str)
2041     return str
2042
2043
2044 @rule ((2, 3, 22), 'paper -> layout, bookpaper -> paper')
2045 def conv (str):
2046     str = re.sub (r'\\paper', r'\\layout', str)
2047     str = re.sub (r'\\bookpaper', r'\\paper', str)
2048     if re.search ('paper-set-staff-size', str):
2049         warning (_ ('''staff size should be changed at top-level
2050 with
2051
2052   #(set-global-staff-size <STAFF-HEIGHT-IN-POINT>)
2053
2054 '''))
2055
2056
2057     str = re.sub (r'#\(paper-set-staff-size', '%Use set-global-staff-size at toplevel\n% #(layout-set-staff-size', str)
2058     return str
2059     
2060
2061 @rule ((2, 3, 23), r'\context Foo = NOTENAME -> \context Foo = "NOTENAME"')
2062 def conv (str):
2063     str = re.sub (r'\\context\s+([a-zA-Z]+)\s*=\s*([a-z]+)\s',
2064                   r'\\context \1 = "\2" ',
2065                   str )
2066     return str
2067
2068
2069 @rule ((2, 3, 24), _ ('''regularize other identifiers'''))
2070 def conv (str):
2071     def sub(m):
2072         return regularize_id (m.group (1))
2073     str = re.sub (r'(maintainer_email|maintainer_web|midi_stuff|gourlay_maxmeasures)',
2074                   sub, str)
2075     return str
2076
2077
2078 @rule ((2, 3, 25), 'petrucci_c1 -> petrucci-c1, 1style -> single-digit')
2079 def conv (str):
2080     str = re.sub ('petrucci_c1', 'petrucci-c1', str)
2081     str = re.sub ('1style', 'single-digit', str)
2082     return str
2083
2084
2085 @rule ((2, 4, 0), _ ("bump version for release"))
2086 def conv (str):
2087     return str
2088
2089
2090 @rule ((2, 5, 0), '\\quote -> \\quoteDuring')
2091 def conv (str):
2092     str = re.sub (r'\\quote\s+"?([a-zA-Z0-9]+)"?\s+([0-9.*/]+)',
2093                   r'\\quoteDuring #"\1" { \skip \2 }',
2094                   str)
2095     return str
2096
2097
2098 @rule ((2, 5, 1), 'ly:import-module -> ly:module-copy')
2099 def conv (str):
2100     str = re.sub (r'ly:import-module',
2101                   r'ly:module-copy', str)
2102     return str
2103
2104
2105 @rule ((2, 5, 2), '\markup .. < .. > .. -> \markup .. { .. } ..')
2106 def conv (str):
2107     str = re.sub (r'\\(column|fill-line|dir-column|center-align|right-align|left-align|bracketed-y-column)\s*<(([^>]|<[^>]*>)*)>',
2108                   r'\\\1 {\2}', str)
2109     str = re.sub (r'\\(column|fill-line|dir-column|center-align|right-align|left-align|bracketed-y-column)\s*<(([^>]|<[^>]*>)*)>',
2110                   r'\\\1 {\2}', str)
2111     str = re.sub (r'\\(column|fill-line|dir-column|center-align|right-align|left-align|bracketed-y-column)\s*<(([^>]|<[^>]*>)*)>',
2112                   r'\\\1 {\2}', str)
2113     def get_markup (m):
2114         s = m.group (0)
2115         s = re.sub (r'''((\\"|})\s*){''', '\2 \\line {', s)
2116         return s
2117     str = re.sub (r'\\markup\s*{([^}]|{[^}]*})*}', get_markup, str)
2118     return str
2119
2120
2121 @rule ((2, 5, 3), 'ly:find-glyph-by-name -> ly:font-get-glyph, remove - from glyphnames.')
2122 def conv (str):
2123     str = re.sub ('ly:find-glyph-by-name', 'ly:font-get-glyph', str)
2124     str = re.sub ('"(scripts|clefs|accidentals)-', r'"\1.', str)
2125     str = re.sub ("'hufnagel-do-fa", "'hufnagel.do.fa", str)
2126     str = re.sub ("'(vaticana|hufnagel|medicaea|petrucci|neomensural|mensural)-", r"'\1.", str)
2127     return str
2128
2129
2130 @rule ((2, 5, 12), '\set Slur #\'dashed = #X -> \slurDashed')
2131 def conv (str):
2132     str = re.sub (r"\\override\s+(Voice\.)?Slur #'dashed\s*=\s*#\d*(\.\d+)?",
2133                   r"\\slurDashed", str)
2134     return str
2135
2136
2137 @rule ((2, 5, 13), _ ('\\encoding: smart recode latin1..utf-8. Remove ly:point-and-click'))
2138 def conv (str):
2139     input_encoding = 'latin1'
2140     def func (match):
2141         encoding = match.group (1)
2142
2143         # FIXME: automatic recoding of other than latin1?
2144         if encoding == 'latin1':
2145             return match.group (2)
2146
2147         stderr_write ('\n')
2148         stderr_write (NOT_SMART % ("\\encoding: %s" % encoding))
2149         stderr_write ('\n')
2150         stderr_write (_ ("LilyPond source must be UTF-8"))
2151         stderr_write ('\n')
2152         if encoding == 'TeX':
2153             stderr_write (_ ("Try the texstrings backend"))
2154             stderr_write ('\n')
2155         else:
2156             stderr_write ( _("Do something like: %s") % \
2157                                ("recode %s..utf-8 FILE" % encoding))
2158             stderr_write ('\n')
2159         stderr_write (_ ("Or save as UTF-8 in your editor"))
2160         stderr_write ('\n')
2161         raise FatalConversionError ()
2162
2163         return match.group (0)
2164
2165     str = re.sub (r'\\encoding\s+"?([a-zA-Z0-9]+)"?(\s+)', func, str)
2166
2167     import codecs
2168     de_ascii = codecs.getdecoder ('ascii')
2169     de_utf_8 = codecs.getdecoder ('utf_8')
2170     de_input = codecs.getdecoder (input_encoding)
2171     en_utf_8 = codecs.getencoder ('utf_8')
2172     try:
2173         de_ascii (str)
2174     # only in python >= 2.3
2175     # except UnicodeDecodeError:
2176     except UnicodeError:
2177         # do not re-recode UTF-8 input
2178         try:
2179             de_utf_8 (str)
2180         #except UnicodeDecodeError:
2181         except UnicodeError:
2182             str = en_utf_8 (de_input (str)[0])[0]
2183
2184
2185
2186     str = re.sub (r"#\(ly:set-point-and-click '[a-z-]+\)", '', str)
2187     return str
2188
2189
2190 @rule ((2, 5, 17), _ ('remove %s') % 'ly:stencil-set-extent!')
2191 def conv (str):
2192     if re.search ("ly:stencil-set-extent!", str):
2193         stderr_write ('\n')
2194         stderr_write (NOT_SMART % "ly:stencil-set-extent!")
2195         stderr_write ('\n')
2196         stderr_write ('use (set! VAR (ly:make-stencil (ly:stencil-expr VAR) X-EXT Y-EXT))\n')
2197         raise FatalConversionError ()
2198     if re.search ("ly:stencil-align-to!", str):
2199         stderr_write ('\n')
2200         stderr_write (NOT_SMART % "ly:stencil-align-to!")
2201         stderr_write ('\n')
2202         stderr_write ('use (set! VAR (ly:stencil-aligned-to VAR AXIS DIR))\n')
2203         raise FatalConversionError ()
2204     return str
2205
2206
2207 @rule ((2, 5, 18), 'ly:warn -> ly:warning')
2208 def conv (str):
2209     str = re.sub (r"ly:warn\b", 'ly:warning', str)
2210     return str
2211
2212
2213 @rule ((2, 5, 21), _ ('warn about auto beam settings'))
2214 def conv (str):
2215     if re.search ("(override-|revert-)auto-beam-setting", str)\
2216        or re.search ("autoBeamSettings", str):
2217         stderr_write ('\n')
2218         stderr_write (NOT_SMART % _ ("auto beam settings"))
2219         stderr_write ('\n')
2220         stderr_write (_ ('''
2221 Auto beam settings must now specify each interesting moment in a measure
2222 explicitely; 1/4 is no longer multiplied to cover moments 1/2 and 3/4 too.
2223 '''))
2224         stderr_write (UPDATE_MANUALLY)
2225         stderr_write ('\n')
2226         raise FatalConversionError ()
2227     return str
2228
2229
2230 @rule ((2, 5, 25), 'unfoldrepeats -> unfoldRepeats, compressmusic -> compressMusic')
2231 def conv (str):
2232     str = re.sub (r"unfoldrepeats", 'unfoldRepeats', str)
2233     str = re.sub (r"compressmusic", 'compressMusic', str)
2234     return str
2235
2236
2237 @rule ((2, 6, 0), _ ("bump version for release"))
2238 def conv (str):
2239     return str
2240
2241
2242 @rule ((2, 7, 0), 'ly:get-default-font -> ly:grob-default-font')
2243 def conv (str):
2244     return re.sub('ly:get-default-font', 'ly:grob-default-font', str) 
2245
2246
2247 @rule ((2, 7, 1), '''ly:parser-define -> ly:parser-define!
2248 excentricity -> eccentricity
2249 Timing_engraver -> Timing_translator + Default_bar_line_engraver
2250 ''')
2251 def conv (str):
2252     str = re.sub('ly:parser-define', 'ly:parser-define!', str)
2253     str = re.sub('excentricity', 'eccentricity', str)
2254     str = re.sub(r'\\(consists|remove) *"?Timing_engraver"?',
2255                  r'\\\1 "Timing_translator" \\\1 "Default_bar_line_engraver"',
2256                  str)
2257     return str
2258
2259
2260 @rule ((2, 7, 2), 'ly:X-moment -> ly:moment-X')
2261 def conv (str):
2262     str = re.sub('ly:(add|mul|mod|div)-moment', r'ly:moment-\1', str)
2263     return str
2264
2265
2266 @rule ((2, 7, 4), 'keyAccidentalOrder -> keyAlterationOrder')
2267 def conv (str):
2268     str = re.sub('keyAccidentalOrder', 'keyAlterationOrder', str)
2269     return str
2270
2271
2272 @rule ((2, 7, 6), '''Performer_group_performer -> Performer_group, Engraver_group_engraver -> Engraver_group,
2273 inside-slur -> avoid-slur''')
2274 def conv (str):
2275     str = re.sub('Performer_group_performer', 'Performer_group', str)
2276     str = re.sub('Engraver_group_engraver', 'Engraver_group', str)
2277     str = re.sub (r"#'inside-slur\s*=\s*##t *",
2278                   r"#'avoid-slur = #'inside ", str)
2279     str = re.sub (r"#'inside-slur\s*=\s*##f *",
2280                   r"#'avoid-slur = #'around ", str)
2281     str = re.sub (r"#'inside-slur",
2282                   r"#'avoid-slur", str)
2283     return str
2284
2285
2286 @rule ((2, 7, 10), '\\applyxxx -> \\applyXxx')
2287 def conv (str):
2288     str = re.sub(r'\\applyoutput', r'\\applyOutput', str)
2289     str = re.sub(r'\\applycontext', r'\\applyContext', str)
2290     str = re.sub(r'\\applymusic',  r'\\applyMusic', str)
2291     str = re.sub(r'ly:grob-suicide', 'ly:grob-suicide!', str)
2292     return str
2293
2294
2295 @rule ((2, 7, 11), '"tabloid" -> "11x17"')
2296 def conv (str):
2297     str = re.sub(r'\"tabloid\"', '"11x17"', str)
2298     return str
2299
2300
2301 @rule ((2, 7, 12), 'outputProperty -> overrideProperty')
2302 def conv (str):
2303     str = re.sub(r'outputProperty' , 'overrideProperty', str)
2304     return str
2305
2306
2307 @rule ((2, 7, 13), 'layout engine refactoring [FIXME]')
2308 def conv (str):
2309     def subber (match):
2310         newkey = {'spacing-procedure': 'springs-and-rods',
2311                   'after-line-breaking-callback' : 'after-line-breaking',
2312                   'before-line-breaking-callback' : 'before-line-breaking',
2313                   'print-function' : 'stencil'} [match.group(3)]
2314         what = match.group (1)
2315         grob = match.group (2)
2316
2317         if what == 'revert':
2318             return "revert %s #'callbacks %% %s\n" % (grob, newkey)
2319         elif what == 'override':
2320             return "override %s #'callbacks #'%s" % (grob, newkey)
2321         else:
2322             raise 'urg'
2323             return ''
2324
2325     str = re.sub(r"(override|revert)\s*([a-zA-Z.]+)\s*#'(spacing-procedure|after-line-breaking-callback"
2326                 + r"|before-line-breaking-callback|print-function)",
2327                 subber, str)
2328
2329     if re.search ('bar-size-procedure', str):
2330         stderr_write (NOT_SMART % "bar-size-procedure")
2331     if re.search ('space-function', str):
2332         stderr_write (NOT_SMART % "space-function")
2333     if re.search ('verticalAlignmentChildCallback', str):
2334         stderr_write (_ ('verticalAlignmentChildCallback has been deprecated'))
2335     return str
2336
2337
2338 @rule ((2, 7, 14), _ ('Remove callbacks property, deprecate XY-extent-callback.'))
2339 def conv (str):
2340     str = re.sub (r"\\override +([A-Z.a-z]+) #'callbacks",
2341                   r"\\override \1", str)
2342     str = re.sub (r"\\revert ([A-Z.a-z]+) #'callbacks % ([a-zA-Z]+)",
2343                   r"\\revert \1 #'\2", str)
2344     str = re.sub (r"([XY]-extent)-callback", r'\1', str)
2345     str = re.sub (r"RemoveEmptyVerticalGroup", "VerticalAxisGroup", str)
2346     str = re.sub (r"\\set ([a-zA-Z]*\.?)minimumVerticalExtent",
2347                   r"\\override \1VerticalAxisGroup #'minimum-Y-extent",
2348                   str)
2349     str = re.sub (r"minimumVerticalExtent",
2350                   r"\\override VerticalAxisGroup #'minimum-Y-extent",
2351                   str)
2352     str = re.sub (r"\\set ([a-zA-Z]*\.?)extraVerticalExtent",
2353                   r"\\override \1VerticalAxisGroup #'extra-Y-extent", str)
2354     str = re.sub (r"\\set ([a-zA-Z]*\.?)verticalExtent",
2355                   r"\\override \1VerticalAxisGroup #'Y-extent", str)
2356     return str
2357
2358
2359 @rule ((2, 7, 15), _ ('Use grob closures iso. XY-offset-callbacks.'))
2360 def conv (str):
2361     if re.search ('[XY]-offset-callbacks', str):
2362         stderr_write (NOT_SMART % "[XY]-offset-callbacks")
2363     if re.search ('position-callbacks', str):
2364         stderr_write (NOT_SMART % "position-callbacks")
2365     return str
2366
2367
2368 @rule ((2, 7, 22), r"\tag #'(a b) -> \tag #'a \tag #'b")
2369 def conv (str):
2370     def sub_syms (m):
2371         syms =  m.group (1).split ()
2372         tags = ["\\tag #'%s" % s for s in syms]
2373         return ' '.join (tags)
2374
2375     str = re.sub (r"\\tag #'\(([^)]+)\)",  sub_syms, str)
2376     return str
2377
2378
2379 @rule ((2, 7, 24), _ ('deprecate %s') % 'number-visibility')
2380 def conv (str):
2381     str = re.sub (r"#'number-visibility",
2382                   "#'number-visibility % number-visibility is deprecated. Tune the TupletNumber instead\n",
2383                   str)
2384     return str
2385
2386
2387 @rule ((2, 7, 28), "ly:spanner-get-bound -> ly:spanner-bound")
2388 def conv (str):
2389     str = re.sub (r"ly:spanner-get-bound", "ly:spanner-bound", str)
2390     return str
2391
2392
2393 @rule ((2, 7, 29), "override Stem #'beamed-* -> #'details #'beamed-*")
2394 def conv (str):
2395     for a in ['beamed-lengths', 'beamed-minimum-free-lengths',
2396               'lengths',
2397               'beamed-extreme-minimum-free-lengths']:
2398         str = re.sub (r"\\override\s+Stem\s+#'%s" % a,
2399                       r"\\override Stem #'details #'%s" % a,
2400                       str)
2401     return str
2402
2403
2404 @rule ((2, 7, 30), "\\epsfile")
2405 def conv (str):
2406     str = re.sub (r'\\epsfile *#"', r'\\epsfile #X #10 #"', str)
2407     return str
2408
2409
2410 @rule ((2, 7, 31), "Foo_bar::bla_bla -> ly:foo-bar::bla-bla")
2411 def conv (str):
2412     def sub_cxx_id (m):
2413         str = m.group(1)
2414         return 'ly:' + str.lower ().replace ('_','-')
2415
2416     str = re.sub (r'([A-Z][a-z_0-9]+::[a-z_0-9]+)',
2417                   sub_cxx_id, str)
2418     return str
2419
2420
2421 @rule ((2, 7, 32), _ ("foobar -> foo-bar for \paper, \layout"))
2422 def conv (str):
2423     identifier_subs = [
2424             ('inputencoding', 'input-encoding'),
2425             ('printpagenumber', 'print-page-number'),
2426             ('outputscale', 'output-scale'),
2427             ('betweensystemspace', 'between-system-space'),
2428             ('betweensystempadding', 'between-system-padding'),
2429             ('pagetopspace', 'page-top-space'),
2430             ('raggedlastbottom', 'ragged-last-bottom'),
2431             ('raggedright', 'ragged-right'),
2432             ('raggedlast', 'ragged-last'),
2433             ('raggedbottom', 'ragged-bottom'),
2434             ('aftertitlespace', 'after-title-space'),
2435             ('beforetitlespace', 'before-title-space'),
2436             ('betweentitlespace', 'between-title-space'),
2437             ('topmargin', 'top-margin'),
2438             ('bottommargin', 'bottom-margin'),
2439             ('headsep', 'head-separation'),
2440             ('footsep', 'foot-separation'),
2441             ('rightmargin', 'right-margin'),
2442             ('leftmargin', 'left-margin'),
2443             ('printfirstpagenumber', 'print-first-page-number'),
2444             ('firstpagenumber', 'first-page-number'),
2445             ('hsize', 'paper-width'),
2446             ('vsize', 'paper-height'),
2447             ('horizontalshift', 'horizontal-shift'),
2448             ('staffspace', 'staff-space'),
2449             ('linethickness', 'line-thickness'),
2450             ('ledgerlinethickness', 'ledger-line-thickness'),
2451             ('blotdiameter', 'blot-diameter'),
2452             ('staffheight', 'staff-height'),
2453             ('linewidth', 'line-width'),
2454             ('annotatespacing', 'annotate-spacing')
2455             ]
2456
2457     for (a,b)  in identifier_subs:
2458         ### for C++:
2459         ## str = re.sub ('"%s"' % a, '"%s"' b, str)
2460
2461         str = re.sub (a, b, str)
2462     return str
2463
2464
2465 @rule ((2, 7, 32), "debug-beam-quanting -> debug-beam-scoring")
2466 def conv (str):
2467     str = re.sub ('debug-beam-quanting', 'debug-beam-scoring', str)
2468     return str
2469
2470
2471 @rule ((2, 7, 36), "def-(music-function|markup-command) -> define-(music-function|markup-command)")
2472 def conv (str):
2473     str = re.sub ('def-music-function', 'define-music-function', str)
2474     str = re.sub ('def-markup-command', 'define-markup-command', str)
2475     return str
2476
2477
2478 @rule ((2, 7, 40), "rehearsalMarkAlignSymbol/barNumberAlignSymbol -> break-align-symbol")
2479 def conv (str):
2480     str = re.sub (r'\\set\s+Score\s*\.\s*barNumberAlignSymbol\s*=',
2481                   r"\\override Score.BarNumber #'break-align-symbol = ", str)
2482     str = re.sub (r'\\set\s*Score\s*\.\s*rehearsalMarkAlignSymbol\s*=',
2483                   r"\\override Score.RehearsalMark #'break-align-symbol = ", str)
2484     return str
2485
2486
2487 @rule ((2, 9, 4), "(page-)penalty -> (page-)break-penalty")
2488 def conv (str):
2489     str = re.sub ('page-penalty', 'page-break-penalty', str)
2490     str = re.sub ('([^-])penalty', '\1break-penalty', str)
2491     return str
2492
2493
2494 @rule ((2, 9, 6), "\\context Foo \\applyOutput #bla -> \\applyOutput #'Foo #bla ")
2495 def conv (str):
2496     str = re.sub (r'\\context\s+\"?([a-zA-Z]+)\"?\s*\\applyOutput', r"\\applyOutput #'\1", str)
2497     return str
2498
2499
2500 @rule ((2, 9, 9), "annotatefoo -> annotate-foo")
2501 def conv (str):
2502     str = re.sub ('annotatepage', 'annotate-page', str)
2503     str = re.sub ('annotateheaders', 'annotate-headers', str)
2504     str = re.sub ('annotatesystems', 'annotate-systems', str)
2505     return str
2506
2507
2508 @rule ((2, 9, 11), "\\set tupletNumberFormatFunction -> \\override #'text = ")
2509 def conv (str):
2510     str = re.sub (r"""(\\set\s)?(?P<context>[a-zA-Z]*.?)tupletNumberFormatFunction\s*=\s*#denominator-tuplet-formatter""",
2511                   r"""\\override \g<context>TupletNumber #'text = #tuplet-number::calc-denominator-text""", str)
2512
2513     str = re.sub (r"""(\\set\s+)?(?P<context>[a-zA-Z]*.?)tupletNumberFormatFunction\s*=\s*#fraction-tuplet-formatter""",
2514                   r"""\\override \g<context>TupletNumber #'text = #tuplet-number::calc-fraction-text""", str)
2515
2516     if re.search ('tupletNumberFormatFunction', str):
2517         stderr_write ("\n")
2518         stderr_write ("tupletNumberFormatFunction has been removed. Use #'text property on TupletNumber")
2519         stderr_write ("\n")
2520     return str
2521
2522
2523 @rule ((2, 9, 13), "instrument -> instrumentName, instr -> shortInstrumentName, vocNam -> shortVocalName")
2524 def conv (str):
2525     str = re.sub ('vocNam', 'shortVocalName', str)
2526     str = re.sub (r'\.instr\s*=', r'.shortInstrumentName =', str)
2527     str = re.sub (r'\.instrument\s*=', r'.instrumentName =', str)
2528     return str
2529
2530
2531 @rule ((2, 9, 16), _ ("deprecate \\tempo in \\midi"))
2532 def conv (str):
2533
2534     def sub_tempo (m):
2535         dur = int (m.group (1))
2536         dots = len (m.group (2))
2537         count = int (m.group (3))
2538
2539         log2 = 0
2540         while dur > 1 :
2541             dur /= 2
2542             log2 += 1
2543         
2544         den = (1 << dots) * (1 << log2)
2545         num = ((1 << (dots+1))  - 1)
2546
2547         return  """
2548   \midi {
2549     \context {
2550       \Score
2551       tempoWholesPerMinute = #(ly:make-moment %d %d)
2552       }
2553     }
2554
2555 """ % (num*count, den)
2556     
2557     str = re.sub (r'\\midi\s*{\s*\\tempo ([0-9]+)\s*([.]*)\s*=\s*([0-9]+)\s*}', sub_tempo, str)
2558     return str
2559
2560
2561 @rule ((2, 9, 19), "printfirst-page-number -> print-first-page-number")
2562 def conv (str):
2563     str = re.sub ('printfirst-page-number', 'print-first-page-number', str)
2564     return str
2565
2566
2567 @rule ((2, 10, 0), _ ("bump version for release"))
2568 def conv (str):
2569     return str
2570
2571
2572 @rule ((2, 11, 2), "ly:clone-parser -> ly:parser-clone")
2573 def conv (str):
2574     return re.sub ('ly:clone-parser',
2575                    'ly:parser-clone', str)
2576
2577
2578 @rule ((2, 11, 5), _ ("deprecate cautionary-style. Use AccidentalCautionary properties"))
2579 def conv (str):
2580     str = re.sub ("Accidental\s*#'cautionary-style\s*=\s*#'smaller",
2581                    "AccidentalCautionary #'font-size = #-2", str)
2582     str = re.sub ("Accidental\s*#'cautionary-style\s*=\s*#'parentheses",
2583                    "AccidentalCautionary #'parenthesized = ##t", str)
2584     str = re.sub ("([A-Za-z]+)\s*#'cautionary-style\s*=\s*#'parentheses",
2585                    r"\1 #'parenthesized = ##t", str)
2586     str = re.sub ("([A-Za-z]+)\s*#'cautionary-style\s*=\s*#'smaller",
2587                    r"\1 #'font-size = #-2", str)
2588     return str
2589
2590
2591 @rule ((2, 11, 6), _ ("Rename accidental glyphs, use glyph-name-alist."))
2592 def conv (str):
2593     
2594     def sub_acc_name (m):
2595         idx = int (m.group (1).replace ('M','-'))
2596         
2597         return ["accidentals.doublesharp",
2598                 "accidentals.sharp.slashslash.stemstemstem",
2599                 "accidentals.sharp",
2600                 "accidentals.sharp.slashslash.stem",
2601                 "accidentals.natural",
2602                 "accidentals.mirroredflat",
2603                 "accidentals.flat",
2604                 "accidentals.mirroredflat.flat",
2605                 "accidentals.flatflat"][4-idx]
2606
2607     str = re.sub (r"accidentals[.](M?[-0-9]+)",
2608                   sub_acc_name, str) 
2609     str = re.sub (r"(KeySignature|Accidental[A-Za-z]*)\s*#'style\s*=\s*#'([a-z]+)",
2610                   r"\1 #'glyph-name-alist = #alteration-\2-glyph-name-alist", str)
2611     ## FIXME: standard vs default, alteration-FOO vs FOO-alteration
2612     str = str.replace ('alteration-default-glyph-name-alist',
2613                        'standard-alteration-glyph-name-alist')
2614     return str
2615
2616
2617 @rule ((2, 11, 10), """allowBeamBreak -> Beam #'breakable = ##t
2618 addquote -> addQuote
2619 """)
2620 def conv (str):
2621     str = re.sub (r'(\\set\s+)?([A-Z][a-zA-Z]+\s*\.\s*)allowBeamBreak',
2622                   r"\override \2Beam #'breakable", str)
2623     str = re.sub (r'(\\set\s+)?allowBeamBreak',
2624                   r"\override Beam #'breakable", str)
2625     str = re.sub (r'addquote', 'addQuote', str)
2626     if re.search ("Span_dynamic_performer", str):
2627         stderr_write ("Span_dynamic_performer has been merged into Dynamic_performer")
2628
2629     return str
2630
2631
2632 @rule ((2, 11, 11), "layout-set-staff-size -> layout-set-absolute-staff-size")
2633 def conv (str):
2634     str = re.sub (r'\(layout-set-staff-size \(\*\s*([0-9.]+)\s*(pt|mm|cm)\)\)',
2635                   r'(layout-set-absolute-staff-size (* \1 \2))', str)
2636     return str
2637
2638
2639 @rule ((2, 11, 13), "#'arrow = ##t -> #'bound-details #'right #'arrow = ##t")
2640 def conv (str):
2641     str = re.sub (r"\\override\s*([a-zA-Z.]+)\s*#'arrow\s*=\s*##t",
2642                   r"\\override \1 #'bound-details #'right #'arrow = ##t",
2643                   str)
2644
2645     if re.search ('edge-text', str):
2646         stderr_write (NOT_SMART % _ ("edge-text settings for TextSpanner."))
2647         stderr_write (_ ("Use\n\n%s") %
2648                           "\t\\override TextSpanner #'bound-details #'right #'text = <right-text>\n"
2649                           "\t\\override TextSpanner #'bound-details #'left #'text = <left-text>\n")
2650     return str
2651
2652
2653 @rule ((2, 11, 15), "#'edge-height -> #'bound-details #'right/left #'text = ...")
2654 def conv (str):
2655     def sub_edge_height (m):
2656         s = ''
2657         for (var, h) in [('left', m.group (3)),
2658                          ('right', m.group (4))]:
2659
2660             if h and float (h):
2661                 once = m.group(1)
2662                 if not once:
2663                     once = ''
2664                     
2665                 s += (r"%s \override %s #'bound-details #'%s #'text = \markup { \draw-line #'(0 . %s) }"
2666                       % (once, m.group (2), var, h))
2667
2668                 s += '\n'
2669             
2670         return s
2671     
2672                   
2673     str = re.sub (r"(\\once)?\s*\\override\s*([a-zA-Z.]+)\s*#'edge-height\s*=\s*#'\(([0-9.-]+)\s+[.]\s+([0-9.-]+)\)",
2674                   sub_edge_height, str)
2675     return str
2676
2677
2678 @rule ((2, 11, 23), "#'break-align-symbol -> #'break-align-symbols")
2679 def conv (str):
2680     str = re.sub (r"\\override\s*([a-zA-Z.]+)\s*#'break-align-symbol\s*=\s*#'([a-z-]+)",
2681                   r"\\override \1 #'break-align-symbols = #'(\2)", str)
2682     return str
2683
2684
2685 @rule ((2, 11, 35), """scripts.caesura -> scripts.caesura.curved.
2686 """ + _ ("Use #'style not #'dash-fraction to select solid/dashed lines."))
2687 def conv (str):
2688     str = re.sub (r"scripts\.caesura",
2689                   r"scripts.caesura.curved", str)
2690
2691     if re.search ('dash-fraction', str):
2692         stderr_write (NOT_SMART % _ ("all settings related to dashed lines.\n"))
2693         stderr_write (_ ("Use \\override ... #'style = #'line for solid lines and\n"))
2694         stderr_write (_ ("\t\\override ... #'style = #'dashed-line for dashed lines."))
2695     return str
2696
2697
2698 @rule ((2, 11, 38), """\\setEasyHeads -> \\easyHeadsOn, \\fatText -> \\textLengthOn,
2699 \\emptyText -> \\textLengthOff""")
2700 def conv (str):
2701     str = re.sub (r"setEasyHeads", r"easyHeadsOn", str)
2702     str = re.sub (r"fatText", r"textLengthOn", str)
2703     str = re.sub (r"emptyText", r"textLengthOff", str)
2704     return str
2705
2706
2707 @rule ((2, 11, 46), "\\set hairpinToBarline -> \\override Hairpin #'to-barline")
2708 def conv (str):
2709     str = re.sub (r"\\set\s+([a-zA-Z]+)\s*.\s*hairpinToBarline\s*=\s*##([tf]+)",
2710                   r"\\override \1.Hairpin #'to-barline = ##\2", str)
2711     str = re.sub (r"\\set\s+hairpinToBarline\s*=\s*##([tf]+)",
2712                   r"\\override Hairpin #'to-barline = ##\1", str)
2713     str = re.sub (r"\\unset\s+([a-zA-Z]+)\s*.\s*hairpinToBarline",
2714                   r"\\revert \1.Hairpin #'to-barline", str)
2715     str = re.sub (r"\\unset\s+hairpinToBarline",
2716                   r"\\revert Hairpin #'to-barline", str)
2717     str = re.sub (r"hairpinToBarline\s*=\s*##([tf]+)",
2718                   r"\\override Hairpin #'to-barline = ##\1", str)
2719     str = re.sub (r"\\set (de|)crescendoSpanner = #'dashed-line",
2720                   r"\\set \1crescendoSpanner = #'text", str)
2721     return str
2722
2723
2724 @rule ((2, 11, 48), "\\compressMusic -> \\scaleDurations")
2725 def conv (str):
2726     str = re.sub (r"compressMusic", r"scaleDurations", str)
2727     return str
2728
2729
2730 @rule ((2, 11, 50), _ ("metronomeMarkFormatter uses text markup as second argument,\n\
2731 fret diagram properties moved to fret-diagram-details."))
2732 def conv (str):
2733     ## warning 1/2: metronomeMarkFormatter uses text markup as second argument
2734     if re.search ('metronomeMarkFormatter', str):
2735         stderr_write (NOT_SMART % _ ("metronomeMarkFormatter got an additional text argument.\n"))
2736         stderr_write (_ ("The function assigned to Score.metronomeMarkFunction now uses the signature\n%s") %
2737                           "\t(format-metronome-markup text dur count context)\n")
2738
2739     ## warning 2/2: fret diagram properties moved to fret-diagram-details
2740     fret_props = ['barre-type', 
2741                 'dot-color', 
2742                 'dot-radius',
2743                 'finger-code',
2744                 'fret-count',
2745                 'label-dir',
2746                 'number-type',
2747                 'string-count',
2748                 'xo-font-magnification',
2749                 'mute-string',
2750                 'open-string',
2751                 'orientation']
2752     for prop in fret_props:
2753       if re.search (prop, str):
2754           stderr_write (NOT_SMART %
2755             prop + " in fret-diagram properties. Use fret-diagram-details.")
2756           stderr_write ('\n')
2757     return str
2758
2759 @rule ((2, 11, 51), "\\octave -> \\octaveCheck, \\arpeggioUp -> \\arpeggioArrowUp,\n\
2760 \\arpeggioDown -> \\arpeggioArrowDown, \\arpeggioNeutral -> \\arpeggioNormal,\n\
2761 \\setTextCresc -> \\crescTextCresc, \\setTextDecresc -> \\dimTextDecresc,\n\
2762 \\setTextDecr -> \\dimTextDecr, \\setTextDim -> \\dimTextDim,\n\
2763 \\setHairpinCresc -> \\crescHairpin, \\setHairpinDecresc -> \\dimHairpin,\n\
2764 \\sustainUp -> \\sustainOff, \\sustainDown -> \\sustainOn\n\
2765 \\sostenutoDown -> \\sostenutoOn, \\sostenutoUp -> \\sostenutoOff")
2766 def conv (str):
2767     str = re.sub (r"\\octave", r"\\octaveCheck", str)
2768     str = re.sub (r"arpeggioUp", r"arpeggioArrowUp", str)
2769     str = re.sub (r"arpeggioDown", r"arpeggioArrowDown", str)
2770     str = re.sub (r"arpeggioNeutral", r"arpeggioNormal", str)
2771     str = re.sub (r"setTextCresc", r"crescTextCresc", str)
2772     str = re.sub (r"setTextDecresc", r"dimTextDecresc", str)
2773     str = re.sub (r"setTextDecr", r"dimTextDecr", str)
2774     str = re.sub (r"setTextDim", r"dimTextDim", str)
2775     str = re.sub (r"setHairpinCresc", r"crescHairpin", str)
2776     str = re.sub (r"setHairpinDecresc", r"dimHairpin", str)
2777     str = re.sub (r"sustainUp", r"sustainOff", str)
2778     str = re.sub (r"sustainDown", r"sustainOn", str)
2779     str = re.sub (r"sostenutoDown", r"sostenutoOn", str)
2780     str = re.sub (r"sostenutoUp", r"sostenutoOff", str)
2781     return str
2782
2783 @rule ((2, 11, 52), "\\setHairpinDim -> \\dimHairpin")
2784 def conv (str):
2785     str = str.replace ("setHairpinDim", "dimHairpin")
2786     return str
2787
2788 @rule ((2, 11, 53), "infinite-spacing-height -> extra-spacing-height")
2789 def conv (str):
2790     str = re.sub (r"infinite-spacing-height\s+=\s+##t", r"extra-spacing-height = #'(-inf.0 . +inf.0)", str)
2791     str = re.sub (r"infinite-spacing-height\s+=\s+##f", r"extra-spacing-height = #'(0 . 0)", str)
2792     return str
2793
2794 @rule ((2, 11, 55), "#(set-octavation oct) -> \\ottava #oct,\n\
2795 \\put-adjacent markup axis dir markup -> \\put-adjacent axis dir markup markup")
2796 def conv (str):    
2797     str = re.sub (r"#\(set-octavation (-*[0-9]+)\)", r"\\ottava #\1", str)
2798     if re.search ('put-adjacent', str):
2799         stderr_write (NOT_SMART % _ ("\\put-adjacent argument order.\n"))
2800         stderr_write (_ ("Axis and direction now come before markups:\n"))
2801         stderr_write (_ ("\\put-adjacent axis dir markup markup."))
2802     return str
2803
2804 # Guidelines to write rules (please keep this at the end of this file)
2805 #
2806 # - keep at most one rule per version; if several conversions should be done,
2807 # concatenate them into a single "conv" function;
2808 #
2809 # - enclose strings to be localized with `_(' and  `)';
2810 #
2811 # - write rule for bumping major stable version with
2812 #
2813 #     _ ("bump version for release")
2814 #  
2815 # as exact description.