* python/lilylib.py (setup_temp): temporary directories are mode 700.
[lilypond.git] / scripts / convert-ly.py
blobed2e099ddae168b1d6f63bf5d56620b4bf136bcb
1 #!@PYTHON@
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--2002 Han-Wen Nienhuys <hanwen@cs.uu.nl>
8 # Jan Nieuwenhuizen <janneke@gnu.org>
11 # TODO
12 # use -f and -t for -s output
14 # NEWS
15 # 0.2
16 # - rewrite in python
18 program_name = 'convert-ly'
19 version = '@TOPLEVEL_VERSION@'
21 import os
22 import sys
23 import __main__
24 import getopt
25 import string
26 import re
27 import time
29 # Did we ever have \mudela-version? I doubt it.
30 # lilypond_version_re_str = '\\\\version *\"(.*)\"'
31 lilypond_version_re_str = '\\\\(mudela-)?version *\"(.*)\"'
32 lilypond_version_re = re.compile (lilypond_version_re_str)
33 add_version = 1
36 def program_id ():
37 return '%s (GNU LilyPond) %s' %(program_name, version);
39 def identify ():
40 sys.stderr.write (program_id () + '\n')
42 def usage ():
43 sys.stdout.write (
44 r"""Usage: %s [OPTION]... [FILE]...
45 Try to convert to newer lilypond-versions. The version number of the
46 input is guessed by default from \version directive
48 Options:
49 -a, --assume-old apply all conversions to unversioned files
50 -h, --help print this help
51 -e, --edit in place edit
52 -f, --from=VERSION start from version. Overrides \version found in file.
53 -s, --show-rules print all rules.
54 -t, --to=VERSION target version
55 -n, --no-version don't add new version stamp.
56 --version print program version
58 Report bugs to bugs-gnu-music@gnu.org
60 """ % program_name)
63 sys.exit (0)
65 def print_version ():
67 sys.stdout.write (r"""%s
69 This is free software. It is covered by the GNU General Public
70 License, and you are welcome to change it and/or distribute copies of
71 it under certain conditions. invoke as `%s --warranty' for more
72 information.
74 """ % (program_id() , program_name))
76 def gulp_file(f):
77 try:
78 i = open(f)
79 i.seek (0, 2)
80 n = i.tell ()
81 i.seek (0,0)
82 except:
83 print 'can\'t open file: ' + f + '\n'
84 return ''
85 s = i.read (n)
86 if len (s) <= 0:
87 print 'gulped empty file: ' + f + '\n'
88 i.close ()
89 return s
91 def str_to_tuple (s):
92 return tuple (map (string.atoi, string.split (s,'.')))
94 def tup_to_str (t):
95 return string.join (map (lambda x: '%s' % x, list (t)), '.')
97 def version_cmp (t1, t2):
98 for x in [0,1,2]:
99 if t1[x] - t2[x]:
100 return t1[x] - t2[x]
101 return 0
103 def guess_lilypond_version (filename):
104 s = gulp_file (filename)
105 m = lilypond_version_re.search (s)
106 if m:
107 return m.group (2)
108 else:
109 return ''
111 class FatalConversionError:
112 pass
114 conversions = []
116 def show_rules (file):
117 for x in conversions:
118 file.write ('%s: %s\n' % (tup_to_str (x[0]), x[2]))
120 ############################
122 if 1:
123 def conv(str):
124 if re.search ('\\\\multi', str):
125 sys.stderr.write ('\nNot smart enough to convert \\multi')
126 return str
128 conversions.append (((0,1,9), conv, '\\header { key = concat + with + operator }'))
130 if 1: # need new a namespace
131 def conv (str):
132 if re.search ('\\\\octave', str):
133 sys.stderr.write ('\nNot smart enough to convert \\octave')
134 # raise FatalConversionError()
136 return str
138 conversions.append ((
139 ((0,1,19), conv, 'deprecated \\octave; can\'t convert automatically')))
142 if 1: # need new a namespace
143 def conv (str):
144 str = re.sub ('\\\\textstyle([^;]+);',
145 '\\\\property Lyrics . textstyle = \\1', str)
146 # harmful to current .lys
147 # str = re.sub ('\\\\key([^;]+);', '\\\\accidentals \\1;', str)
149 return str
151 conversions.append ((
152 ((0,1,20), conv, 'deprecated \\textstyle, new \key syntax')))
155 if 1:
156 def conv (str):
157 str = re.sub ('\\\\musical_pitch', '\\\\musicalpitch',str)
158 str = re.sub ('\\\\meter', '\\\\time',str)
160 return str
162 conversions.append ((
163 ((0,1,21), conv, '\\musical_pitch -> \\musicalpitch, '+
164 '\\meter -> \\time')))
166 if 1:
167 def conv (str):
168 return str
170 conversions.append ((
171 ((1,0,0), conv, '0.1.21 -> 1.0.0 ')))
174 if 1:
175 def conv (str):
176 str = re.sub ('\\\\accidentals', '\\\\keysignature',str)
177 str = re.sub ('specialaccidentals *= *1', 'keyoctaviation = 0',str)
178 str = re.sub ('specialaccidentals *= *0', 'keyoctaviation = 1',str)
180 return str
182 conversions.append ((
183 ((1,0,1), conv, '\\accidentals -> \\keysignature, ' +
184 'specialaccidentals -> keyoctaviation')))
186 if 1:
187 def conv(str):
188 if re.search ('\\\\header', str):
189 sys.stderr.write ('\nNot smart enough to convert to new \\header format')
190 return str
192 conversions.append (((1,0,2), conv, '\\header { key = concat + with + operator }'))
194 if 1:
195 def conv(str):
196 str = re.sub ('\\\\melodic([^a-zA-Z])', '\\\\notes\\1',str)
197 return str
199 conversions.append (((1,0,3), conv, '\\melodic -> \\notes'))
201 if 1:
202 def conv(str):
203 str = re.sub ('default_paper *=', '',str)
204 str = re.sub ('default_midi *=', '',str)
205 return str
207 conversions.append (((1,0,4), conv, 'default_{paper,midi}'))
209 if 1:
210 def conv(str):
211 str = re.sub ('ChoireStaff', 'ChoirStaff',str)
212 str = re.sub ('\\\\output', 'output = ',str)
214 return str
216 conversions.append (((1,0,5), conv, 'ChoireStaff -> ChoirStaff'))
218 if 1:
219 def conv(str):
220 if re.search ('[a-zA-Z]+ = *\\translator',str):
221 sys.stderr.write ('\nNot smart enough to change \\translator syntax')
222 # raise FatalConversionError()
223 return str
225 conversions.append (((1,0,6), conv, 'foo = \\translator {\\type .. } ->\\translator {\\type ..; foo; }'))
228 if 1:
229 def conv(str):
230 str = re.sub ('\\\\lyrics*', '\\\\lyrics',str)
232 return str
234 conversions.append (((1,0,7), conv, '\\lyric -> \\lyrics'))
236 if 1:
237 def conv(str):
238 str = re.sub ('\\\\\\[/3+', '\\\\times 2/3 { ',str)
239 str = re.sub ('\\[/3+', '\\\\times 2/3 { [',str)
240 str = re.sub ('\\\\\\[([0-9/]+)', '\\\\times \\1 {',str)
241 str = re.sub ('\\[([0-9/]+)', '\\\\times \\1 { [',str)
242 str = re.sub ('\\\\\\]([0-9/]+)', '}', str)
243 str = re.sub ('\\\\\\]', '}',str)
244 str = re.sub ('\\]([0-9/]+)', '] }', str)
245 return str
247 conversions.append (((1,0,10), conv, '[2/3 ]1/1 -> \\times 2/3 '))
249 if 1:
250 def conv(str):
251 return str
252 conversions.append (((1,0,12), conv, 'Chord syntax stuff'))
255 if 1:
256 def conv(str):
259 str = re.sub ('<([^>~]+)~([^>]*)>','<\\1 \\2> ~', str)
261 return str
263 conversions.append (((1,0,13), conv, '<a ~ b> c -> <a b> ~ c'))
265 if 1:
266 def conv(str):
267 str = re.sub ('<\\[','[<', str)
268 str = re.sub ('\\]>','>]', str)
270 return str
272 conversions.append (((1,0,14), conv, '<[a b> <a b]>c -> [<a b> <a b>]'))
275 if 1:
276 def conv(str):
277 str = re.sub ('\\\\type([^\n]*engraver)','\\\\TYPE\\1', str)
278 str = re.sub ('\\\\type([^\n]*performer)','\\\\TYPE\\1', str)
279 str = re.sub ('\\\\type','\\\\context', str)
280 str = re.sub ('\\\\TYPE','\\\\type', str)
281 str = re.sub ('textstyle','textStyle', str)
283 return str
285 conversions.append (((1,0,16), conv, '\\type -> \\context, textstyle -> textStyle'))
288 if 1:
289 def conv(str):
290 if re.search ('\\\\repeat',str):
291 sys.stderr.write ('\nNot smart enough to convert \\repeat')
292 # raise FatalConversionError()
293 return str
295 conversions.append (((1,0,18), conv,
296 '\\repeat NUM Music Alternative -> \\repeat FOLDSTR Music Alternative'))
298 if 1:
299 def conv(str):
300 str = re.sub ('SkipBars','skipBars', str)
301 str = re.sub ('fontsize','fontSize', str)
302 str = re.sub ('midi_instrument','midiInstrument', str)
304 return str
306 conversions.append (((1,0,19), conv,
307 'fontsize -> fontSize, midi_instrument -> midiInstrument, SkipBars -> skipBars'))
310 if 1:
311 def conv(str):
312 str = re.sub ('tieydirection','tieVerticalDirection', str)
313 str = re.sub ('slurydirection','slurVerticalDirection', str)
314 str = re.sub ('ydirection','verticalDirection', str)
316 return str
318 conversions.append (((1,0,20), conv,
319 '{,tie,slur}ydirection -> {v,tieV,slurV}erticalDirection'))
322 if 1:
323 def conv(str):
324 str = re.sub ('hshift','horizontalNoteShift', str)
326 return str
328 conversions.append (((1,0,21), conv,
329 'hshift -> horizontalNoteShift'))
332 if 1:
333 def conv(str):
334 str = re.sub ('\\\\grouping[^;]*;','', str)
336 return str
338 conversions.append (((1,1,52), conv,
339 'deprecate \\grouping'))
342 if 1:
343 def conv(str):
344 str = re.sub ('\\\\wheel','\\\\coda', str)
346 return str
348 conversions.append (((1,1,55), conv,
349 '\\wheel -> \\coda'))
351 if 1:
352 def conv(str):
353 str = re.sub ('keyoctaviation','keyOctaviation', str)
354 str = re.sub ('slurdash','slurDash', str)
356 return str
358 conversions.append (((1,1,65), conv,
359 'slurdash -> slurDash, keyoctaviation -> keyOctaviation'))
361 if 1:
362 def conv(str):
363 str = re.sub ('\\\\repeat *\"?semi\"?','\\\\repeat "volta"', str)
365 return str
367 conversions.append (((1,1,66), conv,
368 'semi -> volta'))
371 if 1:
372 def conv(str):
373 str = re.sub ('\"?beamAuto\"? *= *\"?0?\"?','noAutoBeaming = "1"', str)
375 return str
377 conversions.append (((1,1,67), conv,
378 'beamAuto -> noAutoBeaming'))
380 if 1:
381 def conv(str):
382 str = re.sub ('automaticMelismas', 'automaticMelismata', str)
384 return str
386 conversions.append (((1,2,0), conv,
387 'automaticMelismas -> automaticMelismata'))
389 if 1:
390 def conv(str):
391 str = re.sub ('dynamicDir\\b', 'dynamicDirection', str)
393 return str
395 conversions.append (((1,2,1), conv,
396 'dynamicDir -> dynamicDirection'))
398 if 1:
399 def conv(str):
400 str = re.sub ('\\\\cadenza *0 *;', '\\\\cadenzaOff', str)
401 str = re.sub ('\\\\cadenza *1 *;', '\\\\cadenzaOn', str)
403 return str
405 conversions.append (((1,3,4), conv,
406 '\\cadenza -> \cadenza{On|Off}'))
408 if 1:
409 def conv (str):
410 str = re.sub ('"?beamAuto([^"=]+)"? *= *"([0-9]+)/([0-9]+)" *;*',
411 'beamAuto\\1 = #(make-moment \\2 \\3)',
412 str)
413 return str
415 conversions.append (((1,3,5), conv, 'beamAuto moment properties'))
417 if 1:
418 def conv (str):
419 str = re.sub ('stemStyle',
420 'flagStyle',
421 str)
422 return str
424 conversions.append (((1,3,17), conv, 'stemStyle -> flagStyle'))
426 if 1:
427 def conv (str):
428 str = re.sub ('staffLineLeading',
429 'staffSpace',
430 str)
431 return str
433 conversions.append (((1,3,18), conv, 'staffLineLeading -> staffSpace'))
436 if 1:
437 def conv(str):
438 if re.search ('\\\\repetitions',str):
439 sys.stderr.write ('\nNot smart enough to convert \\repetitions')
440 # raise FatalConversionError()
441 return str
443 conversions.append (((1,3,23), conv,
444 '\\\\repetitions feature dropped'))
447 if 1:
448 def conv (str):
449 str = re.sub ('textEmptyDimension *= *##t',
450 'textNonEmpty = ##f',
451 str)
452 str = re.sub ('textEmptyDimension *= *##f',
453 'textNonEmpty = ##t',
454 str)
455 return str
457 conversions.append (((1,3,35), conv, 'textEmptyDimension -> textNonEmpty'))
459 if 1:
460 def conv (str):
461 str = re.sub ("([a-z]+)[ \t]*=[ \t]*\\\\musicalpitch *{([- 0-9]+)} *\n",
462 "(\\1 . (\\2))\n", str)
463 str = re.sub ("\\\\musicalpitch *{([0-9 -]+)}",
464 "\\\\musicalpitch #'(\\1)", str)
465 if re.search ('\\\\notenames',str):
466 sys.stderr.write ('\nNot smart enough to convert to new \\notenames format')
467 return str
469 conversions.append (((1,3,38), conv, '\musicalpitch { a b c } -> #\'(a b c)'))
471 if 1:
472 def conv (str):
473 def replace (match):
474 return '\\key %s;' % string.lower (match.group (1))
476 str = re.sub ("\\\\key ([^;]+);", replace, str)
477 return str
479 conversions.append (((1,3,39), conv, '\\key A ; ->\\key a;'))
481 if 1:
482 def conv (str):
483 if re.search ('\\[:',str):
484 sys.stderr.write ('\nNot smart enough to convert to new tremolo format')
485 return str
487 conversions.append (((1,3,41), conv,
488 '[:16 c4 d4 ] -> \\repeat "tremolo" 2 { c16 d16 }'))
490 if 1:
491 def conv (str):
492 str = re.sub ('Staff_margin_engraver' , 'Instrument_name_engraver', str)
493 return str
495 conversions.append (((1,3,42), conv,
496 'Staff_margin_engraver deprecated, use Instrument_name_engraver'))
498 if 1:
499 def conv (str):
500 str = re.sub ('note[hH]eadStyle\\s*=\\s*"?(\\w+)"?' , "noteHeadStyle = #'\\1", str)
501 return str
503 conversions.append (((1,3,49), conv,
504 'noteHeadStyle value: string -> symbol'))
506 if 1:
507 def conv (str):
508 if re.search ('\\\\keysignature', str):
509 sys.stderr.write ('\nNot smart enough to convert to new tremolo format')
510 return str
513 conversions.append (((1,3,58), conv,
514 'noteHeadStyle value: string -> symbol'))
516 if 1:
517 def conv (str):
518 str = re.sub (r"""\\key *([a-z]+) *;""", r"""\\key \1 \major;""",str);
519 return str
520 conversions.append (((1,3,59), conv,
521 '\key X ; -> \key X major; '))
523 if 1:
524 def conv (str):
525 str = re.sub (r'latexheaders *= *"\\\\input ',
526 'latexheaders = "',
527 str)
528 return str
529 conversions.append (((1,3,68), conv, 'latexheaders = "\\input global" -> latexheaders = "global"'))
534 # TODO: lots of other syntax change should be done here as well
535 if 1:
536 def conv (str):
537 str = re.sub ('basicCollisionProperties', 'NoteCollision', str)
538 str = re.sub ('basicVoltaSpannerProperties' , "VoltaBracket", str)
539 str = re.sub ('basicKeyProperties' , "KeySignature", str)
541 str = re.sub ('basicClefItemProperties' ,"Clef", str)
544 str = re.sub ('basicLocalKeyProperties' ,"Accidentals", str)
545 str = re.sub ('basicMarkProperties' ,"Accidentals", str)
546 str = re.sub ('basic([A-Za-z_]+)Properties', '\\1', str)
548 str = re.sub ('Repeat_engraver' ,'Volta_engraver', str)
549 return str
551 conversions.append (((1,3,92), conv, 'basicXXXProperties -> XXX, Repeat_engraver -> Volta_engraver'))
553 if 1:
554 def conv (str):
555 # Ugh, but meaning of \stemup changed too
556 # maybe we should do \stemup -> \stemUp\slurUp\tieUp ?
557 str = re.sub ('\\\\stemup', '\\\\stemUp', str)
558 str = re.sub ('\\\\stemdown', '\\\\stemDown', str)
559 str = re.sub ('\\\\stemboth', '\\\\stemBoth', str)
561 str = re.sub ('\\\\slurup', '\\\\slurUp', str)
562 str = re.sub ('\\\\slurboth', '\\\\slurBoth', str)
563 str = re.sub ('\\\\slurdown', '\\\\slurDown', str)
564 str = re.sub ('\\\\slurdotted', '\\\\slurDotted', str)
565 str = re.sub ('\\\\slurnormal', '\\\\slurNoDots', str)
567 str = re.sub ('\\\\shiftoff', '\\\\shiftOff', str)
568 str = re.sub ('\\\\shifton', '\\\\shiftOn', str)
569 str = re.sub ('\\\\shiftonn', '\\\\shiftOnn', str)
570 str = re.sub ('\\\\shiftonnn', '\\\\shiftOnnn', str)
572 str = re.sub ('\\\\onevoice', '\\\\oneVoice', str)
573 str = re.sub ('\\\\voiceone', '\\\\voiceOne', str)
574 str = re.sub ('\\\\voicetwo', '\\\\voiceTwo', str)
575 str = re.sub ('\\\\voicethree', '\\\\voiceThree', str)
576 str = re.sub ('\\\\voicefour', '\\\\voiceFour', str)
578 # I don't know exactly when these happened...
579 # ugh, we loose context setting here...
580 str = re.sub ('\\\\property *[^ ]*verticalDirection[^=]*= *#?"?(1|(\\\\up))"?', '\\\\stemUp\\\\slurUp\\\\tieUp', str)
581 str = re.sub ('\\\\property *[^ ]*verticalDirection[^=]*= *#?"?((-1)|(\\\\down))"?', '\\\\stemDown\\\\slurDown\\\\tieDown', str)
582 str = re.sub ('\\\\property *[^ ]*verticalDirection[^=]*= *#?"?(0|(\\\\center))"?', '\\\\stemBoth\\\\slurBoth\\\\tieBoth', str)
584 str = re.sub ('verticalDirection[^=]*= *#?"?(1|(\\\\up))"?', 'Stem \\\\override #\'direction = #0\nSlur \\\\override #\'direction = #0\n Tie \\\\override #\'direction = #1', str)
585 str = re.sub ('verticalDirection[^=]*= *#?"?((-1)|(\\\\down))"?', 'Stem \\\\override #\'direction = #0\nSlur \\\\override #\'direction = #0\n Tie \\\\override #\'direction = #-1', str)
586 str = re.sub ('verticalDirection[^=]*= *#?"?(0|(\\\\center))"?', 'Stem \\\\override #\'direction = #0\nSlur \\\\override #\'direction = #0\n Tie \\\\override #\'direction = #0', str)
588 str = re.sub ('\\\\property *[^ .]*[.]?([a-z]+)VerticalDirection[^=]*= *#?"?(1|(\\\\up))"?', '\\\\\\1Up', str)
589 str = re.sub ('\\\\property *[^ .]*[.]?([a-z]+)VerticalDirection[^=]*= *#?"?((-1)|(\\\\down))"?', '\\\\\\1Down', str)
590 str = re.sub ('\\\\property *[^ .]*[.]?([a-z]+)VerticalDirection[^=]*= *#?"?(0|(\\\\center))"?', '\\\\\\1Both', str)
592 # (lacks capitalisation slur -> Slur)
593 str = re.sub ('([a-z]+)VerticalDirection[^=]*= *#?"?(1|(\\\\up))"?', '\\1 \\\\override #\'direction = #1', str)
594 str = re.sub ('([a-z]+)VerticalDirection[^=]*= *#?"?((-1)|(\\\\down))"?', '\\1 \\override #\'direction = #-1', str)
595 str = re.sub ('([a-z]+)VerticalDirection[^=]*= *#?"?(0|(\\\\center))"?', '\\1 \\\\override #\'direction = #0', str)
597 ## dynamic..
598 str = re.sub ('\\\\property *[^ .]*[.]?dynamicDirection[^=]*= *#?"?(1|(\\\\up))"?', '\\\\dynamicUp', str)
599 str = re.sub ('\\\\property *[^ .]*[.]?dyn[^=]*= *#?"?((-1)|(\\\\down))"?', '\\\\dynamicDown', str)
600 str = re.sub ('\\\\property *[^ .]*[.]?dyn[^=]*= *#?"?(0|(\\\\center))"?', '\\\\dynamicBoth', str)
602 str = re.sub ('\\\\property *[^ .]*[.]?([a-z]+)Dash[^=]*= *#?"?(0|(""))"?', '\\\\\\1NoDots', str)
603 str = re.sub ('\\\\property *[^ .]*[.]?([a-z]+)Dash[^=]*= *#?"?([1-9]+)"?', '\\\\\\1Dotted', str)
605 str = re.sub ('\\\\property *[^ .]*[.]?noAutoBeaming[^=]*= *#?"?(0|(""))"?', '\\\\autoBeamOn', str)
606 str = re.sub ('\\\\property *[^ .]*[.]?noAutoBeaming[^=]*= *#?"?([1-9]+)"?', '\\\\autoBeamOff', str)
610 return str
612 conversions.append (((1,3,93), conv,
613 'property definiton case (eg. onevoice -> oneVoice)'))
616 if 1:
617 def conv (str):
618 str = re.sub ('ChordNames*', 'ChordNames', str)
619 if re.search ('\\\\textscript "[^"]* *"[^"]*"', str):
620 sys.stderr.write ('\nNot smart enough to convert to new \\textscript markup text')
622 str = re.sub ('\\textscript +("[^"]*")', '\\textscript #\\1', str)
624 return str
626 conversions.append (((1,3,97), conv, 'ChordName -> ChordNames'))
629 # TODO: add lots of these
631 if 1:
632 def conv (str):
633 str = re.sub ('\\\\property *"?Voice"? *[.] *"?textStyle"? *= *"([^"]*)"', '\\\\property Voice.TextScript \\\\set #\'font-style = #\'\\1', str)
634 str = re.sub ('\\\\property *"?Lyrics"? *[.] *"?textStyle"? *= *"([^"]*)"', '\\\\property Lyrics.LyricText \\\\set #\'font-style = #\'\\1', str)
636 str = re.sub ('\\\\property *"?([^.]+)"? *[.] *"?timeSignatureStyle"? *= *"([^"]*)"', '\\\\property \\1.TimeSignature \\\\override #\'style = #\'\\2', str)
638 str = re.sub ('"?timeSignatureStyle"? *= *#?""', 'TimeSignature \\\\override #\'style = ##f', str)
640 str = re.sub ('"?timeSignatureStyle"? *= *#?"([^"]*)"', 'TimeSignature \\\\override #\'style = #\'\\1', str)
642 str = re.sub ('#\'style *= #*"([^"])"', '#\'style = #\'\\1', str)
644 str = re.sub ('\\\\property *"?([^.]+)"? *[.] *"?horizontalNoteShift"? *= *"?#?([-0-9]+)"?', '\\\\property \\1.NoteColumn \\\\override #\'horizontal-shift = #\\2', str)
646 # ugh
647 str = re.sub ('\\\\property *"?([^.]+)"? *[.] *"?flagStyle"? *= *""', '\\\\property \\1.Stem \\\\override #\'flag-style = ##f', str)
649 str = re.sub ('\\\\property *"?([^.]+)"? *[.] *"?flagStyle"? *= *"([^"]*)"', '\\\\property \\1.Stem \\\\override #\'flag-style = #\'\\2', str)
650 return str
652 conversions.append (((1,3,98), conv, 'CONTEXT.textStyle -> GROB.#font-style '))
654 if 1:
655 def conv (str):
656 str = re.sub ('"?beamAutoEnd_([0-9]*)"? *= *(#\\([^)]*\\))', 'autoBeamSettings \\push #\'(end 1 \\1 * *) = \\2', str)
657 str = re.sub ('"?beamAutoBegin_([0-9]*)"? *= *(#\\([^)]*\))', 'autoBeamSettings \\push #\'(begin 1 \\1 * *) = \\2', str)
658 str = re.sub ('"?beamAutoEnd"? *= *(#\\([^)]*\\))', 'autoBeamSettings \\push #\'(end * * * *) = \\1', str)
659 str = re.sub ('"?beamAutoBegin"? *= *(#\\([^)]*\\))', 'autoBeamSettings \\push #\'(begin * * * *) = \\1', str)
662 return str
664 conversions.append (((1,3,102), conv, 'beamAutoEnd -> autoBeamSettings \\push (end * * * *)'))
667 if 1:
668 def conv (str):
669 str = re.sub ('\\\\push', '\\\\override', str)
670 str = re.sub ('\\\\pop', '\\\\revert', str)
672 return str
674 conversions.append (((1,3,111), conv, '\\push -> \\override, \\pop -> \\revert'))
676 if 1:
677 def conv (str):
678 str = re.sub ('LyricVoice', 'LyricsVoice', str)
679 # old fix
680 str = re.sub ('Chord[Nn]ames*.Chord[Nn]ames*', 'ChordNames.ChordName', str)
681 str = re.sub ('Chord[Nn]ames([ \t\n]+\\\\override)', 'ChordName\\1', str)
682 return str
684 conversions.append (((1,3,113), conv, 'LyricVoice -> LyricsVoice'))
686 def regularize_id (str):
687 s = ''
688 lastx = ''
689 for x in str:
690 if x == '_':
691 lastx = x
692 continue
693 elif x in string.digits:
694 x = chr(ord (x) - ord ('0') +ord ('A'))
695 elif x not in string.letters:
696 x = 'x'
697 elif x in string.lowercase and lastx == '_':
698 x = string.upper (x)
699 s = s + x
700 lastx = x
701 return s
703 if 1:
704 def conv (str):
706 def regularize_dollar_reference (match):
707 return regularize_id (match.group (1))
708 def regularize_assignment (match):
709 return '\n' + regularize_id (match.group (1)) + ' = '
710 str = re.sub ('\$([^\t\n ]+)', regularize_dollar_reference, str)
711 str = re.sub ('\n([^ \t\n]+)[ \t]*= *', regularize_assignment, str)
712 return str
714 conversions.append (((1,3,117), conv, 'identifier names: $!foo_bar_123 -> xfooBarABC'))
717 if 1:
718 def conv (str):
719 def regularize_paper (match):
720 return regularize_id (match.group (1))
722 str = re.sub ('(paper_[a-z]+)', regularize_paper, str)
723 str = re.sub ('sustainup', 'sustainUp', str)
724 str = re.sub ('nobreak', 'noBreak', str)
725 str = re.sub ('sustaindown', 'sustainDown', str)
726 str = re.sub ('sostenutoup', 'sostenutoUp', str)
727 str = re.sub ('sostenutodown', 'sostenutoDown', str)
728 str = re.sub ('unachorda', 'unaChorda', str)
729 str = re.sub ('trechorde', 'treChorde', str)
731 return str
733 conversions.append (((1,3,120), conv, 'paper_xxx -> paperXxxx, pedalup -> pedalUp.'))
735 if 1:
736 def conv (str):
737 str = re.sub ('drarnChords', 'chordChanges', str)
738 str = re.sub ('\\musicalpitch', '\\pitch', str)
739 return str
741 conversions.append (((1,3,122), conv, 'drarnChords -> chordChanges, \\musicalpitch -> \\pitch'))
743 if 1:
744 def conv (str):
745 str = re.sub ('ly-([sg])et-elt-property', 'ly-\\1et-grob-property', str)
746 return str
748 conversions.append (((1,3,136), conv, 'ly-X-elt-property -> ly-X-grob-property'))
750 if 1:
751 def conv (str):
752 str = re.sub ('point-and-click +#t', 'point-and-click line-column-location', str)
753 return str
755 conversions.append (((1,3,138), conv, 'point-and-click argument changed to procedure.'))
757 if 1:
758 def conv (str):
759 str = re.sub ('followThread', 'followVoice', str)
760 str = re.sub ('Thread.FollowThread', 'Voice.VoiceFollower', str)
761 str = re.sub ('FollowThread', 'VoiceFollower', str)
762 return str
764 conversions.append (((1,3,138), conv, 'followThread -> followVoice.'))
766 if 1:
767 def conv (str):
768 str = re.sub ('font-point-size', 'font-design-size', str)
769 return str
771 conversions.append (((1,3,139), conv, 'font-point-size -> font-design-size.'))
773 if 1:
774 def conv (str):
775 str = re.sub ('([a-zA-Z]*)NoDots', '\\1Solid', str)
776 return str
778 conversions.append (((1,3,141), conv, 'xNoDots -> xSolid'))
780 if 1:
781 def conv (str):
782 str = re.sub ('([Cc])hord([ea])', '\\1ord\\2', str)
783 return str
785 conversions.append (((1,3,144), conv, 'Chorda -> Corda'))
788 if 1:
789 def conv (str):
790 str = re.sub ('([A-Za-z]+)MinimumVerticalExtent', 'MinimumV@rticalExtent', str)
791 str = re.sub ('([A-Za-z]+)ExtraVerticalExtent', 'ExtraV@rticalExtent', str)
792 str = re.sub ('([A-Za-z]+)VerticalExtent', 'VerticalExtent', str)
793 str = re.sub ('ExtraV@rticalExtent', 'ExtraVerticalExtent', str)
794 str = re.sub ('MinimumV@rticalExtent', 'MinimumVerticalExtent', str)
795 return str
797 conversions.append (((1,3,145), conv,
798 'ContextNameXxxxVerticalExtent -> XxxxVerticalExtent'))
800 if 1:
801 def conv (str):
802 str = re.sub ('\\\\key[ \t]*;', '\\key \\default;', str)
803 str = re.sub ('\\\\mark[ \t]*;', '\\mark \\default;', str)
805 # Make sure groups of more than one ; have space before
806 # them, so that non of them gets removed by next rule
807 str = re.sub ("([^ \n\t;]);(;+)", "\\1 ;\\2", str)
809 # Only remove ; that are not after spaces, # or ;
810 # Otherwise we interfere with Scheme comments,
811 # which is badbadbad.
812 str = re.sub ("([^ \t;#]);", "\\1", str)
814 return str
815 conversions.append (((1,3,146), conv, 'semicolons removed'))
817 if 1:
818 def conv (str):
819 str = re.sub ('default-neutral-direction', 'neutral-direction',str)
820 return str
821 conversions.append (((1,3,147), conv, 'default-neutral-direction -> neutral-direction'))
823 if 1:
824 def conv (str):
825 str = re.sub ('\(align', '(axis', str)
826 str = re.sub ('\(rows', '(columns', str)
827 return str
828 conversions.append (((1,3,148), conv, '"(align" -> "(axis", "(rows" -> "(columns"'))
831 if 1:
832 def conv (str):
833 str = re.sub ('SystemStartDelimiter', 'systemStartDelimiter', str)
834 return str
835 conversions.append (((1,5,33), conv, 'SystemStartDelimiter -> systemStartDelimiter'))
837 if 1:
838 def conv (str):
839 str = re.sub ('arithmetic-multiplier', 'spacing-increment', str)
840 str = re.sub ('arithmetic-basicspace', 'shortest-duration-space', str)
841 return str
843 conversions.append (((1,5,38), conv, 'SystemStartDelimiter -> systemStartDelimiter'))
846 if 1:
847 def conv (str):
849 def func(match):
850 break_dict = {
851 "Instrument_name": "instrument-name",
852 "Left_edge_item": "left-edge",
853 "Span_bar": "span-bar",
854 "Breathing_sign": "breathing-sign",
855 "Staff_bar": "staff-bar",
856 "Clef_item": "clef",
857 "Key_item": "key-signature",
858 "Time_signature": "time-signature",
859 "Custos": "custos"
861 props = match.group (1)
862 for (k,v) in break_dict.items():
863 props = re.sub (k, v, props)
864 return "breakAlignOrder = #'(%s)" % props
866 str = re.sub ("breakAlignOrder *= *#'\\(([a-z_\n\tA-Z ]+)\\)",
867 func, str)
868 return str
870 # 40 ?
871 conversions.append (((1,5,40), conv, 'breakAlignOrder property names'))
874 if 1:
875 def conv (str):
876 str = re.sub ('noAutoBeaming *= *##f', 'autoBeaming = ##t', str)
877 str = re.sub ('noAutoBeaming *= *##t', 'autoBeaming = ##f', str)
878 return str
880 conversions.append (((1,5,49), conv, 'noAutoBeaming -> autoBeaming'))
882 if 1:
883 def conv (str):
884 str = re.sub ('tuplet-bracket-visibility', 'bracket-visibility', str)
885 str = re.sub ('tuplet-number-visibility', 'number-visibility', str)
886 return str
888 conversions.append (((1,5,52), conv, 'tuplet-X-visibility -> X-visibility'))
890 if 1:
891 def conv (str):
892 str = re.sub ('Pitch::transpose', 'ly-transpose-pitch', str)
894 return str
896 conversions.append (((1,5,56), conv, 'Pitch::transpose -> ly-transpose-pitch'))
898 if 1:
899 def conv (str):
900 str = re.sub ('textNonEmpty *= *##t', "TextScript \\set #'no-spacing-rods = ##f", str)
901 str = re.sub ('textNonEmpty *= *##f', "TextScript \\set #'no-spacing-rods = ##t", str)
902 return str
904 conversions.append (((1,5,58), conv, 'deprecate textNonEmpty'))
907 if 1:
908 def conv (str):
909 str = re.sub ('MinimumVerticalExtent', 'minimumV@rticalExtent', str)
910 str = re.sub ('minimumVerticalExtent', 'minimumV@rticalExtent', str)
911 str = re.sub ('ExtraVerticalExtent', 'extraV@rticalExtent', str)
912 str = re.sub ('extraVerticalExtent', 'extraV@rticalExtent', str)
913 str = re.sub ('VerticalExtent', 'verticalExtent', str)
914 str = re.sub ('extraV@rticalExtent', 'extraVerticalExtent', str)
915 str = re.sub ('minimumV@rticalExtent', 'minimumVerticalExtent', str)
916 return str
918 conversions.append (((1,5,59), conv,
919 'XxxxVerticalExtent -> xxxVerticalExtent'))
921 if 1:
922 def conv (str):
923 str = re.sub ('visibility-lambda', 'break-visibility', str)
924 return str
926 conversions.append (((1,5,62), conv,
927 'visibility-lambda -> break-visibility'))
930 if 1:
931 def conv (str):
932 if re.search (r'\addlyrics',str) \
933 and re.search ('automaticMelismata', str) == None:
934 sys.stderr.write ('automaticMelismata is turned on by default since 1.5.67. Please fix this by hand.')
935 raise FatalConversionError()
936 return str
938 conversions.append (((1,5,67), conv,
939 'automaticMelismata turned on by default'))
941 if 1:
942 def conv (str):
943 str = re.sub ('ly-set-grob-property([^!])', 'ly-set-grob-property!\1', str)
944 str = re.sub ('ly-set-mus-property([^!])', 'ly-set-mus-property!\1', str)
945 return str
947 conversions.append (((1,5,68), conv, 'ly-set-X-property -> ly-set-X-property!'))
949 if 1:
950 def conv (str):
951 str = re.sub ('extent-X', 'X-extent', str)
952 str = re.sub ('extent-Y', 'Y-extent', str)
953 return str
955 conversions.append (((1,5,71), conv, 'extent-[XY] -> [XY]-extent'))
958 if 1:
959 def conv (str):
960 str = re.sub ("""#\(set! +point-and-click +line-column-location\)""",
961 """#(set-point-and-click! \'line-column)""", str)
962 str = re.sub ("""#\(set![ \t]+point-and-click +line-location\)""",
963 '#(set-point-and-click! \'line)', str)
964 str = re.sub ('#\(set! +point-and-click +#f\)',
965 '#(set-point-and-click! \'none)', str)
966 return str
968 conversions.append (((1,5,72), conv, 'set! point-and-click -> set-point-and-click!'))
971 if 1:
972 def conv (str):
973 str = re.sub ('flag-style', 'stroke-style', str)
974 str = re.sub (r"""Stem([ ]+)\\override #'style""", r"""Stem \\override #'flag-style""", str);
975 str = re.sub (r"""Stem([ ]+)\\set([ ]+)#'style""", r"""Stem \\set #'flag-style""", str);
976 return str
978 conversions.append (((1,6,5), conv, 'Stems: flag-style -> stroke-style; style -> flag-style'))
981 if 1:
982 def subst_req_name (match):
983 return "(make-music-by-name \'%sEvent)" % regularize_id (match.group(1))
985 def conv (str):
986 str = re.sub ('\\(ly-make-music *\"([A-Z][a-z_]+)_req\"\\)', subst_req_name, str)
987 str = re.sub ('Request_chord', 'EventChord', str)
988 return str
990 conversions.append (((1,7,1), conv, 'ly-make-music foo_bar_req -> make-music-by-name FooBarEvent'))
993 if 1:
994 spanner_subst ={
995 "text" : 'TextSpanEvent',
996 "decrescendo" : 'DecrescendoEvent',
997 "crescendo" : 'CrescendoEvent',
998 "Sustain" : 'SustainPedalEvent',
999 "slur" : 'SlurEvent',
1000 "UnaCorda" : 'UnaCordaEvent',
1001 "Sostenuto" : 'SostenutoEvent',
1003 def subst_ev_name (match):
1004 stype = 'STOP'
1005 if re.search ('start', match.group(1)):
1006 stype= 'START'
1008 mtype = spanner_subst[match.group(2)]
1009 return "(make-span-event '%s %s)" % (mtype , stype)
1011 def subst_definition_ev_name(match):
1012 return ' = #%s' % subst_ev_name (match)
1013 def subst_inline_ev_name (match):
1014 s = subst_ev_name (match)
1015 return '#(ly-export %s)' % s
1016 def subst_csp_definition (match):
1017 return ' = #(make-event-chord (list %s))' % subst_ev_name (match)
1018 def subst_csp_inline (match):
1019 return '#(ly-export (make-event-chord (list %s)))' % subst_ev_name (match)
1021 def conv (str):
1022 str = re.sub (r' *= *\\spanrequest *([^ ]+) *"([^"]+)"', subst_definition_ev_name, str)
1023 str = re.sub (r'\\spanrequest *([^ ]+) *"([^"]+)"', subst_inline_ev_name, str)
1024 str = re.sub (r' *= *\\commandspanrequest *([^ ]+) *"([^"]+)"', subst_csp_definition, str)
1025 str = re.sub (r'\\commandspanrequest *([^ ]+) *"([^"]+)"', subst_csp_inline, str)
1026 str = re.sub (r'ly-id ', 'ly-import ', str)
1028 str = re.sub (r' *= *\\script "([^"]+)"', ' = #(make-articulation "\\1")', str)
1029 str = re.sub (r'\\script "([^"]+)"', '#(ly-export (make-articulation "\\1"))', str)
1030 return str
1032 conversions.append (((1,7,2), conv, '\\spanrequest -> #(make-span-event .. ), \script -> #(make-articulation .. )'))
1034 if 1:
1035 def conv(str):
1036 str = re.sub (r'\(ly-', '(ly:', str)
1038 changed = [
1039 r'duration\?',
1040 r'font-metric\?',
1041 r'molecule\?',
1042 r'moment\?',
1043 r'music\?',
1044 r'pitch\?',
1045 'make-duration',
1046 'music-duration-length',
1047 'duration-log',
1048 'duration-dotcount',
1049 'intlog2',
1050 'duration-factor',
1051 'transpose-key-alist',
1052 'get-system',
1053 'get-broken-into',
1054 'get-original',
1055 'set-point-and-click!',
1056 'make-moment',
1057 'make-pitch',
1058 'pitch-octave',
1059 'pitch-alteration',
1060 'pitch-notename',
1061 'pitch-semitones',
1062 r'pitch<\?',
1063 r'dir\?',
1064 'music-duration-compress',
1065 'set-point-and-click!'
1068 origre = r'\b(%s)' % string.join (changed, '|')
1070 str = re.sub (origre, r'ly:\1',str)
1071 str = re.sub ('set-point-and-click!', 'set-point-and-click', str)
1073 return str
1075 conversions.append (((1,7,3), conv, 'ly- -> ly:'))
1077 if 1:
1078 def conv(str):
1079 if re.search ('new-chords-done',str):
1080 return str
1082 str = re.sub (r'<<', '< <', str)
1083 str = re.sub (r'>>', '> >', str)
1084 return str
1086 conversions.append (((1,7,4), conv, '<< >> -> < < > >'))
1088 if 1:
1089 def conv(str):
1090 str = re.sub (r"\\transpose", r"\\transpose c'", str)
1091 str = re.sub (r"\\transpose c' *([a-z]+)'", r"\\transpose c \1", str)
1092 return str
1093 conversions.append (((1,7,5), conv, '\\transpose TO -> \\transpose FROM TO'))
1095 if 1:
1096 def conv(str):
1097 kws = ['arpeggio',
1098 'sustainDown',
1099 'sustainUp',
1100 'f',
1101 'p',
1102 'pp',
1103 'ppp',
1104 'fp',
1105 'ff',
1106 'mf',
1107 'mp',
1108 'sfz',
1111 origstr = string.join (kws, '|')
1112 str = re.sub (r'([^_^-])\\(%s)\b' % origstr, r'\1-\\\2', str)
1113 return str
1114 conversions.append (((1,7,6), conv, 'note\\script -> note-\script'))
1117 if 1:
1118 def conv(str):
1119 str = re.sub (r"\\property *ChordNames *\. *ChordName *\\(set|override) *#'style *= *#('[a-z]+)",
1120 r"#(set-chord-name-style \2)", str)
1121 str = re.sub (r"\\property *ChordNames *\. *ChordName *\\revert *#'style",
1122 r"", str)
1123 return str
1124 conversions.append (((1,7,10), conv, "\property ChordName #'style -> #(set-chord-name-style 'style)"))
1128 if 1:
1129 def conv(str):
1130 str = re.sub (r"ly:transpose-pitch", "ly:pitch-transpose", str)
1132 return str
1133 conversions.append (((1,7,11), conv, "transpose-pitch -> pitch-transpose"))
1135 if 1:
1136 def conv(str):
1137 str = re.sub (r"ly:get-molecule-extent", "ly:molecule-get-extent", str)
1138 str = re.sub (r"ly:set-molecule-extent!", "ly:molecule-set-extent!", str)
1139 str = re.sub (r"ly:add-molecule", "ly:molecule-add", str)
1140 str = re.sub (r"ly:combine-molecule-at-edge", "ly:molecule-combine-at-edge", str)
1141 str = re.sub (r"ly:align-to!", "ly:molecule-align-to!", str)
1143 return str
1145 conversions.append (((1,7,13), conv, "ly:XX-molecule-YY -> ly:molecule-XX-YY"))
1149 ################################
1150 # END OF CONVERSIONS
1151 ################################
1153 def get_conversions (from_version, to_version):
1154 def version_b (v, f = from_version, t = to_version):
1155 return version_cmp (v[0], f) > 0 and version_cmp (v[0], t) <= 0
1156 return filter (version_b, conversions)
1159 def latest_version ():
1160 return conversions[-1][0]
1162 def do_conversion (infile, from_version, outfile, to_version):
1163 conv_list = get_conversions (from_version, to_version)
1165 sys.stderr.write ('Applying conversions: ')
1166 str = infile.read ()
1167 last_conversion = ()
1168 try:
1169 for x in conv_list:
1170 sys.stderr.write (tup_to_str (x[0]) + ', ')
1171 str = x[1] (str)
1172 last_conversion = x[0]
1174 except FatalConversionError:
1175 sys.stderr.write ('Error while converting; I won\'t convert any further')
1177 if last_conversion:
1178 sys.stderr.write ('\n')
1179 new_ver = '\\version \"%s\"' % tup_to_str (last_conversion)
1181 if re.search (lilypond_version_re_str, str):
1182 str = re.sub (lilypond_version_re_str,'\\'+new_ver , str)
1183 elif add_version:
1184 str = new_ver + '\n' + str
1186 outfile.write(str)
1188 return last_conversion
1190 class UnknownVersion:
1191 pass
1193 def do_one_file (infile_name):
1194 sys.stderr.write ('Processing `%s\' ... '% infile_name)
1195 outfile_name = ''
1196 if __main__.edit:
1197 outfile_name = infile_name + '.NEW'
1198 elif __main__.outfile_name:
1199 outfile_name = __main__.outfile_name
1201 if __main__.from_version:
1202 from_version = __main__.from_version
1203 else:
1204 guess = guess_lilypond_version (infile_name)
1205 if not guess:
1206 raise UnknownVersion()
1207 from_version = str_to_tuple (guess)
1209 if __main__.to_version:
1210 to_version = __main__.to_version
1211 else:
1212 to_version = latest_version ()
1215 if infile_name:
1216 infile = open (infile_name,'r')
1217 else:
1218 infile = sys.stdin
1220 if outfile_name:
1221 outfile = open (outfile_name, 'w')
1222 else:
1223 outfile = sys.stdout
1225 touched = do_conversion (infile, from_version, outfile, to_version)
1227 if infile_name:
1228 infile.close ()
1230 if outfile_name:
1231 outfile.close ()
1233 if __main__.edit and touched:
1234 try:
1235 os.remove(infile_name + '~')
1236 except:
1237 pass
1238 os.rename (infile_name, infile_name + '~')
1239 os.rename (infile_name + '.NEW', infile_name)
1241 sys.stderr.write ('\n')
1242 sys.stderr.flush ()
1244 edit = 0
1245 assume_old = 0
1246 to_version = ()
1247 from_version = ()
1248 outfile_name = ''
1250 (options, files) = getopt.getopt (
1251 sys.argv[1:], 'ao:f:t:senh', ['no-version', 'assume-old', 'version', 'output', 'show-rules', 'help', 'edit', 'from=', 'to='])
1253 for opt in options:
1254 o = opt[0]
1255 a = opt[1]
1256 if o== '--help' or o == '-h':
1257 usage ()
1258 sys.exit (0)
1259 if o == '--version' or o == '-v':
1260 print_version ()
1261 sys.exit (0)
1262 elif o== '--from' or o=='-f':
1263 from_version = str_to_tuple (a)
1264 elif o== '--to' or o=='-t':
1265 to_version = str_to_tuple (a)
1266 elif o== '--edit' or o == '-e':
1267 edit = 1
1268 elif o== '--show-rules' or o == '-s':
1269 show_rules (sys.stdout)
1270 sys.exit(0)
1271 elif o == '--output' or o == '-o':
1272 outfile_name = a
1273 elif o == '--assume-old' or o == '-a':
1274 assume_old = 1
1275 elif o == '--no-version' or o == '-n':
1276 add_version = 0
1277 else:
1278 print o
1279 raise getopt.error
1281 identify ()
1282 for f in files:
1283 if f == '-':
1284 f = ''
1285 if not os.path.isfile (f):
1286 continue
1287 try:
1288 do_one_file (f)
1289 except UnknownVersion:
1290 sys.stderr.write ('\n')
1291 sys.stderr.write ("%s: can't determine version for `%s'" % (program_name, f))
1292 sys.stderr.write ('\n')
1293 if assume_old:
1294 fv = from_version
1295 from_version = (0,0,0)
1296 do_one_file (f)
1297 from_version = fv
1298 else:
1299 sys.stderr.write ("%s: skipping: `%s' " % (program_name, f))
1300 pass
1301 sys.stderr.write ('\n')