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