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