X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=scripts%2Fabc2ly.py;h=e6e0d12407e4ed53006ee529da85f55f7ac7dbab;hb=HEAD;hp=e28577fb1c88b9eaed15d91b6b3309c5f42fc616;hpb=63d0ac052683737e60b2268c98d480ad5ab1227c;p=lilypond.git diff --git a/scripts/abc2ly.py b/scripts/abc2ly.py index e28577fb1c..e6e0d12407 100644 --- a/scripts/abc2ly.py +++ b/scripts/abc2ly.py @@ -1,11 +1,28 @@ #!@TARGET_PYTHON@ # -*- coding: utf-8 -*- + # once upon a rainy monday afternoon. + +# This file is part of LilyPond, the GNU music typesetter. +# +# LilyPond is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# LilyPond is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with LilyPond. If not, see . + # # ... # # (not finished.) -# ABC standard v1.6: http://www.gre.ac.uk/~c.walshaw/abc2mtex/abc.txt +# ABC standard v1.6: http://abcnotation.com/ # # Enhancements (Roy R. Rankin) # @@ -58,43 +75,36 @@ #TODO: # +# * coding style # * lilylib # * GNU style messages: warning:FILE:LINE: # * l10n -# +# # Convert to new chord styles. # # UNDEF -> None # - + import __main__ import getopt import sys import re -import string import os program_name = sys.argv[0] -for d in ['@lilypond_datadir@', - '@lilypond_libdir@']: - sys.path.insert (0, os.path.join (d, 'python')) - -# dynamic relocation, for GUB binaries. -bindir = os.path.abspath (os.path.split (sys.argv[0])[0]) -for p in ['share', 'lib']: - datadir = os.path.abspath (bindir + '/../%s/lilypond/current/python/' % p) - sys.path.insert (0, datadir) - +""" +@relocate-preamble@ +""" import lilylib as ly global _;_=ly._ version = '@TOPLEVEL_VERSION@' if version == '@' + 'TOPLEVEL_VERSION' + '@': - version = '(unknown version)' # uGUHGUHGHGUGH + version = '(unknown version)' # uGUHGUHGHGUGH UNDEF = 255 state = UNDEF @@ -124,38 +134,51 @@ def error (msg): sys.stderr.write (msg) if global_options.strict: sys.exit (1) - + def alphabet (i): return chr (i + ord('A')) - + def check_clef(s): + # the number gives the base_octave + clefs = [("treble", "treble", 0), + ("treble1", "french", 0), + ("bass3", "varbaritone", 0), + ("bass", "bass", 0), + ("alto4", "tenor", 0), + ("alto2", "mezzosoprano", 0), + ("alto1", "soprano", 0), + ("alto", "alto", 0), + ("perc", "percussion", 0)] + modifier = [("-8va", "_8", -1), + ("-8", "_8", -1), + ("\+8", "^8", +1), + ("8", "_8", -1)] + if not s: return '' - if re.match('-8va', s) or re.match('treble8', s): - # treble8 is used by abctab2ps; -8va is used by barfly, - # and by my patch to abc2ps. If there's ever a standard - # about this we'll support that. - s = s[4:] - state.base_octave = -1 - voices_append("\\clef \"G_8\"\n") - elif re.match('^treble', s): - s = s[6:] - if re.match ('^-8', s): - s = s[2:] - state.base_octave = -2 - voices_append("\\clef \"G_8\"\n") - else: - state.base_octave = 0 - voices_append("\\clef treble\n") - elif re.match('^alto', s): - s = s[4:] - state.base_octave = -1 - voices_append ("\\clef alto\n" ) - elif re.match('^bass',s ): - s = s[4:] - state.base_octave = -2 - voices_append ("\\clef bass\n" ) + clef = None; + octave = 0; + for c in clefs: + m = re.match('^'+c[0], s) + if m: + (clef, octave) = (c[1], c[2]) + s = s[m.end():] + break; + if not clef: + return s + + mod = ""; + for md in modifier: + m = re.match('^'+md[0], s) + if m: + mod = md[1]; + octave += md[2]; + s = s[m.end():] + break; + + state.base_octave = octave + voices_append ("\\clef \""+clef+mod+"\"\n") return s def select_voice (name, rol): @@ -181,7 +204,7 @@ def select_voice (name, rol): value = re.sub ('\\\\','\\\\\\\\', value) ## < 2.2 voices_append ("\\set Staff.instrument = %s\n" % value ) - + __main__.part_names = 1 elif keyword == "sname" or keyword == "snm": voices_append ("\\set Staff.instr = %s\n" % value ) @@ -193,24 +216,24 @@ def dump_header (outf,hdr): ks = hdr.keys () ks.sort () for k in ks: - hdr[k] = re.sub('"', '\\"', hdr[k]) + hdr[k] = re.sub('"', '\\"', hdr[k]) outf.write ('\t%s = "%s"\n'% (k,hdr[k])) outf.write ('}') def dump_lyrics (outf): if (len(lyrics)): - outf.write("\n\\score\n{\n \\lyrics\n <<\n") + outf.write("\n\\markup \\column {\n") for i in range (len (lyrics)): - outf.write ( lyrics [i]) + outf.write (lyrics [i]) outf.write ("\n") - outf.write(" >>\n \\layout{}\n}\n") + outf.write("}\n") def dump_default_bar (outf): """ Nowadays abc2ly outputs explicits barlines (?) """ ## < 2.2 - outf.write ("\n\\set Score.defaultBarType = \"empty\"\n") + outf.write ("\n\\set Score.defaultBarType = \"\"\n") def dump_slyrics (outf): @@ -218,12 +241,12 @@ def dump_slyrics (outf): ks.sort () for k in ks: if re.match('[1-9]', k): - m = alphabet(string.atoi(k)) + m = alphabet (int (k)) else: m = k for i in range (len(slyrics[voice_idx_dict[k]])): l= alphabet(i) - outf.write ("\nwords%sV%s = \lyricmode {" % (m, l)) + outf.write ("\nwords%sV%s = \\lyricmode {" % (m, l)) outf.write ("\n" + slyrics [voice_idx_dict[k]][i]) outf.write ("\n}") @@ -233,7 +256,7 @@ def dump_voices (outf): ks.sort () for k in ks: if re.match ('[1-9]', k): - m = alphabet(string.atoi(k)) + m = alphabet (int (k)) else: m = k outf.write ("\nvoice%s = {" % m) @@ -249,22 +272,28 @@ def dump_voices (outf): outf.write ("\n}") def try_parse_q(a): - global midi_specs - #assume that Q takes the form "Q:1/4=120" + #assume that Q takes the form "Q:'opt. description' 1/4=120" #There are other possibilities, but they are deprecated - if string.count(a, '/') == 1: - array=string.split(a,'/') - numerator=array[0] - if int(numerator) != 1: - sys.stderr.write("abc2ly: Warning, unable to translate a Q specification with a numerator of %s: %s\n" % (numerator, a)) - array2=string.split(array[1],'=') - denominator=array2[0] - perminute=array2[1] - duration=str(string.atoi(denominator)/string.atoi(numerator)) - midi_specs=string.join([" \n\t\t\context {\n\t\t \Score tempoWholesPerMinute = #(ly:make-moment ", perminute, " ", duration, ")\n\t\t }\n"]) + r = re.compile ('^(.*) *([0-9]+) */ *([0-9]+) *=* *([0-9]+)\s*') + m = r.match (a) + if m: + descr = m.group(1) # possibly empty + numerator = int(m.group (2)) + denominator = int(m.group (3)) + tempo = m.group (4) + dur = duration_to_lilypond_duration ((numerator,denominator), 1, 0) + voices_append ("\\tempo " + descr + " " + dur + "=" + tempo + "\n") else: - sys.stderr.write("abc2ly: Warning, unable to parse Q specification: %s\n" % a) - + # Parsing of numeric tempi, as these are fairly + # common. The spec says the number is a "beat" so using + # a quarter note as the standard time + numericQ = re.compile ('[0-9]+') + m = numericQ.match (a) + if m: + voices_append ("\\tempo 4=" + m.group(0)) + else: + sys.stderr.write("abc2ly: Warning, unable to parse Q specification: %s\n" % a) + def dump_score (outf): outf.write (r""" @@ -276,12 +305,12 @@ def dump_score (outf): ks.sort () for k in ks: if re.match('[1-9]', k): - m = alphabet (string.atoi(k)) + m = alphabet (int (k)) else: m = k if k == 'default' and len (voice_idx_dict) > 1: break - outf.write ("\n\t\\context Staff=\"%s\"\n\t{\n" %k ) + outf.write ("\n\t\\context Staff=\"%s\"\n\t{\n" %k ) if k != 'default': outf.write ("\t \\voicedefault\n") outf.write ("\t \\voice%s " % m) @@ -289,9 +318,9 @@ def dump_score (outf): l = ord( 'A' ) for lyrics in slyrics [voice_idx_dict[k]]: - outf.write ("\n\t\\addlyrics { \n") + outf.write ("\n\t\\addlyrics {\n") if re.match('[1-9]',k): - m = alphabet (string.atoi(k)) + m = alphabet (int (k)) else: m = k @@ -308,14 +337,14 @@ def set_default_length (s): global length_specified m = re.search ('1/([0-9]+)', s) if m: - __main__.default_len = string.atoi ( m.group (1)) + __main__.default_len = int ( m.group (1)) length_specified = 1 def set_default_len_from_time_sig (s): m = re.search ('([0-9]+)/([0-9]+)', s) if m: - n = string.atoi (m.group (1)) - d = string.atoi (m.group (2)) + n = int (m.group (1)) + d = int (m.group (2)) if (n * 1.0 )/(d * 1.0) < 0.75: __main__.default_len = 16 else: @@ -328,7 +357,7 @@ def gulp_file(f): n = i.tell () i.seek (0,0) except: - sys.stderr.write ("can't open file: `%s'\n" % f) + sys.stderr.write ("cannot open file: `%s'\n" % f) return '' s = i.read (n) if len (s) <= 0: @@ -339,17 +368,17 @@ def gulp_file(f): # pitch manipulation. Tuples are (name, alteration). # 0 is (central) C. Alteration -1 is a flat, Alteration +1 is a sharp -# pitch in semitones. +# pitch in semitones. def semitone_pitch (tup): p =0 t = tup[0] p = p + 12 * (t / 7) t = t % 7 - + if t > 2: p = p- 1 - + p = p + t* 2 + tup[1] return p @@ -358,7 +387,7 @@ def fifth_above_pitch (tup): difference = 7 - (semitone_pitch ((n,a)) - semitone_pitch (tup)) a = a + difference - + return (n,a) def sharp_keys (): @@ -392,29 +421,31 @@ def quart_above_pitch (tup): difference = 5 - (semitone_pitch ((n,a)) - semitone_pitch (tup)) a = a + difference - + return (n,a) key_lookup = { # abc to lilypond key mode names 'm' : 'minor', 'min' : 'minor', 'maj' : 'major', - 'major' : 'major', + 'major' : 'major', 'phr' : 'phrygian', 'ion' : 'ionian', 'loc' : 'locrian', 'aeo' : 'aeolian', 'mix' : 'mixolydian', - 'mixolydian' : 'mixolydian', + 'mixolydian' : 'mixolydian', 'lyd' : 'lydian', 'dor' : 'dorian', - 'dorian' : 'dorian' + 'dorian' : 'dorian' } def lily_key (k): + if k == 'none': + return orig = "" + k # UGR - k = string.lower (k) + k = k.lower () key = k[0] #UGH k = k[1:] @@ -455,28 +486,28 @@ key_shift = { # semitone shifts for key mode names 'min' : 3, 'minor' : 3, 'maj' : 0, - 'major' : 0, + 'major' : 0, 'phr' : -4, 'phrygian' : -4, 'ion' : 0, 'ionian' : 0, 'loc' : 1, - 'locrian' : 1, + 'locrian' : 1, 'aeo' : 3, 'aeolian' : 3, 'mix' : 5, - 'mixolydian' : 5, + 'mixolydian' : 5, 'lyd' : -5, - 'lydian' : -5, + 'lydian' : -5, 'dor' : -2, - 'dorian' : -2 + 'dorian' : -2 } def compute_key (k): - k = string.lower (k) + k = k.lower () intkey = (ord (k[0]) - ord('a') + 5) % 7 intkeyacc =0 k = k[1:] - + if k and k[0] == 'b': intkeyacc = -1 k = k[1:] @@ -487,7 +518,7 @@ def compute_key (k): if k and key_shift.has_key(k): (intkey, intkeyacc) = shift_key(intkey, intkeyacc, key_shift[k]) keytup = (intkey, intkeyacc) - + sharp_key_seq = sharp_keys () flat_key_seq = flat_keys () @@ -504,8 +535,8 @@ def compute_key (k): accseq = map (lambda x: (3*x + 3 ) % 7, range (1, key_count + 1)) else: error ("Huh?") - raise "Huh" - + raise Exception ("Huh") + key_table = [0] * 7 for a in accseq: key_table[a] = key_table[a] + accsign @@ -528,9 +559,9 @@ def try_parse_tuplet_begin (str, state): dig = str[1] str = str[2:] prev_tuplet_state = state.parsing_tuplet - state.parsing_tuplet = string.atoi (dig[0]) + state.parsing_tuplet = int (dig[0]) if prev_tuplet_state: - voices_append ("}") + voices_append ("}") voices_append ("\\times %s {" % tup_lookup[dig]) return str @@ -539,7 +570,7 @@ def try_parse_group_end (str, state): str = str[1:] close_beam_state(state) return str - + def header_append (key, a): s = '' if header.has_key (key): @@ -547,7 +578,7 @@ def header_append (key, a): header [key] = s + a def wordwrap(a, v): - linelen = len (v) - string.rfind(v, '\n') + linelen = len (v) - v.rfind ('\n') if linelen + len (a) > 80: v = v + '\n' return v + a + ' ' @@ -590,11 +621,11 @@ def repeat_prepend(): if not using_old: repeat_state[current_voice_idx] = 't' - + def lyrics_append(a): a = re.sub ('#', '\\#', a) # latex does not like naked #'s a = re.sub ('"', '\\"', a) # latex does not like naked "'s - a = '\t{ "' + a + '" }\n' + a = ' \\line { "' + a + '" }\n' stuff_append (lyrics, current_lyric_idx, a) # break lyrics to words and put "'s around words containing numbers and '"'s @@ -617,7 +648,7 @@ def fix_lyric(str): def slyrics_append(a): a = re.sub ( '_', ' _ ', a) # _ to ' _ ' - a = re.sub ( '([^-])-([^-])', '\\1- \\2', a) # split words with "-" unless was originally "--" + a = re.sub ( '([^-])-([^-])', '\\1- \\2', a) # split words with "-" unless was originally "--" a = re.sub ( '\\\\- ', '-', a) # unless \- a = re.sub ( '~', '_', a) # ~ to space('_') a = re.sub ( '\*', '_ ', a) # * to to space @@ -657,12 +688,12 @@ def try_parse_header_line (ln, state): if a == 'C': if not state.common_time: state.common_time = 1 - voices_append (" \\override Staff.TimeSignature #\'style = #'C\n") + voices_append (" \\override Staff.TimeSignature #'style = #'C\n") a = '4/4' if a == 'C|': if not state.common_time: state.common_time = 1 - voices_append ("\\override Staff.TimeSignature #\'style = #'C\n") + voices_append ("\\override Staff.TimeSignature #'style = #'C\n") a = '2/2' if not length_specified: set_default_len_from_time_sig (a) @@ -674,16 +705,19 @@ def try_parse_header_line (ln, state): if g == 'K': # KEY a = check_clef(a) if a: - m = re.match ('^([^ \t]*) *(.*)$', a) # seperate clef info + m = re.match ('^([^ \t]*) *([^ ]*)( *)(.*)$', a) # separate clef info if m: # there may or may not be a space # between the key letter and the mode - if key_lookup.has_key(m.group(2)[0:3]): - key_info = m.group(1) + m.group(2)[0:3] - clef_info = m.group(2)[4:] + # convert the mode to lower-case before comparing + mode = m.group(2)[0:3].lower(); + if key_lookup.has_key(mode): + # use the full mode, not only the first three letters + key_info = m.group(1) + m.group(2).lower() + clef_info = a[m.start(4):] else: key_info = m.group(1) - clef_info = m.group(2) + clef_info = a[m.start(2):] __main__.global_key = compute_key (key_info) k = lily_key (key_info) if k: @@ -716,7 +750,7 @@ def try_parse_header_line (ln, state): header ['subtitle'] = a if g == 'L': # Default note length set_default_length (ln) - if g == 'V': # Voice + if g == 'V': # Voice voice = re.sub (' .*$', '', a) rest = re.sub ('^[^ \t]* *', '', a) if state.next_bar: @@ -727,8 +761,12 @@ def try_parse_header_line (ln, state): lyrics_append(a) if g == 'w': # vocals slyrics_append (a) - if g == 'Q': #tempo + if g == 'Q': # tempo try_parse_q (a) + if g == 'R': # Rhythm (e.g. jig, reel, hornpipe) + header['meter'] = a + if g == 'Z': # Transcription (e.g. Steve Mansfield 1/2/2000) + header['transcription'] = a return '' return ln @@ -745,7 +783,7 @@ def pitch_to_lilypond_name (name, acc, bar_acc, key): s = 'es' elif acc == 1: s = 'is' - + if name > 4: name = name -7 return(chr (name + ord('c')) + s) @@ -770,7 +808,7 @@ def parse_num (str): n = None if durstr: - n =string.atoi (durstr) + n = int (durstr) return (str,n) @@ -786,7 +824,7 @@ def duration_to_lilypond_duration (multiply_tup, defaultlen, dots): base = '\\breve' dots = 1 if (multiply_tup[0] / multiply_tup[1]) == 4: - base = '\longa' + base = '\\longa' return '%s%s' % ( base, '.'* dots) class Parser_state: @@ -804,7 +842,7 @@ class Parser_state: -# return (str, num,den,dots) +# return (str, num,den,dots) def parse_duration (str, parser_state): num = 0 den = parser_state.next_den @@ -825,7 +863,7 @@ def parse_duration (str, parser_state): den = den * d den = den * default_len - + current_dots = parser_state.next_dots parser_state.next_dots = 0 if re.match ('[ \t]*[<>]', str): @@ -835,7 +873,7 @@ def parse_duration (str, parser_state): str = str [1:] current_dots = current_dots + 1 parser_state.next_den = parser_state.next_den * 2 - + while str[0] == '<': str = str [1:] den = den * 2 @@ -851,7 +889,7 @@ def parse_duration (str, parser_state): num = num / multiplier den = den / f current_dots = current_dots + d - + return (str, num,den,current_dots) @@ -894,7 +932,7 @@ artic_tbl = { 'O' : '^\\coda', 'v' : '^\\downbow' } - + def try_parse_articulation (str, state): while str and artic_tbl.has_key(str[:1]): state.next_articulation = state.next_articulation + artic_tbl[str[:1]] @@ -903,11 +941,11 @@ def try_parse_articulation (str, state): str = str[1:] - - - # s7m2 input doesnt care about spaces + + + # s7m2 input doesn't care about spaces if re.match('[ \t]*\(', str): - str = string.lstrip (str) + str = str.lstrip () slur_begin =0 while str[:1] =='(' and str[1] not in DIGITS: @@ -916,7 +954,7 @@ def try_parse_articulation (str, state): str = str[1:] return str - + # # remember accidental for rest of bar # @@ -935,9 +973,8 @@ def get_bar_acc(note, octave, state): return(UNDEF) def clear_bar_acc(state): - for k in state.in_acc.keys(): - del state.in_acc[k] - + state.in_acc = {} + # if we are parsing a beam, close it off def close_beam_state(state): @@ -945,7 +982,7 @@ def close_beam_state(state): state.parsing_beam = 0 voices_append_back( ']' ) - + # WAT IS ABC EEN ONTZETTENDE PROGRAMMEERPOEP ! def try_parse_note (str, parser_state): mud = '' @@ -968,7 +1005,7 @@ def try_parse_note (str, parser_state): octave = parser_state.base_octave if str[0] in "ABCDEFG": - str = string.lower (str[0]) + str[1:] + str = str[0].lower () + str[1:] octave = octave - 1 @@ -979,7 +1016,7 @@ def try_parse_note (str, parser_state): else: return str # failed; not a note! - + __main__.lyric_idx = -1 if parser_state.next_bar: @@ -996,14 +1033,14 @@ def try_parse_note (str, parser_state): (str, num,den,current_dots) = parse_duration (str, parser_state) if re.match('[ \t]*\)', str): - str = string.lstrip (str) - + str = str.lstrip () + slur_end =0 while str[:1] ==')': slur_end = slur_end + 1 str = str[1:] - + bar_acc = get_bar_acc(notename, octave, parser_state) pit = pitch_to_lilypond_name(notename, acc, bar_acc, global_key[notename]) oct = octave_to_lilypond_quotes (octave) @@ -1014,7 +1051,7 @@ def try_parse_note (str, parser_state): voices_append ("%s%s%s%s" % (pit, oct, mod, duration_to_lilypond_duration ((num,den), default_len, current_dots))) - + set_bar_acc(notename, octave, acc, parser_state) if parser_state.next_articulation: articulation = articulation + parser_state.next_articulation @@ -1022,22 +1059,23 @@ def try_parse_note (str, parser_state): voices_append (articulation) - if parser_state.parsing_tuplet: - parser_state.parsing_tuplet = parser_state.parsing_tuplet - 1 - if not parser_state.parsing_tuplet: - voices_append ("}") if slur_begin: voices_append ('-(' * slur_begin ) if slur_end: voices_append ('-)' *slur_end ) + if parser_state.parsing_tuplet: + parser_state.parsing_tuplet = parser_state.parsing_tuplet - 1 + if not parser_state.parsing_tuplet: + voices_append ("}") + if global_options.beams and \ str[0] in '^=_ABCDEFGabcdefg' and \ not parser_state.parsing_beam and \ not parser_state.parsing_tuplet: parser_state.parsing_beam = 1 voices_append_back( '[' ) - + return str def junk_space (str,state): @@ -1060,7 +1098,7 @@ def try_parse_guitar_chord (str, state): while str and str[0] != '"': gc = gc + str[0] str = str[1:] - + if str: str = str[1:] gc = re.sub('#', '\\#', gc) # escape '#'s @@ -1071,7 +1109,7 @@ def try_parse_guitar_chord (str, state): def try_parse_escape (str): if not str or str [0] != '\\': return str - + str = str[1:] if str[:1] =='K': key_table = compute_key () @@ -1090,12 +1128,12 @@ old_bar_dict = { '|]' : '|.', '||' : '||', '[|' : '||', -':|' : ':|', +':|' : ':|.', '|:' : '|:', -'::' : ':|:', +'::' : ':|.|:', '|1' : '|', '|2' : '|', -':|2' : ':|', +':|2' : ':|.', '|' : '|' } bar_dict = { @@ -1168,18 +1206,21 @@ def try_parse_bar (str,state): str = str[1:] clear_bar_acc(state) close_beam_state(state) - + + if str[:1] == '}': + close_beam_state(state) + if bs <> None or state.next_bar != '': if state.parsing_tuplet: state.parsing_tuplet =0 voices_append ('} ') - + if bs <> None: clear_bar_acc(state) close_beam_state(state) voices_append (bs) if do_curly != '': - voices_append("} }") + voices_append("} ") do_curly = '' return str @@ -1229,7 +1270,7 @@ def try_parse_chord_delims (str, state): end = end + 1 str = str[1:] - + voices_append ("\\spanrequest \\stop \"slur\"" * end) voices_append (ch) return str @@ -1264,19 +1305,19 @@ def try_parse_comment (str): #Since ABC is frequently used for music in styles that do not use this #convention, such as most music written before 1700, or ethnic music in #non-western scales, it is necessary to be able to tell a translator that -#the barlines should not affect its interpretation of the pitch. +#the barlines should not affect its interpretation of the pitch. if 'nobarlines' in str: nobarlines = 1 elif str[0:3] == '%LY': - p = string.find(str, 'voices') + p = str.find ('voices') if (p > -1): voices_append(str[p+7:]) voices_append("\n") - p = string.find(str, 'slyrics') + p = str.find ('slyrics') if (p > -1): slyrics_append(str[p+8:]) - -#write other kinds of appending if we ever need them. + +#write other kinds of appending if we ever need them. return str lineno = 0 @@ -1289,10 +1330,11 @@ def parse_file (fn): select_voice('default', '') global lineno lineno = 0 - sys.stderr.write ("Line ... ") - sys.stderr.flush () + if not global_options.quiet: + sys.stderr.write ("Line ... ") + sys.stderr.flush () __main__.state = state_list[current_voice_idx] - + for ln in ls: lineno = lineno + 1 @@ -1307,7 +1349,8 @@ def parse_file (fn): ln = m.group (1) orig_ln = ln - + + ln = junk_space (ln, state) ln = try_parse_header_line (ln, state) # Try nibbling characters off until the line doesn't change. @@ -1331,14 +1374,15 @@ def parse_file (fn): error ("%s: %d: Huh? Don't understand\n" % (fn, lineno)) left = orig_ln[0:-len (ln)] sys.stderr.write (left + '\n') - sys.stderr.write (' ' * len (left) + ln + '\n') + sys.stderr.write (' ' * len (left) + ln + '\n') def identify(): - sys.stderr.write ("%s from LilyPond %s\n" % (program_name, version)) + if not global_options.quiet: + sys.stderr.write ("%s from LilyPond %s\n" % (program_name, version)) authors = """ -Written by Han-Wen Nienhuys , Laura Conrad +Written by Han-Wen Nienhuys , Laura Conrad , Roy Rankin . """ @@ -1346,40 +1390,58 @@ def print_version (): print r"""abc2ly (GNU lilypond) %s""" % version def get_option_parser (): - p = ly.get_option_parser (usage='abc2ly [OPTIONS] FILE', - version="abc2ly (LilyPond) @TOPLEVEL_VERSION@", - description=_('''This program converts ABC music files (see -http://www.gre.ac.uk/~c.walshaw/abc2mtex/abc.txt) to LilyPond input.''')) - - p.add_option ('-o', '--output', metavar='FILE',help=_("set output filename to FILE"), - action='store') - p.add_option ('-s', '--strict', help=_("be strict about succes"), - action='store_true') - p.add_option ('-b', '--beams', help=_("preserve ABC's notion of beams")) - p.add_option_group ('bugs', - description='''Report bugs via http://post.gmane.org/post.php''' - '''?group=gmane.comp.gnu.lilypond.bugs\n''') - + p = ly.get_option_parser (usage=_ ("%s [OPTION]... FILE") % 'abc2ly', + description=_ ('''abc2ly converts ABC music files (see +%s) to LilyPond input. +''') % 'http://abcnotation.com/abc2mtex/abc.txt', + add_help_option=False) + + p.version = "abc2ly (LilyPond) @TOPLEVEL_VERSION@" + p.add_option("--version", + action="version", + help=_ ("show version number and exit")) + p.add_option("-h", "--help", + action="help", + help=_ ("show this help and exit")) + p.add_option ("-o", "--output", metavar='FILE', + action="store", + help=_ ("write output to FILE")) + p.add_option ("-s", "--strict", + action="store_true", + help=_ ("be strict about success")) + p.add_option ('-b', '--beams', + action="store_true", + help=_ ("preserve ABC's notion of beams")) + p.add_option ('-q', '--quiet', + action="store_true", + help=_ ("suppress progress messages")) + p.add_option_group ('', + description=( + _ ('Report bugs via %s') + % 'http://post.gmane.org/post.php' + '?group=gmane.comp.gnu.lilypond.bugs') + '\n') return p -option_parser = get_option_parser() -(global_options, files) = option_parser.parse_args() +option_parser = get_option_parser () +(global_options, files) = option_parser.parse_args () -identify() +identify () header['tagline'] = 'Lily was here %s -- automatically converted from ABC' % version for f in files: if f == '-': f = '' - sys.stderr.write ('Parsing `%s\'...\n' % f) + if not global_options.quiet: + sys.stderr.write ('Parsing `%s\'...\n' % f) parse_file (f) if not global_options.output: global_options.output = os.path.basename (os.path.splitext (f)[0]) + ".ly" - sys.stderr.write ('lilypond output to: `%s\'...' % global_options.output) + if not global_options.quiet: + sys.stderr.write ('lilypond output to: `%s\'...' % global_options.output) outf = open (global_options.output, 'w') # don't substitute @VERSION@. We want this to reflect @@ -1392,5 +1454,5 @@ for f in files: dump_voices (outf) dump_score (outf) dump_lyrics (outf) - sys.stderr.write ('\n') - + if not global_options.quiet: + sys.stderr.write ('\n')