]> git.donarmstrong.com Git - lilypond.git/blob - scripts/mudela-book.py
03b479bfb260c54ada2d9fb9b76e7e30c916004d
[lilypond.git] / scripts / mudela-book.py
1 #!@PYTHON@
2 # vim: set noexpandtab:
3 # TODO: Figure out clean set of options.
4 # add support for .lilyrc
5
6 import os
7 import stat
8 import string
9 import re
10 import getopt
11 import sys
12 import __main__
13
14
15 program_version = '@TOPLEVEL_VERSION@'
16
17 include_path = [os.getcwd()]
18
19 g_dep_prefix = ''
20 g_outdir = ''
21 g_force_mudela_fontsize = 0
22 g_read_lys = 0
23 g_do_pictures = 1
24 g_num_cols = 1
25 format = ''
26 g_run_lilypond = 1
27 no_match = 'a\ba'
28
29 default_music_fontsize = 16
30 default_text_fontsize = 12
31
32 # latex linewidths:
33 # indices are no. of columns, papersize,  fontsize
34 # Why can't this be calculated?
35 latex_linewidths = {
36  1: {'a4':{10: 345, 11: 360, 12: 390},
37          'a5':{10: 276, 11: 276, 12: 276},
38          'b5':{10: 345, 11: 356, 12: 356},
39          'letter':{10: 345, 11: 360, 12: 390},
40          'legal': {10: 345, 11: 360, 12: 390},
41          'executive':{10: 345, 11: 360, 12: 379}},
42  2: {'a4':{10: 167, 11: 175, 12: 190},
43          'a5':{10: 133, 11: 133, 12: 133},
44          'b5':{10: 167, 11: 173, 12: 173},
45          'letter':{10: 167, 11: 175, 12: 190},
46          'legal':{10: 167, 11: 175, 12: 190},
47          'executive':{10: 167, 11: 175, 12: 184}}}
48
49 texi_linewidths = {
50         'a4': {12: 455},
51         'a4wide': {12: 470},
52         'smallbook': {12: 361},
53         'texidefault': {12: 433}}
54
55
56 def get_linewidth(cols, paper, fontsize):
57         if __main__.format == 'latex':
58                 return latex_linewidths[cols][paper][fontsize]
59         elif __main__.format == 'texi':
60                 return texi_linewidths[paper][fontsize]
61         raise "never here"
62
63 option_definitions = [
64   ('EXT', 'f', 'format', 'set format.  EXT is one of texi and latex.'),
65   ('DIM',  '', 'default-music-fontsize', 'default fontsize for music.  DIM is assumed to be in points'),
66   ('DIM',  '', 'default-mudela-fontsize', 'deprecated, use --default-music-fontsize'),
67   ('DIM', '', 'force-music-fontsize', 'force fontsize for all inline mudela. DIM is assumed be to in points'),
68   ('DIM', '', 'force-mudela-fontsize', 'deprecated, use --force-music-fontsize'),
69   ('DIR', 'I', 'include', 'include path'),
70   ('', 'M', 'dependencies', 'write dependencies'),
71   ('PREF', '',  'dep-prefix', 'prepend PREF before each -M dependency'),
72   ('', 'n', 'no-lily', 'don\'t run lilypond'),
73   ('', '', 'no-pictures', "don\'t generate pictures"),
74   ('', '', 'read-lys', "don't write ly files."),
75   ('FILE', 'o', 'outname', 'filename main output file'),
76   ('FILE', '', 'outdir', "where to place generated files"),
77   ('', 'v', 'version', 'print version information' ),
78   ('', 'h', 'help', 'print help'),
79   ]
80
81 # format specific strings, ie. regex-es for input, and % strings for output
82 output_dict= {
83         'latex': {
84                 'output-mudela-fragment' : r"""\begin[eps,singleline,%s]{mudela}
85   \context Staff <
86     \context Voice{
87       %s
88     }
89   >
90 \end{mudela}""", 
91                 'output-mudela':r"""\begin[%s]{mudela}
92 %s
93 \end{mudela}""",
94                 'output-verbatim': r"""\begin{verbatim}%s\end{verbatim}""",
95                 'output-default-post': r"""\def\postMudelaExample{}""",
96                 'output-default-pre': r"""\def\preMudelaExample{}""",
97                 'output-eps': '\\noindent\\parbox{\\mudelaepswidth{%(fn)s.eps}}{\includegraphics{%(fn)s.eps}}',
98                 'output-tex': '\\preMudelaExample \\input %(fn)s.tex \\postMudelaExample\n',
99                 'pagebreak': r'\pagebreak',
100                 },
101         'texi' : {'output-mudela': """@mudela[%s]
102 %s
103 @end mudela 
104 """,
105                   'output-mudela-fragment': """@mudela[%s]
106 \context Staff\context Voice{ %s }
107 @end mudela """,
108                   'pagebreak': None,
109                   'output-verbatim': r"""@example
110 %s
111 @end example
112 """,
113
114 # do some tweaking: @ is needed in some ps stuff.
115 # override EndLilyPondOutput, since @tex is done
116 # in a sandbox, you can't do \input lilyponddefs at the
117 # top of the document.
118
119 # should also support fragment in
120                   
121                   'output-all': r"""@tex
122 \catcode`\@=12
123 \input lilyponddefs
124 \def\EndLilyPondOutput{}
125 \input %(fn)s.tex
126 \catcode`\@=0
127 @end tex
128 @html
129 <p>
130 <img src=%(fn)s.png>
131 @end html
132 """,
133                 }
134         }
135
136 def output_verbatim (body):#ugh .format
137         if __main__.format == 'texi':
138                 body = re.sub ('([@{}])', '@\\1', body)
139         return get_output ('output-verbatim') % body
140
141 def output_mbverbatim (body):#ugh .format
142         if __main__.format == 'texi':
143                 body = re.sub ('([@{}])', '@\\1', body)
144         return get_output ('output-verbatim') % body
145
146 re_dict = {
147         'latex': {'input': '\\\\mbinput{?([^}\t \n}]*)',
148                   'include': '\\\\mbinclude{(?P<filename>[^}]+)}',
149                  
150                   'option-sep' : ', *',
151                   'header': r"""\\documentclass(\[.*?\])?""",
152                   'preamble-end': '\\\\begin{document}',
153                   'verbatim': r"""(?s)(?P<code>\\begin{verbatim}.*?\\end{verbatim})""",
154                   'verb': r"""(?P<code>\\verb(?P<del>.).*?(?P=del))""",
155                   'mudela-file': r'\\mudelafile(\[(?P<options>.*?)\])?\{(?P<filename>.+)}',
156                   'mudela' : '(?m)\\\\mudela(\[(?P<options>.*?)\])?{(?P<code>.*?)}',
157                   #'mudela-block': r"""(?m)^[^%]*?\\begin(\[(?P<options>.*?)\])?{mudela}(?P<code>.*?)\\end{mudela}""",
158                   'mudela-block': r"""(?s)\\begin(\[(?P<options>.*?)\])?{mudela}(?P<code>.*?)\\end{mudela}""",
159                   'def-post-re': r"""\\def\\postMudelaExample""",
160                   'def-pre-re': r"""\\def\\preMudelaExample""",           
161                   'intertext': r',?\s*intertext=\".*?\"',
162                   'ignore': r"(?m)(?P<code>%.*?^)",
163                   'numcols': r"(?P<code>\\(?P<num>one|two)column)",
164                   },
165         
166         'texi': {
167                  'include':  '@mbinclude[ \n\t]+(?P<filename>[^\t \n]*)',
168                  'input': no_match,
169                  'header': no_match,
170                  'preamble-end': no_match,
171                  'verbatim': r"""(?s)(?P<code>@example\s.*?@end example\s)""",
172                  'verb': r"""(?P<code>@code{.*?})""",
173                  'mudela-file': '@mudelafile(\[(?P<options>.*?)\])?{(?P<filename>[^}]+)}',
174                  'mudela' : '@mudela(\[(?P<options>.*?)\])?{(?P<code>.*?)}',
175                  'mudela-block': r"""(?s)@mudela(\[(?P<options>.*?)\])?\s(?P<code>.*?)@end mudela\s""",
176                   'option-sep' : ', *',
177                   'intertext': r',?\s*intertext=\".*?\"',
178                   'ignore': r"(?s)(?P<code>@ignore\s.*?@end ignore)\s",
179                   'numcols': no_match,
180                  }
181         }
182
183
184 for r in re_dict.keys ():
185         olddict = re_dict[r]
186         newdict = {}
187         for k in olddict.keys ():
188                 newdict[k] = re.compile (olddict[k])
189         re_dict[r] = newdict
190
191         
192 def uniq (list):
193         list.sort ()
194         s = list
195         list = []
196         for x in s:
197                 if x not in list:
198                         list.append (x)
199         return list
200                 
201
202 def get_output (name):
203         return  output_dict[format][name]
204
205 def get_re (name):
206         return  re_dict[format][name]
207
208 def bounding_box_dimensions(fname):
209         try:
210                 fd = open(fname)
211         except IOError:
212                 error ("Error opening `%s'" % fname)
213         str = fd.read ()
214         s = re.search('%%BoundingBox: ([0-9]+) ([0-9]+) ([0-9]+) ([0-9]+)', str)
215         if s:
216                 return (int(s.group(3))-int(s.group(1)), 
217                         int(s.group(4))-int(s.group(2)))
218         else:
219                 return (0,0)
220
221
222 def error (str):
223         sys.stderr.write (str + "\n  Exiting ... \n\n")
224         raise 'Exiting.'
225
226
227 def compose_full_body (body, opts):
228         """Construct the mudela code to send to Lilypond.
229         Add stuff to BODY using OPTS as options."""
230         if __main__.format == 'texi':
231                 paper = 'texidefault'
232         else:
233                 paper = 'letter' # yes, latex use letter as default, at least
234                                  # my tetex distro
235         music_size = default_music_fontsize
236         latex_size = default_text_fontsize
237         for o in opts:
238                 m = re.search ('^(.*)paper$', o)
239                 if m:
240                         paper = m.group (1)
241                 
242                 if g_force_mudela_fontsize:
243                         music_size = g_force_mudela_fontsize
244                 else:
245                         m = re.match ('([0-9]+)pt', o)
246                         if m:
247                                 music_size = string.atoi(m.group (1))
248
249                 m = re.match ('latexfontsize=([0-9]+)pt', o)
250                 if m:
251                         latex_size = string.atoi (m.group (1))
252
253         if re.search ('\\\\score', body):
254                 is_fragment = 0
255         else:
256                 is_fragment = 1
257         if 'fragment' in opts:
258                 is_fragment = 1
259         if 'nonfragment' in opts:
260                 is_fragment = 0
261
262         if is_fragment and not 'multiline' in opts:
263                 opts.append('singleline')
264         if 'singleline' in opts:
265                 l = -1.0;
266         else:
267                 l = get_linewidth(g_num_cols, paper, latex_size)
268         
269         if 'relative' in opts:#ugh only when is_fragment
270                 body = '\\relative c { %s }' % body
271         
272         if is_fragment:
273                 body = r"""\score { 
274  \notes { %s }
275   \paper { }  
276 }""" % body
277
278         opts = uniq (opts)
279         optstring = string.join (opts, ' ')
280         optstring = re.sub ('\n', ' ', optstring)
281         
282         body = r"""
283 %% Generated by mudela-book.py; options are %s  %%ughUGH not original options
284 \include "paper%d.ly"
285 \paper  { linewidth = %f \pt; } 
286 """ % (optstring, music_size, l) + body
287         return body
288
289
290 def scan_preamble (str):
291         options = []
292         if __main__.format == 'texi':
293                 x = 250
294                 if string.find(str[:x], "@afourpaper") != -1:
295                         options = ['a4paper']
296                 elif string.find(str[:x], "@afourwide") != -1:
297                         options = ['a4widepaper']
298                 elif string.find(str[:x], "@smallbook") != -1:
299                         options = ['smallbookpaper']
300         m = get_re ('header').search( str)
301         # should extract paper & fontsz.
302         if m and m.group (1):
303                 options = options + re.split (',[\n \t]*', m.group(1)[1:-1])
304
305         def verbose_fontsize ( x):
306                 if re.match('[0-9]+pt', x):
307                         return 'latexfontsize=' + x
308                 else:
309                         return x 
310                         
311         options = map (verbose_fontsize, options)
312         return options
313
314
315 def completize_preamble (str):
316         m = get_re ('preamble-end').search( str)
317         if not m:
318                 return str
319         
320         preamble = str [:m.start (0)]
321         str = str [m.start(0):]
322         
323         if not get_re('def-post-re').search (preamble):
324                 preamble = preamble + get_output('output-default-post')
325         if not get_re ('def-pre-re').search(  preamble):
326                 preamble = preamble + get_output ('output-default-pre')
327
328         # UGH ! BUG!
329         #if  re.search ('\\\\includegraphics', str) and not re.search ('usepackage{graphics}',str):
330
331         preamble = preamble + '\\usepackage{graphics}\n'
332
333         return preamble + str
334
335
336 read_files = []
337 def find_file (name):
338         f = None
339         for a in include_path:
340                 try:
341                         nm = os.path.join (a, name)
342                         f = open (nm)
343                         __main__.read_files.append (nm)
344                         break
345                 except IOError:
346                         pass
347         if f:
348                 return f.read ()
349         else:
350                 error ("File not found `%s'\n" % name)
351                 return ''
352
353 def do_ignore(match_object):
354         return [('ignore', match_object.group('code'))]
355
356 def make_verbatim(match_object):
357         return [('verbatim', match_object.group('code'))]
358
359 def make_verb(match_object):
360         return [('verb', match_object.group('code'))]
361
362 def do_include_file(m):
363         "m: MatchObject"
364         return [('input', get_output ('pagebreak'))] \
365              + read_doc_file(m.group('filename')) \
366              + [('input', get_output ('pagebreak'))] 
367
368 def do_input_file(m):
369         return read_doc_file(m.group('filename'))
370
371 def make_mudela(m):
372         if m.group('options'):
373                 options = m.group('options')
374         else:
375                 options = ''
376         return [('input', get_output('output-mudela-fragment') % 
377                         (options, m.group('code')))]
378
379 def make_mudela_file(m):
380         if m.group('options'):
381                 options = m.group('options')
382         else:
383                 options = ''
384         return [('input', get_output('output-mudela') %
385                         (options, find_file(m.group('filename'))))]
386
387 def make_mudela_block(m):
388         if m.group('options'):
389                 options = get_re('option-sep').split (m.group('options'))
390         else:
391             options = []
392         options = filter(lambda s: s != '', options)
393         if 'mbverbatim' in options:#ugh this is ugly and only for texi format
394                 s  = m.group()
395                 im = get_re('intertext').search(s)
396                 if im:
397                         s = s[:im.start()] + s[im.end():]
398                 im = re.search('mbverbatim', s)
399                 if im:
400                         s = s[:im.start()] + s[im.end():]
401                 if s[:9] == "@mudela[]":
402                         s = "@mudela" + s[9:]
403                 return [('mudela', m.group('code'), options, s)]
404         return [('mudela', m.group('code'), options)]
405
406 def do_columns(m):
407         if __main__.format != 'latex':
408                 return []
409         if m.group('num') == 'one':
410                 return [('numcols', m.group('code'), 1)]
411         if m.group('num') == 'two':
412                 return [('numcols', m.group('code'), 2)]
413         
414 def chop_chunks(chunks, re_name, func):
415     newchunks = []
416     for c in chunks:
417         if c[0] == 'input':
418             str = c[1]
419             while str:
420                 m = get_re (re_name).search (str)
421                 if m == None:
422                     newchunks.append (('input', str))
423                     str = ''
424                 else:
425                     newchunks.append (('input', str[:m.start (0)]))
426                     #newchunks.extend(func(m))
427                     # python 1.5 compatible:
428                     newchunks = newchunks + func(m)
429                     str = str [m.end(0):]
430         else:
431             newchunks.append(c)
432     return newchunks
433
434 def read_doc_file (filename):
435         """Read the input file, find verbatim chunks and do \input and \include
436         """
437         str = ''
438         str = find_file(filename)
439
440         if __main__.format == '':
441                 latex =  re.search ('\\\\document', str[:200])
442                 texinfo =  re.search ('@node|@setfilename', str[:200])
443                 if (texinfo and latex) or not (texinfo or latex):
444                         error("error: can't determine format, please specify")
445                 if texinfo:
446                         __main__.format = 'texi'
447                 else:
448                         __main__.format = 'latex'
449         chunks = [('input', str)]
450         # we have to check for verbatim before doing include,
451         # because we don't want to include files that are mentioned
452         # inside a verbatim environment
453         chunks = chop_chunks(chunks, 'verbatim', make_verbatim)
454         chunks = chop_chunks(chunks, 'verb', make_verb)
455         #ugh fix input
456         chunks = chop_chunks(chunks, 'include', do_include_file)
457         chunks = chop_chunks(chunks, 'input', do_input_file)
458         return chunks
459
460
461 taken_file_names = {}
462 def schedule_mudela_block (chunk, extra_opts):
463         """Take the body and options from CHUNK, figure out how the
464         real .ly should look, and what should be left MAIN_STR (meant
465         for the main file).  The .ly is written, and scheduled in
466         TODO.
467
468         Return: a chunk (TYPE_STR, MAIN_STR, OPTIONS, TODO, BASE)
469
470         TODO has format [basename, extension, extension, ... ]
471         
472         """
473         if len(chunk) == 3:
474                 (type, body, opts) = chunk
475                 complete_body = None
476         else:# mbverbatim
477                 (type, body, opts, complete_body) = chunk
478         assert type == 'mudela'
479         opts = opts +  extra_opts
480         file_body = compose_full_body (body, opts)
481         basename = `abs(hash (file_body))`
482         for o in opts:
483                 m = re.search ('filename="(.*?)"', o)
484                 if m:
485                         basename = m.group (1)
486                         if not taken_file_names.has_key(basename):
487                             taken_file_names[basename] = 0
488                         else:
489                             taken_file_names[basename] = taken_file_names[basename] + 1
490                             basename = basename + "-%i" % taken_file_names[basename]
491         # writes the file if necessary, returns true if it was written
492         if not g_read_lys:
493                 update_file(file_body, os.path.join(g_outdir, basename) + '.ly')
494         needed_filetypes = ['tex']
495
496         if format  == 'texi':
497                 needed_filetypes.append('eps')
498                 needed_filetypes.append('png')
499         if 'eps' in opts and not ('eps' in needed_filetypes):
500                 needed_filetypes.append('eps')
501         outname = os.path.join(g_outdir, basename)
502         if not os.path.isfile(outname + '.tex') \
503                 or os.stat(outname+'.ly')[stat.ST_MTIME] > \
504                         os.stat(outname+'.tex')[stat.ST_MTIME]:
505                 todo = needed_filetypes
506         else:
507                 todo = []
508                 
509         newbody = ''
510         if 'verbatim' in opts:
511                 newbody = output_verbatim (body)
512         elif 'mbverbatim' in opts:
513                 newbody = output_mbverbatim (complete_body)
514
515         for o in opts:
516                 m = re.search ('intertext="(.*?)"', o)
517                 if m:
518                         newbody = newbody  + m.group (1)
519         if format == 'latex':
520                 if 'eps' in opts:
521                         s = 'output-eps'
522                 else:
523                         s = 'output-tex'
524         else: # format == 'texi'
525                 s = 'output-all'
526         newbody = newbody + get_output(s) % {'fn': basename }
527         return ('mudela', newbody, opts, todo, basename)
528
529 def process_mudela_blocks(outname, chunks, global_options):#ugh rename
530         newchunks = []
531         # Count sections/chapters.
532         for c in chunks:
533                 if c[0] == 'mudela':
534                         c = schedule_mudela_block (c, global_options)
535                 elif c[0] == 'numcols':
536                         __main__.g_num_cols = c[2]
537                 newchunks.append (c)
538         return newchunks
539
540
541 def find_eps_dims (match):
542         "Fill in dimensions of EPS files."
543         
544         fn =match.group (1)
545         dims = bounding_box_dimensions (fn)
546
547         return '%ipt' % dims[0]
548
549
550 def system (cmd):
551         sys.stderr.write ("invoking `%s'\n" % cmd)
552         st = os.system (cmd)
553         if st:
554                 error ('Error command exited with value %d\n' % st)
555         return st
556
557 def compile_all_files (chunks):
558         eps = []
559         tex = []
560         png = []
561
562         for c in chunks:
563                 if c[0] <> 'mudela':
564                         continue
565                 base  = c[4]
566                 exts = c[3]
567                 for e in exts:
568                         if e == 'eps':
569                                 eps.append (base)
570                         elif e == 'tex':
571                                 tex.append (base + '.ly')
572                         elif e == 'png' and g_do_pictures:
573                                 png.append (base)
574         d = os.getcwd()
575         if g_outdir:
576                 os.chdir(g_outdir)
577         if tex:
578                 lilyopts = map (lambda x:  '-I ' + x, include_path)
579                 lilyopts = string.join (lilyopts, ' ' )
580                 texfiles = string.join (tex, ' ')
581                 system ('lilypond %s %s' % (lilyopts, texfiles))
582         for e in eps:
583                 system(r"tex '\nonstopmode \input %s'" % e)
584                 system(r"dvips -E -o %s %s" % (e + '.eps', e))
585         for g in png:
586                 cmd = r"""gs -sDEVICE=pgm  -dTextAlphaBits=4 -dGraphicsAlphaBits=4  -q -sOutputFile=- -r90 -dNOPAUSE %s -c quit | pnmcrop | pnmtopng > %s"""
587                 cmd = cmd % (g + '.eps', g + '.png')
588                 system (cmd)
589         if g_outdir:
590                 os.chdir(d)
591
592
593 def update_file (body, name):
594         """
595         write the body if it has changed
596         """
597         same = 0
598         try:
599                 f = open (name)
600                 fs = f.read (-1)
601                 same = (fs == body)
602         except:
603                 pass
604
605         if not same:
606                 f = open (name , 'w')
607                 f.write (body)
608                 f.close ()
609         
610         return not same
611
612
613 def getopt_args (opts):
614         "Construct arguments (LONG, SHORT) for getopt from  list of options."
615         short = ''
616         long = []
617         for o in opts:
618                 if o[1]:
619                         short = short + o[1]
620                         if o[0]:
621                                 short = short + ':'
622                 if o[2]:
623                         l = o[2]
624                         if o[0]:
625                                 l = l + '='
626                         long.append (l)
627         return (short, long)
628
629 def option_help_str (o):
630         "Transform one option description (4-tuple ) into neatly formatted string"
631         sh = '  '       
632         if o[1]:
633                 sh = '-%s' % o[1]
634
635         sep = ' '
636         if o[1] and o[2]:
637                 sep = ','
638                 
639         long = ''
640         if o[2]:
641                 long= '--%s' % o[2]
642
643         arg = ''
644         if o[0]:
645                 if o[2]:
646                         arg = '='
647                 arg = arg + o[0]
648         return '  ' + sh + sep + long + arg
649
650
651 def options_help_str (opts):
652         "Convert a list of options into a neatly formatted string"
653         w = 0
654         strs =[]
655         helps = []
656
657         for o in opts:
658                 s = option_help_str (o)
659                 strs.append ((s, o[3]))
660                 if len (s) > w:
661                         w = len (s)
662
663         str = ''
664         for s in strs:
665                 str = str + '%s%s%s\n' % (s[0], ' ' * (w - len(s[0])  + 3), s[1])
666         return str
667
668 def help():
669         sys.stdout.write("""Usage: mudela-book [options] FILE\n
670 Generate hybrid LaTeX input from Latex + mudela
671 Options:
672 """)
673         sys.stdout.write (options_help_str (option_definitions))
674         sys.stdout.write (r"""Warning all output is written in the CURRENT directory
675
676
677
678 Report bugs to bug-gnu-music@gnu.org.
679
680 Written by Tom Cato Amundsen <tca@gnu.org> and
681 Han-Wen Nienhuys <hanwen@cs.uu.nl>
682 """)
683
684         sys.exit (0)
685
686
687 def write_deps (fn, target):
688         sys.stdout.write('writing `%s\'\n' % os.path.join(g_outdir, fn))
689         f = open (os.path.join(g_outdir, fn), 'w')
690         f.write ('%s%s: ' % (g_dep_prefix, target))
691         for d in __main__.read_files:
692                 f.write ('%s ' %  d)
693         f.write ('\n')
694         f.close ()
695         __main__.read_files = []
696
697 def identify():
698         sys.stdout.write ('mudela-book (GNU LilyPond) %s\n' % program_version)
699
700 def print_version ():
701         identify()
702         sys.stdout.write (r"""Copyright 1998--1999
703 Distributed under terms of the GNU General Public License. It comes with
704 NO WARRANTY.
705 """)
706
707 def do_file(input_filename):
708         file_settings = {}
709         if outname:
710                 my_outname = outname
711         else:
712                 my_outname = os.path.basename(os.path.splitext(input_filename)[0])
713         my_depname = my_outname + '.dep'                
714
715         chunks = read_doc_file(input_filename)
716         chunks = chop_chunks(chunks, 'mudela', make_mudela)
717         chunks = chop_chunks(chunks, 'mudela-file', make_mudela_file)
718         chunks = chop_chunks(chunks, 'mudela-block', make_mudela_block)
719         #for c in chunks: print c, "\n"
720         chunks = chop_chunks(chunks, 'ignore', do_ignore)
721         chunks = chop_chunks(chunks, 'numcols', do_columns)
722         global_options = scan_preamble(chunks[0][1])
723         chunks = process_mudela_blocks(my_outname, chunks, global_options)
724         # Do It.
725         if __main__.g_run_lilypond:
726                 compile_all_files (chunks)
727                 newchunks = []
728                 # finishing touch.
729                 for c in chunks:
730                         if c[0] == 'mudela' and 'eps' in c[2]:
731                                 body = re.sub (r"""\\mudelaepswidth{(.*?)}""", find_eps_dims, c[1])
732                                 newchunks.append (('mudela', body))
733                         else:
734                                 newchunks.append (c)
735                 chunks = newchunks
736
737         if chunks and chunks[0][0] == 'input':
738                 chunks[0] = ('input', completize_preamble (chunks[0][1]))
739
740         foutn = os.path.join(g_outdir, my_outname + '.' + format)
741         sys.stderr.write ("Writing `%s'\n" % foutn)
742         fout = open (foutn, 'w')
743         for c in chunks:
744                 fout.write (c[1])
745         fout.close ()
746
747         if do_deps:
748                 write_deps (my_depname, foutn)
749
750
751 outname = ''
752 try:
753         (sh, long) = getopt_args (__main__.option_definitions)
754         (options, files) = getopt.getopt(sys.argv[1:], sh, long)
755 except getopt.error, msg:
756         sys.stderr.write("error: %s" % msg)
757         sys.exit(1)
758
759 do_deps = 0
760 for opt in options:     
761         o = opt[0]
762         a = opt[1]
763
764         if o == '--include' or o == '-I':
765                 include_path.append (a)
766         elif o == '--version' or o == '-v':
767                 print_version ()
768                 sys.exit  (0)
769         elif o == '--format' or o == '-f':
770                 __main__.format = a
771         elif o == '--outname' or o == '-o':
772                 if len(files) > 1:
773                         #HACK
774                         sys.stderr.write("Mudela-book is confused by --outname on multiple files")
775                         sys.exit(1)
776                 outname = a
777         elif o == '--help' or o == '-h':
778                 help ()
779         elif o == '--no-lily' or o == '-n':
780                 __main__.g_run_lilypond = 0
781         elif o == '--dependencies' or o == '-M':
782                 do_deps = 1
783         elif o == '--default-music-fontsize':
784                 default_music_fontsize = string.atoi (a)
785         elif o == '--default-mudela-fontsize':
786                 print "--default-mudela-fontsize is deprecated, use --default-music-fontsize"
787                 default_music_fontsize = string.atoi (a)
788         elif o == '--force-music-fontsize':
789                 g_force_mudela_fontsize = string.atoi(a)
790         elif o == '--force-mudela-fontsize':
791                 print "--force-mudela-fontsize is deprecated, use --default-mudela-fontsize"
792                 g_force_mudela_fontsize = string.atoi(a)
793         elif o == '--dep-prefix':
794                 g_dep_prefix = a
795         elif o == '--no-pictures':
796                 g_do_pictures = 0
797         elif o == '--read-lys':
798                 g_read_lys = 1
799         elif o == '--outdir':
800                 g_outdir = a
801
802 identify()
803 if g_outdir:
804         if os.path.isfile(g_outdir):
805                 error ("outdir is a file: %s" % g_outdir)
806         if not os.path.exists(g_outdir):
807                 os.mkdir(g_outdir)
808 for input_filename in files:
809         do_file(input_filename)
810         
811 #
812 # Petr, ik zou willen dat ik iets zinvoller deed,
813 # maar wat ik kan ik doen, het verandert toch niets?
814 #   --hwn 20/aug/99