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