X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;ds=sidebyside;f=scripts%2Flilypond-book.py;h=6d1a949c39ad51a6a19ea032664bdcf201c500c4;hb=d8a7eb6f3c224acc70abfec92296095b369a5497;hp=60048cacdeaded5a6a4d6169326f4975325ad1a0;hpb=925c9e366ee0d1c91b1e43716be34b0fb4dd0c6a;p=lilypond.git diff --git a/scripts/lilypond-book.py b/scripts/lilypond-book.py index 60048cacde..6d1a949c39 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: @@ -29,7 +44,6 @@ TODO: ''' import glob -import md5 import os import re import stat @@ -273,18 +287,23 @@ TEXIDOC = 'texidoc' TEXINFO = 'texinfo' VERBATIM = 'verbatim' VERSION = 'lilypondversion' -FONTLOAD = 'fontload' 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. # @@ -601,7 +620,6 @@ simple_options = [ TEXIDOC, LANG, VERBATIM, - FONTLOAD, FILENAME, ALT, ADDVERSION @@ -831,8 +849,6 @@ PREAMBLE_LY = '''%%%% Generated by %(program_name)s %(preamble_string)s \paper { - #(define dump-extents #t) - %(font_dump_setting)s %(paper_string)s force-assignment = #"" line-width = #(- line-width (* mm %(padding_mm)f)) @@ -927,7 +943,7 @@ def ly_comment_gettext (t, m): return m.group (1) + t (m.group (2)) def verb_ly_gettext (s): - if not document_language or not langdefs.LANGDICT[document_language].enable_ly_identifier_l10n: + if not document_language: return s try: t = langdefs.translation[document_language] @@ -936,14 +952,15 @@ def verb_ly_gettext (s): s = ly_comment_re.sub (lambda m: ly_comment_gettext (t, m), s) - for v in ly_var_def_re.findall (s): - s = re.sub (r"(?m)(^|[' \\#])%s([^a-zA-Z])" % v, - "\\1" + t (v) + "\\2", - s) - for id in ly_context_id_re.findall (s): - s = re.sub (r'(\s+|")%s(\s+|")' % id, - "\\1" + t (id) + "\\2", - s) + if langdefs.LANGDICT[document_language].enable_ly_identifier_l10n: + for v in ly_var_def_re.findall (s): + s = re.sub (r"(?m)(^|[' \\#])%s([^a-zA-Z])" % v, + "\\1" + t (v) + "\\2", + s) + for id in ly_context_id_re.findall (s): + s = re.sub (r'(\s+|")%s(\s+|")' % id, + "\\1" + t (id) + "\\2", + s) return s texinfo_lang_re = re.compile ('(?m)^@documentlanguage (.*?)( |$)') @@ -1036,10 +1053,12 @@ class LilypondSnippet (Snippet): self.do_options (os, self.type) def verb_ly (self): - if NOGETTEXT in self.option_dict: - return self.substring ('code') - else: - return verb_ly_gettext (self.substring ('code')) + verb_text = self.substring ('code') + if not NOGETTEXT in self.option_dict: + verb_text = verb_ly_gettext (verb_text) + if not verb_text.endswith ('\n'): + verb_text += '\n' + return verb_text def ly (self): contents = self.substring ('code') @@ -1118,13 +1137,28 @@ class LilypondSnippet (Snippet): if not INDENT in self.option_dict: self.option_dict[INDENT] = '0\\mm' - # The QUOTE pattern from ly_options only emits the `line-width' - # keyword. - if has_line_width and QUOTE in self.option_dict: - if no_line_width_value: - del self.option_dict[LINE_WIDTH] - else: - del self.option_dict[QUOTE] + # 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. + 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 \ +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: @@ -1163,11 +1197,10 @@ class LilypondSnippet (Snippet): 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 = {} @@ -1175,7 +1208,10 @@ class LilypondSnippet (Snippet): 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: @@ -1224,9 +1260,6 @@ class LilypondSnippet (Snippet): notes_string = '\n '.join (compose_dict[NOTES]) % vars () preamble_string = '\n '.join (compose_dict[PREAMBLE]) % override padding_mm = global_options.padding_mm - font_dump_setting = '' - if FONTLOAD in self.option_dict: - font_dump_setting = '#(define-public force-eps-font-include #t)\n' d = globals().copy() d.update (locals()) @@ -1234,7 +1267,20 @@ class LilypondSnippet (Snippet): def get_checksum (self): if not self.checksum: - hash = md5.md5 (self.relevant_contents (self.full_ly ())) + # Work-around for md5 module deprecation warning in python 2.5+: + try: + from hashlib import md5 + except ImportError: + from md5 import md5 + + # 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] @@ -1243,7 +1289,7 @@ class LilypondSnippet (Snippet): 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 def write_ly (self): @@ -1252,13 +1298,20 @@ class LilypondSnippet (Snippet): 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 not diff_against_existing.startswith ('\n'): + 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) @@ -1475,9 +1528,9 @@ class LilypondSnippet (Snippet): doctitle = base + '.doctitle' translated_doctitle = doctitle + document_language if os.path.exists (translated_doctitle): - str += '@lydoctitle %s\n' % open (translated_doctitle).read () + str += '@lydoctitle %s\n\n' % open (translated_doctitle).read () elif os.path.exists (doctitle): - str += '@lydoctitle %s\n' % open (doctitle).read () + str += '@lydoctitle %s\n\n' % open (doctitle).read () if TEXIDOC in self.option_dict: texidoc = base + '.texidoc' translated_texidoc = texidoc + document_language @@ -1522,7 +1575,11 @@ class LilypondFileSnippet (LilypondSnippet): s = self.contents s = re_begin_verbatim.split (s)[-1] s = re_end_verbatim.split (s)[0] - return verb_ly_gettext (s) + if not NOGETTEXT in self.option_dict: + s = verb_ly_gettext (s) + if not s.endswith ('\n'): + s += '\n' + return s def ly (self): name = self.substring ('filename') @@ -1697,7 +1754,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) @@ -1746,17 +1803,17 @@ def get_latex_textwidth (source): os.unlink (logfile) columns = 0 - m = re.search ('columns=([0-9.]*)', parameter_string) + m = re.search ('columns=([0-9.]+)', parameter_string) if m: columns = int (m.group (1)) columnsep = 0 - m = re.search ('columnsep=([0-9.]*)pt', parameter_string) + m = re.search ('columnsep=([0-9.]+)pt', parameter_string) if m: columnsep = float (m.group (1)) textwidth = 0 - m = re.search ('textwidth=([0-9.]*)pt', parameter_string) + m = re.search ('textwidth=([0-9.]+)pt', parameter_string) if m: textwidth = float (m.group (1)) if columns: