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