X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=scripts%2Flilypond-book.py;h=9c49508d7a85bfba912400108a31d345be678b97;hb=25ca54b640c067e2286a1d7ba47f24a1b4dc070e;hp=832cea0c6292ad1f77a79f2d6dda7337ab39d3f3;hpb=6e739853dc4b996f8b4c9f5dc8db2282b303dea8;p=lilypond.git diff --git a/scripts/lilypond-book.py b/scripts/lilypond-book.py index 832cea0c62..9c49508d7a 100644 --- a/scripts/lilypond-book.py +++ b/scripts/lilypond-book.py @@ -91,18 +91,17 @@ authors = ('Jan Nieuwenhuizen ', ################################################################ def exit (i): - if global_options.verbose: + if ly.is_verbose (): raise Exception (_ ('Exiting (%d)...') % i) else: sys.exit (i) -def identify (): - ly.encoded_write (sys.stdout, '%s (GNU LilyPond) %s\n' % (ly.program_name, ly.program_version)) - progress = ly.progress warning = ly.warning error = ly.error +def identify (): + progress('%s (GNU LilyPond) %s' % (ly.program_name, ly.program_version)) def warranty (): identify () @@ -113,11 +112,12 @@ def warranty (): %s %s -''' % ( _ ('Copyright (c) %s by') % '2001--2010', +''' % ( _ ('Copyright (c) %s by') % '2001--2012', '\n '.join (authors), _ ("Distributed under terms of the GNU General Public License."), _ ("It comes with NO WARRANTY."))) + def get_option_parser (): p = ly.get_option_parser (usage=_ ("%s [OPTION]... FILE") % 'lilypond-book', description=help_summary, @@ -142,7 +142,7 @@ def get_option_parser (): p.add_option ("-I", '--include', help=_ ("add DIR to include path"), metavar=_ ("DIR"), action='append', dest='include_path', - default=[os.path.abspath (os.getcwd ())]) + default=[]) p.add_option ('--info-images-dir', help=_ ("format Texinfo output so that Info will " @@ -158,6 +158,12 @@ def get_option_parser (): type="float", default=3.0) + p.add_option ('--lily-loglevel', + help=_ ("Print lilypond log messages according to LOGLEVEL"), + metavar=_ ("LOGLEVEL"), + action='store', dest='lily_loglevel', + default=os.environ.get ("LILYPOND_LOGLEVEL", None)) + p.add_option ('--lily-output-dir', help=_ ("write lily-XXX files to DIR, link into --output dir"), metavar=_ ("DIR"), @@ -169,6 +175,14 @@ def get_option_parser (): action='append', dest='custom_packages', default=[]) + p.add_option ("-l", "--loglevel", + help=_ ("Print log messages according to LOGLEVEL " + "(NONE, ERROR, WARNING, PROGRESS (default), DEBUG)"), + metavar=_ ("LOGLEVEL"), + action='callback', + callback=ly.handle_loglevel_option, + type='string') + p.add_option ("-o", '--output', help=_ ("write output to DIR"), metavar=_ ("DIR"), action='store', dest='output_dir', @@ -179,6 +193,16 @@ def get_option_parser (): action='store', dest='process_cmd', default='') + p.add_option ('--redirect-lilypond-output', + help = _ ("Redirect the lilypond output"), + action='store_true', + dest='redirect_output', default=False) + + p.add_option ('-s', '--safe', help=_ ("Compile snippets in safe mode"), + action="store_true", + default=False, + dest="safe_mode") + p.add_option ('--skip-lily-check', help=_ ("do not fail if no lilypond output is found"), metavar=_ ("DIR"), @@ -197,9 +221,9 @@ def get_option_parser (): default=False) p.add_option ('-V', '--verbose', help=_ ("be verbose"), - action="store_true", - default=False, - dest="verbose") + action="callback", + callback=ly.handle_loglevel_option, + callback_args=("DEBUG",)) p.version = "@TOPLEVEL_VERSION@" p.add_option("--version", @@ -217,6 +241,11 @@ case --pdf option is set instead of pdflatex"), metavar=_ ("PROG"), action='store', dest='latex_program', default='latex') + group.add_option ('--texinfo-program', + help=_ ("run executable PROG instead of texi2pdf"), + metavar=_ ("PROG"), + action='store', dest='texinfo_program', + default='texi2pdf') group.add_option ('--pdf', action="store_true", dest="create_pdf", @@ -248,6 +277,11 @@ if 'bindir' in globals () and bindir: if '@bindir@' == ('@' + 'bindir@') or not os.path.exists (lilypond_binary): lilypond_binary = 'lilypond' +# Need to shell-quote, issue 3468 + +import pipes +lilypond_binary = pipes.quote (lilypond_binary) + global_options = None @@ -342,7 +376,7 @@ def find_toplevel_snippets (input_string, formatter): return snippets -def system_in_directory (cmd, directory): +def system_in_directory (cmd, directory, logfile): """Execute a command in a different directory. Because of win32 compatibility, we can't simply use subprocess. @@ -350,8 +384,19 @@ def system_in_directory (cmd, directory): current = os.getcwd() os.chdir (directory) - ly.system(cmd, be_verbose=global_options.verbose, - progress_p=1) + """NB - ignore_error is deliberately set to the same value + as redirect_output - this is not a typo.""" + retval = ly.system(cmd, + be_verbose=ly.is_verbose (), + redirect_output=global_options.redirect_output, + log_file=logfile, + progress_p=1, + ignore_error=global_options.redirect_output) + if retval != 0: + print ("Error trapped by lilypond-book") + print ("\nPlease see " + logfile + ".log\n") + sys.exit(1) + os.chdir (current) @@ -369,11 +414,12 @@ def process_snippets (cmd, snippets, + list (set ([snip.basename() + '.ly' for snip in snippets]))) name = os.path.join (lily_output_dir, 'snippet-names-%d.ly' % checksum) + logfile = name.replace('.ly', '') file (name, 'wb').write (contents) system_in_directory (' '.join ([cmd, ly.mkarg (name)]), - lily_output_dir) - + lily_output_dir, + logfile) def snippet_list_checksum (snippets): return hash (' '.join([l.basename() for l in snippets])) @@ -388,7 +434,7 @@ def write_file_map (lys, name): #(define output-empty-score-list #f) #(ly:add-file-name-alist '(%s ))\n -""" % '\n'.join(['("%s.ly" . "%s")\n' % (ly.basename (), name) +""" % '\n'.join(['("%s.ly" . "%s")\n' % (ly.basename ().replace('\\','/'), name) for ly in lys])) def split_output_files(directory): @@ -414,25 +460,24 @@ def do_process_cmd (chunks, input_name, options): progress (_ ("Writing snippets...")) for snippet in outdated: snippet.write_ly() - progress ('\n') if outdated: progress (_ ("Processing...")) - progress ('\n') process_snippets (options.process_cmd, outdated, options.formatter, options.lily_output_dir) else: progress (_ ("All snippets are up to date...")) - if options.lily_output_dir != options.output_dir: - output_files = split_output_files (options.lily_output_dir) + progress (_ ("Linking files...")) + abs_lily_output_dir = os.path.join (options.original_dir, options.lily_output_dir) + abs_output_dir = os.path.join (options.original_dir, options.output_dir) + if abs_lily_output_dir != abs_output_dir: + output_files = split_output_files (abs_lily_output_dir) for snippet in snippets: - snippet.link_all_output_files (options.lily_output_dir, + snippet.link_all_output_files (abs_lily_output_dir, output_files, - options.output_dir) - - progress ('\n') + abs_output_dir) ### @@ -454,7 +499,6 @@ def write_if_updated (file_name, lines): new_str = ''.join (lines) if oldstr == new_str: progress (_ ("%s is up to date.") % file_name) - progress ('\n') # this prevents make from always rerunning lilypond-book: # output file must be touched in order to be up to date @@ -469,7 +513,6 @@ def write_if_updated (file_name, lines): progress (_ ("Writing `%s'...") % file_name) file (file_name, 'w').writelines (lines) - progress ('\n') def note_input_file (name, inputs=[]): @@ -487,6 +530,7 @@ def samefile (f1, f2): def do_file (input_filename, included=False): # Ugh. + input_absname = input_filename if not input_filename or input_filename == '-': in_handle = sys.stdin input_fullname = '' @@ -499,16 +543,18 @@ def do_file (input_filename, included=False): # Otherwise, "lilypond-book -o out test.tex" will complain that it is # overwriting the input file (which it is actually not), since the # input filename is relative to the CWD... - input_fullname = os.path.abspath (input_fullname) + input_absname = os.path.abspath (input_fullname) note_input_file (input_fullname) in_handle = file (input_fullname) if input_filename == '-': + global_options.input_dir = os.getcwd () input_base = 'stdin' elif included: input_base = os.path.splitext (input_filename)[0] else: + global_options.input_dir = os.path.split (input_absname)[0] input_base = os.path.basename ( os.path.splitext (input_filename)[0]) @@ -526,7 +572,7 @@ def do_file (input_filename, included=False): input_base + global_options.formatter.default_extension) if (os.path.exists (input_filename) and os.path.exists (output_filename) - and samefile (output_filename, input_fullname)): + and samefile (output_filename, input_absname)): error ( _ ("Output would overwrite input file; use --output.")) exit (2) @@ -534,7 +580,6 @@ def do_file (input_filename, included=False): try: progress (_ ("Reading %s...") % input_fullname) source = in_handle.read () - progress ('\n') if not included: global_options.formatter.init_default_snippet_options (source) @@ -545,7 +590,6 @@ def do_file (input_filename, included=False): # Let the formatter modify the chunks before further processing chunks = global_options.formatter.process_chunks (chunks) - progress ('\n') if global_options.filter_cmd: write_if_updated (output_filename, @@ -553,7 +597,6 @@ def do_file (input_filename, included=False): elif global_options.process_cmd: do_process_cmd (chunks, input_fullname, global_options) progress (_ ("Compiling %s...") % output_filename) - progress ('\n') write_if_updated (output_filename, [s.replacement_text () for s in chunks]) @@ -562,7 +605,6 @@ def do_file (input_filename, included=False): os.chdir (original_dir) name = snippet.substring ('filename') progress (_ ("Processing include: %s") % name) - progress ('\n') return do_file (name, included=True) include_chunks = map (process_include, @@ -574,9 +616,24 @@ def do_file (input_filename, included=False): except BookSnippet.CompileError: os.chdir (original_dir) progress (_ ("Removing `%s'") % output_filename) - progress ('\n') raise BookSnippet.CompileError +def inverse_relpath (path, relpath): + """Given two paths, the second relative to the first, + return the first path relative to the second.""" + if os.path.isabs (relpath): + return os.path.abspath (path) + relparts = [] + parts = os.path.normpath (path).split (os.path.sep) + for part in os.path.normpath (relpath).split (os.path.sep): + if part == '..': + relparts.append (parts[-1]) + parts.pop () + else: + relparts.append ('..') + parts.append (part) + return os.path.sep.join (relparts[::-1]) + def do_options (): global global_options @@ -584,15 +641,24 @@ def do_options (): (global_options, args) = opt_parser.parse_args () global_options.information = {'program_version': ly.program_version, 'program_name': ly.program_name } + global_options.original_dir = original_dir + + if global_options.lily_output_dir: + global_options.lily_output_dir = os.path.expanduser (global_options.lily_output_dir) + global_options.include_path.insert (0, inverse_relpath (original_dir, global_options.lily_output_dir)) + + if global_options.output_dir: + global_options.output_dir = os.path.expanduser (global_options.output_dir) + global_options.include_path.insert (0, inverse_relpath (original_dir, global_options.output_dir)) - global_options.include_path = map (os.path.abspath, global_options.include_path) + global_options.include_path.insert (0, ".") # Load the python packages (containing e.g. custom formatter classes) # passed on the command line nr = 0 for i in global_options.custom_packages: nr += 1 - print imp.load_source ("book_custom_package%s" % nr, i) + progress (str(imp.load_source ("book_custom_package%s" % nr, i))) if global_options.warranty: @@ -606,6 +672,8 @@ def do_options (): def main (): # FIXME: 85 lines of `main' macramee?? + if (os.environ.has_key ("LILYPOND_BOOK_LOGLEVEL")): + ly.set_loglevel (os.environ["LILYPOND_BOOK_LOGLEVEL"]) files = do_options () basename = os.path.splitext (files[0])[0] @@ -633,14 +701,22 @@ def main (): if global_options.lily_output_dir: # This must be first, so lilypond prefers to read .ly # files in the other lybookdb dir. - includes = [os.path.abspath(global_options.lily_output_dir)] + includes + includes = [global_options.lily_output_dir] + includes global_options.process_cmd += ' '.join ([' -I %s' % ly.mkarg (p) for p in includes]) global_options.formatter.process_options (global_options) - if global_options.verbose: - global_options.process_cmd += " --verbose " + if global_options.lily_loglevel: + ly.debug_output (_ ("Setting LilyPond's loglevel to %s") % global_options.lily_loglevel, True) + global_options.process_cmd += " --loglevel=%s" % global_options.lily_loglevel + elif ly.is_verbose (): + if os.environ.get ("LILYPOND_LOGLEVEL", None): + ly.debug_output (_ ("Setting LilyPond's loglevel to %s (from environment variable LILYPOND_LOGLEVEL)") % os.environ.get ("LILYPOND_LOGLEVEL", None), True) + global_options.process_cmd += " --loglevel=%s" % os.environ.get ("LILYPOND_LOGLEVEL", None) + else: + ly.debug_output (_ ("Setting LilyPond's output to --verbose, implied by lilypond-book's setting"), True) + global_options.process_cmd += " --verbose" if global_options.padding_mm: global_options.process_cmd += " -deps-box-padding=%f " % global_options.padding_mm @@ -654,6 +730,7 @@ def main (): else: global_options.lily_output_dir = os.path.abspath(global_options.output_dir) + relative_output_dir = global_options.output_dir identify () try: @@ -666,12 +743,11 @@ def main (): base_file_name = os.path.splitext (os.path.basename (files[0]))[0] dep_file = os.path.join (global_options.output_dir, base_file_name + '.dep') - final_output_file = os.path.join (global_options.output_dir, - base_file_name - + '.%s' % global_options.format) + final_output_file = os.path.join (relative_output_dir, + base_file_name + global_options.formatter.default_extension) os.chdir (original_dir) - file (dep_file, 'w').write ('%s: %s' + file (dep_file, 'w').write ('%s: %s\n' % (final_output_file, ' '.join (inputs))) if __name__ == '__main__':