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