X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=scripts%2Fabc2ly.py;h=1257182f718cf0ae268b436a357c099d9b1c2086;hb=cd97f3fa5b1275595307e89b5b070f833adb573a;hp=943cc94b3b821e64192db3c27a9fb34395f961c4;hpb=5f7bad2f8c6b46083405261f2912a91426482d26;p=lilypond.git diff --git a/scripts/abc2ly.py b/scripts/abc2ly.py index 943cc94b3b..1257182f71 100644 --- a/scripts/abc2ly.py +++ b/scripts/abc2ly.py @@ -1,5 +1,5 @@ #!@PYTHON@ - +# -*- coding: utf-8 -*- # once upon a rainy monday afternoon. # # ... @@ -66,12 +66,7 @@ # UNDEF -> None # - -program_name = 'abc2ly' -version = '@TOPLEVEL_VERSION@' -if version == '@' + 'TOPLEVEL_VERSION' + '@': - version = '(unknown version)' # uGUHGUHGHGUGH - + import __main__ import getopt import sys @@ -79,11 +74,38 @@ import re import string import os +program_name = sys.argv[0] + + +datadir = '@local_lilypond_datadir@' +if not os.path.isdir (datadir): + datadir = '@lilypond_datadir@' + +sys.path.insert (0, os.path.join (datadir, 'python')) + +if os.environ.has_key ('LILYPONDPREFIX'): + datadir = os.environ['LILYPONDPREFIX'] + while datadir[-1] == os.sep: + datadir= datadir[:-1] + + datadir = os.path.join (datadir, "share/lilypond/current/") +sys.path.insert (0, os.path.join (datadir, 'python')) + +# dynamic relocation, for GUB binaries. +bindir = 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, os.path.join (datadir)) + +import lilylib as ly +global _;_=ly._ + +version = '@TOPLEVEL_VERSION@' +if version == '@' + 'TOPLEVEL_VERSION' + '@': + version = '(unknown version)' # uGUHGUHGHGUGH UNDEF = 255 state = UNDEF -strict = 0 -preserve_beams = 0 voice_idx_dict = {} header = {} header['footnotes'] = '' @@ -102,16 +124,18 @@ 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: + if global_options.strict: sys.exit (1) + +def alphabet (i): + return chr (i + ord('A')) def check_clef(s): if not s: @@ -140,7 +164,7 @@ def check_clef(s): s = s[4:] state.base_octave = -2 voices_append ("\\clef bass\n" ) - return s + return s def select_voice (name, rol): if not voice_idx_dict.has_key (name): @@ -163,10 +187,12 @@ def select_voice (name, rol): check_clef(value) elif keyword == "name": value = re.sub ('\\\\','\\\\\\\\', value) - voices_append ("\\property Staff.instrument = %s\n" % value ) + ## < 2.2 + voices_append ("\\set Staff.instrument = %s\n" % value ) + __main__.part_names = 1 elif keyword == "sname" or keyword == "snm": - voices_append ("\\property Staff.instr = %s\n" % value ) + voices_append ("\\set Staff.instr = %s\n" % value ) else: break @@ -181,17 +207,18 @@ def dump_header (outf,hdr): def dump_lyrics (outf): if (len(lyrics)): - outf.write("\n\\score\n{\n \\context Lyrics\n <<\n") + outf.write("\n\\score\n{\n \\lyrics\n <<\n") for i in range (len (lyrics)): outf.write ( lyrics [i]) outf.write ("\n") - outf.write(" >>\n \\paper{}\n}\n") + outf.write(" >>\n \\layout{}\n}\n") def dump_default_bar (outf): """ Nowadays abc2ly outputs explicits barlines (?) """ - outf.write ("\n\\property Score.defaultBarType=\"empty\"\n") + ## < 2.2 + outf.write ("\n\\set Score.defaultBarType = \"empty\"\n") def dump_slyrics (outf): @@ -199,12 +226,12 @@ def dump_slyrics (outf): ks.sort () for k in ks: if re.match('[1-9]', k): - m = alphabet[string.atoi(k)] + m = alphabet(string.atoi(k)) else: m = k for i in range (len(slyrics[voice_idx_dict[k]])): - l=alphabet[i] - outf.write ("\nwords%sV%s = \\lyrics {" % (m, l)) + l= alphabet(i) + outf.write ("\nwords%sV%s = \lyricmode {" % (m, l)) outf.write ("\n" + slyrics [voice_idx_dict[k]][i]) outf.write ("\n}") @@ -214,10 +241,10 @@ def dump_voices (outf): ks.sort () for k in ks: if re.match ('[1-9]', k): - m = alphabet[string.atoi(k)] + m = alphabet(string.atoi(k)) else: m = k - outf.write ("\nvoice%s = \\notes {" % m) + outf.write ("\nvoice%s = {" % m) dump_default_bar(outf) if repeat_state[voice_idx_dict[k]]: outf.write("\n\\repeat volta 2 {") @@ -247,43 +274,40 @@ def try_parse_q(a): sys.stderr.write("abc2ly: Warning, unable to parse Q specification: %s\n" % a) def dump_score (outf): - outf.write (r"""\score{ - \notes << + outf.write (r""" + +\score{ + << """) ks = voice_idx_dict.keys (); ks.sort () for k in ks: if re.match('[1-9]', k): - m = alphabet[string.atoi(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 " % m) outf.write ("\n\t}\n") - if len ( slyrics [voice_idx_dict[k]] ): - outf.write ("\n\t\\context Lyrics=\"%s\" \n\t<<\t" % k) + + l = ord( 'A' ) + for lyrics in slyrics [voice_idx_dict[k]]: + outf.write ("\n\t\\addlyrics { \n") if re.match('[1-9]',k): - m = alphabet[string.atoi(k)] + m = alphabet (string.atoi(k)) else: m = k - for i in range (len(slyrics[voice_idx_dict[k]])): - l=alphabet[i] - outf.write("\n\t { \\words%sV%s }" % ( m, l) ) - outf.write ( "\n\t>>\n" ) + + outf.write ( " \\words%sV%s } " % ( m, chr (l)) ) + l += 1 + 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 }\n") + outf.write ("\n\t\\layout {\n") outf.write ("\t}\n\t\\midi {%s}\n}\n" % midi_specs) @@ -576,9 +600,9 @@ def repeat_prepend(): 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{ \\lyrics "' + a + '" }\n' + a = re.sub ('#', '\\#', a) # latex does not like naked #'s + a = re.sub ('"', '\\"', a) # latex does not like naked "'s + a = '\t{ "' + a + '" }\n' stuff_append (lyrics, current_lyric_idx, a) # break lyrics to words and put "'s around words containing numbers and '"'s @@ -629,7 +653,10 @@ def try_parse_header_line (ln, state): if header.has_key('title'): if a: if len(header['title']): - header['title'] = header['title'] + '\\\\\\\\' + a + # the non-ascii character + # in the string below is a + # punctuation dash. (TeX ---) + header['title'] = header['title'] + ' — ' + a else: header['subtitle'] = a else: @@ -638,12 +665,12 @@ def try_parse_header_line (ln, state): if a == 'C': if not state.common_time: state.common_time = 1 - voices_append ("\\property Staff.TimeSignature \\override #\'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 ("\\property Staff.TimeSignature \\override #\'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) @@ -920,7 +947,7 @@ def clear_bar_acc(state): # if we are parsing a beam, close it off def close_beam_state(state): - if state.parsing_beam and preserve_beams: + if state.parsing_beam and global_options.beams: state.parsing_beam = 0 voices_append_back( ']' ) @@ -1010,7 +1037,7 @@ def try_parse_note (str, parser_state): if slur_end: voices_append ('-)' *slur_end ) - if preserve_beams and \ + if global_options.beams and \ str[0] in '^=_ABCDEFGabcdefg' and \ not parser_state.parsing_beam and \ not parser_state.parsing_tuplet: @@ -1184,24 +1211,24 @@ def try_parse_chord_delims (str, state): if state.next_bar: voices_append(state.next_bar) state.next_bar = '' - voices_append ('<') + voices_append ('<<') if str[:1] == '+': str = str[1:] if state.plus_chord: - voices_append ('>') + voices_append ('>>') state.plus_chord = 0 else: if state.next_bar: voices_append(state.next_bar) state.next_bar = '' - voices_append ('<') + voices_append ('<<') state.plus_chord = 1 ch = '' if str[:1] ==']': str = str[1:] - ch = '>' + ch = '>>' end = 0 while str[:1] ==')': @@ -1316,25 +1343,7 @@ def parse_file (fn): def identify(): sys.stderr.write ("%s from LilyPond %s\n" % (program_name, version)) -def help (): - print r""" -Convert ABC to lilypond. - -Usage: abc2ly [OPTIONS]... ABC-FILE - -Options: - -h, --help print this help - -o, --output=FILE set output filename to FILE - -v, --version show version information - -s, --strict be strict about succes - -b, --beams preserve ABC's notion of beams - -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. - +authors = """ Written by Han-Wen Nienhuys , Laura Conrad , Roy Rankin . """ @@ -1342,29 +1351,27 @@ Written by Han-Wen Nienhuys , Laura Conrad 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''') + + return p + +option_parser = get_option_parser() +(global_options, files) = option_parser.parse_args() -(options, files) = getopt.getopt (sys.argv[1:], 'vo:hsb', ['help','version', 'output=', 'strict', 'beams']) -out_filename = '' - -for opt in options: - o = opt[0] - a = opt[1] - if o== '--help' or o == '-h': - help () - sys.exit (0) - elif o == '--version' or o == '-v': - print_version () - sys.exit(0) - elif o == '--strict' or o == '-s': - strict = 1 - elif o == '--output' or o == '-o': - out_filename = a - elif o == '--beams' or o == '-b': - preserve_beams = 1 - else: - print o - raise getopt.error identify() @@ -1376,10 +1383,14 @@ for f in files: 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 ('lilypond output to: `%s\'...' % out_filename) - outf = open (out_filename, 'w') + 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) + outf = open (global_options.output, 'w') + +# don't substitute @VERSION@. We want this to reflect +# the last version that was verified to work. + outf.write ('\\version "2.7.40"\n') # dump_global (outf) dump_header (outf, header)