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