import os
import sys
import re
+import md5
-# Users of python modules should include this snippet
-# and customize variables below.
-
-# We'll suffer this path initialization stuff as long as we don't install
-# our python packages in <prefix>/lib/pythonX.Y
-
-# If set, LILYPONDPREFIX must take prevalence.
-# if datadir is not set, we're doing a build and LILYPONDPREFIX.
-
-################
-# RELOCATION
-################
-
-datadir = '@local_lilypond_datadir@'
-if not os.path.isdir (datadir):
- datadir = '@lilypond_datadir@'
-
-sys.path.insert (0, os.path.join (datadir, 'python'))
-
-if os.environ.has_key ('LILYPONDPREFIX'):
- datadir = os.environ['LILYPONDPREFIX']
- while datadir[-1] == os.sep:
- datadir= datadir[:-1]
-
- datadir = os.path.join (datadir, "share/lilypond/current/")
-sys.path.insert (0, os.path.join (datadir, 'python'))
-
-# dynamic relocation, for GUB binaries.
-bindir = os.path.split (sys.argv[0])[0]
-
-
-for prefix_component in ['share', 'lib']:
- datadir = os.path.abspath (bindir + '/../%s/lilypond/current/python/' % prefix_component)
- sys.path.insert (0, datadir)
-
+"""
+@relocate-preamble@
+"""
import lilylib as ly
import fontextract
original_dir = os.getcwd ()
backend = 'ps'
-help_summary = _ (
-'''Process LilyPond snippets in hybrid HTML, LaTeX, or texinfo document.
-
-Example usage:
-
- lilypond-book --filter="tr '[a-z]' '[A-Z]'" BOOK
- lilypond-book --filter="convert-ly --no-version --from=2.0.0 -" BOOK
- lilypond-book --process='lilypond -I include' BOOK
-''')
+help_summary = (
+_ ("Process LilyPond snippets in hybrid HTML, LaTeX, texinfo or DocBook document.")
++ '\n\n'
++ _ ("Examples:")
++ '''
+ lilypond-book --filter="tr '[a-z]' '[A-Z]'" %(BOOK)s
+ lilypond-book --filter="convert-ly --no-version --from=2.0.0 -" %(BOOK)s
+ lilypond-book --process='lilypond -I include' %(BOOK)s
+''' % {'BOOK': _ ("BOOK")})
authors = ('Jan Nieuwenhuizen <janneke@gnu.org>',
- 'Han-Wen Nienhuys <hanwen@cs.uu.nl>')
+ 'Han-Wen Nienhuys <hanwen@xs4all.nl>')
-
################################################################
def exit (i):
if global_options.verbose:
%s
%s
-''' % ( _('Copyright (c) %s by') % '2001--2006',
+''' % ( _ ('Copyright (c) %s by') % '2001--2006',
' '.join (authors),
- _('Distributed under terms of the GNU General Public License.'),
- _('It comes with NO WARRANTY.')))
-
+ _ ("Distributed under terms of the GNU General Public License."),
+ _ ("It comes with NO WARRANTY.")))
def get_option_parser ():
- p = ly.get_option_parser (usage='lilypond-book [OPTIONS] FILE',
+ p = ly.get_option_parser (usage=_ ("%s [OPTION]... FILE") % 'lilypond-book',
version="@TOPLEVEL_VERSION@",
description=help_summary)
help=_ ("pipe snippets through FILTER [convert-ly -n -]"),
default=None)
p.add_option ('-f', '--format',
- help=_('''use output format FORMAT (texi [default], texi-html, latex, html)'''),
+ help=_ ("use output format FORMAT (texi [default], texi-html, latex, html, docbook)"),
action='store')
- p.add_option ("-I", '--include', help=_('add DIR to include path'),
- metavar="DIR",
+
+ p.add_option ("-I", '--include', help=_ ("add DIR to include path"),
+ metavar=_ ("DIR"),
action='append', dest='include_path',
default=[os.path.abspath (os.getcwd ())])
+
+ 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 ("-o", '--output', help=_('write output to DIR'),
- metavar="DIR",
+ p.add_option ("-o", '--output', help=_ ("write output to DIR"),
+ metavar=_ ("DIR"),
action='store', dest='output_name',
default='')
- p.add_option ('-P', '--process', metavar=_("COMMAND"),
+
+ p.add_option ('-P', '--process', metavar=_ ("COMMAND"),
help = _ ("process ly_files using COMMAND FILE..."),
action='store',
dest='process_cmd', default='lilypond -b eps')
-
+ p.add_option ('--pdf',
+ action="store_true",
+ dest="create_pdf",
+ help=_ ("Create PDF files for use with PDFTeX"),
+ default=False)
p.add_option ('', '--psfonts', action="store_true", dest="psfonts",
- help=_ ('''extract all PostScript fonts into INPUT.psfonts for LaTeX'''
- '''must use this with dvips -h INPUT.psfonts'''),
+ help=_ ('''extract all PostScript fonts into INPUT.psfonts for LaTeX
+must use this with dvips -h INPUT.psfonts'''),
default=None)
- p.add_option ('-V', '--verbose', help=_("be verbose"),
+ p.add_option ('-V', '--verbose', help=_ ("be verbose"),
action="store_true",
default=False,
dest="verbose")
-
p.add_option ('-w', '--warranty',
- help=_("show warranty and copyright"),
+ help=_ ("show warranty and copyright"),
action='store_true')
-
-
- p.add_option_group ('bugs',
- description='''Report bugs via http://post.gmane.org/post.php'''
- '''?group=gmane.comp.gnu.lilypond.bugs\n''')
-
+ p.add_option_group ('bugs',
+ description=(_ ("Report bugs via")
+ + ''' http://post.gmane.org/post.php'''
+ '''?group=gmane.comp.gnu.lilypond.bugs\n'''))
return p
lilypond_binary = os.path.join ('@bindir@', 'lilypond')
#
AFTER = 'after'
BEFORE = 'before'
+DOCBOOK = 'docbook'
EXAMPLEINDENT = 'exampleindent'
FILTER = 'filter'
FRAGMENT = 'fragment'
# (?x) -- Ignore whitespace in patterns.
no_match = 'a\ba'
snippet_res = {
+ ##
+ DOCBOOK: {
+ 'include':
+ no_match,
+
+ 'lilypond':
+ r'''(?smx)
+ (?P<match>
+ <(?P<inline>(inline)?)mediaobject>\s*<textobject.*?>\s*<programlisting\s+language="lilypond".*?(role="(?P<options>.*?)")?>(?P<code>.*?)</programlisting\s*>\s*</textobject\s*>\s*</(inline)?mediaobject>)''',
+
+ 'lilypond_block':
+ r'''(?smx)
+ (?P<match>
+ <(?P<inline>(inline)?)mediaobject>\s*<textobject.*?>\s*<programlisting\s+language="lilypond".*?(role="(?P<options>.*?)")?>(?P<code>.*?)</programlisting\s*>\s*</textobject\s*>\s*</(inline)?mediaobject>)''',
+
+ 'lilypond_file':
+ r'''(?smx)
+ (?P<match>
+ <(?P<inline>(inline)?)mediaobject>\s*<imageobject.*?>\s*<imagedata\s+fileref="(?P<filename>.*?\.ly)"\s*(role="(?P<options>.*?)")?\s*(/>|>\s*</imagedata>)\s*</imageobject>\s*</(inline)?mediaobject>)''',
+
+ 'multiline_comment':
+ r'''(?smx)
+ (?P<match>
+ \s*(?!@c\s+)
+ (?P<code><!--\s.*?!-->)
+ \s)''',
+
+ 'singleline_comment':
+ no_match,
+
+ 'verb':
+ no_match,
+
+ 'verbatim':
+ no_match,
+
+ },
##
HTML: {
'include':
format_res = {
+ DOCBOOK: {
+ 'intertext': r',?\s*intertext=\".*?\"',
+ 'option_sep': '\s*',
+ },
HTML: {
'intertext': r',?\s*intertext=\".*?\"',
'option_sep': '\s*',
}
output = {
+ ##
+ DOCBOOK: {
+ FILTER: r'''<mediaobject><textobject><programlisting language="lilypond" role="%(options)s">%(code)s</programlisting></textobject></mediaobject>''',
+
+ OUTPUT: r'''
+ <imageobject role="latex">
+ <imagedata fileref="%(base)s.pdf" format="PDF"/>
+ </imageobject>
+ <imageobject role="html">
+ <imagedata fileref="%(base)s.png" format="PNG"/></imageobject>''',
+
+ VERBATIM: r'''<programlisting>%(verb)s</programlisting>''',
+
+ PRINTFILENAME: '<textobject><simpara><ulink url="%(base)s.ly"><filename>%(filename)s</filename></ulink></simpara></textobject>'
+ },
##
HTML: {
FILTER: r'''<lilypond %(options)s>
LATEX: {
OUTPUT: r'''{%%
\parindent 0pt%%
-\catcode`\@=12%%
\ifx\preLilyPondExample \undefined%%
\relax%%
\else%%
PREAMBLE_LY = '''%%%% Generated by %(program_name)s
%%%% Options: [%(option_string)s]
-
-#(set! toplevel-score-handler print-score-with-defaults)
-#(set! toplevel-music-handler
- (lambda (p m)
- (if (not (eq? (ly:music-property m \'void) #t))
- (print-score-with-defaults
- p (scorify-music m p)))))
-
-#(ly:set-option (quote no-point-and-click))
-#(define inside-lilypond-book #t)
-#(define version-seen? #t)
+\\include "lilypond-book-preamble.ly"
%(preamble_string)s
%% ****************************************************************
\paper {
- #(define dump-extents #t)
- %(font_dump_setting)s
- %(paper_string)s
+ #(define dump-extents #t)
+ %(font_dump_setting)s
+ %(paper_string)s
+ force-assignment = #""
+ line-width = #(- line-width (* mm %(padding_mm)f))
}
\layout {
- %(layout_string)s
+ %(layout_string)s
}
'''
self.do_options (os, self.type)
def ly (self):
- return self.substring ('code')
+ contents = self.substring ('code')
+ return ('\\sourcefileline %d\n%s'
+ % (self.line_number - 1, contents))
def full_ly (self):
s = self.ly ()
options = split_options (option_string)
for i in options:
- if string.find (i, '=') > 0:
+ if '=' in i:
(key, value) = re.split ('\s*=\s*', i)
self.option_dict[key] = value
else:
'\n ') % vars ()
preamble_string = string.join (compose_dict[PREAMBLE],
'\n ') % 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.update (locals())
return (PREAMBLE_LY + body) % d
- # TODO: Use md5?
def get_hash (self):
if not self.hash:
- self.hash = abs (hash (self.full_ly ()))
+ hash = md5.md5 (self.relevant_contents (self.full_ly ()))
+
+ ## let's not create too long names.
+ self.hash = hash.hexdigest ()[:10]
+
return self.hash
def basename (self):
if FILENAME in self.option_dict:
return self.option_dict[FILENAME]
if global_options.use_hash:
- return 'lily-%d' % self.get_hash ()
+ return 'lily-%s' % self.get_hash ()
raise 'to be done'
def write_ly (self):
outf = open (self.basename () + '.ly', 'w')
outf.write (self.full_ly ())
-
open (self.basename () + '.txt', 'w').write ('image of music')
+ def relevant_contents (self, ly):
+ return re.sub (r'\\(version|sourcefileline)[^\n]*\n', '', ly)
+
def ly_is_outdated (self):
base = self.basename ()
-
- tex_file = '%s.tex' % base
- eps_file = '%s.eps' % base
- system_file = '%s-systems.tex' % base
- ly_file = '%s.ly' % base
- ok = os.path.exists (ly_file) \
- 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 (not global_options.use_hash 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.
+ ly_file = base + '.ly'
+ tex_file = base + '.tex'
+ eps_file = base + '.eps'
+ systems_file = base + '-systems.tex'
+
+ if (os.path.exists (ly_file)
+ and os.path.exists (systems_file)
+ and os.stat (systems_file)[stat.ST_SIZE]
+ and re.match ('% eof', open (systems_file).readlines ()[-1])
+ and (global_options.use_hash or FILENAME in self.option_dict)
+ and (self.relevant_contents (self.full_ly ())
+ == self.relevant_contents (open (ly_file).read ()))):
return None
+
return self
def png_is_outdated (self):
base = self.basename ()
+ # FIXME: refactor stupid OK stuff
ok = not self.ly_is_outdated ()
if global_options.format in (HTML, TEXINFO):
ok = ok and os.path.exists (base + '.eps')
if backend == 'ps':
return 0
+ # FIXME: refactor stupid OK stuff
base = self.basename ()
ok = self.ly_is_outdated ()
ok = ok and (os.path.exists (base + '.texstr'))
images = tuple (images)
return images
+ def output_docbook (self):
+ str = ''
+ base = self.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 = '<inlinemediaobject>' + str + '</inlinemediaobject>'
+ else:
+ str = '<mediaobject>' + str + '</mediaobject>'
+ if VERBATIM in self.option_dict:
+ verb = verbatim_html (self.substring ('code'))
+ str = output[DOCBOOK][VERBATIM] % vars () + str
+ return str
+
def output_html (self):
str = ''
base = self.basename ()
if VERBATIM in self.option_dict:
verb = self.substring ('code')
str += (output[LATEX][VERBATIM] % vars ())
-
+
str += (output[LATEX][OUTPUT] % vars ())
## todo: maintain breaks
def ly (self):
name = self.substring ('filename')
contents = open (find_file (name)).read ()
-
- ## strip version string to make automated regtest comparisons
- ## across versions easier.
- contents = re.sub (r'\\version *"[^"]*"', '', contents)
-
- return ('\\sourcefilename \"%s\"\n%s'
- % (name, contents).read ()))
+ return ('\\sourcefilename \"%s\"\n\\sourcefileline 0\n%s'
+ % (name, contents))
snippet_type_to_class = {
'lilypond_file': Lilypond_file_snippet,
snippets = []
index = 0
- found = dict ((t, None) for t in types))
+ found = dict ([(t, None) for t in types])
line_starts = find_linestarts (s)
line_start_idx = 0
status = 0
def my_system (cmd):
status = ly.system (cmd,
- be_verbose=global_options.verbose,
- progress_p= 1)
+ be_verbose=global_options.verbose,
+ progress_p=1)
- if global_options.format in (HTML, TEXINFO):
- cmd += ' --format png '
+ if global_options.format in (HTML, TEXINFO) and '--formats' not in cmd:
+ cmd += ' --formats=png '
+ elif global_options.format in (DOCBOOK) and '--formats' not in cmd:
+ cmd += ' --formats=png,pdf '
+
# UGH
# the --process=CMD switch is a bad idea
# it is too generic for lilypond-book.
my_system ('latex %s.texstr' % l)
if ly_names:
- my_system (string.join ([cmd, 'snippet-map.ly'] + ly_names))
+ open ('snippet-names', 'wb').write ('\n'.join (['snippet-map.ly']
+ + ly_names))
+
+ my_system (string.join ([cmd, 'snippet-names']))
+
LATEX_INSPECTION_DOCUMENT = r'''
\nonstopmode
def get_latex_textwidth (source):
m = re.search (r'''(?P<preamble>\\begin\s*{document})''', source)
if m == None:
- warning (_ ("Can't find \\begin{document} in LaTeX document"))
+ warning (_ ("cannot find \\begin{document} in LaTeX document"))
## what's a sensible default?
return 550.0
'.texi': TEXINFO,
'.texinfo': TEXINFO,
'.xml': HTML,
+ '.lyxml': DOCBOOK
}
format2ext = {
# TEXINFO: '.texinfo',
TEXINFO: '.texi',
LATEX: '.tex',
+ DOCBOOK: '.xml'
}
class Compile_error:
def write_file_map (lys, name):
snippet_map = open ('snippet-map.ly', 'w')
snippet_map.write ("""
-#(define version-seen? #t)
+#(define version-seen #t)
+#(define output-empty-score-list #f)
#(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")\n'
% (ly.basename (),
- name,
- ly.line_number,
- ly.basename ()))
+ name))
snippet_map.write ('))\n')
def do_process_cmd (chunks, input_name):
all_lys = filter (lambda x: is_derived_class (x.__class__,
Lilypond_snippet),
- chunks)
+ chunks)
write_file_map (all_lys, input_name)
ly_outdated = filter (lambda x: is_derived_class (x.__class__,
# FIXME
format = ext2format[e]
else:
- error (_ ("can't determine format for: %s" \
+ error (_ ("cannot determine format for: %s" \
% input_filename))
exit (1)
return format
return args
+def psfonts_warning (options, basename):
+ if options.format in (TEXINFO, LATEX):
+ psfonts_file = os.path.join (options.output_name, basename + '.psfonts')
+ output = os.path.join (options.output_name, basename + '.dvi' )
+
+ if not options.create_pdf:
+ if not options.psfonts:
+ warning (_ ("option --psfonts not used"))
+ warning (_ ("processing with dvips will have no fonts"))
+ else:
+ progress ('\n')
+ progress (_ ("DVIPS usage:"))
+ progress ('\n')
+ progress (" dvips -h %(psfonts_file)s %(output)s" % vars ())
+ progress ('\n')
+
def main ():
+ # FIXME: 85 lines of `main' macramee??
files = do_options ()
file = files[0]
global_options.format = guess_format (files[0])
formats = 'ps'
- if global_options.format in (TEXINFO, HTML):
+ if global_options.format in (TEXINFO, HTML, DOCBOOK):
formats += ',png'
+
+
if global_options.process_cmd == '':
- global_options.process_cmd = lilypond_binary \
- + ' --formats=%s --backend eps ' % formats
+ global_options.process_cmd = (lilypond_binary
+ + ' --formats=%s --backend eps ' % formats)
if global_options.process_cmd:
- global_options.process_cmd += string.join ([(' -I %s' % commands.mkarg (p))
+ global_options.process_cmd += string.join ([(' -I %s' % ly.mkarg (p))
for p in global_options.include_path])
+ if global_options.format in (TEXINFO, LATEX):
+ ## prevent PDF from being switched on by default.
+ 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.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 "
+
identify ()
try:
except Compile_error:
exit (1)
- if global_options.format in (TEXINFO, LATEX):
- if not global_options.psfonts:
- warning (_ ("option --psfonts not used"))
- warning (_ ("processing with dvips will have no fonts"))
-
- psfonts_file = os.path.join (global_options.output_name, basename + '.psfonts')
- output = os.path.join (global_options.output_name, basename + '.dvi' )
-
- progress ('\n')
- progress (_ ("DVIPS usage:"))
- progress ('\n')
- progress (" dvips -h %(psfonts_file)s %(output)s" % vars ())
- progress ('\n')
+ psfonts_warning (global_options, basename)
inputs = note_input_file ('')
inputs.pop ()