X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;ds=inline;f=scripts%2Flilypond-book.py;h=ac3969c9cc27335d69feae420d47b8d249bdb112;hb=d4abad893fb2465b053058584bc5db9442c47ebf;hp=29cde34202208b7699ee41ee16cd110e098e2e4a;hpb=98ff0d93569a59412763835f250a559f414eef11;p=lilypond.git diff --git a/scripts/lilypond-book.py b/scripts/lilypond-book.py index 29cde34202..ac3969c9cc 100644 --- a/scripts/lilypond-book.py +++ b/scripts/lilypond-book.py @@ -1,5 +1,20 @@ #!@TARGET_PYTHON@ +# 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 . + ''' Example usage: @@ -111,7 +126,7 @@ def warranty (): %s %s -''' % ( _ ('Copyright (c) %s by') % '2001--2009', +''' % ( _ ('Copyright (c) %s by') % '2001--2010', '\n '.join (authors), _ ("Distributed under terms of the GNU General Public License."), _ ("It comes with NO WARRANTY."))) @@ -149,7 +164,8 @@ def get_option_parser (): default='') p.add_option ('--latex-program', - help=_ ("run executable PROG instead of latex"), + help=_ ("run executable PROG instead of latex, or in\n\ +case --pdf option is set instead of pdflatex"), metavar=_ ("PROG"), action='store', dest='latex_program', default='latex') @@ -161,11 +177,28 @@ def get_option_parser (): type="float", default=3.0) + p.add_option ('--lily-output-dir', + help=_ ("write lily-XXX files to DIR, link into --output dir"), + metavar=_ ("DIR"), + action='store', dest='lily_output_dir', + default=None) + p.add_option ("-o", '--output', help=_ ("write output to DIR"), metavar=_ ("DIR"), action='store', dest='output_dir', default='') + p.add_option ('--pdf', + action="store_true", + dest="create_pdf", + help=_ ("create PDF files for use with PDFTeX"), + default=False) + + p.add_option ('-P', '--process', metavar=_ ("COMMAND"), + help = _ ("process ly_files using COMMAND FILE..."), + action='store', + dest='process_cmd', default='') + p.add_option ('--skip-lily-check', help=_ ("do not fail if no lilypond output is found"), metavar=_ ("DIR"), @@ -178,21 +211,9 @@ def get_option_parser (): action='store_true', dest='skip_png_check', default=False) - p.add_option ('--lily-output-dir', - help=_ ("write lily-XXX files to DIR, link into --output dir"), - metavar=_ ("DIR"), - action='store', dest='lily_output_dir', - default=None) - - p.add_option ('-P', '--process', metavar=_ ("COMMAND"), - help = _ ("process ly_files using COMMAND FILE..."), - action='store', - dest='process_cmd', default='') - - p.add_option ('--pdf', - action="store_true", - dest="create_pdf", - help=_ ("create PDF files for use with PDFTeX"), + p.add_option ('--use-source-file-names', + help=_ ("write snippet output files with the same base name as their source file"), + action='store_true', dest='use_source_file_names', default=False) p.add_option ('-V', '--verbose', help=_ ("be verbose"), @@ -276,13 +297,19 @@ FILENAME = 'filename' ALT = 'alt' -# NOTIME has no opposite so it isn't part of this dictionary. +# NOTIME and NOGETTEXT have no opposite so they aren't part of this +# dictionary. # NOQUOTE is used internally only. no_options = { NOFRAGMENT: FRAGMENT, NOINDENT: INDENT, } +# Options that have no impact on processing by lilypond (or --process +# argument) +PROCESSING_INDEPENDENT_OPTIONS = ( + ALT, NOGETTEXT, VERBATIM, ADDVERSION, + TEXIDOC, DOCTITLE, VERSION, PRINTFILENAME) # Recognize special sequences in the input. # @@ -1117,16 +1144,28 @@ class LilypondSnippet (Snippet): self.option_dict[INDENT] = '0\\mm' # Set a default line-width if there is none. We need this, because - # lilypond-book has set left-padding by default and therefore does - # #(define line-width (- line-width (* 3 mm))) - # TODO: Junk this ugly hack if the code gets rewritten to concatenate - # all settings before writing them in the \paper block. + # lilypond-book has set left-padding by default and therefore does + # #(define line-width (- line-width (* 3 mm))) + # TODO: Junk this ugly hack if the code gets rewritten to concatenate + # all settings before writing them in the \paper block. if not LINE_WIDTH in self.option_dict: - if not QUOTE in self.option_dict: - if not LILYQUOTE in self.option_dict: - self.option_dict[LINE_WIDTH] = "#(- paper-width \ + if not QUOTE in self.option_dict: + if not LILYQUOTE in self.option_dict: + self.option_dict[LINE_WIDTH] = "#(- paper-width \ left-margin-default right-margin-default)" + def get_option_list (self): + if not 'option_list' in self.__dict__: + option_list = [] + for (key, value) in self.option_dict.items (): + if value == None: + option_list.append (key) + else: + option_list.append (key + '=' + value) + option_list.sort () + self.option_list = option_list + return self.option_list + def compose_ly (self, code): if FRAGMENT in self.option_dict: body = FRAGMENT_LY @@ -1164,11 +1203,10 @@ left-margin-default right-margin-default)" override.update (default_ly_options) option_list = [] - for (key, value) in self.option_dict.items (): - if value == None: - option_list.append (key) - else: - option_list.append (key + '=' + value) + for option in self.get_option_list (): + for name in PROCESSING_INDEPENDENT_OPTIONS: + if not option.startswith (name): + option_list.append (option) option_string = ','.join (option_list) compose_dict = {} @@ -1176,7 +1214,10 @@ left-margin-default right-margin-default)" for a in compose_types: compose_dict[a] = [] - for (key, value) in self.option_dict.items (): + option_names = self.option_dict.keys () + option_names.sort () + for key in option_names: + value = self.option_dict[key] (c_key, c_value) = classic_lilypond_book_compatibility (key, value) if c_key: if c_value: @@ -1238,9 +1279,14 @@ left-margin-default right-margin-default)" except ImportError: from md5 import md5 - # We only want to calculate the hash based - # on the snippet code, not the snippet + preamble + # We only want to calculate the hash based on the snippet + # code plus fragment options relevant to processing by + # lilypond, not the snippet + preamble hash = md5 (self.relevant_contents (self.ly ())) + for option in self.get_option_list (): + for name in PROCESSING_INDEPENDENT_OPTIONS: + if not option.startswith (name): + hash.update (option) ## let's not create too long names. self.checksum = hash.hexdigest ()[:10] @@ -1249,22 +1295,31 @@ left-margin-default right-margin-default)" def basename (self): cs = self.get_checksum () - name = '%s/lily-%s' % (cs[:2], cs[2:10]) + name = '%s/lily-%s' % (cs[:2], cs[2:]) return name + final_basename = basename + def write_ly (self): base = self.basename () path = os.path.join (global_options.lily_output_dir, base) directory = os.path.split(path)[0] if not os.path.isdir (directory): os.makedirs (directory) - out = file (path + '.ly', 'w') - out.write (self.full_ly ()) - file (path + '.txt', 'w').write ('image of music') + filename = path + '.ly' + if os.path.exists (filename): + diff_against_existing = filter_pipe (self.full_ly (), 'diff -u %s -' % filename) + if diff_against_existing: + warning ("%s: duplicate filename but different contents of orginal file,\n\ +printing diff against existing file." % filename) + ly.stderr_write (diff_against_existing) + else: + out = file (filename, 'w') + out.write (self.full_ly ()) + file (path + '.txt', 'w').write ('image of music') def relevant_contents (self, ly): - return re.sub (r'\\(version|sourcefileline|sourcefilename)[^\n]*\n|' + - NOGETTEXT + '[,\]]', '', ly) + return re.sub (r'\\(version|sourcefileline|sourcefilename)[^\n]*\n', '', ly) def link_all_output_files (self, output_dir, output_dir_files, destination): existing, missing = self.all_output_files (output_dir, output_dir_files) @@ -1272,13 +1327,25 @@ left-margin-default right-margin-default)" print '\nMissing', missing raise CompileError(self.basename()) for name in existing: + if (global_options.use_source_file_names + and isinstance (self, LilypondFileSnippet)): + base, ext = os.path.splitext (name) + components = base.split ('-') + # ugh, assume filenames with prefix with one dash (lily-xxxx) + if len (components) > 2: + base_suffix = '-' + components[-1] + else: + base_suffix = '' + final_name = self.final_basename () + base_suffix + ext + else: + final_name = name try: - os.unlink (os.path.join (destination, name)) + os.unlink (os.path.join (destination, final_name)) except OSError: pass src = os.path.join (output_dir, name) - dst = os.path.join (destination, name) + dst = os.path.join (destination, final_name) dst_path = os.path.split(dst)[0] if not os.path.isdir (dst_path): os.makedirs (dst_path) @@ -1379,7 +1446,7 @@ left-margin-default right-margin-default)" return func (self) def get_images (self): - base = self.basename () + base = self.final_basename () single = '%(base)s.png' % vars () multiple = '%(base)s-page1.png' % vars () @@ -1396,7 +1463,7 @@ left-margin-default right-margin-default)" def output_docbook (self): str = '' - base = self.basename () + base = self.final_basename () for image in self.get_images (): (base, ext) = os.path.splitext (image) str += output[DOCBOOK][OUTPUT] % vars () @@ -1412,7 +1479,7 @@ left-margin-default right-margin-default)" def output_html (self): str = '' - base = self.basename () + base = self.final_basename () if self.format == HTML: str += self.output_print_filename (HTML) if VERBATIM in self.option_dict: @@ -1441,13 +1508,13 @@ left-margin-default right-margin-default)" info_image_path = os.path.join (global_options.info_images_dir, base) str += output[TEXINFO][OUTPUTIMAGE] % vars () - base = self.basename () + base = self.final_basename () str += output[self.format][OUTPUT] % vars () return str def output_latex (self): str = '' - base = self.basename () + base = self.final_basename () if self.format == LATEX: str += self.output_print_filename (LATEX) if VERBATIM in self.option_dict: @@ -1468,7 +1535,7 @@ left-margin-default right-margin-default)" def output_print_filename (self, format): str = '' if PRINTFILENAME in self.option_dict: - base = self.basename () + base = self.final_basename () filename = os.path.basename (self.substring ('filename')) str = output[format][PRINTFILENAME] % vars () @@ -1476,7 +1543,7 @@ left-margin-default right-margin-default)" def output_texinfo (self): str = self.output_print_filename (TEXINFO) - base = self.basename () + base = self.final_basename () if DOCTITLE in self.option_dict: doctitle = base + '.doctitle' translated_doctitle = doctitle + document_language @@ -1539,6 +1606,13 @@ class LilypondFileSnippet (LilypondSnippet): return ('\\sourcefilename \"%s\"\n\\sourcefileline 0\n%s' % (name, self.contents)) + def final_basename (self): + if global_options.use_source_file_names: + base = os.path.splitext (os.path.basename (self.substring ('filename')))[0] + return base + else: + return self.basename () + class LilyPondVersionString (Snippet): """A string that does not require extra memory.""" @@ -1707,7 +1781,7 @@ def process_snippets (cmd, snippets, checksum = snippet_list_checksum (snippets) contents = '\n'.join (['snippet-map-%d.ly' % checksum] - + [snip.basename() + '.ly' for snip in snippets]) + + list (set ([snip.basename() + '.ly' for snip in snippets]))) name = os.path.join (lily_output_dir, 'snippet-names-%d.ly' % checksum) file (name, 'wb').write (contents) @@ -2077,6 +2151,8 @@ def main (): global_options.process_cmd += ' --formats=eps ' if global_options.create_pdf: global_options.process_cmd += "--pdf -dinclude-eps-fonts -dgs-load-fonts " + if global_options.latex_program == 'latex': + global_options.latex_program = 'pdflatex' if global_options.verbose: global_options.process_cmd += " --verbose "