'''
+import glob
import md5
import os
import re
import lilylib as ly
import fontextract
+import langdefs
global _;_=ly._
+ly.require_python_version ()
# Lilylib globals.
program_version = '@TOPLEVEL_VERSION@'
+ '\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
+ $ lilypond-book --filter="tr '[a-z]' '[A-Z]'" %(BOOK)s
+ $ lilypond-book -F "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>',
p.add_option ('-F', '--filter', metavar=_ ("FILTER"),
action="store",
dest="filter_cmd",
- help=_ ("pipe snippets through FILTER [convert-ly -n -]"),
+ help=_ ("pipe snippets through FILTER [default: `convert-ly -n -']"),
default=None)
p.add_option ('-f', '--format',
help=_ ("use output format FORMAT (texi [default], texi-html, latex, html, docbook)"),
+ metavar=_ ("FORMAT"),
action='store')
p.add_option("-h", "--help",
action='store', dest='info_images_dir',
default='')
+ p.add_option ('--latex-program',
+ help=_ ("run executable PROG instead of latex"),
+ metavar=_ ("PROG"),
+ action='store', dest='latex_program',
+ default='latex')
+
p.add_option ('--left-padding',
metavar=_ ("PAD"),
dest="padding_mm",
default='')
p.add_option ('--skip-lily-check',
- help=_ ("do not fail if no lilypond output is found."),
+ help=_ ("do not fail if no lilypond output is found"),
metavar=_ ("DIR"),
action='store_true', dest='skip_lilypond_run',
default=False)
default=False)
p.add_option ('--lily-output-dir',
- help=_ ("write lily-XXX files to DIR, link into --output dir."),
+ help=_ ("write lily-XXX files to DIR, link into --output dir"),
metavar=_ ("DIR"),
action='store', dest='lily_output_dir',
default=None)
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'''),
- default=None)
-
p.add_option ('-V', '--verbose', help=_ ("be verbose"),
action="store_true",
default=False,
p.add_option ('-w', '--warranty',
help=_ ("show warranty and copyright"),
action='store_true')
- p.add_option_group (ly.display_encode (_ ('Bugs')),
+ p.add_option_group ('',
description=(
_ ("Report bugs via")
+ ' http://post.gmane.org/post.php?group=gmane.comp.gnu.lilypond.bugs\n'))
lilypond_binary = os.path.join ('@bindir@', 'lilypond')
+# If we are called with full path, try to use lilypond binary
+# installed in the same path; this is needed in GUB binaries, where
+# @bindir is always different from the installed binary path.
+if 'bindir' in globals () and bindir:
+ lilypond_binary = os.path.join (bindir, 'lilypond')
+
# Only use installed binary when we are installed too.
if '@bindir@' == ('@' + 'bindir@') or not os.path.exists (lilypond_binary):
lilypond_binary = 'lilypond'
default_ly_options = { 'alt': "[image of music]" }
+document_language = ''
+
#
# Is this pythonic? Personally, I find this rather #define-nesque. --hwn
#
NOFRAGMENT = 'nofragment'
NOINDENT = 'noindent'
NOQUOTE = 'noquote'
+NORAGGED_RIGHT = 'noragged-right'
NOTES = 'body'
NOTIME = 'notime'
OUTPUT = 'output'
RAGGED_RIGHT = 'ragged-right'
RELATIVE = 'relative'
STAFFSIZE = 'staffsize'
+DOCTITLE = 'doctitle'
TEXIDOC = 'texidoc'
TEXINFO = 'texinfo'
VERBATIM = 'verbatim'
NOFRAGMENT,
NOINDENT,
PRINTFILENAME,
+ DOCTITLE,
TEXIDOC,
LANG,
VERBATIM,
RAGGED_RIGHT: r'''ragged-right = ##t''',
+ NORAGGED_RIGHT: r'''ragged-right = ##f''',
+
PACKED: r'''packed = ##t''',
},
LAYOUT: {
NOTIME: r'''
\context {
- \Score
- timing = ##f
+ \Score
+ timing = ##f
}
\context {
- \Staff
- \remove Time_signature_engraver
+ \Staff
+ \remove "Time_signature_engraver"
}''',
},
re.sub ('<', '<',
re.sub ('&', '&', s)))
+ly_var_def_re = re.compile (r'^([a-zA-Z]+)[\t ]*=', re.M)
+ly_comment_re = re.compile (r'(%+[\t ]*)(.*)$', re.M)
+ly_context_id_re = re.compile ('\\\\(?:new|context)\\s+(?:[a-zA-Z]*?(?:Staff\
+(?:Group)?|Voice|FiguredBass|FretBoards|Names|Devnull))\\s+=\\s+"?([a-zA-Z]+)"?\\s+')
+
+def ly_comment_gettext (t, m):
+ return m.group (1) + t (m.group (2))
+
+def verb_ly_gettext (s):
+ if not document_language:
+ return s
+ try:
+ t = langdefs.translation[document_language]
+ except:
+ 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)
+ return s
texinfo_lang_re = re.compile ('(?m)^@documentlanguage (.*?)( |$)')
def set_default_options (source, default_ly_options, format):
+ global document_language
if LINE_WIDTH not in default_ly_options:
if format == LATEX:
textwidth = get_latex_textwidth (source)
elif format == TEXINFO:
m = texinfo_lang_re.search (source)
if m and not m.group (1).startswith ('en'):
- default_ly_options[LANG] = m.group (1)
+ document_language = m.group (1)
else:
- default_ly_options[LANG] = ''
+ document_language = ''
for regex in texinfo_line_widths:
# FIXME: @layout is usually not in
# chunk #0:
self.do_options (os, self.type)
def verb_ly (self):
- return self.substring ('code')
+ return verb_ly_gettext (self.substring ('code'))
def ly (self):
contents = self.substring ('code')
if k not in self.option_dict:
self.option_dict[k] = default_ly_options[k]
+ # RELATIVE does not work without FRAGMENT;
+ # make RELATIVE imply FRAGMENT
+ has_relative = self.option_dict.has_key (RELATIVE)
+ if has_relative and not self.option_dict.has_key (FRAGMENT):
+ self.option_dict[FRAGMENT] = None
+
if not has_line_width:
if type == 'lilypond' or FRAGMENT in self.option_dict:
self.option_dict[RAGGED_RIGHT] = None
return self.checksum
def basename (self):
- if FILENAME in self.option_dict:
- return self.option_dict[FILENAME]
-
cs = self.get_checksum ()
-
- # TODO: use xx/xxxxx directory layout.
- name = 'lily-%s' % cs[:10]
+ name = '%s/lily-%s' % (cs[:2], cs[2:10])
return name
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')
src = os.path.join (output_dir, name)
dst = os.path.join (destination, name)
+ dst_path = os.path.split(dst)[0]
+ if not os.path.isdir (dst_path):
+ os.makedirs (dst_path)
os.link (src, dst)
if not skip_lily:
require_file (base + '-systems.count')
+ if 'ddump-profile' in global_options.process_cmd:
+ require_file (base + '.profile')
+ if 'dseparate-log-file' in global_options.process_cmd:
+ require_file (base + '.log')
+
map (consider_file, [base + '.tex',
base + '.eps',
base + '.texidoc',
+ base + '.doctitle',
base + '-systems.texi',
base + '-systems.tex',
base + '-systems.pdftexi'])
+ if document_language:
+ map (consider_file,
+ [base + '.texidoc' + document_language,
+ base + '.doctitle' + document_language])
# UGH - junk global_options
if (base + '.eps' in result and self.format in (HTML, TEXINFO)
system_count = 0
if not skip_lily and not missing:
system_count = int(file (full + '-systems.count').read())
+
for number in range(1, system_count + 1):
systemfile = '%s-%d' % (base, number)
require_file (systemfile + '.eps')
consider_file (systemfile + '.pdf')
-
+
+ # We can't require signatures, since books and toplevel
+ # 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):
def output_texinfo (self):
str = self.output_print_filename (TEXINFO)
base = self.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 ()
+ elif os.path.exists (doctitle):
+ str += '@lydoctitle %s\n' % open (doctitle).read ()
if TEXIDOC in self.option_dict:
texidoc = base + '.texidoc'
- translated_texidoc = texidoc + default_ly_options[LANG]
+ translated_texidoc = texidoc + document_language
if os.path.exists (translated_texidoc):
str += '@include %(translated_texidoc)s\n\n' % vars ()
elif os.path.exists (texidoc):
s = self.contents
s = re_begin_verbatim.split (s)[-1]
s = re_end_verbatim.split (s)[0]
- return s
+ return verb_ly_gettext (s)
def ly (self):
name = self.substring ('filename')
checksum = snippet_list_checksum (snippets)
contents = '\n'.join (['snippet-map-%d.ly' % checksum]
- + [snip.basename() for snip in snippets])
+ + [snip.basename() + '.ly' for snip in snippets])
name = os.path.join (lily_output_dir,
- 'snippet-names-%d' % checksum)
+ 'snippet-names-%d.ly' % checksum)
file (name, 'wb').write (contents)
- system_in_directory (' '.join ([cmd, name]),
+ system_in_directory (' '.join ([cmd, ly.mkarg (name)]),
lily_output_dir)
tmp_handle.write (latex_document)
tmp_handle.close ()
- ly.system ('latex %s' % tmpfile, be_verbose=global_options.verbose)
+ ly.system ('%s %s' % (global_options.latex_program, tmpfile),
+ be_verbose=global_options.verbose)
parameter_string = file (logfile).read()
os.unlink (tmpfile)
#(define output-empty-score-list #f)
#(ly:add-file-name-alist '(%s
))\n
-""" % '\n'.join('("%s.ly" . "%s")\n' % (ly.basename (), name)
- for ly in lys))
+""" % '\n'.join(['("%s.ly" . "%s")\n' % (ly.basename (), name)
+ for ly in lys]))
+
+def split_output_files(directory):
+ """Returns directory entries in DIRECTORY/XX/ , where XX are hex digits.
+
+ Return value is a set of strings.
+ """
+ files = []
+ for subdir in glob.glob (os.path.join (directory, '[a-f0-9][a-f0-9]')):
+ base_subdir = os.path.split (subdir)[1]
+ sub_files = [os.path.join (base_subdir, name)
+ for name in os.listdir (subdir)]
+ files += sub_files
+ return set (files)
def do_process_cmd (chunks, input_name, options):
snippets = [c for c in chunks if isinstance (c, LilypondSnippet)]
-
- output_files = set(os.listdir(options.lily_output_dir))
+ 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)
progress (_ ("All snippets are up to date..."))
if options.lily_output_dir != options.output_dir:
- output_files = set(os.listdir(options.lily_output_dir))
+ output_files = split_output_files (options.lily_output_dir)
for snippet in snippets:
snippet.link_all_output_files (options.lily_output_dir,
output_files,
# this prevents make from always rerunning lilypond-book:
# output file must be touched in order to be up to date
os.utime (file_name, None)
+ return
except:
pass
+ output_dir = os.path.dirname (file_name)
+ if not os.path.exists (output_dir):
+ os.makedirs (output_dir)
+
progress (_ ("Writing `%s'...") % file_name)
file (file_name, 'w').writelines (lines)
progress ('\n')
f2 = re.sub ("//*", "/", f2)
return f1 == f2
-def do_file (input_filename):
+def do_file (input_filename, included=False):
# Ugh.
if not input_filename or input_filename == '-':
in_handle = sys.stdin
if input_filename == '-':
input_base = 'stdin'
+ elif included:
+ input_base = os.path.splitext (input_filename)[0]
else:
input_base = os.path.basename (
os.path.splitext (input_filename)[0])
name = snippet.substring ('filename')
progress (_ ("Processing include: %s") % name)
progress ('\n')
- return do_file (name)
+ return do_file (name, included=True)
include_chunks = map (process_include,
filter (lambda x: isinstance (x, IncludeSnippet),
+ ' --formats=%s -dbackend=eps ' % formats)
if global_options.process_cmd:
- global_options.process_cmd += ' '.join ([(' -I %s' % ly.mkarg (p))
- for p in global_options.include_path])
+ includes = global_options.include_path
+ if global_options.lily_output_dir:
+ # This must be first, so lilypond prefers to read .ly
+ # files in the other lybookdb dir.
+ includes = [os.path.abspath(global_options.lily_output_dir)] + includes
+ global_options.process_cmd += ' '.join ([' -I %s' % ly.mkarg (p)
+ for p in includes])
if global_options.format in (TEXINFO, LATEX):
## prevent PDF from being switched on by default.
if global_options.padding_mm:
global_options.process_cmd += " -deps-box-padding=%f " % global_options.padding_mm
- global_options.process_cmd += " -dread-file-list "
+ global_options.process_cmd += " -dread-file-list -dno-strip-output-dir"
if global_options.lily_output_dir:
global_options.lily_output_dir = os.path.abspath(global_options.lily_output_dir)