X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=scripts%2Fabc2ly.py;h=eac86759a21c1cfda5e4d0129734ab6553de4d9a;hb=d9b43b93f2c885409bafdb157138158f65cc49aa;hp=dc08ba9395177ddd6eb721bf428d7ecff70a129e;hpb=815e3fc50396151a0803f750c8dc0c3ee07ad0e5;p=lilypond.git diff --git a/scripts/abc2ly.py b/scripts/abc2ly.py index dc08ba9395..eac86759a2 100644 --- a/scripts/abc2ly.py +++ b/scripts/abc2ly.py @@ -28,8 +28,12 @@ # Enhancements (Laura Conrad) # -# Beaming now preserved between ABC and lilypond -# +# Barring now preserved between ABC and lilypond +# the default placement for text in abc is above the staff. +# %%LY now supported. +# \breve and \longa supported. +# M:none doesn't crash lily. + # Limitations # # Multiple tunes in single file not supported @@ -39,6 +43,7 @@ # Block comments generate error and are ignored # Postscript commands are ignored # lyrics not resynchronized by line breaks (lyrics must fully match notes) +# %%LY slyrics can't be directly before a w: line. # ??? @@ -63,44 +68,63 @@ import os UNDEF = 255 state = UNDEF +strict = 0 voice_idx_dict = {} header = {} +header['footnotes'] = '' lyrics = [] slyrics = [] voices = [] state_list = [] +repeat_state = [0] * 8 current_voice_idx = -1 current_lyric_idx = -1 lyric_idx = -1 part_names = 0 default_len = 8 length_specified = 0 +nobarlines = 0 global_key = [0] * 7 # UGH names = ["One", "Two", "Three"] DIGITS='0123456789' +alphabet="ABCDEFGHIJKLMNOPQRSTUVWXYZ" HSPACE=' \t' +midi_specs = '' + +def error (msg): + sys.stderr.write (msg) + if strict: + sys.exit (1) + def check_clef(s): if not s: return '' - if re.match('^treble', s): + 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") + voices_append("\\clef \"G_8\"\n") else: state.base_octave = 0 - voices_append("\\clef treble;\n") + voices_append("\\clef treble\n") elif re.match('^alto', s): s = s[4:] state.base_octave = -1 - voices_append ("\\clef alto;\n" ) + voices_append ("\\clef alto\n" ) elif re.match('^bass',s ): s = s[4:] state.base_octave = -2 - voices_append ("\\clef bass;\n" ) + voices_append ("\\clef bass\n" ) return s def select_voice (name, rol): @@ -140,7 +164,8 @@ def dump_header (outf,hdr): ks = hdr.keys () ks.sort () for k in ks: - outf.write ('\t%s = "%s";\n'% (k,hdr[k])) + hdr[k] = re.sub('"', '\\"', hdr[k]) + outf.write ('\t%s = "%s"\n'% (k,hdr[k])) outf.write ('}') def dump_lyrics (outf): @@ -159,20 +184,54 @@ def dump_slyrics (outf): ks = voice_idx_dict.keys() ks.sort () for k in ks: + if re.match('[1-9]', k): + m = alphabet[string.atoi(k)] + else: + m = k for i in range (len(slyrics[voice_idx_dict[k]])): - outf.write ("\nwords%sV%d = \\lyrics {" % (k, i)) + l=alphabet[i] + outf.write ("\nwords%sV%s = \\lyrics {" % (m, l)) outf.write ("\n" + slyrics [voice_idx_dict[k]][i]) outf.write ("\n}") def dump_voices (outf): + global doing_alternative, in_repeat ks = voice_idx_dict.keys() ks.sort () for k in ks: - outf.write ("\nvoice%s = \\notes {" % k) + if re.match ('[1-9]', k): + m = alphabet[string.atoi(k)] + else: + m = k + outf.write ("\nvoice%s = \\notes {" % m) dump_default_bar(outf) + if repeat_state[voice_idx_dict[k]]: + outf.write("\n\\repeat volta 2 {") outf.write ("\n" + voices [voice_idx_dict[k]]) + if not using_old: + if doing_alternative[voice_idx_dict[k]]: + outf.write("}") + if in_repeat[voice_idx_dict[k]]: + outf.write("}") outf.write ("\n}") - + +def try_parse_q(a): + global midi_specs + #assume that Q takes the form "Q:1/4=120" + #There are other possibilities, but they are deprecated + if string.count(a, '/') == 1: + array=string.split(a,'/') + numerator=array[0] + if 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(["\\tempo", duration, "=", perminute]) + else: + sys.stderr.write("abc2ly: Warning, unable to parse Q specification: %s\n" % a) + def dump_score (outf): outf.write (r"""\score{ \notes < @@ -181,32 +240,42 @@ def dump_score (outf): ks = voice_idx_dict.keys (); ks.sort () for k in ks: + if re.match('[1-9]', k): + m = alphabet[string.atoi(k)] + else: + m = k if k == 'default' and len (voice_idx_dict) > 1: break if len ( slyrics [voice_idx_dict[k]] ): outf.write ("\n \\addlyrics") outf.write ("\n\t\\context Staff=\"%s\"\n\t{\n" %k ) if k != 'default': - outf.write ("\t \\$voicedefault\n") - outf.write ("\t \\$voice%s " % k) + outf.write ("\t \\voicedefault\n") + outf.write ("\t \\voice%s " % m) outf.write ("\n\t}\n") if len ( slyrics [voice_idx_dict[k]] ): outf.write ("\n\t\\context Lyrics=\"%s\" \n\t<\t" % k) + if re.match('[1-9]',k): + m = alphabet[string.atoi(k)] + else: + m = k for i in range (len(slyrics[voice_idx_dict[k]])): - outf.write("\n\t { \\$words%sV%d }" % ( k, i) ) + l=alphabet[i] + outf.write("\n\t { \\words%sV%s }" % ( m, l) ) outf.write ( "\n\t>\n" ) outf.write ("\n >") outf.write ("\n\t\\paper {\n") if part_names: outf.write ("\t \\translator \n\t {\n") outf.write ("\t\t\\StaffContext\n") - outf.write ("\t\t\\consists Staff_margin_engraver;\n") +# outf.write ("\t\t\\consists Staff_margin_engraver\n") outf.write ("\t }\n") - outf.write ("\t}\n\t\\midi {}\n}\n") + outf.write ("\t}\n\t\\midi {%s}\n}\n" % midi_specs) 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)) @@ -229,11 +298,11 @@ 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 ("can't open file: `%s'\n" % f) return '' s = i.read (n) if len (s) <= 0: - sys.stderr.write ("gulped emty file: %s\n" % f) + sys.stderr.write ("gulped empty file: `%s'\n" % f) i.close () return s @@ -300,13 +369,16 @@ key_lookup = { # abc to lilypond key mode names 'm' : 'minor', 'min' : 'minor', 'maj' : 'major', + 'major' : 'major', 'phr' : 'phrygian', 'ion' : 'ionian', 'loc' : 'locrian', 'aeo' : 'aeolian', 'mix' : 'mixolydian', + 'mixolydian' : 'mixolydian', 'lyd' : 'lydian', - 'dor' : 'dorian' + 'dor' : 'dorian', + 'dorian' : 'dorian' } def lily_key (k): @@ -325,7 +397,7 @@ def lily_key (k): type = k[0:3] if key_lookup.has_key(type): return("%s \\%s" % ( key, key_lookup[type])) - sys.stderr.write("Unknown key type %s ignored\n" % type) + sys.stderr.write("Unknown key type `%s' ignored\n" % type) return key def shift_key (note, acc , shift): @@ -345,14 +417,23 @@ def shift_key (note, acc , shift): key_shift = { # semitone shifts for key mode names 'm' : 3, 'min' : 3, + 'minor' : 3, 'maj' : 0, + 'major' : 0, 'phr' : -4, + 'phrygian' : -4, 'ion' : 0, + 'ionian' : 0, 'loc' : 1, + 'locrian' : 1, 'aeo' : 3, + 'aeolian' : 3, 'mix' : 5, + 'mixolydian' : 5, 'lyd' : -5, - 'dor' : -2 + 'lydian' : -5, + 'dor' : -2, + 'dorian' : -2 } def compute_key (k): k = string.lower (k) @@ -386,6 +467,7 @@ def compute_key (k): key_count = flat_key_seq.index (keytup) accseq = map (lambda x: (3*x + 3 ) % 7, range (1, key_count + 1)) else: + error ("Huh?") raise "Huh" key_table = [0] * 7 @@ -409,8 +491,10 @@ def try_parse_tuplet_begin (str, state): if re.match ('\([2-9]', str): dig = str[1] str = str[2:] - state.parsing_tuplet = string.atoi (dig[0]) - + prev_tuplet_state = state.parsing_tuplet + state.parsing_tuplet = string.atoi (dig[0]) + if prev_tuplet_state: + voices_append ("}") voices_append ("\\times %s {" % tup_lookup[dig]) return str @@ -418,12 +502,12 @@ def try_parse_group_end (str, state): if str and str[0] in HSPACE: str = str[1:] return str - + def header_append (key, a): s = '' if header.has_key (key): s = header[key] + "\n" - header [key] = s + a + header [key] = s + a def wordwrap(a, v): linelen = len (v) - string.rfind(v, '\n') @@ -442,9 +526,16 @@ def stuff_append (stuff, idx, a): def voices_append(a): if current_voice_idx < 0: select_voice ('default', '') - stuff_append (voices, current_voice_idx, a) +def repeat_prepend(): + global repeat_state + if current_voice_idx < 0: + select_voice ('default', '') + 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 @@ -454,14 +545,13 @@ def lyrics_append(a): # break lyrics to words and put "'s around words containing numbers and '"'s def fix_lyric(str): ret = '' - while str != '': m = re.match('[ \t]*([^ \t]*)[ \t]*(.*$)', str) if m: word = m.group(1) str = m.group(2) word = re.sub('"', '\\"', word) # escape " - if re.match('.*[0-9"]', word): + if re.match('.*[0-9"\(]', word): word = re.sub('_', ' ', word) # _ causes probs inside "" ret = ret + '\"' + word + '\" ' else: @@ -477,7 +567,7 @@ def slyrics_append(a): a = re.sub ( '~', '_', a) # ~ to space('_') a = re.sub ( '\*', '_ ', a) # * to to space a = re.sub ( '#', '\\#', a) # latex does not like naked #'s - if re.match('.*[0-9"]', a): # put numbers and " into quoted string + if re.match('.*[0-9"\(]', a): # put numbers and " and ( into quoted string a = fix_lyric(a) a = re.sub ( '$', ' ', a) # insure space between lines __main__.lyric_idx = lyric_idx + 1 @@ -489,6 +579,7 @@ def slyrics_append(a): def try_parse_header_line (ln, state): + global length_specified m = re.match ('^([A-Za-z]): *(.*)$', ln) if m: @@ -498,35 +589,51 @@ def try_parse_header_line (ln, state): a = re.sub('[ \t]*$','', a) #strip trailing blanks if header.has_key('title'): if a: - header['title'] = header['title'] + '\\\\\\\\' + a + if len(header['title']): + header['title'] = header['title'] + '\\\\\\\\' + a + else: + header['subtitle'] = a else: header['title'] = a if g == 'M': # Meter if a == 'C': if not state.common_time: state.common_time = 1 - voices_append ("\\property Staff.timeSignatureStyle=\"C\"\n") + voices_append ("\\property Staff.TimeSignature \\override #\'style = #'C\n") a = '4/4' if a == 'C|': if not state.common_time: state.common_time = 1 - voices_append ("\\property Staff.timeSignatureStyle=\"C\"\n") + voices_append ("\\property Staff.TimeSignature \\override #\'style = #'C\n") a = '2/2' if not length_specified: set_default_len_from_time_sig (a) - voices_append ('\\time %s;' % a) + else: + length_specified = 0 + if not a == 'none': + voices_append ('\\time %s' % a) state.next_bar = '' if g == 'K': # KEY a = check_clef(a) if a: m = re.match ('^([^ \t]*) *(.*)$', a) # seperate clef info if m: - __main__.global_key =compute_key (m.group(1))# ugh. - voices_append ('\\key %s;' % lily_key(m.group(1))) - check_clef(m.group(2)) + # 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:] + else: + key_info = m.group(1) + clef_info = m.group(2) + __main__.global_key = compute_key (key_info)# ugh. + voices_append ('\\key %s' % lily_key(key_info)) + check_clef(clef_info) else: - __main__.global_key =compute_key (a)# ugh. - voices_append ('\\key %s \\major;' % lily_key(a)) + __main__.global_key = compute_key (a)# ugh. + voices_append ('\\key %s \\major' % lily_key(a)) + if g == 'N': # Notes + header ['footnotes'] = header['footnotes'] + '\\\\\\\\' + a if g == 'O': # Origin header ['origin'] = a if g == 'X': # Reference Number @@ -555,19 +662,21 @@ def try_parse_header_line (ln, state): state.next_bar = '' select_voice (voice, rest) if g == 'W': # Words - lyrics_append(a); + lyrics_append(a) if g == 'w': # vocals - slyrics_append (a); - + slyrics_append (a) + if g == 'Q': #tempo + try_parse_q (a) return '' return ln # we use in this order specified accidental, active accidental for bar, # active accidental for key -def pitch_to_mudela_name (name, acc, bar_acc, key): +def pitch_to_lilypond_name (name, acc, bar_acc, key): s = '' if acc == UNDEF: - acc = bar_acc + if not nobarlines: + acc = bar_acc if acc == UNDEF: acc = key if acc == -1: @@ -580,7 +689,7 @@ def pitch_to_mudela_name (name, acc, bar_acc, key): return(chr (name + ord('c')) + s) -def octave_to_mudela_quotes (o): +def octave_to_lilypond_quotes (o): o = o + 2 s ='' if o < 0: @@ -603,12 +712,20 @@ def parse_num (str): return (str,n) -def duration_to_mudela_duration (multiply_tup, defaultlen, dots): +def duration_to_lilypond_duration (multiply_tup, defaultlen, dots): base = 1 # (num / den) / defaultlen < 1/base while base * multiply_tup[0] < multiply_tup[1]: base = base * 2 - return '%d%s' % ( base, '.'* dots) + if base == 1: + if (multiply_tup[0] / multiply_tup[1]) == 2: + base = '\\breve' + if (multiply_tup[0] / multiply_tup[1]) == 3: + base = '\\breve' + dots = 1 + if (multiply_tup[0] / multiply_tup[1]) == 4: + base = '\longa' + return '%s%s' % ( base, '.'* dots) class Parser_state: def __init__ (self): @@ -633,15 +750,16 @@ def parse_duration (str, parser_state): (str, num) = parse_num (str) if not num: num = 1 - - if str[0] == '/': - while str[:1] == '/': - str= str[1:] - d = 2 - if str[0] in DIGITS: - (str, d) =parse_num (str) + if len(str): + if str[0] == '/': + if len(str[0]): + while str[:1] == '/': + str= str[1:] + d = 2 + if str[0] in DIGITS: + (str, d) =parse_num (str) - den = den * d + den = den * d den = den * default_len @@ -652,7 +770,7 @@ def parse_duration (str, parser_state): str = str[1:] while str[0] == '>': str = str [1:] - current_dots = current_dots + 1; + current_dots = current_dots + 1 parser_state.next_den = parser_state.next_den * 2 while str[0] == '<': @@ -691,7 +809,7 @@ def try_parse_rest (str, parser_state): str = str[1:] (str, num,den,d) = parse_duration (str, parser_state) - voices_append ('%s%s' % (rest, duration_to_mudela_duration ((num,den), default_len, d))) + voices_append ('%s%s' % (rest, duration_to_lilypond_duration ((num,den), default_len, d))) if parser_state.next_articulation: voices_append (parser_state.next_articulation) parser_state.next_articulation = '' @@ -713,11 +831,10 @@ artic_tbl = { } 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]] if not artic_tbl[str[:1]]: - sys.stderr.write("Warning: ignoring %s\n" % str[:1] ) + sys.stderr.write("Warning: ignoring `%s'\n" % str[:1] ) str = str[1:] @@ -821,15 +938,15 @@ def try_parse_note (str, parser_state): voices_append ('%s' % ')' *slur_end ) bar_acc = get_bar_acc(notename, octave, parser_state) - pit = pitch_to_mudela_name(notename, acc, bar_acc, global_key[notename]) - oct = octave_to_mudela_quotes (octave) + pit = pitch_to_lilypond_name(notename, acc, bar_acc, global_key[notename]) + oct = octave_to_lilypond_quotes (octave) if acc != UNDEF and (acc == global_key[notename] or acc == bar_acc): mod='!' else: mod = '' voices_append ("%s%s%s%s" % (pit, oct, mod, - duration_to_mudela_duration ((num,den), default_len, current_dots))) + duration_to_lilypond_duration ((num,den), default_len, current_dots))) set_bar_acc(notename, octave, acc, parser_state) if parser_state.next_articulation: @@ -859,6 +976,11 @@ def try_parse_guitar_chord (str, state): if str[:1] =='"': str = str[1:] gc = '' + if str[0] == '_' or (str[0] == '^'): + position = str[0] + str = str[1:] + else: + position = '^' while str and str[0] != '"': gc = gc + str[0] str = str[1:] @@ -866,7 +988,7 @@ def try_parse_guitar_chord (str, state): if str: str = str[1:] gc = re.sub('#', '\\#', gc) # escape '#'s - state.next_articulation = ("-\"%s\"" % gc) + state.next_articulation + state.next_articulation = ("%c\"%s\"" % (position ,gc)) + state.next_articulation return str def try_parse_escape (str): @@ -887,35 +1009,83 @@ def try_parse_escape (str): # :: left-right repeat # |1 volta 1 # |2 volta 2 -bar_dict = { +old_bar_dict = { '|]' : '|.', '||' : '||', '[|' : '||', ':|' : ':|', '|:' : '|:', -'::' : '::', +'::' : ':|:', '|1' : '|', '|2' : '|', ':|2' : ':|', '|' : '|' } +bar_dict = { + '|]' : '\\bar "|."', + '||' : '\\bar "||"', + '[|' : '\\bar "||"', + ':|' : '}', + '|:' : '\\repeat volta 2 {', + '::' : '} \\repeat volta 2 {', + '|1' : '} \\alternative{{', + '|2' : '} {', + ':|2' : '} {', + '|' : '\\bar "|"' + } warn_about = ['|:', '::', ':|', '|1', ':|2', '|2'] +alternative_opener = ['|1', '|2', ':|2'] +repeat_ender = ['::', ':|'] +repeat_opener = ['::', '|:'] +in_repeat = [''] * 8 +doing_alternative = [''] * 8 +using_old = '' def try_parse_bar (str,state): + global in_repeat, doing_alternative, using_old + do_curly = '' bs = None - + if current_voice_idx < 0: + select_voice ('default', '') # first try the longer one for trylen in [3,2,1]: if str[:trylen] and bar_dict.has_key (str[:trylen]): s = str[:trylen] - bs = "\\bar \"%s\";" % bar_dict[s] - if s in warn_about: - sys.stderr.write('Warning kludging for barline `%s\'\n' % s) + if using_old: + bs = "\\bar \"%s\"" % old_bar_dict[s] + else: + bs = "%s" % bar_dict[s] str = str[trylen:] - break + if s in alternative_opener: + if not in_repeat[current_voice_idx]: + using_old = 't' + bs = "\\bar \"%s\"" % old_bar_dict[s] + else: + doing_alternative[current_voice_idx] = 't' + if s in repeat_ender: + if not in_repeat[current_voice_idx]: + sys.stderr.write("Warning: inserting repeat to beginning of notes.\n") + repeat_prepend() + in_repeat[current_voice_idx] = '' + else: + if doing_alternative[current_voice_idx]: + do_curly = 't' + if using_old: + bs = "\\bar \"%s\"" % old_bar_dict[s] + else: + bs = bar_dict[s] + doing_alternative[current_voice_idx] = '' + in_repeat[current_voice_idx] = '' + if s in repeat_opener: + in_repeat[current_voice_idx] = 't' + if using_old: + bs = "\\bar \"%s\"" % old_bar_dict[s] + else: + bs = bar_dict[s] + break if str[:1] == '|': state.next_bar = '|\n' str = str[1:] @@ -929,7 +1099,9 @@ def try_parse_bar (str,state): if bs <> None: clear_bar_acc(state) voices_append (bs) - + if do_curly != '': + voices_append("} }") + do_curly = '' return str def try_parse_tie (str): @@ -979,7 +1151,7 @@ def try_parse_chord_delims (str, state): str = str[1:] - voices_append ("\\spanrequest \\stop \"slur\"" * end); + voices_append ("\\spanrequest \\stop \"slur\"" * end) voices_append (ch) return str @@ -997,6 +1169,36 @@ def try_parse_grace_delims (str, state): return str +def try_parse_comment (str): + global nobarlines + if (str[0] == '%'): + if str[0:5] == '%MIDI': +#the nobarlines option is necessary for an abc to lilypond translator for +#exactly the same reason abc2midi needs it: abc requires the user to enter +#the note that will be printed, and MIDI and lilypond expect entry of the +#pitch that will be played. +# +#In standard 19th century musical notation, the algorithm for translating +#between printed note and pitch involves using the barlines to determine +#the scope of the accidentals. +# +#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. + if (string.find(str,'nobarlines') > 0): + nobarlines = 1 + elif str[0:3] == '%LY': + p = string.find(str, 'voices') + if (p > -1): + voices_append(str[p+7:]) + voices_append("\n") + p = string.find(str, 'slyrics') + if (p > -1): + slyrics_append(str[p+8:]) + +#write other kinds of appending if we ever need them. + return str happy_count = 100 def parse_file (fn): @@ -1018,6 +1220,7 @@ def parse_file (fn): m = re.match ('^([^%]*)%(.*)$',ln) # add comments to current voice if m: if m.group(2): + try_parse_comment(m.group(2)) voices_append ('%% %s\n' % m.group(2)) ln = m.group (1) @@ -1043,8 +1246,7 @@ def parse_file (fn): ln = junk_space (ln) if ln: - msg = "%s: %d: Huh? Don't understand\n" % (fn, lineno) - sys.stderr.write (msg) + 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') @@ -1055,7 +1257,7 @@ def identify(): def help (): print r""" -Convert ABC to Mudela. +Convert ABC to lilypond. Usage: abc2ly [OPTIONS]... ABC-FILE @@ -1063,9 +1265,16 @@ Options: -h, --help this help -o, --output=FILE set output filename to FILE -v, --version version information - + -s, --strict be strict about succes. + This program converts ABC music files (see http://www.gre.ac.uk/~c.walshaw/abc2mtex/abc.txt) To LilyPond input. + + +Report bugs to bug-lilypond@gnu.org + +Written by Han-Wen Nienhuys , Laura Conrad +, Roy Rankin """ def print_version (): @@ -1073,7 +1282,7 @@ def print_version (): -(options, files) = getopt.getopt (sys.argv[1:], 'vo:h', ['help','version', 'output=']) +(options, files) = getopt.getopt (sys.argv[1:], 'vo:hs', ['help','version', 'output=', 'strict']) out_filename = '' for opt in options: @@ -1082,11 +1291,12 @@ for opt in options: if o== '--help' or o == '-h': help () sys.exit (0) - if o == '--version' or o == '-v': + elif o == '--version' or o == '-v': print_version () sys.exit(0) - - if o == '--output' or o == '-o': + elif o == '--strict' or o == '-s': + strict = 1 + elif o == '--output' or o == '-o': out_filename = a else: print o @@ -1099,12 +1309,12 @@ for f in files: if f == '-': f = '' - sys.stderr.write ('Parsing... [%s]\n' % f) + sys.stderr.write ('Parsing `%s\'...\n' % f) parse_file (f) if not out_filename: out_filename = os.path.basename (os.path.splitext (f)[0]) + ".ly" - sys.stderr.write ('Ly output to: %s...' % out_filename) + sys.stderr.write ('lilypond output to: `%s\'...' % out_filename) outf = open (out_filename, 'w') # dump_global (outf)