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