options = [
- ('', 'h', 'help', 'print help'),
- ('EXT', 'f', 'format', 'set format. EXT is one of texi and latex.'),
- ('', 'v', 'version', 'print version information' ),
- ('FILE', 'o', 'outname', 'prefix for filenames'),
('DIM', '', 'default-mudela-fontsize', 'default fontsize for music. DIM is assumed to in points'),
+ ('EXT', 'f', 'format', 'set format. EXT is one of texi and latex.'),
+ ('', 'h', 'help', 'print help'),
+ ('DIR', 'I', 'include', 'include path'),
+ ('', '', 'init', 'mudela-book initfile'),
# ('DIM', '', 'force-mudela-fontsize', 'force fontsize for all inline mudela. DIM is assumed to in points'),
('', '', 'force-verbatim', 'make all mudela verbatim'),
('', 'M', 'dependencies', 'write dependencies'),
- ('DIR', 'I', 'include', 'include path'),
- ('', '', 'init', 'mudela-book initfile')
+ ('', 'n', 'no-lily', 'don\'t run lilypond'),
+ ('FILE', 'o', 'outname', 'prefix for filenames'),
+ ('', 'v', 'version', 'print version information' )
]
-format = 'latex'
+format = ''
+no_lily = 0
no_match = 'a\ba'
# format specific strings, ie. regex-es for input, and % strings for output
+output_dict= {
+ 'latex': {
+ 'output-mudela-fragment' : r"""\begin[eps,fragment%s]{mudela}
+ \context Staff <
+ \context Voice{
+ %s
+ }
+ >
+\end{mudela}""",
+ 'output-mudela':r"""\begin%s{mudela}
+%s
+\end{mudela}""",
+ 'output-verbatim': r"""\begin{verbatim}%s\end{verbatim}""",
+ 'output-default-post': r"""\def\postMudelaExample{}""",
+ 'output-default-pre': r"""\def\preMudelaExample{}""",
+ 'output-eps': '\\noindent\\parbox{\\mudelaepswidth{%s.eps}}{\includegraphics{%s.eps}}',
+ 'output-tex': '\\preMudelaExample \\input %s.tex \\postMudelaExample\n'
+ },
+ 'texi' : {'output-mudela': """@mudela[%s]
+%s
+@end mudela
+""",
+ 'output-verbatim': r"""@example
+%s
+@end example
+""",
+ 'output-all': r"""@tex
+\input %s.tex
+@end tex
+@html
+<img src=%s.png>
+@end html
+""",
+ }
+ }
+
re_dict = {
'latex': {'input': '\\\\input{?([^}\t \n}]*)',
'include': '\\\\include{([^}]+)}',
- 'include-mudela':r"""\begin%s{mudela}
-%s
-\end{mudela}""",
+
+ 'comma-sep' : ', *',
'header': r"""\\documentclass(\[.*?\])?""",
'preamble-end': '\\\\begin{document}',
'verbatim': r"""(?s)\\begin{verbatim}(.*?)\\end{verbatim}""",
'mudela-file': '\\\\mudelafile(\[[^\\]]+\])?{([^}]+)}',
'mudela' : '\\\\mudela(\[.*?\])?{(.*?)}',
'mudela-block': r"""(?s)\\begin(\[.*?\])?{mudela}(.*?)\\end{mudela}""",
- 'interesting-cs': '\\\\(chapter|section|mudelagraphic|twocolumn|onecolumn)',
- 'quote-verbatim': r"""\begin{verbatim}%s\end{verbatim}""",
+ 'interesting-cs': '\\\\(chapter|section|twocolumn|onecolumn)',
'def-post-re': r"""\\def\\postMudelaExample""",
'def-pre-re': r"""\\def\\preMudelaExample""",
- 'default-post': r"""\def\postMudelaExample{}""",
- 'default-pre': r"""\def\preMudelaExample{}""",
- 'output-eps': '\\noindent\\parbox{\\mudelaepswidth{%s.eps}}{\includegraphics{%s.eps}}',
- 'output-tex': '\\preMudelaExample \\input %s.tex \\postMudelaExample\n'
},
'texi': {'input': '@include[ \n\t]+([^\t \n]*)',
'include': no_match,
- 'include-mudela': """@mudela[%s]
-%s
-@end mudela
-""",
'header': no_match,
'preamble-end': no_match,
'verbatim': r"""(?s)@example(.*?)@end example$""",
'mudela' : '@mudela(\[.*?\])?{(.*?)}',
'mudela-block': r"""(?s)@mudela(\[.*?\])?(.*?)@end mudela""",
'interesting-cs': r"""[\\@](node|mudelagraphic)""",
- 'quote-verbatim': r"""@example
-%s
-@end example""",
- 'output-all': r"""@tex
-\input %s.tex
-@end tex
-@html
-<img src=%s.png>
-@end html
-""",
- }
+ 'comma-sep' : ', *',
+ }
}
+for r in re_dict.keys ():
+ olddict = re_dict[r]
+ newdict = {}
+ for k in olddict.keys ():
+ newdict[k] = re.compile (olddict[k])
+ re_dict[r] = newdict
+
+def get_output (name):
+ return output_dict[format][name]
def get_re (name):
return re_dict[format][name]
else:
l = latex_linewidths[cols][paper][latex_size]
- if not 'nofly' in opts and not re.search ('\\\\score', body):
- opts.append ('fly')
-
+ # urg: breaks on \include of full score
+ # if not 'nofly' in opts and not re.search ('\\\\score', body):
+ # opts.append ('fly')
if 'fly' in opts:
body = r"""\score {
return body
+def inclusion_func (match, surround):
+ insert = match.group (0)
+ try:
+ (insert, d) = read_doc_file (match.group(1))
+ deps = deps + d
+ insert = surround + insert + surround
+ except:
+ sys.stderr.write("warning: can't find %s, let's hope latex will\n" % m.group(1))
-#
-# Petr, ik zou willen dat ik iets zinvoller deed,
-# maar wat ik kan ik doen, het verandert toch niets?
-# --hwn 20/aug/99
-#
+ return (insert, deps)
+def find_inclusion_chunks (regex, surround, str):
+ chunks = []
+ while str:
+ m = regex.search (str)
-def read_tex_file (filename):
+ if m == None:
+ chunks.append (('input', str))
+ str = ''
+ break
+
+ chunks.append (('input', str[: m.start (0)]))
+ chunks.append (('input', surround))
+ chunks = chunks + read_doc_file (m.group (1))
+ chunks.append (('input', surround))
+
+ str = str [m.end (0):]
+ return chunks
+
+def find_include_chunks (str):
+ return find_inclusion_chunks (get_re ('include'), '\\newpage', str)
+
+def find_input_chunks (str):
+ return find_inclusion_chunks (get_re ('input'), '', str)
+
+def read_doc_file (filename):
"""Read the input file, substituting for \input, \include, \mudela{} and \mudelafile"""
str = ''
for fn in [filename, filename+'.tex', filename+'.doc']:
retdeps = [filename]
- def inclusion_func (match, surround):
- insert = match.group (0)
- try:
- (insert, d) = read_tex_file (match.group(1))
- deps = deps + d
- insert = surround + insert + surround
- except:
- sys.stderr.write("warning: can't find %s, let's hope latex will\n" % m.group(1))
+ if __main__.format == '':
+ latex = re.search ('\\\\document', str[:200])
+ texinfo = re.search ('@node', str[:200])
+ if (texinfo and latex) or not (texinfo or latex):
+ error("error: can't determine format, please specify")
+ if texinfo:
+ __main__.format = 'texi'
+ else:
+ __main__.format = 'latex'
+
+ chunks = find_verbatim_chunks (str)
+ newchunks = []
+
+ for func in (find_include_chunks, find_input_chunks):
+ for c in chunks:
+ if c[0] == 'input':
+ ch = func (c[1])
+ newchunks = newchunks + ch
+ else:
+ newchunks.append (c)
- return (insert, deps)
- def include_func (match, d = retdeps):
- (s,d) = inclusion_func (match, '\\newpage ', retdeps)
- retdeps = retdeps + d
- return s
+ return chunks
- str = re.sub (get_re ('input'), include_func, str)
- def input_func (match, d = retdeps):
- (s,d) = inclusion_func (match, '', retdeps)
- retdeps = retdeps + d
- return s
-
- str = re.sub (get_re ('include'), input_func, str)
-
- return (str, retdeps)
def scan_preamble (str):
options = []
- m = re.search (get_re ('header'), str)
+ m = get_re ('header').search( str)
# should extract paper & fontsz.
if m and m.group (1):
options = options + re.split (',[\n \t]*', m.group(1)[1:-1])
def verbose_fontsize ( x):
- if o.match('[0-9]+pt'):
+ # o ??
+ #if o.match('[0-9]+pt'):
+ if re.match('[0-9]+pt', x):
return 'latexfontsize=' + x
else:
return x
def completize_preamble (str):
- m = re.search (get_re ('preamble-end'), str)
+ m = get_re ('preamble-end').search( str)
if not m:
return str
preamble = str [:m.start (0)]
str = str [m.start(0):]
- if not re.search (get_re('def-post-re'), preamble):
- preamble = preamble + get_re('default-post')
- if not re.search (get_re ('def-pre-re'), preamble):
- preamble = preamble + get_re ('default-pre')
+ if not get_re('def-post-re').search (preamble):
+ preamble = preamble + get_output('output-default-post')
+ if not get_re ('def-pre-re').search( preamble):
+ preamble = preamble + get_output ('output-default-pre')
- if re.search ('\\\\includegraphics', str) and not re.search ('usepackage{graphics}',str):
- preamble = preamble + '\\usepackage{graphics}\n'
+ # UGH ! BUG!
+ #if re.search ('\\\\includegraphics', str) and not re.search ('usepackage{graphics}',str):
+
+ preamble = preamble + '\\usepackage{graphics}\n'
return preamble + str
+
+def find_verbatim_chunks (str):
+ """Chop STR into a list of tagged chunks, ie. tuples of form
+ (TYPE_STR, CONTENT_STR), where TYPE_STR is one of 'input' and 'verbatim'
+ """
+
-def find_mudela_sections (str):
- """Find mudela blocks, while watching for verbatim. Returns
- (STR,MUDS) with \mudelagraphic substituted for the blocks in STR,
- and the blocks themselves MUDS"""
+ chunks = []
- mudelas = []
- verbblocks = []
- noverbblocks = []
-
while str:
- m = re.search (get_re ('verbatim'), str)
- m2 = re.search (get_re ("verb"), str)
+ m = get_re ('verbatim').search( str)
+ m2 = get_re ("verb").search( str)
if m == None and m2 == None:
- noverbblocks.append (str)
+ chunks.append (('input', str))
str = ''
break
if m2 and m2.start (0) < m.start (0):
m = m2
- noverbblocks.append (str[:m.start (0)])
- verbblocks.append (m.group (0))
+ chunks.append (('input', str[:m.start (0)]))
+ chunks.append (('verbatim', m.group (0)))
+
str = str [m.end(0):]
+ return chunks
+
+def find_mudela_shorthand_chunks (str):
+ return [('input', find_mudela_shorthands(str))]
+
+def find_mudela_shorthands (b):
def mudela_short (match):
"Find \mudela{}, and substitute appropriate \begin / \end blocks."
opts = match.group (1)
opts = ',' + opts[1:-1]
else:
opts = ''
- return r"""\begin[eps,fragment%s]{mudela}
- \context Staff <
- \context Voice{
- %s
- }
- >
-\end{mudela}""" % (opts, match.group (2))
+ return get_output ('output-mudela-fragment') % (opts, match.group (2))
def mudela_file (match):
"Find \mudelafile, and substitute appropriate \begin / \end blocks."
str = "%% copied from %s" % full_path + str
- return get_re ('include-mudela') % (str_opts, str)
+ return get_output ('output-mudela') % (str_opts, str)
+ b = get_re('mudela-file').sub (mudela_file, b)
+ b = get_re('mudela').sub (mudela_short, b)
+ return b
+
+def find_mudela_chunks (str):
+ """Find mudela blocks, while watching for verbatim. Returns
+ (STR,MUDS) with \mudelagraphic substituted for the blocks in STR,
+ and the blocks themselves MUDS"""
- def find_one_mudela_block (match,muds =mudelas):
- "extract body and options from a mudela block, and append into MUDELAS"
- opts = match.group (1)
+ chunks = []
+ while str:
+ m = get_re ("mudela-block").search( str)
+ if not m:
+ chunks.append (('input', str))
+ str = ''
+ break
+
+ chunks.append (('input', str[:m.start (0)]))
+
+ opts = m.group (1)
if opts:
opts = opts[1:-1]
else:
opts = ''
-
- body = match.group (2)
- optlist = re.split (', *', opts)
- muds.append ((body, optlist))
-
- return '\\mudelagraphic\n'# UGH.
-
- doneblocks = []
- for b in noverbblocks:
- b = re.sub (get_re('mudela-file'), mudela_file, b)
- b = re.sub (get_re('mudela'), mudela_short, b)
- b = re.sub (get_re ("mudela-block"), find_one_mudela_block, b)
- doneblocks.append (b)
-
- allblocks = []
- verbblocks.append ('')
- while doneblocks:
- allblocks = allblocks + doneblocks[0:1] + verbblocks[0:1]
- verbblocks = verbblocks[1:]
- doneblocks =doneblocks[1:]
-
- str = string.join (allblocks,'')
-
- return (str, mudelas)
-
-
-def eps_file_cs (base):
- if format == 'latex':
- return
- els
+ optlist = get_re('comma-sep').split (opts)
+
+ body = m.group (2)
+ chunks.append (('mudela', body, optlist))
-def tex_file_cs (base):
- return
+ str = str [m.end (0):]
+ return chunks
-def make_files (str, mudelas, filename):
- (chapter, section, count) = (0,0,0)
- total = 0
+def advance_counters (counter, opts, str):
+ """Advance chap/sect counters,
+ revise OPTS. Return the new counter tuple"""
+
+ (chapter, section, count) = counter
done = ''
-
- # number them.
- numbering = []
- current_opts = []
while str:
- m = re.search (get_re ('interesting-cs'), str)
+ m = get_re ('interesting-cs').search(str)
if not m:
done = done + str
str = ''
g = m.group (1)
if g == 'twocolumn':
- current_opts.append ('twocolumn')
+ opts.append ('twocolumn')
elif g == 'onecolumn':
try:
current_opts.remove ('twocolumn')
except IndexError:
pass
- if g == 'mudelagraphic':
- numbering.append ((chapter, section, count, current_opts[:]))
- count = count + 1
elif g == 'chapter':
(chapter, section, count) = (chapter + 1, 0, 0)
elif g == 'section' or g == 'node':
(section, count) = (section + 1, 0)
- todo = []
- str = done
+ return (chapter, section, count)
+
+
+def schedule_mudela_block (base, chunk, extra_opts):
+
+ """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.
+
+ Return: a chunk (TYPE_STR, MAIN_STR, OPTIONS, TODO)
+
+ TODO has format [basename, extension, extension, ... ]
+ """
- done = ''
- while str:
- m = re.search ('\\\\mudelagraphic', str)
- if not m:
- done = done + str;
- str = ''
- break
+ (type, body, opts) = chunk
+ assert type == 'mudela'
+ opts = opts + extra_opts
+
+ newbody = ''
+ if 'verbatim' in opts:
+ verbatim_mangle = body
+ if __main__.format == 'texi':
+ verbatim_mangle = re.sub ('([{}])', '@\\1', body)
+ newbody = get_output ('output-verbatim') % verbatim_mangle
- done = done + str[:m.start(0)]
- str = str[m.end(0):]
-
- (c1,c2,c3, file_opts) = numbering[0]
- (body, opts) = mudelas[0]
- numbering = numbering[1:]
- mudelas = mudelas[1:]
-
- opts = opts + file_opts
+ file_body = compose_full_body (body, opts)
+ updated = update_file (file_body, base + '.ly')
- base = '%s-%d.%d.%d' % (filename, c1, c2,c3)
- if 'verbatim' in opts:
- done = done + get_re ('quote-verbatim') % body
-
+ todo = [base] # UGH.
+
+ if not os.path.isfile (base + '.tex') or updated:
+ todo.append ('tex')
+ updated = 1
- body = compose_full_body (body, opts)
- updated = update_file (body, base + '.ly')
- def is_updated (extension, t = todo):
- for x in t:
- if t[0] == extension:
- return 1
- return 0
-
- if not os.path.isfile (base + '.tex') or updated:
- todo.append (('tex', base, opts))
- updated = 1
-
- for o in opts:
- m = re.search ('intertext="(.*?)"', o)
- if m:
- done = done + m.group (1)
-
- if format == 'texi':
- opts.append ('png')
-
- if 'png' in opts:
- opts.append ('eps')
+ for o in opts:
+ m = re.search ('intertext="(.*?)"', o)
+ if m:
+ newbody = newbody + m.group (1)
- if 'eps' in opts and (is_updated ('tex') or
- not os.path.isfile (base + '.eps')):
- todo.append (('eps', base, opts))
+ if format == 'texi':
+ opts.append ('png')
- if 'png' in opts and (is_updated ('eps') or
- not os.path.isfile (base + '.png')):
- todo.append (('png', base, opts))
-
- if format == 'latex':
- if 'eps' in opts :
- done = done + get_re ('output-eps') % (base, base )
+ if 'png' in opts:
+ opts.append ('eps')
+
+ if 'eps' in opts and ('tex' in todo or
+ not os.path.isfile (base + '.eps')):
+ todo.append ('eps')
+
+ if 'png' in opts and ('eps' in todo or
+ not os.path.isfile (base + '.png')):
+ todo.append ('png')
+
+ if format == 'latex':
+ if 'eps' in opts :
+ newbody = newbody + get_output ('output-eps') % (base, base)
+ else:
+ newbody = newbody + get_output ('output-tex') % base
+
+ elif format == 'texi':
+ newbody = newbody + get_output ('output-all') % (base, base)
+
+
+
+ return ('mudela', newbody, opts, todo)
+
+def find_eps_dims (match):
+ "Fill in dimensions of EPS files."
+ fn =match.group (1)
+ dims = bounding_box_dimensions (fn)
+
+ return '%ipt' % dims[0]
+
+
+def print_chunks (ch):
+ for c in ch:
+ print '-->%s\n%s' % (c[0], c[1])
+ if len (c) > 2:
+ print '==>%s' % list (c[2:])
+ print foo
+
+
+def transform_input_file (in_filename, out_filename):
+ """Read the input, and deliver a list of chunks
+ ready for writing.
+ """
+
+ chunks = read_doc_file (in_filename)
+
+ #. Process \mudela and \mudelafile.
+ for func in [find_mudela_shorthand_chunks,
+ find_mudela_chunks]:
+ newchunks = []
+ for c in chunks:
+ if c[0] == 'input':
+ newchunks = newchunks + func (c[1])
else:
- done = done + get_re ('output-tex') % base
- elif format == 'texi':
- done = done + get_re ('output-all') % (base, base)
+ newchunks.append (c)
+ chunks = newchunks
+ opts = []
+ if chunks:
+ opts = scan_preamble (chunks[0][1])
+
+ (chap,sect,count) = (0,0,0)
+ newchunks = []
+ # Count sections/chapters.
+ for c in chunks:
+ if c[0] == 'input':
+ (chap,sect,count) = advance_counters((chap,sect,count), opts, c[1])
+ elif c[0] == 'mudela':
+ base = '%s-%d.%d.%d' % (out_filename, chap, sect, count)
+ count = count + 1
+ c = schedule_mudela_block (base, c, opts)
+
+ newchunks.append (c)
- compile_all_files (todo)
+ chunks = newchunks
+ newchunks = []
- def find_eps_dims (match):
- "Fill in dimensions of EPS files."
- fn =match.group (1)
- dims = bounding_box_dimensions (fn)
-
- return '%ipt' % dims[0]
- done = re.sub (r"""\\mudelaepswidth{(.*?)}""", find_eps_dims, done)
+ # Do It.
+ if not __main__.no_lily:
+ compile_all_files (chunks)
+
+ # finishing touch.
+ for c in chunks:
+ if c[0] == 'mudela' and 'eps' in c[2]:
+ body = re.sub (r"""\\mudelaepswidth{(.*?)}""", find_eps_dims, c[1])
+ newchunks.append (('mudela', body))
+ else:
+ newchunks.append (c)
- return done
+ if chunks and chunks[0][0] == 'input':
+ chunks[0] = ('input', completize_preamble (chunks[0][1]))
+
+ return chunks
def system (cmd):
sys.stderr.write ("invoking `%s'\n" % cmd)
sys.stderr.write ('Error command exited with value %d\n' % st)
return st
-def compile_all_files ( list):
+def compile_all_files (chunks):
eps = []
tex = []
- gif = []
- for l in list:
- if l[0] == 'eps':
- eps.append (l[1])
- elif l[0] == 'tex':
- tex.append (l[1] + '.ly')
- elif l[0] == 'png':
- gif.append (l[1])
+ png = []
+
+ for c in chunks:
+ if c[0] <> 'mudela':
+ continue
+ base = c[3][0]
+ exts = c[3][1:]
+ for e in exts:
+ if e == 'eps':
+ eps.append (base)
+ elif e == 'tex':
+ tex.append (base + '.ly')
+ elif e == 'png':
+ png.append (base)
if tex:
lilyopts = map (lambda x: '-I ' + x, include_path)
- texfiles = string.join (tex, ' ')
lilyopts = string.join (lilyopts, ' ' )
+ texfiles = string.join (tex, ' ')
system ('lilypond %s %s' % (lilyopts, texfiles))
-
for e in eps:
cmd = r"""tex %s; dvips -E -o %s %s""" % \
(e, e + '.eps', e)
system (cmd)
- for g in gif:
+ for g in png:
cmd = r"""gs -sDEVICE=pgm -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -q -sOutputFile=- -r90 -dNOPAUSE %s -c quit | pnmcrop | pnmtopng > %s"""
cmd = cmd % (g + '.eps', g + '.png')
def options_help_str (opts):
- "Transform a list of options into a neatly formatted string"
+ "Convert a list of options into a neatly formatted string"
w = 0
strs =[]
helps = []
outdir = a
elif o == '--help' or o == '-h':
help ()
+ elif o == '--no-lily' or o == '-n':
+ __main__.no_lily = 1
elif o == '--dependencies':
do_deps = 1
elif o == '--default-mudela-fontsize':
my_outname = os.path.basename(os.path.splitext(input_filename)[0])
my_depname = my_outname + '.dep'
- (input, deps) = read_tex_file (input_filename)
- (input, muds) = find_mudela_sections (input)
- output = make_files (input, muds, my_outname)
- output = completize_preamble (output)
-
+ chunks = transform_input_file (input_filename, my_outname)
+
foutn = my_outname + '.' + format
sys.stderr.write ("Writing `%s'\n" % foutn)
fout = open (foutn, 'w')
-
- fout.write (output)
+ for c in chunks:
+ fout.write (c[1])
fout.close ()
if do_deps:
- write_deps (my_depname, my_outname, deps)
+ # write_deps (my_depname, my_outname, deps)
+ sys.stderr.write ("--dependencies broken")
main()
+
+
+
+#
+# Petr, ik zou willen dat ik iets zinvoller deed,
+# maar wat ik kan ik doen, het verandert toch niets?
+# --hwn 20/aug/99