# TODO: magnification support should also work for texinfo -> html: eg. add as option to dvips.
#
+
+#
+# This is a slightly hairy program. The general approach is as follows
+# The input string is chopped up in chunks, i.e. , a list of tuples
+#
+# with the format (TAG_STR, MAIN_STR, OPTIONS, TODO, BASE)
+#
+# This list is build step by step: first ignore and verbatim commands are handled,
+# delivering a list of chunks.
+#
+# then all chunks containing lilypnod commands are chopped up
+#
+# when all chunks have their final form, all bodies from lilypond blocks are
+# extracted, and if applicable, written do disk and run through lilypond.
+#
+
+
# This is was the idea for handling of comments:
+
+
# Multiline comments, @ignore .. @end ignore is scanned for
# in read_doc_file, and the chunks are marked as 'ignore', so
# lilypond-book will not touch them any more. The content of the
# chunks are written to the output file. Also 'include' and 'input'
# regex has to check if they are commented out.
#
+
# Then it is scanned for 'lilypond', 'lilypond-file' and 'lilypond-block'.
# These three regex's has to check if they are on a commented line,
# % for latex, @c for texinfo.
default_text_fontsize = 12
paperguru = None
-
+################################################################
+# Dimension handling for LaTeX.
+#
class LatexPaper:
def __init__ (self):
self.m_document_preamble = []
'smallbook': {12: in2pt (5)},
'letterpaper': {12: in2pt (6)}}
+
+################################################################
+# How to output various structures.
output_dict= {
return get_output (key) % body
-# Warning: This uses extended regular expressions. Treat with care.
+################################################################
+# Recognize special sequences in the input
+
+
+# Warning: This uses extended regular expressions. Tread with care.
#
# legenda
#
'singleline-comment': no_match,
'numcols': no_match,
'multicols': no_match,
+ 'ly2dvi': r'(?m)(?P<match><ly2dvifile(?P<options>[^>]+)?>\s*(?P<filename>[^<]+)\s*</ly2dvifile>)',
},
'latex': {
'singleline-comment': r"(?m)^.*?(?P<match>(?P<code>^%.*$\n+))",
'numcols': r"(?P<code>\\(?P<num>one|two)column)",
'multicols': r"(?P<code>\\(?P<be>begin|end)\s*{multicols}({(?P<num>\d+)?})?)",
+ 'ly2dvi': no_match,
+
},
# why do we have distinction between @mbinclude and @include?
'singleline-comment': r"(?m)^.*?(?P<match>(?P<code>@c.*$\n+))",
'numcols': no_match,
'multicols': no_match,
+ 'ly2dvi': no_match,
}
}
return [('input', get_output ('output-lilypond') %
(options, content))]
+def make_ly2dvi_block (m):
+ '''
+
+ Find <ly2dvifile .. >
+ '''
+
+ return [('ly2dvi', m.group ('filename'), m.group ('options'))]
+
+
def make_lilypond_block (m):
if not g_do_music:
return []
options = filter (lambda s: s != '', options)
return [('lilypond', m.group ('code'), options)]
+
def do_columns (m):
global format
if format != 'latex':
taken_file_names = {}
+
+def unique_file_name (body):
+ return 'lily-' + `abs (hash (body))`
+
def schedule_lilypond_block (chunk):
'''Take the body and options from CHUNK, figure out how the
real .ly should look, and what should be left MAIN_STR (meant
## Hmm, we should hash only lilypond source, and skip the
## %options are ...
## comment line
- basename = 'lily-' + `abs (hash (file_body))`
+ basename = unique_file_name (file_body)
for o in opts:
m = re.search ('filename="(.*?)"', o)
if m:
needed_filetypes.append ('png')
if 'eps' in opts and not ('eps' in needed_filetypes):
needed_filetypes.append ('eps')
+
pathbase = os.path.join (g_outdir, basename)
def f (base, ext1, ext2):
a = os.path.isfile (base + ext2)
newbody = newbody + get_output (s) % {'fn': basename }
return ('lilypond', newbody, opts, todo, basename)
+
+
+
def process_lilypond_blocks (chunks):#ugh rename
newchunks = []
# Count sections/chapters.
newchunks.append (c)
return newchunks
+def process_ly2dvi_blocks (chunks):
+
+ def process_ly2dvi_block (chunk):
+ """
+
+Run ly2dvi script on filename specified in CHUNK.
+This is only supported for HTML output.
+
+In HTML output it will leave a download menu with ps/pdf/midi etc. in
+a separate HTML file, and a title + preview in the main html file,
+linking to the menu.
+
+ """
+ (tag, name, opts) = chunk
+ assert format == 'html'
+ (content, original_name) = find_file (name)
+
+ original_name = os.path.basename (original_name)
+
+ base = unique_file_name (content)
+ outname = base + '.ly'
+ changed = update_file (content, outname)
+
+ preview = base + ".png"
+ if changed or not os.path.isfile (preview):
+ ly.system ('ly2dvi --preview --postscript --verbose %s ' % base)
+
+ ly.make_page_images (base)
+ ly.system ('gzip -9 - < %s.ps > %s.ps.gz' % (base, base))
+
+ def size_str (fn):
+ b = os.stat(fn)[stat.ST_SIZE]
+ if b < 1024:
+ return '%d bytes' % b
+ elif b < (2 << 20):
+ return '%d kb' % (b >> 10)
+ else:
+ return '%d mb' % (b >> 20)
+
+ exts = {
+ 'pdf' : "Print (PDF, %s)",
+ 'ps.gz' : "Print (gzipped PostScript, %s)",
+ 'png' : "View (PNG, %s)",
+ 'midi' : "Listen (MIDI, %s)",
+ 'ly' : "View source code (%s)",
+ }
+
+ menu = ''
+ page_files = ly.read_pipe ('ls --color=no -1 %s-page*.png' % base)
+
+ for p in string.split (page_files, '\n'):
+ p = p.strip()
+ if os.path.isfile (p):
+ sz = size_str (p)
+ page = re.sub ('.*page([0-9])+.*', 'View page \\1 (PNG picture, %s)\n', p)
+ page = page % sz
+ menu += '<li><a href="%s">%s</a>' % (p, page)
+
+ ext_order = ['ly', 'pdf', 'ps.gz', 'midi']
+ for e in ext_order:
+ fn = base + '.' + e
+ print 'checking,' , fn
+ if not os.path.isfile (fn):
+ continue
+
+ entry = exts[e] % size_str (fn)
+
+ ## TODO: do something like
+ ## this for texinfo/latex as well ?
+
+ menu += '<li><a href="%s">%s</a>\n\n' % (fn, entry)
+
+
+ explanatory_para = """The pictures are 90dpi
+anti-aliased snapshots of the printed output, in PNG format. Both PDF and PS
+use scalable fonts and should look OK at any resolution."""
+
+ separate_menu =r'''
+<title>LilyPond example %s</title>
+
+<h1>%s</h1>
+<p><img src="%s">
+<p>%s
+<p>
+<ul>%s</ul>''' % (original_name,original_name, preview, explanatory_para, menu)
+
+ open (base + '.html','w'). write (separate_menu)
+
+ inline_menu = '<p/><a href="%s.html"><img src="%s"><p/></a>' % (base, original_name, preview)
+
+ return ('ly2dvi', inline_menu)
+
+ newchunks = []
+ for c in chunks:
+ if c[0] == 'ly2dvi':
+ c = process_ly2dvi_block (c)
+ newchunks.append (c)
+
+ return newchunks
+
def compile_all_files (chunks):
global foutn
eps = []
def update_file (body, name):
'''
- write the body if it has changed
+ write the body if it has changed. Return whether BODY has changed.
'''
same = 0
try:
def do_file (input_filename):
chunks = read_doc_file (input_filename)
+ chunks = chop_chunks (chunks, 'ly2dvi', make_ly2dvi_block, 1)
chunks = chop_chunks (chunks, 'lilypond', make_lilypond, 1)
chunks = chop_chunks (chunks, 'lilypond-file', make_lilypond_file, 1)
chunks = chop_chunks (chunks, 'lilypond-block', make_lilypond_block, 1)
#sys.exit ()
scan_preamble (chunks)
chunks = process_lilypond_blocks (chunks)
-
+ chunks = process_ly2dvi_blocks (chunks)
+
# Do It.
global g_run_lilypond
if g_run_lilypond:
temp_dir = os.path.join (original_dir, '%s.dir' % program_name)
keep_temp_dir_p = 0
preview_resolution = 90
+debug_p = 0
## FIXME
## ly2dvi: silly name?
('', 'd', 'dependencies',
_ ("write Makefile dependencies for every input file")),
('', 'h', 'help', _ ("this help")),
+ ('', '', 'debug', _ ("print even more output")),
(_ ("DIR"), 'I', 'include', _ ("add DIR to LilyPond's search path")),
('', 'k', 'keep',
_ ("keep all output, output to directory %s.dir") % program_name),
global verbose_p
if verbose_p:
opts = opts + ' --verbose'
+
+ if debug_p:
ly.print_environment ()
cmd = string.join ((lilypond_cmd,opts, fs))
# make a preview by rendering only the 1st line.
preview_fn = outbase + '.preview.tex'
f = open (preview_fn, 'w')
- f.write (r'''
-%s
-\input lilyponddefs
-\pagestyle{empty}
-\begin{document}
-\def\interscoreline{\endinput}
-\input %s
-\end{document}
-''' % (global_latex_preamble (extra), outbase))
-
+ wfs = find_tex_files (files, extra)
+ s = global_latex_definition (wfs, extra)
+
+ s = re.sub ('thispagestyle{firstpage}', r'''thispagestyle{empty}%
+\\def\\interscoreline{\\endinput}''',s )
+ s = re.sub ('thispagestyle{lastpage}', r'''thispagestyle{empty}%
+\\def\\interscoreline{\\endinput}''',s )
+ f.write (s)
f.close()
cmd = '%s \\\\nonstopmode \\\\input %s' % (latex_cmd, preview_fn)
ly.system (cmd)
opts = opts + ' -Ppdf -G0 -u lilypond.map'
else:
ly.warning (_ ('''Trying create PDF, but no PFA fonts found.
-Using bitmap fonts instead. This will look poorly.'''))
-
+Using bitmap fonts instead. This will look bad.'''))
+
cmd = 'dvips %s -o%s %s' % (opts, outbase + '.ps', outbase + '.dvi')
ly.system (cmd)
targets.append ('PDF')
elif o == '--keep' or o == '-k':
keep_temp_dir_p = 1
+ elif o == '--debug':
+ verbose_p = 1
+ debug_p = 1
elif o == '--no-lily':
lily_p = 0
elif o == '--preview':