X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=scripts%2Flilypond-book.py;h=e123e8b6b5f71af85e2e641bbe5d329494a6ea72;hb=a29cc8172070dd25a8da459c378a4fc6c0a3455d;hp=48f04c345641cccf74e2e8cb99ac0e856a0b34c3;hpb=e0431f3036e85764f05e3860a6b70ec0606584eb;p=lilypond.git diff --git a/scripts/lilypond-book.py b/scripts/lilypond-book.py index 48f04c3456..e123e8b6b5 100644 --- a/scripts/lilypond-book.py +++ b/scripts/lilypond-book.py @@ -55,12 +55,13 @@ sys.path.insert (0, os.path.join (datadir, 'python')) #if __name__ == '__main__': import lilylib as ly +import fontextract global _;_=ly._ global re;re = ly.re # Lilylib globals. program_version = '@TOPLEVEL_VERSION@' -program_name = sys.argv[0] +program_name = os.path.basename (sys.argv[0]) verbose_p = 0 pseudo_filter_p = 0 original_dir = os.getcwd () @@ -79,8 +80,8 @@ copyright = ('Jan Nieuwenhuizen ', 'Han-Wen Nienhuys ') option_definitions = [ - (_ ("EXT"), 'f', 'format', - _ ('''use output format EXT (texi [default], texi-html, + (_ ("FMT"), 'f', 'format', + _ ('''use output format FMT (texi [default], texi-html, latex, html)''')), (_ ("FILTER"), 'F', 'filter', _ ("pipe snippets through FILTER [convert-ly -n -]")), @@ -92,6 +93,9 @@ option_definitions = [ _ ("write output to DIR")), (_ ("COMMAND"), 'P', 'process', _ ("process ly_files using COMMAND FILE...")), + (_('FILE'), '', 'psfonts', + _ ('''extract all PostScript fonts into FILE for LaTeX + must use this with dvips -h FILE''')), ('', 'V', 'verbose', _ ("be verbose")), ('', 'v', 'version', @@ -107,13 +111,14 @@ lilypond_binary = os.path.join ('@bindir@', 'lilypond') if '@bindir@' == ('@' + 'bindir@') or not os.path.exists (lilypond_binary): lilypond_binary = 'lilypond' +psfonts_file = '' use_hash_p = 1 format = 0 -output_name = 0 +output_name = '' latex_filter_cmd = 'latex "\\nonstopmode \input /dev/stdin"' filter_cmd = 0 process_cmd = '' -default_ly_options = {} +default_ly_options = { 'alt': "[image of music]" } # # Is this pythonic? Personally, I find this rather #define-nesque. --hwn @@ -147,6 +152,8 @@ TEXIDOC = 'texidoc' TEXINFO = 'texinfo' VERBATIM = 'verbatim' FONTLOAD = 'fontload' +FILENAME = 'filename' +ALT = 'alt' # NOTIME has no opposite so it isn't part of this dictionary. @@ -156,6 +163,7 @@ no_options = { NOINDENT: INDENT, } + # Recognize special sequences in the input. # # (?Pregex) -- Assign result of REGEX to NAME. @@ -384,7 +392,9 @@ simple_options = [ PRINTFILENAME, TEXIDOC, VERBATIM, - FONTLOAD + FONTLOAD, + FILENAME, + ALT ] ly_options = { @@ -408,7 +418,12 @@ ly_options = { ## LAYOUT: { - NOTIME: r'''\context { + NOTIME: r''' + \context { + \Score + timing = ##f + } + \context { \Staff \remove Time_signature_engraver }''', @@ -437,7 +452,7 @@ output = { OUTPUT: r''' [image of music]''', + border="0" src="%(image)s" alt="%(alt)s">''', PRINTFILENAME: '

%(filename)s

', @@ -501,13 +516,13 @@ output = { OUTPUTIMAGE: r'''@noindent @ifinfo -@image{%(base)s,,,[image of music],%(ext)s} +@image{%(base)s,,,%(alt)s,%(ext)s} @end ifinfo @html

[image of music] + border="0" src="%(image)s" alt="%(alt)s">

@end html @@ -617,8 +632,14 @@ def verbatim_texinfo (s): def split_options (option_string): if option_string: - return re.split (format_res[format]['option_sep'], - option_string) + if format == HTML: + options = re.findall('[\w\.-:]+(?:\s*=\s*(?:"[^"]*"|\'[^\']*\'|\S+))?',option_string) + for i in range(len(options)): + options[i] = re.sub('^([^=]+=\s*)(?P["\'])(.*)(?P=q)','\g<1>\g<3>',options[i]) + return options + else: + return re.split (format_res[format]['option_sep'], + option_string) return [] class Chunk: @@ -677,8 +698,7 @@ class Lilypond_snippet (Snippet): def __init__ (self, type, match, format, line_number): Snippet.__init__ (self, type, match, format, line_number) os = match.group ('options') - if os: - self.do_options (os, self.type) + self.do_options (os, self.type) def ly (self): return self.substring ('code') @@ -866,6 +886,8 @@ class Lilypond_snippet (Snippet): return self.hash def basename (self): + if FILENAME in self.option_dict: + return self.option_dict[FILENAME] if use_hash_p: return 'lily-%d' % self.get_hash () raise 'to be done' @@ -887,8 +909,9 @@ class Lilypond_snippet (Snippet): and os.path.exists (system_file)\ and os.stat (system_file)[stat.ST_SIZE] \ and re.match ('% eof', open (system_file).readlines ()[-1]) - if ok and (use_hash_p \ - or self.ly () == open (ly_file).read ()): + if ok and (not use_hash_p or FILENAME in self.option_dict): + ok = (self.full_ly () == open (ly_file).read ()) + if ok: # TODO: Do something smart with target formats # (ps, png) and m/ctimes. return None @@ -951,6 +974,7 @@ class Lilypond_snippet (Snippet): str += output[HTML][BEFORE] % vars () for image in self.get_images (): (base, ext) = os.path.splitext (image) + alt = self.option_dict[ALT] str += output[HTML][OUTPUT] % vars () str += output[HTML][AFTER] % vars () return str @@ -963,6 +987,7 @@ class Lilypond_snippet (Snippet): # URG, makeinfo implicitly prepends dot to extension. # Specifying no extension is most robust. ext = '' + alt = self.option_dict[ALT] str += output[TEXINFO][OUTPUTIMAGE] % vars () base = self.basename () @@ -1265,9 +1290,12 @@ class Compile_error: def write_file_map (lys, name): snippet_map = open ('snippet-map.ly', 'w') - snippet_map.write ("\n#(ly:add-file-name-alist '(") + snippet_map.write (""" +#(define version-seen? #t) +#(ly:add-file-name-alist '( +""") for ly in lys: - snippet_map.write ('("%s.ly" . "%s:%d (%s.ly)")\n' \ + snippet_map.write ('("%s.ly" . "%s:%d (%s.ly)")\n' % (ly.basename (), name, ly.line_number, @@ -1316,11 +1344,27 @@ def guess_format (input_filename): # FIXME format = ext2format[e] else: - ly.error (_ ("cannot determine format for: %s" \ + ly.error (_ ("can't determine format for: %s" \ % input_filename)) ly.exit (1) return format +def write_if_updated (file_name, lines): + try: + f = open (file_name) + oldstr = f.read () + new_str = string.join (lines, '') + if oldstr == new_str: + ly.progress (_ ("%s is up to date.") % file_name) + ly.progress ('\n') + return + except: + pass + + ly.progress (_ ("Writing `%s'...") % file_name) + open (file_name, 'w').writelines (lines) + ly.progress ('\n') + def do_file (input_filename): # Ugh. if not input_filename or input_filename == '-': @@ -1348,15 +1392,12 @@ def do_file (input_filename): output_filename = '-' output_file = sys.stdout else: - if not output_name: - output_filename = input_base + format2ext[format] - else: + if output_name: if not os.path.isdir (output_name): os.mkdir (output_name, 0777) - output_filename = (output_name - + '/' + input_base - + format2ext[format]) + os.chdir (output_name) + output_filename = input_base + format2ext[format] if os.path.exists (input_filename) \ and os.path.exists (output_filename) \ and os.path.samefile (output_filename, input_fullname): @@ -1364,9 +1405,6 @@ def do_file (input_filename): _ ("Output would overwrite input file; use --output.")) ly.exit (2) - output_file = open (output_filename, 'w') - if output_name: - os.chdir (output_name) try: ly.progress (_ ("Reading %s...") % input_fullname) source = in_handle.read () @@ -1410,37 +1448,39 @@ def do_file (input_filename): break if filter_cmd: - output_file.writelines ([c.filter_text () \ - for c in chunks]) - + write_if_updated (output_filename, + [c.filter_text () for c in chunks]) elif process_cmd: do_process_cmd (chunks, input_fullname) ly.progress (_ ("Compiling %s...") % output_filename) - output_file.writelines ([s.replacement_text () \ - for s in chunks]) ly.progress ('\n') - + write_if_updated (output_filename, + [s.replacement_text () + for s in chunks]) + def process_include (snippet): os.chdir (original_dir) name = snippet.substring ('filename') ly.progress (_ ("Processing include: %s") % name) ly.progress ('\n') - do_file (name) + return do_file (name) + + include_chunks = map (process_include, + filter (lambda x: is_derived_class (x.__class__, + Include_snippet), + chunks)) + - map (process_include, - filter (lambda x: is_derived_class (x.__class__, - Include_snippet), - chunks)) + return chunks + reduce (lambda x,y: x + y, include_chunks, []) + except Compile_error: os.chdir (original_dir) ly.progress (_ ("Removing `%s'") % output_filename) ly.progress ('\n') - - os.unlink (output_filename) raise Compile_error def do_options (): - global format, output_name + global format, output_name, psfonts_file global filter_cmd, process_cmd, verbose_p (sh, long) = ly.getopt_args (option_definitions) @@ -1476,8 +1516,6 @@ def do_options (): ly.abspath (a))) elif o == '--output' or o == '-o': output_name = a - elif o == '--outdir': - output_name = a elif o == '--process' or o == '-P': process_cmd = a filter_cmd = 0 @@ -1486,6 +1524,8 @@ def do_options (): sys.exit (0) elif o == '--verbose' or o == '-V': verbose_p = 1 + elif o == '--psfonts': + psfonts_file = a elif o == '--warranty' or o == '-w': if 1 or status: ly.warranty () @@ -1494,8 +1534,8 @@ def do_options (): def main (): files = do_options () - if not files: - ly.warning ("Need to have command line option") + if not files or len (files) > 1: + ly.help () ly.exit (2) file = files[0] @@ -1518,10 +1558,37 @@ def main (): ly.setup_environment () try: - do_file (file) + chunks = do_file (file) + if psfonts_file: + fontextract.verbose = verbose_p + snippet_chunks = filter (lambda x: is_derived_class (x.__class__, + Lilypond_snippet), + chunks) + if not verbose_p: + ly.progress (_ ("Writing fonts to %s...") % psfonts_file) + fontextract.extract_fonts (psfonts_file, + [x.basename() + '.eps' + for x in snippet_chunks]) + if not verbose_p: + ly.progress ('\n') + except Compile_error: ly.exit (1) + if format == TEXINFO or format == LATEX: + psfonts = os.path.join (output_name, psfonts_file) + output = os.path.join (output_name, + os.path.splitext (os.path.basename + (file))[0]) + '.dvi' + if not psfonts: + ly.warning (_ ("option --psfonts=FILE not used")) + ly.warning (_ ("processing with dvips will have no fonts")) + psfonts = 'PSFONTS-FILE' + ly.progress ('\n') + ly.progress (_ ("DVIPS usage:")) + ly.progress ('\n') + ly.progress (" dvips -h %(psfonts)s %(output)s" % vars ()) + ly.progress ('\n') if __name__ == '__main__': main ()