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