X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=scripts%2Flilypond-book.py;h=ac3969c9cc27335d69feae420d47b8d249bdb112;hb=d4abad893fb2465b053058584bc5db9442c47ebf;hp=b8c765d3fb0b74799d2269f922a4bcbf2e3f43a4;hpb=96e14d746b102f223acf6b6f4cdb8b0f0a11cd24;p=lilypond.git diff --git a/scripts/lilypond-book.py b/scripts/lilypond-book.py index b8c765d3fb..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: @@ -15,7 +30,7 @@ classic lilypond-book: TODO: * this script is too complex. Modularize. - + * ly-options: intertext? * --line-width? * eps in latex / eps by lilypond -b ps? @@ -29,7 +44,6 @@ TODO: ''' import glob -import md5 import os import re import stat @@ -51,6 +65,17 @@ ly.require_python_version () program_version = '@TOPLEVEL_VERSION@' program_name = os.path.basename (sys.argv[0]) +# Check if program_version contains @ characters. This will be the case if +# the .py file is called directly while building the lilypond documentation. +# If so, try to check for the env var LILYPOND_VERSION, which is set by our +# makefiles and use its value. +at_re = re.compile (r'@') +if at_re.match (program_version): + if os.environ.has_key('LILYPOND_VERSION'): + program_version = os.environ['LILYPOND_VERSION'] + else: + program_version = "unknown" + original_dir = os.getcwd () backend = 'ps' @@ -97,12 +122,12 @@ def warranty (): ly.encoded_write (sys.stdout, ''' %s -%s + %s %s %s -''' % ( _ ('Copyright (c) %s by') % '2001--2007', - ' '.join (authors), +''' % ( _ ('Copyright (c) %s by') % '2001--2010', + '\n '.join (authors), _ ("Distributed under terms of the GNU General Public License."), _ ("It comes with NO WARRANTY."))) @@ -139,23 +164,41 @@ 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') - p.add_option ('--left-padding', + p.add_option ('--left-padding', metavar=_ ("PAD"), dest="padding_mm", help=_ ("pad left side of music to align music inspite of uneven bar numbers (in mm)"), 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"), @@ -167,22 +210,10 @@ def get_option_parser (): metavar=_ ("DIR"), 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"), @@ -200,8 +231,9 @@ def get_option_parser (): action='store_true') p.add_option_group ('', description=( - _ ("Report bugs via") - + ' http://post.gmane.org/post.php?group=gmane.comp.gnu.lilypond.bugs\n')) + _ ("Report bugs via %s") + % ' http://post.gmane.org/post.php' + '?group=gmane.comp.gnu.lilypond.bugs') + '\n') return p lilypond_binary = os.path.join ('@bindir@', 'lilypond') @@ -241,6 +273,7 @@ LAYOUT = 'layout' LINE_WIDTH = 'line-width' LILYQUOTE = 'lilyquote' NOFRAGMENT = 'nofragment' +NOGETTEXT = 'nogettext' NOINDENT = 'noindent' NOQUOTE = 'noquote' NORAGGED_RIGHT = 'noragged-right' @@ -248,7 +281,6 @@ NOTES = 'body' NOTIME = 'notime' OUTPUT = 'output' OUTPUTIMAGE = 'outputimage' -PACKED = 'packed' PAPER = 'paper' PREAMBLE = 'preamble' PRINTFILENAME = 'printfilename' @@ -260,23 +292,32 @@ DOCTITLE = 'doctitle' TEXIDOC = 'texidoc' TEXINFO = 'texinfo' VERBATIM = 'verbatim' -FONTLOAD = 'fontload' +VERSION = 'lilypondversion' 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. # # (?Pregex) -- Assign result of REGEX to NAME. # *? -- Match non-greedily. +# (?!...) -- Match if `...' doesn't match next (without consuming +# the string). +# # (?m) -- Multiline regex: Make ^ and $ match at each line. # (?s) -- Make the dot match all characters including newline. # (?x) -- Ignore whitespace in patterns. @@ -290,17 +331,36 @@ snippet_res = { 'lilypond': r'''(?smx) (?P - <(?P(inline)?)mediaobject>\s*\s*.*?)")?>(?P.*?)\s*\s*)''', + <(?P(inline)?)mediaobject>\s* + \s* + .*?)")?> + (?P.*?) + \s* + \s* + )''', 'lilypond_block': r'''(?smx) (?P - <(?P(inline)?)mediaobject>\s*\s*.*?)")?>(?P.*?)\s*\s*)''', + <(?P(inline)?)mediaobject>\s* + \s* + .*?)")?> + (?P.*?) + \s* + \s* + )''', 'lilypond_file': r'''(?smx) (?P - <(?P(inline)?)mediaobject>\s*\s*.*?\.ly)"\s*(role="(?P.*?)")?\s*(/>|>\s*)\s*\s*)''', + <(?P(inline)?)mediaobject>\s* + \s* + |>\s*)\s* + \s* + )''', 'multiline_comment': r'''(?smx) @@ -316,9 +376,11 @@ snippet_res = { no_match, 'verbatim': - no_match, - - }, + no_match, + + 'lilypondversion': + no_match, + }, ## HTML: { 'include': @@ -370,6 +432,11 @@ snippet_res = { (?s) (?P (?P
\s.*?
\s))''', + + 'lilypondversion': + r'''(?mx) + (?P + )''', }, ## @@ -443,6 +510,12 @@ snippet_res = { \\begin\s*{verbatim} .*? \\end\s*{verbatim}))''', + + 'lilypondversion': + r'''(?smx) + (?P + \\lilypondversion)[^a-zA-Z]''', + }, ## @@ -509,17 +582,21 @@ snippet_res = { @example \s.*? @end\s+example\s))''', - }, -} + 'lilypondversion': + r'''(?mx) + [^@](?P + @lilypondversion)[^a-zA-Z]''', + }, +} format_res = { - DOCBOOK: { - 'intertext': r',?\s*intertext=\".*?\"', + DOCBOOK: { + 'intertext': r',?\s*intertext=\".*?\"', 'option_sep': '\s*', - }, + }, HTML: { 'intertext': r',?\s*intertext=\".*?\"', 'option_sep': '\s*', @@ -536,18 +613,19 @@ format_res = { }, } + # Options without a pattern in ly_options. simple_options = [ EXAMPLEINDENT, FRAGMENT, NOFRAGMENT, + NOGETTEXT, NOINDENT, PRINTFILENAME, DOCTITLE, TEXIDOC, LANG, VERBATIM, - FONTLOAD, FILENAME, ALT, ADDVERSION @@ -572,8 +650,6 @@ ly_options = { RAGGED_RIGHT: r'''ragged-right = ##t''', NORAGGED_RIGHT: r'''ragged-right = ##f''', - - PACKED: r'''packed = ##t''', }, ## @@ -597,19 +673,37 @@ ly_options = { output = { ## - DOCBOOK: { - FILTER: r'''%(code)s''', - - OUTPUT: r''' - - - - - ''', - - VERBATIM: r'''%(verb)s''', - - PRINTFILENAME: '%(filename)s' + DOCBOOK: { + FILTER: r''' + + +%(code)s + + +''', + + OUTPUT: r''' + + + + +''', + + VERBATIM: r''' +%(verb)s''', + + VERSION: program_version, + + PRINTFILENAME: r''' + + + + %(filename)s + + + +''' }, ## HTML: { @@ -626,8 +720,10 @@ output = { ''', OUTPUT: r''' - %(alt)s''', + %(alt)s''', PRINTFILENAME: '

%(filename)s

', @@ -638,34 +734,38 @@ output = { VERBATIM: r'''
 %(verb)s
''', + + VERSION: program_version, }, ## LATEX: { OUTPUT: r'''{%% -\parindent 0pt%% -\ifx\preLilyPondExample \undefined%% - \relax%% -\else%% - \preLilyPondExample%% -\fi%% +\parindent 0pt +\ifx\preLilyPondExample \undefined +\else + \expandafter\preLilyPondExample +\fi \def\lilypondbook{}%% -\input %(base)s-systems.tex%% -\ifx\postLilyPondExample \undefined%% - \relax%% -\else%% - \postLilyPondExample%% -\fi%% +\input %(base)s-systems.tex +\ifx\postLilyPondExample \undefined +\else + \expandafter\postLilyPondExample +\fi }''', PRINTFILENAME: '''\\texttt{%(filename)s} - ''', +''', - QUOTE: r'''\begin{quotation}%(str)s + QUOTE: r'''\begin{quotation} +%(str)s \end{quotation}''', VERBATIM: r'''\noindent -\begin{verbatim}%(verb)s\end{verbatim}''', +\begin{verbatim}%(verb)s\end{verbatim} +''', + + VERSION: program_version, FILTER: r'''\begin{lilypond}[%(options)s] %(code)s @@ -692,7 +792,9 @@ output = {

%(alt)s + border="0" + src="%(image)s" + alt="%(alt)s">

@end html @@ -721,6 +823,8 @@ output = { %(verb)s@end verbatim ''', + VERSION: program_version, + ADDVERSION: r'''@example \version @w{"@version{}"} @end example @@ -745,14 +849,12 @@ PREAMBLE_LY = '''%%%% Generated by %(program_name)s %% **************************************************************** -%% Start cut-&-pastable-section +%% Start cut-&-pastable-section %% **************************************************************** %(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)) @@ -827,7 +929,7 @@ def find_file (name, raise_error=True): full = os.path.join (i, name) if os.path.exists (full): return full - + if raise_error: error (_ ("file not found: %s") % name + '\n') exit (1) @@ -855,15 +957,16 @@ def verb_ly_gettext (s): return 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 (.*?)( |$)') @@ -901,7 +1004,7 @@ class Chunk: def is_plain (self): return False - + class Substring (Chunk): """A string that does not require extra memory.""" def __init__ (self, source, start, end, line_number): @@ -910,7 +1013,7 @@ class Substring (Chunk): self.end = end self.line_number = line_number self.override_text = None - + def is_plain (self): return True @@ -956,7 +1059,12 @@ class LilypondSnippet (Snippet): self.do_options (os, self.type) def verb_ly (self): - 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') @@ -1035,13 +1143,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: @@ -1080,11 +1203,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 = {} @@ -1092,7 +1214,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: @@ -1141,9 +1266,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()) @@ -1151,27 +1273,50 @@ 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] - + return self.checksum 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', '', ly) @@ -1182,19 +1327,31 @@ class LilypondSnippet (Snippet): 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) os.link (src, dst) - + def all_output_files (self, output_dir, output_dir_files): """Return all files generated in lily_output_dir, a set. @@ -1207,7 +1364,7 @@ class LilypondSnippet (Snippet): def consider_file (name): if name in output_dir_files: result.add (name) - + def require_file (name): if name in output_dir_files: result.add (name) @@ -1262,14 +1419,14 @@ class LilypondSnippet (Snippet): # markups do not output a signature. if 'ddump-signature' in global_options.process_cmd: consider_file (systemfile + '.signature') - - + + return (result, missing) - + def is_outdated (self, output_dir, current_files): found, missing = self.all_output_files (output_dir, current_files) return missing - + def filter_text (self): """Run snippet bodies through a command (say: convert-ly). @@ -1289,29 +1446,29 @@ class LilypondSnippet (Snippet): 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 () images = (single,) - if (os.path.exists (multiple) + if (os.path.exists (multiple) and (not os.path.exists (single) or (os.stat (multiple)[stat.ST_MTIME] > os.stat (single)[stat.ST_MTIME]))): count = ps_page_count ('%(base)s.eps' % vars ()) images = ['%s-page%d.png' % (base, page) for page in range (1, count+1)] images = tuple (images) - + return images 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 () - str += self.output_print_filename (DOCBOOK) - if (self.substring('inline') == 'inline'): + str += self.output_print_filename (DOCBOOK) + if (self.substring('inline') == 'inline'): str = '' + str + '' else: str = '' + str + '' @@ -1319,10 +1476,10 @@ class LilypondSnippet (Snippet): verb = verbatim_html (self.verb_ly ()) str = output[DOCBOOK][VERBATIM] % vars () + str return str - + 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: @@ -1351,13 +1508,13 @@ class LilypondSnippet (Snippet): 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: @@ -1370,7 +1527,7 @@ class LilypondSnippet (Snippet): if 0: breaks = self.ly ().count ("\n") str += "".ljust (breaks, "\n").replace ("\n","%\n") - + if QUOTE in self.option_dict: str = output[LATEX][QUOTE] % vars () return str @@ -1378,7 +1535,7 @@ class LilypondSnippet (Snippet): 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 () @@ -1386,14 +1543,14 @@ class LilypondSnippet (Snippet): 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 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 @@ -1438,19 +1595,40 @@ 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') 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.""" + def __init__ (self, type, match, format, line_number): + Snippet.__init__ (self, type, match, format, line_number) + + def replacement_text (self): + return output[self.format][self.type] + snippet_type_to_class = { 'lilypond_file': LilypondFileSnippet, 'lilypond_block': LilypondSnippet, 'lilypond': LilypondSnippet, 'include': IncludeSnippet, + 'lilypondversion': LilyPondVersionString, } def find_linestarts (s): @@ -1493,7 +1671,7 @@ def find_toplevel_snippets (input_string, format, types): for type in types: if not found[type] or found[type][0] < index: found[type] = None - + m = res[type].search (input_string[index:endex]) if not m: continue @@ -1512,8 +1690,8 @@ def find_toplevel_snippets (input_string, format, types): found[type] = (start, snip) - if (found[type] - and (not first + if (found[type] + and (not first or found[type][0] < found[first][0])): first = type @@ -1546,7 +1724,7 @@ def find_toplevel_snippets (input_string, format, types): def filter_pipe (input, cmd): """Pass input through cmd, and return the result.""" - + if global_options.verbose: progress (_ ("Opening filter `%s'") % cmd) @@ -1581,13 +1759,13 @@ def system_in_directory (cmd, directory): Because of win32 compatibility, we can't simply use subprocess. """ - + current = os.getcwd() os.chdir (directory) - ly.system(cmd, be_verbose=global_options.verbose, + ly.system(cmd, be_verbose=global_options.verbose, progress_p=1) os.chdir (current) - + def process_snippets (cmd, snippets, format, lily_output_dir): @@ -1595,23 +1773,23 @@ def process_snippets (cmd, snippets, if not snippets: return - + if format in (HTML, TEXINFO) and '--formats' not in cmd: cmd += ' --formats=png ' elif format in (DOCBOOK) and '--formats' not in cmd: cmd += ' --formats=png,pdf ' checksum = snippet_list_checksum (snippets) - contents = '\n'.join (['snippet-map-%d.ly' % checksum] - + [snip.basename() + '.ly' for snip in snippets]) + contents = '\n'.join (['snippet-map-%d.ly' % checksum] + + 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) system_in_directory (' '.join ([cmd, ly.mkarg (name)]), lily_output_dir) - - + + ### # Retrieve dimensions from LaTeX LATEX_INSPECTION_DOCUMENT = r''' @@ -1629,13 +1807,13 @@ def get_latex_textwidth (source): m = re.search (r'''(?P\\begin\s*{document})''', source) if m == None: warning (_ ("cannot find \\begin{document} in LaTeX document")) - + ## what's a sensible default? return 550.0 - + preamble = source[:m.start (0)] latex_document = LATEX_INSPECTION_DOCUMENT % vars () - + (handle, tmpfile) = tempfile.mkstemp('.tex') logfile = os.path.splitext (tmpfile)[0] + '.log' logfile = os.path.split (logfile)[1] @@ -1643,26 +1821,26 @@ def get_latex_textwidth (source): tmp_handle = os.fdopen (handle,'w') tmp_handle.write (latex_document) tmp_handle.close () - + ly.system ('%s %s' % (global_options.latex_program, tmpfile), be_verbose=global_options.verbose) parameter_string = file (logfile).read() - + os.unlink (tmpfile) 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: @@ -1678,7 +1856,7 @@ def modify_preamble (chunk): r"\\usepackage{graphics}" + '\n' + r"\\begin{document}", str) - chunk.override_text = str + chunk.override_text = str format2ext = { @@ -1726,8 +1904,8 @@ def do_process_cmd (chunks, input_name, options): output_files = split_output_files (options.lily_output_dir) outdated = [c for c in snippets if c.is_outdated (options.lily_output_dir, output_files)] - - write_file_map (outdated, input_name) + + write_file_map (outdated, input_name) progress (_ ("Writing snippets...")) for snippet in outdated: snippet.write_ly() @@ -1846,15 +2024,15 @@ def do_file (input_filename, included=False): global_options.output_dir = os.getcwd() else: global_options.output_dir = os.path.abspath(global_options.output_dir) - + if not os.path.isdir (global_options.output_dir): os.mkdir (global_options.output_dir, 0777) os.chdir (global_options.output_dir) output_filename = os.path.join(global_options.output_dir, input_base + format2ext[global_options.format]) - if (os.path.exists (input_filename) - and os.path.exists (output_filename) + if (os.path.exists (input_filename) + and os.path.exists (output_filename) and samefile (output_filename, input_fullname)): error ( _ ("Output would overwrite input file; use --output.")) @@ -1879,6 +2057,7 @@ def do_file (input_filename, included=False): 'lilypond_file', 'include', 'lilypond', + 'lilypondversion', ) progress (_ ("Dissecting...")) chunks = find_toplevel_snippets (source, global_options.format, snippet_types) @@ -1901,7 +2080,7 @@ def do_file (input_filename, included=False): write_if_updated (output_filename, [s.replacement_text () for s in chunks]) - + def process_include (snippet): os.chdir (original_dir) name = snippet.substring ('filename') @@ -1914,7 +2093,7 @@ def do_file (input_filename, included=False): chunks)) return chunks + reduce (lambda x, y: x + y, include_chunks, []) - + except CompileError: os.chdir (original_dir) progress (_ ("Removing `%s'") % output_filename) @@ -1930,14 +2109,14 @@ def do_options (): global_options.format = TEXINFO global_options.include_path = map (os.path.abspath, global_options.include_path) - + if global_options.warranty: warranty () exit (0) if not args or len (args) > 1: opt_parser.print_help () exit (2) - + return args def main (): @@ -1946,7 +2125,7 @@ def main (): basename = os.path.splitext (files[0])[0] basename = os.path.split (basename)[1] - + if not global_options.format: global_options.format = guess_format (files[0]) @@ -1955,7 +2134,7 @@ def main (): formats += ',png' if global_options.process_cmd == '': - global_options.process_cmd = (lilypond_binary + global_options.process_cmd = (lilypond_binary + ' --formats=%s -dbackend=eps ' % formats) if global_options.process_cmd: @@ -1972,13 +2151,15 @@ 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 " if global_options.padding_mm: global_options.process_cmd += " -deps-box-padding=%f " % global_options.padding_mm - + global_options.process_cmd += " -dread-file-list -dno-strip-output-dir" if global_options.lily_output_dir: @@ -1987,7 +2168,7 @@ def main (): os.makedirs (global_options.lily_output_dir) else: global_options.lily_output_dir = os.path.abspath(global_options.output_dir) - + identify () try: @@ -2003,7 +2184,7 @@ def main (): final_output_file = os.path.join (global_options.output_dir, base_file_name + '.%s' % global_options.format) - + os.chdir (original_dir) file (dep_file, 'w').write ('%s: %s' % (final_output_file, ' '.join (inputs)))