import os
import stat
import string
-import re
import getopt
import sys
import __main__
-import operator
+
+# Handle bug in Python 1.6-2.1
+#
+# there are recursion limits for some patterns in Python 1.6 til 2.1.
+# fix this by importing the 1.5.2 implementation pre instead. Fix by Mats.
+
+
+## We would like to do this for python 2.2 as well, unfortunately
+## python 2.2 has another bug, see Sf.net bugtracker
+##
+## https://sourceforge.net/tracker/?func=detail&aid=604803&group_id=5470&atid=105470
+##
+
+if float (sys.version[0:3]) <= 2.1:
+ try:
+ import pre
+ re = pre
+ del pre
+ except ImportError:
+ import re
+else:
+ import re
+
+# Attempt to fix problems with limited stack size set by Python!
+# Sets unlimited stack size. Note that the resource module only
+# is available on UNIX.
+try:
+ import resource
+ resource.setrlimit (resource.RLIMIT_STACK, (-1, -1))
+except:
+ pass
+
+errorport = sys.stderr
+verbose_p = 0
+
+
+
+try:
+ import gettext
+ gettext.bindtextdomain ('lilypond', localedir)
+ gettext.textdomain ('lilypond')
+ _ = gettext.gettext
+except:
+ def _ (s):
+ return s
+
+def progress (s):
+ errorport.write (s + '\n')
program_version = '@TOPLEVEL_VERSION@'
if program_version == '@' + 'TOPLEVEL_VERSION' + '@':
- program_version = '1.5.18'
+ program_version = '1.6.0'
# if set, LILYPONDPREFIX must take prevalence
# if datadir is not set, we're doing a build and LILYPONDPREFIX
-datadir = '@datadir@'
+datadir = '@local_lilypond_datadir@'
if os.environ.has_key ('LILYPONDPREFIX') :
datadir = os.environ['LILYPONDPREFIX']
else:
- datadir = '@datadir@'
+ datadir = '@local_lilypond_datadir@'
while datadir[-1] == os.sep:
datadir= datadir[:-1]
-# Try to cater for bad installations of LilyPond, that have
-# broken TeX setup. Just hope this doesn't hurt good TeX
-# setups. Maybe we should check if kpsewhich can find
-# feta16.{afm,mf,tex,tfm}, and only set env upon failure.
+kpse = os.popen ('kpsexpand \$TEXMF').read()
+kpse = re.sub('[ \t\n]+$','', kpse)
+type1_paths = os.popen ('kpsewhich -expand-path=\$T1FONTS').read ()
+
+binary = 'lilypond'
+#binary = 'valgrind --suppressions=/home/hanwen/usr/src/guile-1.6.supp --num-callers=10 /home/hanwen/usr/src/lilypond/lily/out/lilypond'
environment = {
- 'MFINPUTS' : datadir + '/mf:',
- 'TEXINPUTS': datadir + '/tex:' + datadir + '/ps:.:',
- 'TFMFONTS' : datadir + '/tfm:',
- 'GS_FONTPATH' : datadir + '/afm:' + datadir + '/pfa',
+ # TODO: * prevent multiple addition.
+ # * clean TEXINPUTS, MFINPUTS, TFMFONTS,
+ # as these take prevalence over $TEXMF
+ # and thus may break tex run?
+ 'TEXMF' : "{%s,%s}" % (datadir, kpse) ,
+ 'GS_FONTPATH' : type1_paths,
'GS_LIB' : datadir + '/ps',
}
}
def setup_environment ():
+ # $TEXMF is special, previous value is already taken care of
+ if os.environ.has_key ('TEXMF'):
+ del os.environ['TEXMF']
+
for key in environment.keys ():
val = environment[key]
if os.environ.has_key (key):
for key in non_path_environment.keys ():
val = non_path_environment[key]
- print '%s=%s' % (key,val)
os.environ[key] = val
include_path = [os.getcwd()]
# g_ is for global (?)
-
+g_extra_opts = ''
g_here_dir = os.getcwd ()
g_dep_prefix = ''
g_outdir = ''
-g_force_lilypond_fontsize = 0
+g_force_music_fontsize = 0
g_read_lys = 0
g_do_pictures = 1
-g_num_cols = 1
+g_do_music = 1
+
format = ''
g_run_lilypond = 1
no_match = 'a\ba'
default_text_fontsize = 12
paperguru = None
-# this code is ugly. It should be cleaned
class LatexPaper:
def __init__(self):
- self.m_paperdef = {
- # the dimensions are from geometry.sty
- 'a0paper': (mm2pt(841), mm2pt(1189)),
- 'a1paper': (mm2pt(595), mm2pt(841)),
- 'a2paper': (mm2pt(420), mm2pt(595)),
- 'a3paper': (mm2pt(297), mm2pt(420)),
- 'a4paper': (mm2pt(210), mm2pt(297)),
- 'a5paper': (mm2pt(149), mm2pt(210)),
- 'b0paper': (mm2pt(1000), mm2pt(1414)),
- 'b1paper': (mm2pt(707), mm2pt(1000)),
- 'b2paper': (mm2pt(500), mm2pt(707)),
- 'b3paper': (mm2pt(353), mm2pt(500)),
- 'b4paper': (mm2pt(250), mm2pt(353)),
- 'b5paper': (mm2pt(176), mm2pt(250)),
- 'letterpaper': (in2pt(8.5), in2pt(11)),
- 'legalpaper': (in2pt(8.5), in2pt(14)),
- 'executivepaper': (in2pt(7.25), in2pt(10.5))}
- self.m_use_geometry = None
- self.m_papersize = 'letterpaper'
- self.m_fontsize = 10
+ self.m_document_preamble = []
self.m_num_cols = 1
- self.m_landscape = 0
- self.m_geo_landscape = 0
- self.m_geo_width = None
- self.m_geo_textwidth = None
- self.m_geo_lmargin = None
- self.m_geo_rmargin = None
- self.m_geo_includemp = None
- self.m_geo_marginparwidth = {10: 57, 11: 50, 12: 35}
- self.m_geo_marginparsep = {10: 11, 11: 10, 12: 10}
- self.m_geo_x_marginparwidth = None
- self.m_geo_x_marginparsep = None
- self.__body = None
- def set_geo_option(self, name, value):
-
- if type(value) == type(""):
- m = re.match ("([0-9.]+)(cm|in|pt|mm|em|ex)",value)
- if m:
- unit = m.group (2)
- num = string.atof(m.group (1))
- conv = dimension_conversion_dict[m.group(2)]
-
- value = conv(num)
-
- if name == 'body' or name == 'text':
- if type(value) == type(""):
- self.m_geo_textwidth = value
- else:
- self.m_geo_textwidth = value[0]
- self.__body = 1
- elif name == 'portrait':
- self.m_geo_landscape = 0
- elif name == 'reversemp' or name == 'reversemarginpar':
- if self.m_geo_includemp == None:
- self.m_geo_includemp = 1
- elif name == 'marginparwidth' or name == 'marginpar':
- self.m_geo_x_marginparwidth = value
- self.m_geo_includemp = 1
- elif name == 'marginparsep':
- self.m_geo_x_marginparsep = value
- self.m_geo_includemp = 1
- elif name == 'scale':
- if type(value) == type(""):
- self.m_geo_width = self.get_paperwidth() * float(value)
- else:
- self.m_geo_width = self.get_paperwidth() * float(value[0])
- elif name == 'hscale':
- self.m_geo_width = self.get_paperwidth() * float(value)
- elif name == 'left' or name == 'lmargin':
- self.m_geo_lmargin = value
- elif name == 'right' or name == 'rmargin':
- self.m_geo_rmargin = value
- elif name == 'hdivide' or name == 'divide':
- if value[0] not in ('*', ''):
- self.m_geo_lmargin = value[0]
- if value[1] not in ('*', ''):
- self.m_geo_width = value[1]
- if value[2] not in ('*', ''):
- self.m_geo_rmargin = value[2]
- elif name == 'hmargin':
- if type(value) == type(""):
- self.m_geo_lmargin = value
- self.m_geo_rmargin = value
- else:
- self.m_geo_lmargin = value[0]
- self.m_geo_rmargin = value[1]
- elif name == 'margin':#ugh there is a bug about this option in
- # the geometry documentation
- if type(value) == type(""):
- self.m_geo_lmargin = value
- self.m_geo_rmargin = value
- else:
- self.m_geo_lmargin = value[0]
- self.m_geo_rmargin = value[0]
- elif name == 'total':
- if type(value) == type(""):
- self.m_geo_width = value
- else:
- self.m_geo_width = value[0]
- elif name == 'width' or name == 'totalwidth':
- self.m_geo_width = value
- elif name == 'paper' or name == 'papername':
- self.m_papersize = value
- elif name[-5:] == 'paper':
- self.m_papersize = name
- else:
- pass
- # what is _set_dimen ?? /MB
- #self._set_dimen('m_geo_'+name, value)
- def __setattr__(self, name, value):
- if type(value) == type("") and \
- dimension_conversion_dict.has_key (value[-2:]):
- f = dimension_conversion_dict[value[-2:]]
- self.__dict__[name] = f(float(value[:-2]))
+ self.m_multicols = 1
+
+ def find_latex_dims(self):
+ if g_outdir:
+ fname = os.path.join(g_outdir, "lily-tmp.tex")
else:
- self.__dict__[name] = value
+ fname = "lily-tmp.tex"
+ try:
+ f = open(fname, "w")
+ except IOError:
+ error ("Error creating temporary file '%s'" % fname)
+
+ for s in self.m_document_preamble:
+ f.write(s)
+ f.write(r"""
+\begin{document}
+\typeout{---}
+\typeout{\columnsep \the\columnsep}
+\typeout{\textwidth \the\textwidth}
+\typeout{---}
+\end{document}
+ """)
+ f.close()
+ re_dim = re.compile(r"\\(\w+)\s+(\d+\.\d+)")
+
+ cmd = "latex '\\nonstopmode \input %s'" % fname
+ if verbose_p:
+ sys.stderr.write ("Invoking `%s' as pipe" % cmd)
+ try:
+ status = quiet_system (cmd, "Latex for finding dimensions")
+ except:
+ sys.stderr.write (_("Invoking LaTeX failed.") + '\n' )
+ sys.stderr.write (_("This is the error log:\n") + '\n')
+
+ lns = open ('lily-tmp.log').readlines()
+
+ countdown = -3
+ for ln in lns:
+ sys.stderr.write (ln)
+ if re.match('^!', ln):
+ countdown = 3
+
+ if countdown == 0:
+ break
+
+ if countdown > 0:
+ countdown = countdown -1
+
+ sys.stderr.write (" ... (further messages elided)...\n")
+ sys.exit (1)
- def __str__(self):
- s = "LatexPaper:\n-----------"
- for v in self.__dict__.keys():
- if v[:2] == 'm_':
- s = s + str (v) + ' ' + str (self.__dict__[v])
- s = s + "-----------"
- return s
-
+ lns = open ('lily-tmp.log').readlines()
+ for ln in lns:
+ ln = string.strip(ln)
+ m = re_dim.match(ln)
+ if m:
+ if m.groups()[0] in ('textwidth', 'columnsep'):
+ self.__dict__['m_%s' % m.groups()[0]] = float(m.groups()[1])
+
+ try:
+ os.remove (fname)
+ os.remove (os.path.splitext(fname)[0]+".aux")
+ os.remove (os.path.splitext(fname)[0]+".log")
+ except:
+ pass
+
+ if not self.__dict__.has_key ('m_textwidth'):
+ raise 'foo!'
+
def get_linewidth(self):
- w = self._calc_linewidth()
- if self.m_num_cols == 2:
- return (w - 10) / 2
+ if self.m_num_cols == 1:
+ w = self.m_textwidth
else:
- return w
- def get_paperwidth(self):
- #if self.m_use_geometry:
- return self.m_paperdef[self.m_papersize][self.m_landscape or self.m_geo_landscape]
- #return self.m_paperdef[self.m_papersize][self.m_landscape]
-
- def _calc_linewidth(self):
- # since geometry sometimes ignores 'includemp', this is
- # more complicated than it should be
- mp = 0
- if self.m_geo_includemp:
- if self.m_geo_x_marginparsep is not None:
- mp = mp + self.m_geo_x_marginparsep
- else:
- mp = mp + self.m_geo_marginparsep[self.m_fontsize]
- if self.m_geo_x_marginparwidth is not None:
- mp = mp + self.m_geo_x_marginparwidth
- else:
- mp = mp + self.m_geo_marginparwidth[self.m_fontsize]
+ w = (self.m_textwidth - self.m_columnsep)/2
+ if self.m_multicols > 1:
+ return (w - self.m_columnsep*(self.m_multicols-1)) \
+ / self.m_multicols
+ return w
- #ugh test if this is necessary
- if self.__body:
- mp = 0
- if not self.m_use_geometry:
- return latex_linewidths[self.m_papersize][self.m_fontsize]
- else:
- geo_opts = (self.m_geo_lmargin == None,
- self.m_geo_width == None,
- self.m_geo_rmargin == None)
-
- if geo_opts == (1, 1, 1):
- if self.m_geo_textwidth:
- return self.m_geo_textwidth
- w = self.get_paperwidth() * 0.8
- return w - mp
- elif geo_opts == (0, 1, 1):
- if self.m_geo_textwidth:
- return self.m_geo_textwidth
- return self.f1(self.m_geo_lmargin, mp)
- elif geo_opts == (1, 1, 0):
- if self.m_geo_textwidth:
- return self.m_geo_textwidth
- return self.f1(self.m_geo_rmargin, mp)
- elif geo_opts \
- in ((0, 0, 1), (1, 0, 0), (1, 0, 1)):
- if self.m_geo_textwidth:
- return self.m_geo_textwidth
- return self.m_geo_width - mp
- elif geo_opts in ((0, 1, 0), (0, 0, 0)):
- w = self.get_paperwidth() \
- - self.m_geo_lmargin - self.m_geo_rmargin - mp
- if w < 0:
- w = 0
- return w
- raise "Never do this!"
- def f1(self, m, mp):
- tmp = self.get_paperwidth() - m * 2 - mp
- if tmp < 0:
- tmp = 0
- return tmp
- def f2(self):
- tmp = self.get_paperwidth() - self.m_geo_lmargin \
- - self.m_geo_rmargin
- if tmp < 0:
- return 0
- return tmp
+class HtmlPaper:
+ def __init__(self):
+ self.m_papersize = 'letterpaper'
+ self.m_fontsize = 12
+ def get_linewidth(self):
+ return html_linewidths[self.m_papersize][self.m_fontsize]
class TexiPaper:
def __init__(self):
'pt': pt2pt
}
-
-# latex linewidths:
-# indices are no. of columns, papersize, fontsize
-# Why can't this be calculated?
-latex_linewidths = {
- 'a4paper':{10: 345, 11: 360, 12: 390},
- 'a4paper-landscape': {10: 598, 11: 596, 12:592},
- 'a5paper':{10: 276, 11: 276, 12: 276},
- 'b5paper':{10: 345, 11: 356, 12: 356},
- 'letterpaper':{10: 345, 11: 360, 12: 390},
- 'letterpaper-landscape':{10: 598, 11: 596, 12:596},
- 'legalpaper': {10: 345, 11: 360, 12: 390},
- 'executivepaper':{10: 345, 11: 360, 12: 379}}
+# Convert numeric values, with or without specific dimension, to floats.
+# Keep other strings
+def conv_dimen_to_float(value):
+ if type(value) == type(""):
+ m = re.match ("([0-9.]+)(cm|in|pt|mm|em|ex)",value)
+ if m:
+ unit = m.group (2)
+ num = string.atof(m.group (1))
+ conv = dimension_conversion_dict[m.group(2)]
+
+ value = conv(num)
+
+ elif re.match ("^[0-9.]+$",value):
+ value = float(value)
+
+ return value
texi_linewidths = {
'afourpaper': {12: mm2pt(160)},
'smallbook': {12: in2pt(5)},
'letterpaper': {12: in2pt(6)}}
+html_linewidths = {
+ 'afourpaper': {12: mm2pt(160)},
+ 'afourwide': {12: in2pt(6.5)},
+ 'afourlatex': {12: mm2pt(150)},
+ 'smallbook': {12: in2pt(5)},
+ 'letterpaper': {12: in2pt(6)}}
+
option_definitions = [
- ('EXT', 'f', 'format', 'set format. EXT is one of texi and latex.'),
- ('DIM', '', 'default-music-fontsize', 'default fontsize for music. DIM is assumed to be in points'),
- ('DIM', '', 'default-lilypond-fontsize', 'deprecated, use --default-music-fontsize'),
- ('DIM', '', 'force-music-fontsize', 'force fontsize for all inline lilypond. DIM is assumed be to in points'),
- ('DIM', '', 'force-lilypond-fontsize', 'deprecated, use --force-music-fontsize'),
- ('DIR', 'I', 'include', 'include path'),
- ('', 'M', 'dependencies', 'write dependencies'),
- ('PREF', '', 'dep-prefix', 'prepend PREF before each -M dependency'),
- ('', 'n', 'no-lily', 'don\'t run lilypond'),
- ('', '', 'no-pictures', "don\'t generate pictures"),
- ('', '', 'read-lys', "don't write ly files."),
- ('FILE', 'o', 'outname', 'filename main output file'),
- ('FILE', '', 'outdir', "where to place generated files"),
- ('', 'v', 'version', 'print version information' ),
- ('', 'h', 'help', 'print help'),
- ]
+ ('EXT', 'f', 'format', 'use output format EXT (texi [default], latex, html)'),
+ ('DIM', '', 'default-music-fontsize', 'default fontsize for music. DIM is assumed to be in points'),
+ ('DIM', '', 'default-lilypond-fontsize', 'deprecated, use --default-music-fontsize'),
+ ('OPT', '', 'extra-options' , 'Pass OPT quoted to the lilypond command line'),
+ ('DIM', '', 'force-music-fontsize', 'force fontsize for all inline lilypond. DIM is assumed be to in points'),
+ ('DIM', '', 'force-lilypond-fontsize', 'deprecated, use --force-music-fontsize'),
+ ('', 'h', 'help', 'this help'),
+ ('DIR', 'I', 'include', 'include path'),
+ ('', 'M', 'dependencies', 'write dependencies'),
+ ('PREF', '', 'dep-prefix', 'prepend PREF before each -M dependency'),
+ ('', 'n', 'no-lily', 'don\'t run lilypond'),
+ ('', '', 'no-pictures', "don\'t generate pictures"),
+ ('', '', 'no-music', "strip all lilypond blocks from output"),
+ ('', '', 'read-lys', "don't write ly files."),
+ ('FILE', 'o', 'outname', 'filename main output file'),
+ ('FILE', '', 'outdir', "where to place generated files"),
+ ('', 'V', 'verbose', 'verbose' ),
+ ('', 'v', 'version', 'print version information' ),
+ ]
# format specific strings, ie. regex-es for input, and % strings for output
output_dict= {
+ 'html' : {'output-lilypond': '''<lilypond%s>
+%s
+</lilypond>''',
+ 'output-filename' : r'''
+<!-- %s >
+<a href="%s">
+<pre>%s</pre></a>:''',
+ 'output-lilypond-fragment': '''<lilypond%s>
+\context Staff\context Voice{ %s }
+</lilypond>''',
+ 'output-noinline': r'''
+<!-- generated: %(fn)s.png !-->
+''',
+ ## maybe <hr> ?
+ 'pagebreak': None,
+ 'output-verbatim': r'''<pre>
+%s
+</pre>''',
+ 'output-small-verbatim': r'''<font size=-1><pre>
+%s
+</pre></font>''',
+
+ ## Ugh we need to differentiate on origin:
+ ## lilypond-block origin wants an extra <p>, but
+ ## inline music doesn't.
+ ## possibly other center options?
+ 'output-all': r'''
+<a href="%(fn)s.png">
+<img align="center" valign="center" border="0" src="%(fn)s.png" alt="[picture of music]"></a>
+''',
+ },
'latex': {
- 'output-lilypond-fragment' : r"""\begin[eps,singleline,%s]{lilypond}
+ 'output-lilypond-fragment' : r'''\begin[eps,singleline,%s]{lilypond}
\context Staff <
\context Voice{
%s
}
>
-\end{lilypond}""",
+\end{lilypond}''',
'output-filename' : r'''
-
-\verb+%s+:''',
- 'output-lilypond': r"""\begin[%s]{lilypond}
+\verb+%s+:
+%% %s
+%% %s
+''',
+ 'output-lilypond': r'''\begin[%s]{lilypond}
%s
-\end{lilypond}""",
- 'output-verbatim': "\\begin{verbatim}%s\\end{verbatim}",
+\end{lilypond}
+''',
+ 'output-verbatim': r'''\begin{verbatim}%s\end{verbatim}%%
+''',
+ 'output-small-verbatim': r'''{\small\begin{verbatim}%s\end{verbatim}}%%''',
'output-default-post': "\\def\postLilypondExample{}\n",
'output-default-pre': "\\def\preLilypondExample{}\n",
'usepackage-graphics': '\\usepackage{graphics}\n',
- 'output-eps': '\\noindent\\parbox{\\lilypondepswidth{%(fn)s.eps}}{\includegraphics{%(fn)s.eps}}',
+ 'output-eps': '\\noindent\\parbox{\\lilypondepswidth{%(fn)s.eps}}{\includegraphics{%(fn)s}}',
+ 'output-noinline': r'''
+%% generated: %(fn)s.eps
+''',
'output-tex': '{\\preLilypondExample \\input %(fn)s.tex \\postLilypondExample\n}',
'pagebreak': r'\pagebreak',
},
- 'texi' : {'output-lilypond': """@lilypond[%s]
+
+ 'texi' : {'output-lilypond': '''@lilypond[%s]
%s
@end lilypond
-""",
+''',
'output-filename' : r'''
-
-@file{%s}:''',
- 'output-lilypond-fragment': """@lilypond[%s]
+@ifnothtml
+@file{%s}:
+@end ifnothtml
+@ifhtml
+@uref{%s,@file{%s}}
+@end ifhtml
+''',
+ 'output-lilypond-fragment': '''@lilypond[%s]
\context Staff\context Voice{ %s }
-@end lilypond """,
+@end lilypond ''',
+ 'output-noinline': r'''
+@c generated: %(fn)s.png
+''',
'pagebreak': None,
- 'output-verbatim': r"""@example
+ 'output-small-verbatim': r'''@smallexample
+%s
+@end smallexample
+''',
+ 'output-verbatim': r'''@example
%s
@end example
-""",
+''',
# do some tweaking: @ is needed in some ps stuff.
# override EndLilyPondOutput, since @tex is done
# top of the document.
# should also support fragment in
+
+# ugh, the <p> below breaks inline images...
- 'output-all': r"""
+ 'output-all': r'''
@tex
\catcode`\@=12
\input lilyponddefs
<p>
<a href="%(fn)s.png">
<img border=0 src="%(fn)s.png" alt="[picture of music]">
-</a>
+</a><p>
@end html
-""",
+''',
}
+
}
-def output_verbatim (body):
- if __main__.format == 'texi':
- body = re.sub ('([@{}])', '@\\1', body)
- return get_output ('output-verbatim') % body
+def output_verbatim (body, small):
+ if __main__.format == 'html':
+ body = re.sub ('&', '&', body)
+ body = re.sub ('>', '>', body)
+ body = re.sub ('<', '<', body)
+ elif __main__.format == 'texi':
+
+ # clumsy workaround for python 2.2 pre bug.
+ body = re.sub ('@', '@@', body)
+ body = re.sub ('{', '@{', body)
+ body = re.sub ('}', '@}', body)
+ if small:
+ key = 'output-small-verbatim'
+ else:
+ key = 'output-verbatim'
+ return get_output (key) % body
+
+
+#warning: this uses extended regular expressions. Tread with care.
+# legenda
+
+# (?P -- name parameter
+# *? -- match non-greedily.
+# (?m) -- ?
re_dict = {
+ 'html': {
+ 'include': no_match,
+ 'input': no_match,
+ 'header': no_match,
+ 'preamble-end': no_match,
+ 'landscape': no_match,
+ 'verbatim': r'''(?s)(?P<code><pre>\s.*?</pre>\s)''',
+ 'verb': r'''(?P<code><pre>.*?</pre>)''',
+ 'lilypond-file': r'(?m)(?P<match><lilypondfile(?P<options>[^>]+)?>\s*(?P<filename>[^<]+)\s*</lilypondfile>)',
+ 'lilypond' : '(?m)(?P<match><lilypond((?P<options>[^:]*):)(?P<code>.*?)/>)',
+ 'lilypond-block': r'''(?ms)(?P<match><lilypond(?P<options>[^>]+)?>(?P<code>.*?)</lilypond>)''',
+ 'option-sep' : '\s*',
+ 'intertext': r',?\s*intertext=\".*?\"',
+ 'multiline-comment': r"(?sm)\s*(?!@c\s+)(?P<code><!--\s.*?!-->)\s",
+ 'singleline-comment': no_match,
+ 'numcols': no_match,
+ 'multicols': no_match,
+ },
+
'latex': {'input': r'(?m)^[^%\n]*?(?P<match>\\mbinput{?([^}\t \n}]*))',
'include': r'(?m)^[^%\n]*?(?P<match>\\mbinclude{(?P<filename>[^}]+)})',
'option-sep' : ',\s*',
- 'header': r"\\documentclass\s*(\[.*?\])?",
- 'geometry': r"^(?m)[^%\n]*?\\usepackage\s*(\[(?P<options>.*)\])?\s*{geometry}",
- 'preamble-end': r'(?P<code>\\begin{document})',
- 'verbatim': r"(?s)(?P<code>\\begin{verbatim}.*?\\end{verbatim})",
+ 'header': r"\n*\\documentclass\s*(\[.*?\])?",
+ 'preamble-end': r'(?P<code>\\begin\s*{document})',
+ 'verbatim': r"(?s)(?P<code>\\begin\s*{verbatim}.*?\\end{verbatim})",
'verb': r"(?P<code>\\verb(?P<del>.).*?(?P=del))",
'lilypond-file': r'(?m)^[^%\n]*?(?P<match>\\lilypondfile\s*(\[(?P<options>.*?)\])?\s*\{(?P<filename>.+)})',
'lilypond' : r'(?m)^[^%\n]*?(?P<match>\\lilypond\s*(\[(?P<options>.*?)\])?\s*{(?P<code>.*?)})',
'lilypond-block': r"(?sm)^[^%\n]*?(?P<match>\\begin\s*(\[(?P<options>.*?)\])?\s*{lilypond}(?P<code>.*?)\\end{lilypond})",
'def-post-re': r"\\def\\postLilypondExample",
- 'def-pre-re': r"\\def\\preLilypondExample",
- 'usepackage-graphics': r"\usepackage{graphics}",
+ 'def-pre-re': r"\\def\\preLilypondExample",
+ 'usepackage-graphics': r"\usepackage\s*{graphics}",
'intertext': r',?\s*intertext=\".*?\"',
'multiline-comment': no_match,
'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+)?})?)",
},
- # why do we have distinction between @mbinclude and @include?
+ # why do we have distinction between @mbinclude and @include?
+
+
'texi': {
'include': '(?m)^[^%\n]*?(?P<match>@mbinclude[ \n\t]+(?P<filename>[^\t \n]*))',
'input': no_match,
'header': no_match,
'preamble-end': no_match,
'landscape': no_match,
- 'verbatim': r"""(?s)(?P<code>@example\s.*?@end example\s)""",
- 'verb': r"""(?P<code>@code{.*?})""",
- 'lilypond-file': '(?m)^(?!@c)(?P<match>@lilypondfile(\[(?P<options>.*?)\])?{(?P<filename>[^}]+)})',
- 'lilypond' : '(?m)^(?!@c)(?P<match>@lilypond(\[(?P<options>.*?)\])?{(?P<code>.*?)})',
-# pyton2.2b2 barfs on this
- 'lilypond-block': r"""(?m)^(?!@c)(?P<match>(?s)(?P<match>@lilypond(\[(?P<options>.*?)\])?\s(?P<code>.*?)@end lilypond\s))""",
-
-# 1.5.2 barfs on this.
-# 'lilypond-block': r"""(?m)^(?!@c)(?P<match>@lilypond(\[(?P<options>.*?)\])?\s(?P<code>.*?)@end lilypond\s)""",
- 'option-sep' : ',\s*',
- 'intertext': r',?\s*intertext=\".*?\"',
- 'multiline-comment': r"(?sm)^\s*(?!@c\s+)(?P<code>@ignore\s.*?@end ignore)\s",
- 'singleline-comment': r"(?m)^.*?(?P<match>(?P<code>@c.*$\n+))",
- 'numcols': no_match,
+ 'verbatim': r'''(?s)(?P<code>@example\s.*?@end example\s)''',
+ 'verb': r'''(?P<code>@code{.*?})''',
+ 'lilypond-file': '(?m)^(?P<match>@lilypondfile(\[(?P<options>[^]]*)\])?{(?P<filename>[^}]+)})',
+ 'lilypond' : '(?m)^(?P<match>@lilypond(\[(?P<options>[^]]*)\])?{(?P<code>.*?)})',
+ 'lilypond-block': r'''(?ms)^(?P<match>@lilypond(\[(?P<options>[^]]*)\])?\s(?P<code>.*?)@end +lilypond)\s''',
+ 'option-sep' : ',\s*',
+ 'intertext': r',?\s*intertext=\".*?\"',
+ 'multiline-comment': r"(?sm)^\s*(?!@c\s+)(?P<code>@ignore\s.*?@end ignore)\s",
+ 'singleline-comment': r"(?m)^.*?(?P<match>(?P<code>@c.*$\n+))",
+ 'numcols': no_match,
+ 'multicols': no_match,
}
}
olddict = re_dict[r]
newdict = {}
for k in olddict.keys ():
- newdict[k] = re.compile (olddict[k])
+ try:
+ newdict[k] = re.compile (olddict[k])
+ except:
+ print 'invalid regexp: %s' % olddict[k]
+
+ # we'd like to catch and reraise a more detailed error, but
+ # alas, the exceptions changed across the 1.5/2.1 boundary.
+ raise "Invalid re"
re_dict[r] = newdict
str = fd.read ()
s = re.search('%%BoundingBox: ([0-9]+) ([0-9]+) ([0-9]+) ([0-9]+)', str)
if s:
- return (int (s.group (3) - s.group (1) + 0.5),
- int (s.group (4) - s.group (2) + 0.5))
+
+ gs = map (lambda x: string.atoi (x), s.groups ())
+ return (int (gs[2] - gs[0] + 0.5),
+ int (gs[3] - gs[1] + 0.5))
else:
return (0,0)
def error (str):
- sys.stderr.write (str + "\n Exiting ... \n\n")
+ sys.stderr.write ("\n\n" + str + "\nExiting ... \n\n")
raise 'Exiting.'
def compose_full_body (body, opts):
- """Construct the lilypond code to send to Lilypond.
- Add stuff to BODY using OPTS as options."""
+ '''Construct the lilypond code to send to Lilypond.
+ Add stuff to BODY using OPTS as options.'''
music_size = default_music_fontsize
- latex_size = default_text_fontsize
+ if g_force_music_fontsize:
+ music_size = g_force_music_fontsize
+ indent = ''
+ linewidth = ''
for o in opts:
- if g_force_lilypond_fontsize:
- music_size = g_force_lilypond_fontsize
- else:
+ if not g_force_music_fontsize:
m = re.match ('([0-9]+)pt', o)
if m:
music_size = string.atoi(m.group (1))
- m = re.match ('latexfontsize=([0-9]+)pt', o)
+ m = re.match ('indent=([-.0-9]+)(cm|in|mm|pt)', o)
+ if m:
+ f = float (m.group (1))
+ indent = 'indent = %f\\%s' % (f, m.group (2))
+
+ m = re.match ('linewidth=([-.0-9]+)(cm|in|mm|pt)', o)
if m:
- latex_size = string.atoi (m.group (1))
+ f = float (m.group (1))
+ linewidth = 'linewidth = %f\\%s' % (f, m.group (2))
if re.search ('\\\\score', body):
is_fragment = 0
if is_fragment and not 'multiline' in opts:
opts.append('singleline')
+
if 'singleline' in opts:
- l = -1.0;
- else:
- l = __main__.paperguru.get_linewidth()
+ linewidth = 'linewidth = -1.0'
+ elif not linewidth:
+ l = __main__.paperguru.get_linewidth ()
+ linewidth = 'linewidth = %f\pt' % l
+
+ if 'noindent' in opts:
+ indent = 'indent = 0.0\mm'
for o in opts:
m= re.search ('relative(.*)', o)
body = '\\relative %s { %s }' %(pitch, body)
if is_fragment:
- body = r"""\score {
+ body = r'''\score {
\notes { %s }
\paper { }
-}""" % body
+}''' % body
opts = uniq (opts)
optstring = string.join (opts, ' ')
optstring = re.sub ('\n', ' ', optstring)
- body = r"""
+ body = r'''
%% Generated automatically by: lilypond-book.py
%% options are %s
\include "paper%d.ly"
-\paper { linewidth = %f \pt }
-""" % (optstring, music_size, l) + body
+\paper {
+ %s
+ %s
+}
+''' % (optstring, music_size, linewidth, indent) + body
# ughUGH not original options
return body
-def parse_options_string(s):
- d = {}
- r1 = re.compile("((\w+)={(.*?)})((,\s*)|$)")
- r2 = re.compile("((\w+)=(.*?))((,\s*)|$)")
- r3 = re.compile("(\w+?)((,\s*)|$)")
- while s:
- m = r1.match(s)
- if m:
- s = s[m.end():]
- d[m.group(2)] = re.split(",\s*", m.group(3))
- continue
- m = r2.match(s)
- if m:
- s = s[m.end():]
- d[m.group(2)] = m.group(3)
- continue
- m = r3.match(s)
- if m:
- s = s[m.end():]
- d[m.group(1)] = 1
- continue
-
- error ("format of option string invalid (was `%')" % s)
- return d
+def scan_html_preamble (chunks):
+ return
def scan_latex_preamble(chunks):
- # first we want to scan the \documentclass line
- # it should be the first non-comment line
+ # First we want to scan the \documentclass line
+ # it should be the first non-comment line.
+ # The only thing we really need to know about the \documentclass line
+ # is if there are one or two columns to begin with.
idx = 0
while 1:
if chunks[idx][0] == 'ignore':
idx = idx + 1
continue
m = get_re ('header').match(chunks[idx][1])
- if m <> None and m.group (1):
+ if not m:
+ error ("Latex documents must start with a \documentclass command")
+ if m.group (1):
options = re.split (',[\n \t]*', m.group(1)[1:-1])
else:
options = []
- for o in options:
- if o == 'landscape':
- paperguru.m_landscape = 1
- m = re.match("(.*?)paper", o)
- if m:
- paperguru.m_papersize = m.group()
- else:
- m = re.match("(\d\d)pt", o)
- if m:
- paperguru.m_fontsize = int(m.group(1))
+ if 'twocolumn' in options:
+ paperguru.m_num_cols = 2
break
-
- while chunks[idx][0] != 'preamble-end':
+
+
+ # Then we add everythin before \begin{document} to
+ # paperguru.m_document_preamble so that we can later write this header
+ # to a temporary file in find_latex_dims() to find textwidth.
+ while idx < len(chunks) and chunks[idx][0] != 'preamble-end':
if chunks[idx] == 'ignore':
idx = idx + 1
continue
- m = get_re ('geometry').search(chunks[idx][1])
- if m:
- paperguru.m_use_geometry = 1
- o = parse_options_string(m.group('options'))
- for k in o.keys():
- paperguru.set_geo_option(k, o[k])
+ paperguru.m_document_preamble.append(chunks[idx][1])
idx = idx + 1
+ if len(chunks) == idx:
+ error ("Didn't find end of preamble (\\begin{document})")
+
+ paperguru.find_latex_dims()
+
def scan_texi_preamble (chunks):
# this is not bulletproof..., it checks the first 10 chunks
- for c in chunks[:10]:
+ for c in chunks[:10]:
if c[0] == 'input':
for s in ('afourpaper', 'afourwide', 'letterpaper',
'afourlatex', 'smallbook'):
if string.find(c[1], "@%s" % s) != -1:
paperguru.m_papersize = s
+
def scan_preamble (chunks):
- if __main__.format == 'texi':
- scan_texi_preamble(chunks)
- else:
- assert __main__.format == 'latex'
- scan_latex_preamble(chunks)
+ if __main__.format == 'html':
+ scan_html_preamble (chunks)
+ elif __main__.format == 'latex':
+ scan_latex_preamble (chunks)
+ elif __main__.format == 'texi':
+ scan_texi_preamble (chunks)
def completize_preamble (chunks):
- if __main__.format == 'texi':
+ if __main__.format != 'latex':
return chunks
pre_b = post_b = graphics_b = None
for chunk in chunks:
m = get_re('def-post-re').search(chunk[1])
if m:
post_b = 1
+
if chunk[0] == 'input':
m = get_re('usepackage-graphics').search(chunk[1])
if m:
graphics_b = 1
x = 0
- while chunks[x][0] != 'preamble-end':
+ while x < len (chunks) and chunks[x][0] != 'preamble-end':
x = x + 1
+
+ if x == len(chunks):
+ return chunks
+
if not pre_b:
chunks.insert(x, ('input', get_output ('output-default-pre')))
if not post_b:
chunks.insert(x, ('input', get_output ('output-default-post')))
if not graphics_b:
chunks.insert(x, ('input', get_output ('usepackage-graphics')))
+
return chunks
read_files = []
def find_file (name):
- """
+ '''
Search the include path for NAME. If found, return the (CONTENTS, PATH) of the file.
- """
-
+ '''
+
+ if name == '-':
+ return (sys.stdin.read (), '<stdin>')
f = None
nm = ''
for a in include_path:
(options, m.group('code')))]
def make_lilypond_file(m):
- """
+ '''
Find @lilypondfile{bla.ly} occurences and substitute bla.ly
into a @lilypond .. @end lilypond block.
- """
+ '''
if m.group('options'):
options = m.group('options')
(options, content))]
def make_lilypond_block(m):
+ if not g_do_music:
+ return []
+
if m.group('options'):
options = get_re('option-sep').split (m.group('options'))
else:
return [('numcols', m.group('code'), 1)]
if m.group('num') == 'two':
return [('numcols', m.group('code'), 2)]
-
+
+def do_multicols(m):
+ if __main__.format != 'latex':
+ return []
+ if m.group('be') == 'begin':
+ return [('multicols', m.group('code'), int(m.group('num')))]
+ else:
+ return [('multicols', m.group('code'), 1)]
+ return []
+
def chop_chunks(chunks, re_name, func, use_match=0):
- newchunks = []
- for c in chunks:
- if c[0] == 'input':
- str = c[1]
- while str:
- m = get_re (re_name).search (str)
- if m == None:
- newchunks.append (('input', str))
- str = ''
- else:
- if use_match:
- newchunks.append (('input', str[:m.start ('match')]))
- else:
- newchunks.append (('input', str[:m.start (0)]))
- #newchunks.extend(func(m))
- # python 1.5 compatible:
- newchunks = newchunks + func(m)
- str = str [m.end(0):]
- else:
- newchunks.append(c)
- return newchunks
+ newchunks = []
+ for c in chunks:
+ if c[0] == 'input':
+ str = c[1]
+ while str:
+ m = get_re (re_name).search (str)
+ if m == None:
+ newchunks.append (('input', str))
+ str = ''
+ else:
+ if use_match:
+ newchunks.append (('input', str[:m.start ('match')]))
+ else:
+ newchunks.append (('input', str[:m.start (0)]))
+ #newchunks.extend(func(m))
+ # python 1.5 compatible:
+ newchunks = newchunks + func(m)
+ str = str [m.end(0):]
+ else:
+ newchunks.append(c)
+ return newchunks
def determine_format (str):
if __main__.format == '':
- latex = re.search ('\\\\document', str[:200])
- texinfo = re.search ('@node|@setfilename', str[:200])
+ html = re.search ('(?i)<[dh]tml', str[:200])
+ latex = re.search (r'''\\document''', str[:200])
+ texi = re.search ('@node|@setfilename', str[:200])
f = ''
g = None
- if texinfo and latex == None:
- f = 'texi'
- elif latex and texinfo == None:
+ if html and not latex and not texi:
+ f = 'html'
+ elif latex and not html and not texi:
f = 'latex'
+ elif texi and not html and not latex:
+ f = 'texi'
else:
- error("error: can't determine format, please specify")
+ error ("can't determine format, please specify")
__main__.format = f
if __main__.paperguru == None:
- if __main__.format == 'texi':
- g = TexiPaper()
- else:
- g = LatexPaper()
+ if __main__.format == 'html':
+ g = HtmlPaper ()
+ elif __main__.format == 'latex':
+ g = LatexPaper ()
+ elif __main__.format == 'texi':
+ g = TexiPaper ()
__main__.paperguru = g
def read_doc_file (filename):
- """Read the input file, find verbatim chunks and do \input and \include
- """
+ '''Read the input file, find verbatim chunks and do \input and \include
+ '''
(str, path) = find_file(filename)
determine_format (str)
# because we don't want to include files that are mentioned
# inside a verbatim environment
chunks = chop_chunks(chunks, 'verbatim', make_verbatim)
+
+
chunks = chop_chunks(chunks, 'verb', make_verb)
chunks = chop_chunks(chunks, 'multiline-comment', do_ignore)
#ugh fix input
taken_file_names = {}
def schedule_lilypond_block (chunk):
- """Take the body and options from CHUNK, figure out how the
+ '''Take the body and options from CHUNK, figure out how the
real .ly should look, and what should be left MAIN_STR (meant
for the main file). The .ly is written, and scheduled in
TODO.
TODO has format [basename, extension, extension, ... ]
- """
+ '''
(type, body, opts) = chunk
assert type == 'lilypond'
file_body = compose_full_body (body, opts)
+ ## Hmm, we should hash only lilypond source, and skip the
+ ## %options are ...
+ ## comment line
basename = 'lily-' + `abs(hash (file_body))`
for o in opts:
m = re.search ('filename="(.*?)"', o)
if m:
basename = m.group (1)
if not taken_file_names.has_key(basename):
- taken_file_names[basename] = 0
+ taken_file_names[basename] = 0
else:
- taken_file_names[basename] = taken_file_names[basename] + 1
- basename = basename + "-%i" % taken_file_names[basename]
+ taken_file_names[basename] = taken_file_names[basename] + 1
+ basename = basename + "-%i" % taken_file_names[basename]
if not g_read_lys:
update_file(file_body, os.path.join(g_outdir, basename) + '.ly')
needed_filetypes = ['tex']
- if format == 'texi':
- needed_filetypes.append('eps')
- needed_filetypes.append('png')
+ if format == 'html' or format == 'texi':
+ needed_filetypes.append ('eps')
+ 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):
+ def f (base, ext1, ext2):
a = os.path.isfile(base + ext2)
if (os.path.isfile(base + ext1) and
os.path.isfile(base + ext2) and
for o in opts:
m= re.match ("filename=(.*)", o)
if m:
- newbody = newbody + get_output ("output-filename") % m.group(1)
+ newbody = newbody + get_output ("output-filename") % (m.group(1), basename + '.ly', m.group(1))
break
-
- if 'verbatim' in opts:
- newbody = output_verbatim (body)
+
+ if 'smallverbatim' in opts:
+ newbody = newbody + output_verbatim (body, 1)
+ elif 'verbatim' in opts:
+ newbody = newbody + output_verbatim (body, 0)
for o in opts:
m = re.search ('intertext="(.*?)"', o)
if m:
newbody = newbody + m.group (1) + "\n\n"
- if format == 'latex':
+
+ if 'noinline' in opts:
+ s = 'output-noinline'
+ elif format == 'latex':
if 'eps' in opts:
s = 'output-eps'
else:
s = 'output-tex'
- else: # format == 'texi'
- s = 'output-all'
+ else: # format == 'html' or format == 'texi':
+ s = 'output-all'
newbody = newbody + get_output (s) % {'fn': basename }
return ('lilypond', newbody, opts, todo, basename)
-def process_lilypond_blocks(outname, chunks):#ugh rename
+def process_lilypond_blocks(chunks):#ugh rename
newchunks = []
# Count sections/chapters.
for c in chunks:
c = schedule_lilypond_block (c)
elif c[0] == 'numcols':
paperguru.m_num_cols = c[2]
+ elif c[0] == 'multicols':
+ paperguru.m_multicols = c[2]
newchunks.append (c)
return newchunks
error ('Error command exited with value %d\n' % st)
return st
+def quiet_system (cmd, name):
+ if not verbose_p:
+ progress ( _("Running %s...") % name)
+ cmd = cmd + ' 1> /dev/null 2> /dev/null'
+
+ return system (cmd)
def get_bbox (filename):
- f = open (filename)
+
+ # gs bbox device is ugh, it always prints of stderr.
+ system ('gs -sDEVICE=bbox -q -sOutputFile=- -dNOPAUSE %s -c quit > %s.bbox 2>&1' % (filename, filename))
+
+ box = open (filename + '.bbox').read()
+ m = re.match ('^%%BoundingBox: ([0-9]+) ([0-9]+) ([0-9]+) ([0-9]+)', box)
gr = []
- while 1:
- l =f.readline ()
- m = re.match ('^%%BoundingBox: ([0-9]+) ([0-9]+) ([0-9]+) ([0-9]+)', l)
- if m:
- gr = map (string.atoi, m.groups ())
- break
+ if m:
+ gr = map (string.atoi, m.groups ())
return gr
def make_pixmap (name):
bbox = get_bbox (name + '.eps')
- margin = 3
+ margin = 0
fo = open (name + '.trans.eps' , 'w')
fo.write ('%d %d translate\n' % (-bbox[0]+margin, -bbox[1]+margin))
fo.close ()
x = (2* margin + bbox[2] - bbox[0]) * res / 72.
y = (2* margin + bbox[3] - bbox[1]) * res / 72.
- cmd = r"""gs -g%dx%d -sDEVICE=pgm -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -q -sOutputFile=- -r%d -dNOPAUSE %s %s -c quit | pnmtopng > %s"""
+ cmd = r'''gs -g%dx%d -sDEVICE=pnggray -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -q -sOutputFile=%s -r%d -dNOPAUSE %s %s -c quit '''
- cmd = cmd % (x, y, res, name + '.trans.eps', name + '.eps',name + '.png')
+ cmd = cmd % (x, y, name + '.png', res, name + '.trans.eps', name + '.eps')
+ status = 0
try:
status = system (cmd)
except:
+ status = -1
+
+ if status:
os.unlink (name + '.png')
error ("Removing output file")
png = []
for c in chunks:
- if c[0] <> 'lilypond':
+ if c[0] != 'lilypond':
continue
base = c[4]
exts = c[3]
if tex:
# fixme: be sys-independent.
def incl_opt (x):
- if g_outdir and x[0] <> '/' :
+ if g_outdir and x[0] != '/' :
x = os.path.join (g_here_dir, x)
return ' -I %s' % x
if g_outdir:
lilyopts = lilyopts + '--dep-prefix=' + g_outdir + '/'
texfiles = string.join (tex, ' ')
- system ('lilypond --header=texidoc %s %s' % (lilyopts, texfiles))
+ cmd = '%s --header=texidoc %s %s %s' \
+ % (binary, lilyopts, g_extra_opts, texfiles)
+
+ system (cmd)
#
# Ugh, fixing up dependencies for .tex generation
f.close ()
for e in eps:
- system(r"tex '\nonstopmode \input %s'" % e)
- system(r"dvips -E -o %s %s" % (e + '.eps', e))
+ cmd = r"echo $TEXMF; tex '\nonstopmode \input %s'" % e
+ quiet_system (cmd, 'TeX')
+
+ cmd = r"dvips -E -o %s %s" % (e + '.eps', e)
+ quiet_system (cmd, 'dvips')
for g in png:
make_pixmap (g)
def update_file (body, name):
- """
+ '''
write the body if it has changed
- """
+ '''
same = 0
try:
f = open (name)
return str
def help():
- sys.stdout.write("""Usage: lilypond-book [options] FILE\n
+ sys.stdout.write('''Usage: lilypond-book [options] FILE\n
Generate hybrid LaTeX input from Latex + lilypond
Options:
-""")
+''')
sys.stdout.write (options_help_str (option_definitions))
- sys.stdout.write (r"""Warning all output is written in the CURRENT directory
+ sys.stdout.write (r'''Warning all output is written in the CURRENT directory
Written by Tom Cato Amundsen <tca@gnu.org> and
Han-Wen Nienhuys <hanwen@cs.uu.nl>
-""")
+''')
sys.exit (0)
def write_deps (fn, target, chunks):
global read_files
- sys.stdout.write('Writing `%s\'\n' % os.path.join(g_outdir, fn))
+ sys.stderr.write('Writing `%s\'\n' % os.path.join(g_outdir, fn))
f = open (os.path.join(g_outdir, fn), 'w')
f.write ('%s%s: ' % (g_dep_prefix, target))
for d in read_files:
f.close ()
read_files = []
-def identify():
- sys.stdout.write ('lilypond-book (GNU LilyPond) %s\n' % program_version)
+def identify (stream):
+ stream.write ('lilypond-book (GNU LilyPond) %s\n' % program_version)
def print_version ():
- identify()
- sys.stdout.write (r"""Copyright 1998--1999
+ identify (sys.stdout)
+ sys.stdout.write (r'''Copyright 1998--1999
Distributed under terms of the GNU General Public License. It comes with
NO WARRANTY.
-""")
+''')
def check_texidoc (chunks):
def fix_epswidth (chunks):
newchunks = []
for c in chunks:
- if c[0] <> 'lilypond' or 'eps' not in c[2]:
+ if c[0] != 'lilypond' or 'eps' not in c[2]:
newchunks.append (c)
continue
return '%fpt' % (dims[0] *lmag)
- body = re.sub (r"""\\lilypondepswidth{(.*?)}""", replace_eps_dim, c[1])
+ body = re.sub (r'''\\lilypondepswidth{(.*?)}''', replace_eps_dim, c[1])
newchunks.append(('lilypond', body, c[2], c[3], c[4]))
return newchunks
+##docme: why global?
foutn=""
def do_file(input_filename):
- global foutn
- file_settings = {}
- if outname:
- my_outname = outname
- else:
- my_outname = os.path.basename(os.path.splitext(input_filename)[0])
- my_depname = my_outname + '.dep'
chunks = read_doc_file(input_filename)
chunks = chop_chunks(chunks, 'lilypond', make_lilypond, 1)
chunks = chop_chunks(chunks, 'singleline-comment', do_ignore, 1)
chunks = chop_chunks(chunks, 'preamble-end', do_preamble_end)
chunks = chop_chunks(chunks, 'numcols', do_columns)
+ chunks = chop_chunks(chunks, 'multicols', do_multicols)
#print "-" * 50
#for c in chunks: print "c:", c;
#sys.exit()
scan_preamble(chunks)
- chunks = process_lilypond_blocks(my_outname, chunks)
-
- foutn = os.path.join (g_outdir, my_outname + '.' + format)
+ chunks = process_lilypond_blocks(chunks)
# Do It.
if __main__.g_run_lilypond:
x = 0
chunks = completize_preamble (chunks)
- sys.stderr.write ("Writing `%s'\n" % foutn)
- fout = open (foutn, 'w')
+
+
+ global foutn
+
+ if outname:
+ my_outname = outname
+ elif input_filename == '-' or input_filename == "/dev/stdin":
+ my_outname = '-'
+ else:
+ my_outname = os.path.basename (os.path.splitext(input_filename)[0]) + '.' + format
+ my_depname = my_outname + '.dep'
+
+ if my_outname == '-' or my_outname == '/dev/stdout':
+ fout = sys.stdout
+ foutn = "<stdout>"
+ __main__.do_deps = 0
+ else:
+ foutn = os.path.join (g_outdir, my_outname)
+ sys.stderr.write ("Writing `%s'\n" % foutn)
+ fout = open (foutn, 'w')
for c in chunks:
fout.write (c[1])
fout.close ()
if do_deps:
write_deps (my_depname, foutn, chunks)
-
outname = ''
try:
(sh, long) = getopt_args (__main__.option_definitions)
elif o == '--version' or o == '-v':
print_version ()
sys.exit (0)
+ elif o == '--verbose' or o == '-V':
+ __main__.verbose_p = 1
elif o == '--format' or o == '-f':
__main__.format = a
elif o == '--outname' or o == '-o':
elif o == '--default-lilypond-fontsize':
print "--default-lilypond-fontsize is deprecated, use --default-music-fontsize"
default_music_fontsize = string.atoi (a)
+ elif o == '--extra-options':
+ g_extra_opts = a
elif o == '--force-music-fontsize':
- g_force_lilypond_fontsize = string.atoi(a)
+ g_force_music_fontsize = string.atoi(a)
elif o == '--force-lilypond-fontsize':
print "--force-lilypond-fontsize is deprecated, use --default-lilypond-fontsize"
- g_force_lilypond_fontsize = string.atoi(a)
+ g_force_music_fontsize = string.atoi(a)
elif o == '--dep-prefix':
g_dep_prefix = a
elif o == '--no-pictures':
g_do_pictures = 0
+ elif o == '--no-music':
+ g_do_music = 0
elif o == '--read-lys':
g_read_lys = 1
elif o == '--outdir':
g_outdir = a
-identify()
+identify (sys.stderr)
if g_outdir:
if os.path.isfile(g_outdir):
error ("outdir is a file: %s" % g_outdir)