]> git.donarmstrong.com Git - lilypond.git/blob - scripts/mudela-book.py
release: 1.3.0
[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                 fn = match.group (2)
425                 str = find_file (fn)
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$', fn):
434                         opts.append ('fly')
435                 elif re.search ('.sly$', fn):
436                         opts = opts + [ 'fly','fragment']
437                 elif re.search ('.ly$', fn):
438                         opts .append ('nofly')
439                         
440                 str_opts = string.join (opts, ',')
441
442                 str = ("%% copied from file `%s'\n" % fn) + 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                                 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, BASE)
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         basename = base
535         if __main__.use_hash:
536                 basename = `abs(hash (file_body))`
537         updated = update_file (file_body, basename + '.ly')
538         todo = [basename]                       # UGH.
539
540         if not os.path.isfile (basename + '.tex') or updated:
541                 todo.append ('tex')
542                 updated = 1
543
544         for o in opts:
545                 m = re.search ('intertext="(.*?)"', o)
546                 if m:
547                         newbody = newbody  + m.group (1)
548
549         if format == 'texi':
550                 opts.append ('png')
551
552         if 'png' in opts:
553                 opts.append ('eps')
554
555         if 'eps' in opts and ('tex' in todo or
556                               not os.path.isfile (basename + '.eps')):
557                 todo.append ('eps')
558
559         if 'png' in opts and ('eps' in todo or
560                               not os.path.isfile (basename + '.png')):
561                 todo.append ('png')
562
563         if format == 'latex':
564                 if 'eps' in opts :
565                         newbody = newbody + get_output ('output-eps') %  (basename, basename)
566                 else:
567                         newbody = newbody + get_output ('output-tex') % basename
568
569         elif format == 'texi':
570                 newbody = newbody + get_output ('output-all') % (basename, basename) 
571
572         return ('mudela', newbody, opts, todo, base)
573
574
575 def find_eps_dims (match):
576         "Fill in dimensions of EPS files."
577         
578         fn =match.group (1)
579         dims = bounding_box_dimensions (fn)
580
581         return '%ipt' % dims[0]
582
583
584 def print_chunks (ch):
585         for c in ch:
586                 print '-->%s\n%s' % (c[0], c[1])
587                 if len (c) > 2:
588                         print '==>%s' % list (c[2:])
589         print foo
590
591
592 def transform_input_file (in_filename, out_filename):
593         """Read the input, and deliver a list of chunks
594         ready for writing.
595
596         """
597
598         chunks = read_doc_file (in_filename)
599
600         #.  Process \mudela and \mudelafile.
601         for func in [find_mudela_shorthand_chunks,
602                      find_mudela_chunks]:
603                 newchunks = []
604                 for c in chunks:
605                         if c[0] == 'input':
606                                 newchunks = newchunks + func (c[1])
607                         else:
608                                 newchunks.append (c)
609                 chunks = newchunks
610
611         opts = []
612         if chunks:
613                 opts = scan_preamble (chunks[0][1]) 
614         
615         (chap,sect,count) = (0,0,0)
616         newchunks = []
617         # Count sections/chapters.
618         for c in chunks:
619                 if c[0] == 'input':
620                         (chap,sect,count) = advance_counters((chap,sect,count), opts, c[1])
621                 elif c[0] == 'mudela':
622                         base = '%s-%d.%d.%d' % (out_filename, chap, sect, count)
623                         count = count + 1
624                         c = schedule_mudela_block (base, c, opts)
625                         
626                 newchunks.append (c)
627
628         chunks = newchunks
629         newchunks = []
630
631         # Do It.
632         if __main__.run_lilypond:
633                 compile_all_files (chunks)
634                 
635                 # finishing touch.
636                 for c in chunks:
637                         if c[0] == 'mudela' and 'eps' in c[2]:
638                                 body = re.sub (r"""\\mudelaepswidth{(.*?)}""", find_eps_dims, c[1])
639                                 newchunks.append (('mudela', body))
640                         else:
641                                 newchunks.append (c)
642                 chunks = newchunks
643                 
644         if chunks and chunks[0][0] == 'input':
645                 chunks[0] = ('input', completize_preamble (chunks[0][1]))
646
647         return chunks
648
649 def system (cmd):
650         sys.stderr.write ("invoking `%s'\n" % cmd)
651         st = os.system (cmd)
652         if st:
653                 error ('Error command exited with value %d\n' % st)
654         return st
655
656 def compile_all_files (chunks):
657         eps = []
658         tex = []
659         png = []
660         hash_dict = {}
661
662         for c in chunks:
663                 if c[0] <> 'mudela':
664                         continue
665                 base  = c[3][0]
666                 exts = c[3][1:]
667                 for e in exts:
668                         if e == 'eps':
669                                 eps.append (base)
670                         elif e == 'tex':
671                                 tex.append (base + '.ly')
672                         elif e == 'png':
673                                 png.append (base)
674
675                 if __main__.use_hash:
676                         hash_dict[c[4]] = c[3][0]
677
678         if tex:
679                 lilyopts = map (lambda x:  '-I ' + x, include_path)
680                 lilyopts = string.join (lilyopts, ' ' )
681                 texfiles = string.join (tex, ' ')
682                 system ('lilypond %s %s' % (lilyopts, texfiles))
683
684         for e in eps:
685                 cmd = r"""tex '\nonstopmode \input %s'; dvips -E -o %s %s""" % \
686                       (e, e + '.eps', e)
687                 system (cmd)
688
689         for g in png:
690                 cmd = r"""gs -sDEVICE=pgm  -dTextAlphaBits=4 -dGraphicsAlphaBits=4  -q -sOutputFile=- -r90 -dNOPAUSE %s -c quit | pnmcrop | pnmtopng > %s"""
691
692                 cmd = cmd % (g + '.eps', g + '.png')
693                 system (cmd)
694
695         if __main__.use_hash:
696                 name = ''
697                 last_name = ''
698                 f = 0
699                 ks = hash_dict.keys ()
700                 ks.sort ()
701                 for i in ks:
702                         name = re.sub ("(.*)-[0-9]+\.[0-9]+\.[0-9]+", "\\1", i)
703                         name = name + '.mix'
704                         if name != last_name:
705                                 if last_name:
706                                         f.close ()
707                                 f = open (name, 'w')
708                                 last_name = name
709                         f.write ("%s:%s\n" % (i, hash_dict[i]))
710
711         
712 def update_file (body, name):
713         same = 0
714         try:
715                 f = open (name)
716                 fs = f.read (-1)
717                 same = (fs == body)
718         except:
719                 pass
720
721         if not same:
722                 f = open (name , 'w')
723                 f.write (body)
724                 f.close ()
725
726         
727         return not same
728
729
730
731 def getopt_args (opts):
732         "Construct arguments (LONG, SHORT) for getopt from  list of options."
733         short = ''
734         long = []
735         for o in opts:
736                 if o[1]:
737                         short = short + o[1]
738                         if o[0]:
739                                 short = short + ':'
740                 if o[2]:
741                         l = o[2]
742                         if o[0]:
743                                 l = l + '='
744                         long.append (l)
745         return (short, long)
746
747 def option_help_str (o):
748         "Transform one option description (4-tuple ) into neatly formatted string"
749         sh = '  '       
750         if o[1]:
751                 sh = '-%s' % o[1]
752
753         sep = ' '
754         if o[1] and o[2]:
755                 sep = ','
756                 
757         long = ''
758         if o[2]:
759                 long= '--%s' % o[2]
760
761         arg = ''
762         if o[0]:
763                 if o[2]:
764                         arg = '='
765                 arg = arg + o[0]
766         return '  ' + sh + sep + long + arg
767
768
769 def options_help_str (opts):
770         "Convert a list of options into a neatly formatted string"
771         w = 0
772         strs =[]
773         helps = []
774         for o in opts:
775                 s = option_help_str (o)
776                 strs.append ((s, o[3]))
777                 if len (s) > w:
778                         w = len (s)
779
780         str = ''
781         for s in strs:
782                 str = str + '%s%s%s\n' % (s[0], ' ' * (w - len(s[0])  + 3), s[1])
783         return str
784
785 def help():
786         sys.stdout.write("""Usage: mudela-book [options] FILE\n
787 Generate hybrid LaTeX input from Latex + mudela
788 Options:
789 """)
790         sys.stdout.write (options_help_str (options))
791         sys.stdout.write (r"""Warning all output is written in the CURRENT directory
792
793
794
795 Report bugs to bug-gnu-music@gnu.org.
796
797 Written by Tom Cato Amundsen <tomcato@xoommail.com> and
798 Han-Wen Nienhuys <hanwen@cs.uu.nl>
799 """)
800
801         sys.exit (0)
802
803
804 def write_deps (fn, target):
805         sys.stdout.write('writing `%s\'\n' % fn)
806
807         f = open (fn, 'w')
808         
809         f.write ('%s%s: ' % (dep_prefix, target))
810         for d in __main__.read_files:
811                 f.write ('%s ' %  d)
812         f.write ('\n')
813         f.close ()
814         __main__.read_files = []
815
816 def identify():
817         sys.stdout.write ('mudela-book (GNU LilyPond) %s\n' % program_version)
818
819 def print_version ():
820         identify()
821         sys.stdout.write (r"""Copyright 1998--1999
822 Distributed under terms of the GNU General Public License. It comes with
823 NO WARRANTY.
824 """)
825
826
827 outname = ''
828 try:
829         (sh, long) = getopt_args (__main__.options)
830         (options, files) = getopt.getopt(sys.argv[1:], sh, long)
831 except getopt.error, msg:
832         sys.stderr.write("error: %s" % msg)
833         sys.exit(1)
834
835 do_deps = 0
836 for opt in options:     
837         o = opt[0]
838         a = opt[1]
839
840         if o == '--include' or o == '-I':
841                 include_path.append (a)
842         elif o == '--version':
843                 print_version ()
844                 sys.exit  (0)
845
846         elif o == '--format' or o == '-o':
847                 __main__.format = a
848         elif o == '--outname' or o == '-o':
849                 if len(files) > 1:
850                         #HACK
851                         sys.stderr.write("Mudela-book is confused by --outname on multiple files")
852                         sys.exit(1)
853                 outname = a
854         elif o == '--help' or o == '-h':
855                 help ()
856         elif o == '--no-lily' or o == '-n':
857                 __main__.run_lilypond = 0
858         elif o == '--dependencies':
859                 do_deps = 1
860         elif o == '--default-mudela-fontsize':
861                 default_music_fontsize = string.atoi (a)
862         elif o == '--init':
863                 initfile =  a
864         elif o == '--dep-prefix':
865                 dep_prefix = a
866
867 identify()
868
869 for input_filename in files:
870         file_settings = {}
871         if outname:
872                 my_outname = outname
873         else:
874                 my_outname = os.path.basename(os.path.splitext(input_filename)[0])
875         my_depname = my_outname + '.dep'                
876
877         chunks = transform_input_file (input_filename, my_outname)
878
879         foutn = my_outname + '.' + format
880         sys.stderr.write ("Writing `%s'\n" % foutn)
881         fout = open (foutn, 'w')
882         for c in chunks:
883                 fout.write (c[1])
884         fout.close ()
885
886         if do_deps:
887                 write_deps (my_depname, foutn)
888
889
890
891 #
892 # Petr, ik zou willen dat ik iets zinvoller deed,
893 # maar wat ik kan ik doen, het verandert toch niets?
894 #   --hwn 20/aug/99