]> git.donarmstrong.com Git - lilypond.git/blobdiff - scripts/mudela-book.py
release: 1.3.85
[lilypond.git] / scripts / mudela-book.py
index 869b7907acfc7d7e1b3f917e4232e837d60a0696..c60924d43498712dafdab9014699494091f3aae1 100644 (file)
 #!@PYTHON@
-#
-# The bugs you find are made by Tom Cato Amundsen <tomcato@xoommail.com>
-# Send patches/questions/bugreports to a mailinglist:
-#  gnu-music-discuss@gnu.org
-#  bug-gnu-music@gnu.org
-#  help-gnu-music@gnu.org
-#
-#  TODO:
-# * center option (??)
-# * make mudela-book understand usepackage{geometry}
-# * check that linewidth set in \paper is not wider than actual linewidth?
-# * the following fails because mudelabook doesn't care that the
-#   last } after \end{mudela} finishes the marginpar:
-#     \marginpar{
-#     \begin{mudela}
-#        c d e f g
-#     \end{mudela}}
-# * force-verbatim is maybe not that useful since latex fails with footnotes,
-#   marginpars and others
-# log:
-# 0.3:
-#   rewrite in Python.
-# 0.4:
-#   much rewritten by new author. I think the work has been split more
-#   logical between different classes.
-# 0.4.1:
-#   - cleanup
-#   - speedup, do all mudela parsing at the same time to avoid multiple
-#     guile startup that takes some seconds on my computer
-# 0.4.2:
-#   - fixed default latex fontsize, it should be 10pt not 11pt
-#   - verbatim option no longer visible
-#   - mudela-book produces .dvi output
-#   - change to use castingalgorithm = \Gourlay instead of \Wordwrap. It gives
-#     better result on small linewidths.
-#   - mudela-book-doc.doc rewritten
-# 0.5:
-#   - junked floating and fragment options, added eps option
-#   - mudela-book will scan the mudela code to find out if it has to add
-#     paper-definition and \score{\notes{...}}
-#   - possible to define commands that look like this: \mudela{ c d e }
-#   - don't produce .dvi output, it was a silly idea...
-# 0.5.1:
-#   - removed init/mudela-book-defs.py, \mudela is defined inside mudela-book
-#   - fragment and nonfragment options will override autodetection of type of
-#     in mudela-block (voice contents or complete code)
-# 0.5.2:
-#   - fixed verbatim option behaviour: don't show \begin{mudela} \end{mudela}
-#     and show both mudela code and music
-#   - veryverbatim option, same as verbatim but show \begin{mudela}
-#     and \end{mudela}. (saves keystrokes in mudela-book-doc.doc)
-#   - intertext="bla bla bla" option
-#   - mudela-book now understand latex \begin{verbatim}
-# 0.5.3:
-#   - bf: \mudela{ \times 2/3{...} }
-#        * \t in \times is not tab character and
-#        * dont treat the first '}' as command ending
-# 0.5.4: (Mats B)
-#   - .fly and .sly files in \mudelafile{} are treated as standalone Lilypond.
-#   - Fragments, .fly and .sly files are in \relative mode.
-# 0.5.5: (Mats B)
-#   - bf: Default fragments have linewidth=-1.0
-#   - Added 'singleline' and 'multiline' options.
-# 0.5.6:
-#   - \mudelafile{} set linewidth correct, -1 for .sly and texlinewidth for .fly
-#   - changes to Mudela_output
-#   - changed RE to search for pre/postMudelaExample to make it possible to
-#     comment out a definition.
-#   - use sys.stderr and sys.stdout instead of print
+# vim: set noexpandtab:
+# TODO: Figure out clean set of options.
+# add support for .lilyrc
+
 import os
+import stat
 import string
 import re
 import getopt
 import sys
+import __main__
+
+
+
+program_version = '@TOPLEVEL_VERSION@'
+if program_version == '@' + 'TOPLEVEL_VERSION' + '@':
+       program_version = '1.3.69-very-unstable'        
+
+include_path = [os.getcwd()]
+
+g_dep_prefix = ''
+g_outdir = ''
+g_force_mudela_fontsize = 0
+g_read_lys = 0
+g_do_pictures = 1
+g_num_cols = 1
+format = ''
+g_run_lilypond = 1
+no_match = 'a\ba'
+
+default_music_fontsize = 16
+default_text_fontsize = 12
+
+# latex linewidths:
+# indices are no. of columns, papersize,  fontsize
+# Why can't this be calculated?
+latex_linewidths = {
+ 1: {'a4':{10: 345, 11: 360, 12: 390},
+        'a5':{10: 276, 11: 276, 12: 276},
+        'b5':{10: 345, 11: 356, 12: 356},
+        'letter':{10: 345, 11: 360, 12: 390},
+        'legal': {10: 345, 11: 360, 12: 390},
+        'executive':{10: 345, 11: 360, 12: 379}},
+ 2: {'a4':{10: 167, 11: 175, 12: 190},
+        'a5':{10: 133, 11: 133, 12: 133},
+        'b5':{10: 167, 11: 173, 12: 173},
+        'letter':{10: 167, 11: 175, 12: 190},
+        'legal':{10: 167, 11: 175, 12: 190},
+        'executive':{10: 167, 11: 175, 12: 184}}}
+
+texi_linewidths = {
+       'a4': {12: 455},
+       'a4wide': {12: 470},
+       'smallbook': {12: 361},
+       'texidefault': {12: 433}}
+
+
+def get_linewidth(cols, paper, fontsize):
+       if __main__.format == 'latex':
+               return latex_linewidths[cols][paper][fontsize]
+       elif __main__.format == 'texi':
+               return texi_linewidths[paper][fontsize]
+       raise "never here"
+
+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-mudela-fontsize', 'deprecated, use --default-music-fontsize'),
+  ('DIM', '', 'force-music-fontsize', 'force fontsize for all inline mudela. DIM is assumed be to in points'),
+  ('DIM', '', 'force-mudela-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'),
+  ]
+
+# format specific strings, ie. regex-es for input, and % strings for output
+output_dict= {
+       'latex': {
+               'output-mudela-fragment' : r"""\begin[eps,singleline,%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{%(fn)s.eps}}{\includegraphics{%(fn)s.eps}}',
+               'output-tex': '\\preMudelaExample \\input %(fn)s.tex \\postMudelaExample\n',
+               'pagebreak': r'\pagebreak',
+               },
+       'texi' : {'output-mudela': """@mudela[%s]
+%s
+@end mudela 
+""",
+                 'output-mudela-fragment': """@mudela[%s]
+\context Staff\context Voice{ %s }
+@end mudela """,
+                 'pagebreak': None,
+                 'output-verbatim': r"""@example
+%s
+@end example
+""",
+
+# do some tweaking: @ is needed in some ps stuff.
+# override EndLilyPondOutput, since @tex is done
+# in a sandbox, you can't do \input lilyponddefs at the
+# top of the document.
+
+# should also support fragment in
+                 
+                 'output-all': r"""@tex
+\catcode`\@=12
+\input lilyponddefs
+\def\EndLilyPondOutput{}
+\input %(fn)s.tex
+\catcode`\@=0
+@end tex
+@html
+<p>
+<img src=%(fn)s.png>
+@end html
+""",
+               }
+       }
+
+def output_verbatim (body):#ugh .format
+       if __main__.format == 'texi':
+               body = re.sub ('([@{}])', '@\\1', body)
+       return get_output ('output-verbatim') % body
+
+def output_mbverbatim (body):#ugh .format
+       if __main__.format == 'texi':
+               body = re.sub ('([@{}])', '@\\1', body)
+       return get_output ('output-verbatim') % body
+
+re_dict = {
+       'latex': {'input': '\\\\mbinput{?([^}\t \n}]*)',
+                 'include': '\\\\mbinclude{(?P<filename>[^}]+)}',
+                
+                 'option-sep' : ', *',
+                 'header': r"""\\documentclass(\[.*?\])?""",
+                 'preamble-end': '\\\\begin{document}',
+                 'verbatim': r"""(?s)(?P<code>\\begin{verbatim}.*?\\end{verbatim})""",
+                 'verb': r"""(?P<code>\\verb(?P<del>.).*?(?P=del))""",
+                 'mudela-file': r'\\mudelafile(\[(?P<options>.*?)\])?\{(?P<filename>.+)}',
+                 'mudela' : '(?m)\\\\mudela(\[(?P<options>.*?)\])?{(?P<code>.*?)}',
+                 #'mudela-block': r"""(?m)^[^%]*?\\begin(\[(?P<options>.*?)\])?{mudela}(?P<code>.*?)\\end{mudela}""",
+                 'mudela-block': r"""(?s)\\begin(\[(?P<options>.*?)\])?{mudela}(?P<code>.*?)\\end{mudela}""",
+                 'def-post-re': r"""\\def\\postMudelaExample""",
+                 'def-pre-re': r"""\\def\\preMudelaExample""",           
+                 'intertext': r',?\s*intertext=\".*?\"',
+                 'ignore': r"(?m)(?P<code>%.*?^)",
+                 'numcols': r"(?P<code>\\(?P<num>one|two)column)",
+                 },
+       
+       'texi': {
+                'include':  '@mbinclude[ \n\t]+(?P<filename>[^\t \n]*)',
+                'input': no_match,
+                'header': no_match,
+                'preamble-end': no_match,
+                'verbatim': r"""(?s)(?P<code>@example\s.*?@end example\s)""",
+                'verb': r"""(?P<code>@code{.*?})""",
+                'mudela-file': '@mudelafile(\[(?P<options>.*?)\])?{(?P<filename>[^}]+)}',
+                'mudela' : '@mudela(\[(?P<options>.*?)\])?{(?P<code>.*?)}',
+                'mudela-block': r"""(?s)@mudela(\[(?P<options>.*?)\])?\s(?P<code>.*?)@end mudela\s""",
+                 'option-sep' : ', *',
+                 'intertext': r',?\s*intertext=\".*?\"',
+                 'ignore': r"(?s)(?P<code>@ignore\s.*?@end ignore)\s",
+                 'numcols': no_match,
+                }
+       }
+
+
+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 uniq (list):
+       list.sort ()
+       s = list
+       list = []
+       for x in s:
+               if x not in list:
+                       list.append (x)
+       return list
+               
 
-outdir = 'out'
-initfile = ''
-program_version = '0.5.6'
-include_path = ['.']
-
-out_files = []
-
-fontsize_i2a = {11:'eleven', 13:'thirteen', 16:'sixteen',
-                20:'twenty', 26:'twentysix'}
-fontsize_pt2i = {'11pt':11, '13pt':13, '16pt':16, '20pt':20, '26pt':26}
-
-# perhaps we can do without this?
-
-begin_mudela_re = re.compile ('^ *\\\\begin{mudela}')
-begin_verbatim_re = re.compile ('^ *\\\\begin{verbatim}')
-end_verbatim_re = re.compile ('^ *\\\\end{verbatim}')
-extract_papersize_re = re.compile('\\\\documentclass[\[, ]*(\w*)paper[\w ,]*\]\{\w*\}')
-extract_fontsize_re = re.compile('[ ,\[]*([0-9]*)pt')
-begin_mudela_opts_re = re.compile('\[[^\]]*\]')
-end_mudela_re = re.compile ('^ *\\\\end{mudela}')
-section_re = re.compile ('\\\\section')
-chapter_re = re.compile ('\\\\chapter')
-input_re = re.compile ('^\\\\input{([^}]*)')
-include_re = re.compile ('^\\\\include{([^}]*)')
-begin_document_re = re.compile ('^ *\\\\begin{document}')
-documentclass_re = re.compile('\\\\documentclass')
-twocolumn_re = re.compile('\\\\twocolumn')
-onecolumn_re = re.compile('\\\\onecolumn')
-mudela_file_re = re.compile('\\\\mudelafile{([^}]+)}')
-file_ext_re = re.compile('.+\\.([^.}]+$)')
-preMudelaExample_re = re.compile('^\s*\\\\def\\\\preMudelaExample')
-postMudelaExample_re = re.compile('^\s*\\\\def\\\\postMudelaExample')
-boundingBox_re = re.compile('%%BoundingBox: ([0-9]+) ([0-9]+) ([0-9]+) ([0-9]+)')
-intertext_re = re.compile("intertext=\"([^\"]*)\"")
-
-def file_exist_b(name):
-    try: 
-       f = open(name)
-    except IOError:
-       return 0
-    f.close ()
-    return 1
-
-def ps_dimention(fname):
-    fd = open(fname)
-    lines = fd.readlines()
-    for line in lines:
-        s = boundingBox_re.search(line)
-        if s:
-            break
-    return (int(s.groups()[2])-int(s.groups()[0]), 
-            int(s.groups()[3])-int(s.groups()[1]))
+def get_output (name):
+       return  output_dict[format][name]
 
+def get_re (name):
+       return  re_dict[format][name]
 
-def find_file (name):
-    for a in include_path:
+def bounding_box_dimensions(fname):
        try:
-           nm = os.path.join (a, name)
-           f = open (nm)
-           return nm
+               fd = open(fname)
        except IOError:
-           pass
-    return ''
+               error ("Error opening `%s'" % fname)
+       str = fd.read ()
+       s = re.search('%%BoundingBox: ([0-9]+) ([0-9]+) ([0-9]+) ([0-9]+)', str)
+       if s:
+               return (int(s.group(3))-int(s.group(1)), 
+                       int(s.group(4))-int(s.group(2)))
+       else:
+               return (0,0)
+
+
+def error (str):
+       sys.stderr.write (str + "\n  Exiting ... \n\n")
+       raise 'Exiting.'
+
+
+def compose_full_body (body, opts):
+       """Construct the mudela code to send to Lilypond.
+       Add stuff to BODY using OPTS as options."""
+       if __main__.format == 'texi':
+               paper = 'texidefault'
+       else:
+               paper = 'letter' # yes, latex use letter as default, at least
+                                # my tetex distro
+       music_size = default_music_fontsize
+       latex_size = default_text_fontsize
+       for o in opts:
+               m = re.search ('^(.*)paper$', o)
+               if m:
+                       paper = m.group (1)
+               
+               if g_force_mudela_fontsize:
+                       music_size = g_force_mudela_fontsize
+               else:
+                       m = re.match ('([0-9]+)pt', o)
+                       if m:
+                               music_size = string.atoi(m.group (1))
+
+               m = re.match ('latexfontsize=([0-9]+)pt', o)
+               if m:
+                       latex_size = string.atoi (m.group (1))
+
+       if re.search ('\\\\score', body):
+               is_fragment = 0
+       else:
+               is_fragment = 1
+       if 'fragment' in opts:
+               is_fragment = 1
+       if 'nonfragment' in opts:
+               is_fragment = 0
+
+       if is_fragment and not 'multiline' in opts:
+               opts.append('singleline')
+       if 'singleline' in opts:
+               l = -1.0;
+       else:
+               l = get_linewidth(g_num_cols, paper, latex_size)
+       
+       if 'relative' in opts:#ugh only when is_fragment
+               body = '\\relative c { %s }' % body
+       
+       if is_fragment:
+               body = r"""\score { 
+ \notes { %s }
+  \paper { }  
+}""" % body
+
+       opts = uniq (opts)
+       optstring = string.join (opts, ' ')
+       optstring = re.sub ('\n', ' ', optstring)
+       
+       body = r"""
+%% Generated by mudela-book.py; options are %s  %%ughUGH not original options
+\include "paper%d.ly"
+\paper  { linewidth = %f \pt; } 
+""" % (optstring, music_size, l) + body
+       return body
+
+
+def scan_preamble (str):
+       options = []
+       if __main__.format == 'texi':
+               x = 250
+               if string.find(str[:x], "@afourpaper") != -1:
+                       options = ['a4paper']
+               elif string.find(str[:x], "@afourwide") != -1:
+                       options = ['a4widepaper']
+               elif string.find(str[:x], "@smallbook") != -1:
+                       options = ['smallbookpaper']
+       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 re.match('[0-9]+pt', x):
+                       return 'latexfontsize=' + x
+               else:
+                       return x 
+                       
+       options = map (verbose_fontsize, options)
+       return options
+
+
+def completize_preamble (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 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')
 
+       # UGH ! BUG!
+       #if  re.search ('\\\\includegraphics', str) and not re.search ('usepackage{graphics}',str):
 
-class CompileStatus:
-    pass
-class SomethingIsSeriouslyBroken:
-    pass
+       preamble = preamble + '\\usepackage{graphics}\n'
 
-def file_mtime (name):
-    return os.stat (name)[8] #mod time
+       return preamble + str
 
-def need_recompile_b(infile, outfile):
-    indate = file_mtime (infile)
-    try:
-        outdate = file_mtime (outfile)
-        return indate > outdate
-    except os.error:
-        return 1
 
-#
-# executes os.system(command) if infile is newer than
-# outfile or outfile don't exist
-#
-def compile (command, workingdir, infile, outfile):
-    "Test if infile is newer than outfile. If so, cd to workingdir"
-    "and execute command"
-    indate = file_mtime (workingdir+infile)
-    try:
-        outdate = file_mtime (workingdir+outfile)
-        recompile = indate > outdate
-
-    except os.error:
-        recompile = 1
-
-    if recompile:
-        sys.stderr.write ('invoking `%s\'\n' % command)
-        if workingdir == '':
-            status = os.system (command)
-        else:
-            status = os.system ('cd %s; %s' %(workingdir, command))
-        if status:
-            raise CompileStatus
-
-class Properties:
-    #
-    # init
-    #
-    def __init__(self):
-        self.__linewidth = {
-            1: {'a4':{10: 345, 11: 360, 12: 390},
-                'a5':{10: 276, 11: 276, 12: 276},
-                'b5':{10: 345, 11: 356, 12: 356},
-                'letter':{10: 345, 11: 360, 12: 390},
-                'legal': {10: 345, 11: 360, 12: 390},
-                'executive':{10: 345, 11: 360, 12: 379}},
-            2: {'a4':{10: 167, 11: 175, 12: 190},
-                'a5':{10: 133, 11: 133, 12: 133},
-                'b5':{10: 167, 11: 173, 12: 173},
-                'letter':{10: 167, 11: 175, 12: 190},
-                'legal':{10: 167, 11: 175, 12: 190},
-                'executive':{10: 167, 11: 175, 12: 184}}}
-        # >0 --> force all mudela to this pt size
-        self.force_mudela_fontsize = 0
-        self.force_verbatim_b = 0
-        self.__data = {
-            'mudela-fontsize' : {'init': 16},
-            'papersize' : {'init': 'a4'},
-            'num-column' : {'init': 1},
-            'tex-fontsize' : {'init': 10}
-            }
-    def clear_for_new_file(self):
-        for var in self.__data.keys():
-            self.__data[var] = {'init': self.__data[var]['init']}
-    def clear_for_new_block(self):
-        for var in self.__data.keys():
-            if self.__data[var].has_key('block'):
-                del self.__data[var]['block']
-    def __get_variable(self, var):
-        if self.__data[var].has_key('block'):
-            return self.__data[var]['block']
-        elif self.__data[var].has_key('file'):
-            return self.__data[var]['file']
-        else:
-            return self.__data[var]['init']
-    def setPapersize(self, size, requester):
-        self.__data['papersize'][requester] = size
-    def getPapersize(self):
-        return self.__get_variable('papersize')
-    def setMudelaFontsize(self, size, requester):
-        self.__data['mudela-fontsize'][requester] = size
-    def getMudelaFontsize(self):
-        if self.force_mudela_fontsize:
-            return self.force_mudela_fontsize
-        return self.__get_variable('mudela-fontsize')
-    def setTexFontsize(self, size, requester):
-        self.__data['tex-fontsize'][requester] = size
-    def getTexFontsize(self):
-        return self.__get_variable('tex-fontsize')
-    def setNumColumn(self, num, requester):
-        self.__data['num-column'][requester] = num
-    def getNumColumn(self):
-        return self.__get_variable('num-column')
-    def getLineWidth(self):
-        return self.__linewidth[self.getNumColumn()][self.getPapersize()][self.getTexFontsize()]
-
-
-class Mudela_output:
-    """ Using only self.code_type to deside both value of linewith and
-    if we have to put code into \score{...} was silly. Now we use:
-    self.code_type:  show us what need to be added.
-                        None : init value
-                        'NOTES' : add \context Voice{ ... }
-                        'CONTEXT' : add \score{ ... }
-                        'COMPLETE' : jupp
-    self.single_line_b:   0 : linewidth=-1  1: linewith=textwidth
-    """
-    def __init__ (self, basename):
-        self.basename = basename
-        self.temp_filename = "%s/%s" %(outdir, 'mudela-temp.ly')
-        self.file = open (self.temp_filename, 'w')
-        self.__lines = []
-        # 'tex' or 'eps'
-        self.graphic_type = 'tex'
-        self.code_type = None
-        self.single_line_b = 1
-        self.optlist = []
-    def write (self, line):
-        # match only if there is nothing but whitespace before \begin.
-        # we should not have to do this RE for every line
-        if re.search('^\s*\\\\begin{mudela}', line):
-            r  = begin_mudela_opts_re.search(line)
-            if r:
-                o = r.group()[1:-1]
-                self.optlist =  re.compile('[\s,]*').split(o)
-            else:
-                self.optlist = []
-        else: # ugh this is NOT bulletproof...
-            if not self.code_type:
-                if re.search('^\s*%', line) or re.search('^\s*$', line):
-                    pass
-                elif re.search('^\s*\\\\context', line):
-                    self.code_type = 'CONTEXT'
-                    self.single_line_b = 0
-                elif re.search('^\s*\\\\score', line) or \
-                     re.search('^\s*\\\\paper', line) or \
-                     re.search('^\s*\\\\header', line) or \
-                     re.search('^\s*\\\\version', line) or \
-                     re.search('^\s*\\\\include', line) or \
-                     re.search('^\s*[A-Za-z]*\s*=', line):
-                    self.code_type = 'COMPLETE'
-                    self.single_line_b = 0
+read_files = []
+def find_file (name):
+       f = None
+       for a in include_path:
+               try:
+                       nm = os.path.join (a, name)
+                       f = open (nm)
+                       __main__.read_files.append (nm)
+                       break
+               except IOError:
+                       pass
+       if f:
+               return f.read ()
+       else:
+               error ("File not found `%s'\n" % name)
+               return ''
+
+def do_ignore(match_object):
+       return [('ignore', match_object.group('code'))]
+
+def make_verbatim(match_object):
+       return [('verbatim', match_object.group('code'))]
+
+def make_verb(match_object):
+       return [('verb', match_object.group('code'))]
+
+def do_include_file(m):
+       "m: MatchObject"
+       return [('input', get_output ('pagebreak'))] \
+            + read_doc_file(m.group('filename')) \
+            + [('input', get_output ('pagebreak'))] 
+
+def do_input_file(m):
+       return read_doc_file(m.group('filename'))
+
+def make_mudela(m):
+       if m.group('options'):
+               options = m.group('options')
+       else:
+               options = ''
+       return [('input', get_output('output-mudela-fragment') % 
+                       (options, m.group('code')))]
+
+def make_mudela_file(m):
+       if m.group('options'):
+               options = m.group('options')
+       else:
+               options = ''
+       return [('input', get_output('output-mudela') %
+                       (options, find_file(m.group('filename'))))]
+
+def make_mudela_block(m):
+       if m.group('options'):
+               options = get_re('option-sep').split (m.group('options'))
+       else:
+           options = []
+       options = filter(lambda s: s != '', options)
+       if 'mbverbatim' in options:#ugh this is ugly and only for texi format
+               s  = m.group()
+               im = get_re('intertext').search(s)
+               if im:
+                       s = s[:im.start()] + s[im.end():]
+               im = re.search('mbverbatim', s)
+               if im:
+                       s = s[:im.start()] + s[im.end():]
+               if s[:9] == "@mudela[]":
+                       s = "@mudela" + s[9:]
+               return [('mudela', m.group('code'), options, s)]
+       return [('mudela', m.group('code'), options)]
+
+def do_columns(m):
+       if __main__.format != 'latex':
+               return []
+       if m.group('num') == 'one':
+               return [('numcols', m.group('code'), 1)]
+       if m.group('num') == 'two':
+               return [('numcols', m.group('code'), 2)]
+       
+def chop_chunks(chunks, re_name, func):
+    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:
-                    self.code_type = 'NOTES'
-                    self.single_line_b = 1
-            self.__lines.append(line)
-    def write_red_tape(self):
-        if 'eps' in self.optlist:
-            self.graphic_type = 'eps'
-            #self.single_line_b = 1
-        if 'fragment' in self.optlist:
-            self.code_type = 'NOTES'
-        if 'nonfragment' in self.optlist:
-            self.code_type = 'COMPLETE'
-        if 'multiline' in self.optlist:
-            self.single_line_b = 0
-        for pt in fontsize_pt2i.keys():
-            if pt in self.optlist:
-                Props.setMudelaFontsize(fontsize_pt2i[pt], 'block')
-        self.file.write ('\\include \"paper%d.ly\"\n' \
-                         % Props.getMudelaFontsize())
-                         
-        s = fontsize_i2a[Props.getMudelaFontsize()]
-        if 'singleline' in self.optlist:
-            self.single_line_b = 1
-        if self.single_line_b:
-            linewidth_str = 'linewidth = -1.\cm;'
-        else:
-            linewidth_str = 'linewidth = %i.\\pt;' % Props.getLineWidth()
-        self.file.write("\\paper {"
-                        + "\\paper_%s " % s
-                        + linewidth_str
-                        + "castingalgorithm = \Gourlay; \n}")
-                        #+ "castingalgorithm = \Wordwrap; indent = 2.\cm; \n}")
-        if self.code_type == 'CONTEXT':
-            self.file.write('\\score{\n\\notes\\relative c{')
-        if self.code_type == 'NOTES' :
-            self.file.write('\\score{\n\\notes\\relative c{\\context Voice{')
-    def close (self):
-        self.write_red_tape()
-        for l in self.__lines:
-            self.file.write(l)
-        if self.code_type == 'CONTEXT':
-            self.file.write('}}')
-        elif self.code_type == 'NOTES':
-            self.file.write('}}}')
-        self.file.close()
-
-        inf = outdir + self.basename + '.ly'
-        outf = outdir + self.basename + '.tex'
-        if not os.path.isfile(inf):
-            status = 1
-        else:
-            status = os.system ('diff -q %s %s' % (self.temp_filename, inf))
-        if status:
-            os.rename (self.temp_filename, inf)
-
-       recompile_b =  need_recompile_b(inf, outf)
-       if recompile_b:
-            out_files.append((self.graphic_type, inf))
-       return recompile_b
-
-    def insert_me_string(self):
-        "ugh the name of this function is wrong"
-        if self.graphic_type == 'tex':
-            return ['tex', self.basename]
-        elif self.graphic_type == 'eps':
-            return ['eps', self.basename]
+                    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:
-            raise SomethingIsSeriouslyBroken
-
-class Tex_output:
-    def __init__ (self, name):
-        self.output_fn = '%s/%s' % (outdir, name)
-        self.__lines = []
-    def open_verbatim (self, line, level):
-        self.__lines.append('\\begin{verbatim}\n')
-        if level == 2:
-            s = re.sub('veryverbatim[\s,]*', '', line)
-            s = re.sub('intertext=\"([^\"]*)\"[\s,]*', '', s)
-            s = re.sub(',\s*\]', ']', s)
-            s = re.sub('\[\]', '', s)
-            self.__lines.append(s);
-    def close_verbatim (self):
-        self.__lines.append('\\end{verbatim}\n')
-    def write (self, s):
-        self.__lines.append(s)
-    def create_graphics(self):
-        s = ''
-        g_vec = []
-        for line in self.__lines:
-            if type(line)==type([]):
-                g_vec.append(line)
-        for g in g_vec:
-            if need_recompile_b(outdir+g[1]+'.ly', outdir+g[1]+'.tex'):
-                    s = s + ' ' + g[1]+'.ly'
-        if s != '':
-            e = os.system('cd %s; lilypond %s' %(outdir, s))
-            if e:
-                sys.stderr.write("error: lilypond exited with value %i\n" % e)
-                sys.exit(e)
-        for g in g_vec:
-            if g[0] == 'eps':
-                compile('tex %s' % g[1]+'.tex', outdir, g[1]+'.tex', g[1]+'.dvi')
-                compile('dvips -E -o %s %s' %(g[1]+'.eps', g[1]+'.dvi'), outdir,
-                        g[1]+'.dvi', g[1]+'.eps')
-    def write_outfile(self):
-        file = open(self.output_fn+'.latex', 'w')
-        file.write('% Created by mudela-book\n')
-        last_line = None
-        for line in self.__lines:
-            if type(line)==type([]):
-                if last_line == '\n':
-                    file.write(r'\vspace{0.5cm}')
-                if line[0] == 'tex':                    
-                    file.write('\\preMudelaExample \\input %s \\postMudelaExample\n'\
-                               % (line[1]+'.tex'))
-                if line[0] == 'eps':
-                    ps_dim = ps_dimention(outdir+line[1]+'.eps')
-                    file.write('\\noindent\\parbox{%ipt}{\includegraphics{%s}}\n' \
-                               % (ps_dim[0], line[1]+'.eps'))
-            else:
-                file.write(line)
-            if type(last_line)==type([]):
-                if line=='\n':
-                    file.write(r'\vspace{0.5cm}')
-            last_line = line
-        file.close()
-
-# given parameter s="\mudela[some options]{CODE} some text and commands"
-# it returns a tuple:
-#    (CODE, integer)
-# where the last number is the index of the ending '}'
-def extract_command(s):
-    start_found_b = 0
-    count = 0
-    start = 0
-    for idx in range(len(s)):
-        if s[idx] == '{':
-            if not start_found_b:
-                start = idx
-                start_found_b = 1
-            count = count + 1
-        if s[idx] == '}':
-            count = count - 1
-        if (start_found_b == 1) and (count == 0):
-            break
-    return s[start+1:idx], idx
-
-class Tex_input:
-    def __init__ (self, filename):
-        for fn in [filename, filename+'.tex', filename+'.doc']:
-            try:
-                self.infile = open (fn)
-                self.filename = fn
-                return
-            except:
-                continue
-        raise IOError
-
-    def get_lines (self):
-        lines = self.infile.readlines ()
-        (retlines, retdeps) = ([],[self.filename])
-        for line in lines:
-            r_inp = input_re.search (line)
-            r_inc = include_re.search (line)
-
-            # Filename rules for \input :
-            # input: no .tex ext
-            # 1. will search for file with exact that name (tex-input.my will be found)
-            # 2. will search for file with .tex ext, (tex-input.my
-            #    will find tex-input.my.tex)
-            # input: with .tex ext
-            # 1. will find exact match
-            
-            # Filename rules for \include :
-            # 1. will only find files with name given to \include + .tex ext
-            if r_inp:
-                try:
-                    t = Tex_input (r_inp.groups()[0])
-                    ls = t.get_lines ()
-                    retlines = retlines + ls[0]
-                    retdeps = retdeps + ls[1]
-                except:
-                    sys.stderr.write("warning: can't find %s, let's hope latex will\n" % r_inp.groups()[0])
-                    retlines.append (line)
-            elif r_inc:
-                try:
-                    t = Tex_input (r_inc.groups()[0]+'.tex')
-                    ls =t.get_lines ()
-                    ls[0].insert(0, '\\newpage\n')
-                    ls[0].append('\\newpage\n')
-                    retlines = retlines + ls[0]
-                    retdeps = retdeps + ls[1]
-                except:
-                    sys.stderr.write("warning: can't find %s, let's hope latex will" % r_inc.groups()[0])
-                    retlines.append (line)
-            else:
-                # This code should be rewritten, it looks terrible
-                r_mud = defined_mudela_cmd_re.search(line)
-                if r_mud:
-                   # TODO document this
-                    ss = "\\\\verb(?P<xx>[^a-zA-Z])\s*\\\\%s\s*(?P=xx)" \
-                         % re.escape(r_mud.group()[1:])
-                    # just append the line if the command is inside \verb|..|
-                    if re.search(ss, line):
-                        retlines.append(line)
-                        continue
-                    while 1:
-                        opts = r_mud.groups()[2]
-                        cmd_start_idx = r_mud.span()[0]
-                        if cmd_start_idx > 0:
-                            retlines.append(line[:cmd_start_idx])
-                            
-                        cmd_data, rest_idx = extract_command(line[cmd_start_idx:])
-                        rest_idx = rest_idx + cmd_start_idx + 1
-                        if opts == None:
-                            opts = ''
-                        else:
-                            opts = ', '+opts
-                        
-                        v = string.split(defined_mudela_cmd[r_mud.groups()[0]], '\n')
-                        for l in v[1:-1]:
-                            l = string.replace(l, '\\fontoptions', opts)
-                            l = string.replace(l, '\\maininput', cmd_data)
-                            retlines.append(l)
-                        r_mud = defined_mudela_cmd_re.search(line[rest_idx:])
-                        if not r_mud:
-                            rs = line[rest_idx:]
-                            while rs[0] == " ":
-                                rs = rs[1:]
-                            if rs != "\n":
-                                retlines.append(line[rest_idx:])
-                            break;
-                        line = line[rest_idx:]
-                else:
-                    retlines.append (line)
-        return (retlines, retdeps)
-
-
-class Main_tex_input(Tex_input):
-    def __init__ (self, name, outname):
-
-        Tex_input.__init__ (self, name) # ugh
-        self.outname = outname
-        self.chapter = 0
-        self.section = 0
-        self.fine_count =0
-        self.mudtex = Tex_output (self.outname)
-        self.mudela = None
-        self.deps = []
-        self.verbatim = 0
-        # set to 'mudela' when we are processing mudela code,
-        # both verbatim and graphic-to-be
-        self.mode = 'latex'
-    def set_sections (self, l):
-        if section_re.search (l):
-            self.section = self.section + 1
-        if chapter_re.search (l):
-            self.section = 0
-            self.chapter = self.chapter + 1
-
-    def gen_basename (self):
-        return '%s-%d.%d.%d' % (self.outname, self.chapter,
-                                self.section, self.fine_count)
-    def extract_papersize_from_documentclass(self, line):
-        pre = extract_papersize_re.search(line)
-        if not pre:
-            return None
-        return pre.groups()[0]
-    def extract_fontsize_from_documentclass(self, line):
-        r = extract_fontsize_re.search(line)
-        if r:
-            return int(r.groups()[0])
-    def do_it(self):
-        preMudelaDef = postMudelaDef = 0
-        (lines, self.deps) = self.get_lines ()
-        #HACK
-        latex_verbatim = 0
-        for line in lines:
-            if documentclass_re.search (line):
-                p = self.extract_papersize_from_documentclass (line)
-                if p:
-                    Props.setPapersize(p, 'file')
-                f = self.extract_fontsize_from_documentclass (line)
-                if f:
-                    Props.setTexFontsize (f, 'file')
-            elif twocolumn_re.search (line):
-                Props.setNumColumn (2, 'file')
-            elif onecolumn_re.search (line):
-                Props.setNumColumn (1, 'file')
-            elif preMudelaExample_re.search (line):
-                preMudelaDef = 1
-            elif postMudelaExample_re.search (line):
-                postMudelaDef = 1
-            elif begin_verbatim_re.search (line):
-                latex_verbatim = 1
-            elif end_verbatim_re.search (line):
-                latex_verbatim = 0
-            elif begin_document_re.search (line):
-                if not preMudelaDef:
-                    self.mudtex.write ('\\def\\preMudelaExample{}\n')
-                if not postMudelaDef:
-                    self.mudtex.write ('\\def\\postMudelaExample{}\n')
-
-            elif mudela_file_re.search(line):
-               r = mudela_file_re.search(line)
-
-               self.mudela = Mudela_output(self.gen_basename())
-               fn = r.group (1)
-               full_path = find_file (fn)
-               if not full_path:
-                   sys.stderr.write("error: can't find file '%s'\n" % fn)
-                   sys.exit (1)
-
-               f = open (full_path, 'r')
-               lines =f.readlines ()
-               self.mudela.write ('%% This is a copy of file %s\n' % full_path)
-               for x in lines:
-                   self.mudela.write (x)
-               r = file_ext_re.search(fn)
-                if r:
-                    if r.group(1) == 'fly':
-                        self.mudela.optlist.append('multiline')
-               stat =self.mudela.close ()
-               if stat:
-                       sys.stdout.write("(File %s needs recompiling)\n" % full_path)
-                self.mudtex.write (self.mudela.insert_me_string())
-               self.deps.append (full_path)
-               del self.mudela
-                self.mudela = None
-                self.fine_count = self.fine_count + 1
-               continue
-            elif begin_mudela_re.search (line) and not latex_verbatim:
-                Props.clear_for_new_block()
-                if __debug__:
-                    if self.mode == 'mudela':
-                        raise AssertionError
-                self.mode = 'mudela'
-                r  = begin_mudela_opts_re.search (line)
-                if r:
-                    o = r.group()[1:][:-1]
-                    optlist =  re.compile('[ ,]*').split(o)
-                    m = intertext_re.search(r.group())
-                    if m:
-                        self.intertext = m.groups()[0]
-                    else:
-                        self.intertext = None
-                else:
-                    optlist = []
-                if ('veryverbatim' in optlist):
-                    self.verbatim = 2
-                elif ('verbatim' in optlist) or (Props.force_verbatim_b):
-                    self.verbatim = 1
-                else:
-                    self.verbatim = 0
-                if self.verbatim:
-                    self.mudtex.open_verbatim (line, self.verbatim)
-                self.mudela = Mudela_output (self.gen_basename ())
-                self.mudela.write (line)
-                continue
-            elif end_mudela_re.search (line) and not latex_verbatim:
-                if __debug__:
-                    if self.mode != 'mudela':
-                        raise AssertionError
-
-                if self.verbatim:
-                    if self.verbatim == 2:
-                        self.mudtex.write (line)
-                    self.mudtex.close_verbatim ()
-                self.mudela.close ()
-                if self.verbatim and self.intertext:
-                    self.mudtex.write(self.intertext)
-                self.mudtex.write (self.mudela.insert_me_string())
-                del self.mudela
-                self.mudela = None
-                self.fine_count = self.fine_count + 1
-                self.mode = 'latex'
-                continue
-
-
-            if self.mode == 'mudela':
-                self.mudela.write (line)
-                if self.verbatim:
-                    self.mudtex.write (line)
-            else:
-                self.mudtex.write (line)
-                self.set_sections(line)
-        self.mudtex.create_graphics()
-        self.mudtex.write_outfile()
-        del self.mudtex
+            newchunks.append(c)
+    return newchunks
+
+def read_doc_file (filename):
+       """Read the input file, find verbatim chunks and do \input and \include
+       """
+       str = ''
+       str = find_file(filename)
+
+       if __main__.format == '':
+               latex =  re.search ('\\\\document', str[:200])
+               texinfo =  re.search ('@node|@setfilename', 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 = [('input', str)]
+       # we have to check for verbatim before doing include,
+       # 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)
+       #ugh fix input
+       chunks = chop_chunks(chunks, 'include', do_include_file)
+       chunks = chop_chunks(chunks, 'input', do_input_file)
+       return chunks
+
+
+taken_file_names = {}
+def schedule_mudela_block (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, BASE)
+
+       TODO has format [basename, extension, extension, ... ]
+       
+       """
+       if len(chunk) == 3:
+               (type, body, opts) = chunk
+               complete_body = None
+       else:# mbverbatim
+               (type, body, opts, complete_body) = chunk
+       assert type == 'mudela'
+       opts = opts +  extra_opts
+       file_body = compose_full_body (body, opts)
+       basename = `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
+                       else:
+                           taken_file_names[basename] = taken_file_names[basename] + 1
+                           basename = basename + "-%i" % taken_file_names[basename]
+       # writes the file if necessary, returns true if it was written
+       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 'eps' in opts and not ('eps' in needed_filetypes):
+               needed_filetypes.append('eps')
+       outname = os.path.join(g_outdir, basename)
+       if not os.path.isfile(outname + '.tex') \
+               or os.stat(outname+'.ly')[stat.ST_MTIME] > \
+                       os.stat(outname+'.tex')[stat.ST_MTIME]:
+               todo = needed_filetypes
+       else:
+               todo = []
                
+       newbody = ''
+       if 'verbatim' in opts:
+               newbody = output_verbatim (body)
+       elif 'mbverbatim' in opts:
+               newbody = output_mbverbatim (complete_body)
+
+       for o in opts:
+               m = re.search ('intertext="(.*?)"', o)
+               if m:
+                       newbody = newbody  + m.group (1)
+       if format == 'latex':
+               if 'eps' in opts:
+                       s = 'output-eps'
+               else:
+                       s = 'output-tex'
+       else: # format == 'texi'
+               s = 'output-all'
+       newbody = newbody + get_output(s) % {'fn': basename }
+       return ('mudela', newbody, opts, todo, basename)
+
+def process_mudela_blocks(outname, chunks, global_options):#ugh rename
+       newchunks = []
+       # Count sections/chapters.
+       for c in chunks:
+               if c[0] == 'mudela':
+                       c = schedule_mudela_block (c, global_options)
+               elif c[0] == 'numcols':
+                       __main__.g_num_cols = c[2]
+               newchunks.append (c)
+       return 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]
+
+
+def system (cmd):
+       sys.stderr.write ("invoking `%s'\n" % cmd)
+       st = os.system (cmd)
+       if st:
+               error ('Error command exited with value %d\n' % st)
+       return st
+
+def compile_all_files (chunks):
+       eps = []
+       tex = []
+       png = []
+
+       for c in chunks:
+               if c[0] <> 'mudela':
+                       continue
+               base  = c[4]
+               exts = c[3]
+               for e in exts:
+                       if e == 'eps':
+                               eps.append (base)
+                       elif e == 'tex':
+                               tex.append (base + '.ly')
+                       elif e == 'png' and g_do_pictures:
+                               png.append (base)
+       d = os.getcwd()
+       if g_outdir:
+               os.chdir(g_outdir)
+       if tex:
+               lilyopts = map (lambda x:  '-I ' + x, include_path)
+               lilyopts = string.join (lilyopts, ' ' )
+               texfiles = string.join (tex, ' ')
+               system ('lilypond %s %s' % (lilyopts, texfiles))
+       for e in eps:
+               system(r"tex '\nonstopmode \input %s'" % e)
+               system(r"dvips -E -o %s %s" % (e + '.eps', e))
+       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')
+               system (cmd)
+       if g_outdir:
+               os.chdir(d)
+
+
+def update_file (body, name):
+       """
+       write the body if it has changed
+       """
+       same = 0
+       try:
+               f = open (name)
+               fs = f.read (-1)
+               same = (fs == body)
+       except:
+               pass
+
+       if not same:
+               f = open (name , 'w')
+               f.write (body)
+               f.close ()
+       
+       return not same
+
+
+def getopt_args (opts):
+       "Construct arguments (LONG, SHORT) for getopt from  list of options."
+       short = ''
+       long = []
+       for o in opts:
+               if o[1]:
+                       short = short + o[1]
+                       if o[0]:
+                               short = short + ':'
+               if o[2]:
+                       l = o[2]
+                       if o[0]:
+                               l = l + '='
+                       long.append (l)
+       return (short, long)
+
+def option_help_str (o):
+       "Transform one option description (4-tuple ) into neatly formatted string"
+       sh = '  '       
+       if o[1]:
+               sh = '-%s' % o[1]
+
+       sep = ' '
+       if o[1] and o[2]:
+               sep = ','
+               
+       long = ''
+       if o[2]:
+               long= '--%s' % o[2]
+
+       arg = ''
+       if o[0]:
+               if o[2]:
+                       arg = '='
+               arg = arg + o[0]
+       return '  ' + sh + sep + long + arg
+
+
+def options_help_str (opts):
+       "Convert a list of options into a neatly formatted string"
+       w = 0
+       strs =[]
+       helps = []
+
+       for o in opts:
+               s = option_help_str (o)
+               strs.append ((s, o[3]))
+               if len (s) > w:
+                       w = len (s)
+
+       str = ''
+       for s in strs:
+               str = str + '%s%s%s\n' % (s[0], ' ' * (w - len(s[0])  + 3), s[1])
+       return str
 
 def help():
-    sys.stdout.write("""Usage: mudela-book [options] FILE\n
+       sys.stdout.write("""Usage: mudela-book [options] FILE\n
 Generate hybrid LaTeX input from Latex + mudela
-Options:\n
-  -h, --help                     print this help
-  -d, --outdir=DIR               directory to put generated files
-  -o, --outname=FILE             prefix for filenames
-  --default-mudela-fontsize=??pt default fontsize for music
-  --force-mudela-fontsize=??pt   force fontsize for all inline mudela
-  --force-verbatim               make all mudela verbatim\n
-  --dependencies                 write dependencies
-  --include                      include path
-  --init                         mudela-book initfile
-  """
-                    )
-    sys.exit (0)
-
-
-def write_deps (fn, out,  deps):
-       out_fn = os.path.join (outdir, fn)
-       
-       sys.stdout.write('writing `%s\'\n' % out_fn)
-       
-       f = open (out_fn, 'w')
-       target = re.sub (os.sep + os.sep, os.sep, os.path.join (outdir, out + '.latex'))
-       f.write ('%s: %s\n'% (target,
-                             reduce (lambda x,y: x + ' '+ y, deps)))
+Options:
+""")
+       sys.stdout.write (options_help_str (option_definitions))
+       sys.stdout.write (r"""Warning all output is written in the CURRENT directory
+
+
+
+Report bugs to bug-gnu-music@gnu.org.
+
+Written by Tom Cato Amundsen <tca@gnu.org> and
+Han-Wen Nienhuys <hanwen@cs.uu.nl>
+""")
+
+       sys.exit (0)
+
+
+def write_deps (fn, target):
+       sys.stdout.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 __main__.read_files:
+               f.write ('%s ' %  d)
+       f.write ('\n')
        f.close ()
+       __main__.read_files = []
 
 def identify():
-    sys.stderr.write ('This is %s version %s\n' % ('mudela-book', program_version))
-
-def main():
-    global outdir, initfile, defined_mudela_cmd, defined_mudela_cmd_re
-    outname = ''
-    try:
-        (options, files) = getopt.getopt(
-            sys.argv[1:], 'hd:o:I:', ['outdir=', 'outname=',
-                                    'default-mudela-fontsize=',
-                                    'force-mudela-fontsize=',
-                                    'help', 'dependencies', 'include=',
-                                    'force-verbatim', 'init='])
-    except getopt.error, msg:
-        sys.stderr.write("error: %s" % msg)
-        sys.exit(1)
-        
-    do_deps = 0
-    for opt in options:    
+       sys.stdout.write ('mudela-book (GNU LilyPond) %s\n' % program_version)
+
+def print_version ():
+       identify()
+       sys.stdout.write (r"""Copyright 1998--1999
+Distributed under terms of the GNU General Public License. It comes with
+NO WARRANTY.
+""")
+
+def do_file(input_filename):
+       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, 'mudela', make_mudela)
+       chunks = chop_chunks(chunks, 'mudela-file', make_mudela_file)
+       chunks = chop_chunks(chunks, 'mudela-block', make_mudela_block)
+       #for c in chunks: print c, "\n"
+       chunks = chop_chunks(chunks, 'ignore', do_ignore)
+       chunks = chop_chunks(chunks, 'numcols', do_columns)
+       global_options = scan_preamble(chunks[0][1])
+       chunks = process_mudela_blocks(my_outname, chunks, global_options)
+       # Do It.
+       if __main__.g_run_lilypond:
+               compile_all_files (chunks)
+               newchunks = []
+               # 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)
+               chunks = newchunks
+
+       if chunks and chunks[0][0] == 'input':
+               chunks[0] = ('input', completize_preamble (chunks[0][1]))
+
+       foutn = os.path.join(g_outdir, my_outname + '.' + format)
+       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)
+
+
+outname = ''
+try:
+       (sh, long) = getopt_args (__main__.option_definitions)
+       (options, files) = getopt.getopt(sys.argv[1:], sh, long)
+except getopt.error, msg:
+       sys.stderr.write("error: %s" % msg)
+       sys.exit(1)
+
+do_deps = 0
+for opt in options:    
        o = opt[0]
        a = opt[1]
+
        if o == '--include' or o == '-I':
-           include_path.append (a)
+               include_path.append (a)
+       elif o == '--version' or o == '-v':
+               print_version ()
+               sys.exit  (0)
+       elif o == '--format' or o == '-f':
+               __main__.format = a
        elif o == '--outname' or o == '-o':
-            if len(files) > 1:
-                #HACK
-                sys.stderr.write("Mudela-book is confused by --outname on multiple files")
-                sys.exit(1)
-            outname = a
-        elif o == '--outdir' or o == '-d':
-            outdir = a
-        elif o == '--help' or o == '-h':
-            help ()
-       elif o == '--dependencies':
-            do_deps = 1
-        elif o == '--default-mudela-fontsize':
-            if not fontsize_pt2i.has_key(a):
-                sys.stderr.write("Error: invalid fontsize: %s" % a)
-                sys.stderr.write("  accepted fontsizes are: 11pt, 13pt, 16pt, 20pt, 26pt")
-                sys.exit()
-            Props.setMudelaFontsize(fontsize_pt2i[a], 'init')
+               if len(files) > 1:
+                       #HACK
+                       sys.stderr.write("Mudela-book is confused by --outname on multiple files")
+                       sys.exit(1)
+               outname = a
+       elif o == '--help' or o == '-h':
+               help ()
+       elif o == '--no-lily' or o == '-n':
+               __main__.g_run_lilypond = 0
+       elif o == '--dependencies' or o == '-M':
+               do_deps = 1
+       elif o == '--default-music-fontsize':
+               default_music_fontsize = string.atoi (a)
+       elif o == '--default-mudela-fontsize':
+               print "--default-mudela-fontsize is deprecated, use --default-music-fontsize"
+               default_music_fontsize = string.atoi (a)
+       elif o == '--force-music-fontsize':
+               g_force_mudela_fontsize = string.atoi(a)
        elif o == '--force-mudela-fontsize':
-            if not fontsize_pt2i.has_key(a):
-                sys.stderr.write("Error: invalid fontsize: %s" % a)
-                sys.stderr.write("  accepted fontsizes are: 11pt, 13pt, 16pt, 20pt, 26pt")
-                sys.exit()
-            Props.force_mudela_fontsize = fontsize_pt2i[a]
-        elif o == '--force-verbatim':
-            Props.force_verbatim_b = 1
-        elif o == '--init':
-            initfile =  a
-    if outdir[-1:] != '/':
-        outdir = outdir + '/'
-
-    # r""" ... """ means: leave escape seqs alone.
-    defined_mudela_cmd = {'mudela': r"""
-\begin{mudela}[eps, singleline \fontoptions]
-  \context Staff <
-    \context Voice{
-      \maininput
-    }
-  >
-\end{mudela}
-"""}
-    if initfile != '':
-        f = open(initfile)
-        s = f.read()
-        f.close()
-        d = eval(s)
-        for i in d.keys():
-            defined_mudela_cmd[i] = d[i]
-        del d
-
-    c = string.join (defined_mudela_cmd.keys(), '|')
-
-    defined_mudela_cmd_re = re.compile("\\\\(%s)(\[(\d*pt)\])*{([^}]*)}" %c)
-
-    if not os.path.isdir(outdir):
-        os.system('mkdir %s' % outdir)
-
-    for input_filename in files:
-        Props.clear_for_new_file()
-        if outname:
-            my_outname = outname
-        else:
-            my_outname = os.path.basename(os.path.splitext(input_filename)[0])
-        my_depname = my_outname + '.dep'        
-        inp = Main_tex_input (input_filename, my_outname)
-        inp.do_it ()
-        if do_deps:
-            write_deps (my_depname, my_outname, inp.deps)
+               print "--force-mudela-fontsize is deprecated, use --default-mudela-fontsize"
+               g_force_mudela_fontsize = string.atoi(a)
+       elif o == '--dep-prefix':
+               g_dep_prefix = a
+       elif o == '--no-pictures':
+               g_do_pictures = 0
+       elif o == '--read-lys':
+               g_read_lys = 1
+       elif o == '--outdir':
+               g_outdir = a
 
 identify()
-Props = Properties()
-main()
+if g_outdir:
+       if os.path.isfile(g_outdir):
+               error ("outdir is a file: %s" % g_outdir)
+       if not os.path.exists(g_outdir):
+               os.mkdir(g_outdir)
+for input_filename in files:
+       do_file(input_filename)
+       
+#
+# Petr, ik zou willen dat ik iets zinvoller deed,
+# maar wat ik kan ik doen, het verandert toch niets?
+#   --hwn 20/aug/99