]> git.donarmstrong.com Git - lilypond.git/blob - scripts/lilypond-book.py
message and silly fix
[lilypond.git] / scripts / lilypond-book.py
1 #!@PYTHON@
2 # vim: set noexpandtab:
3 # TODO:
4 # * junk --outdir for --output 
5 # * Figure out clean set of options.
6 # * 
7 # * EndLilyPondOutput is def'd as vfil. Causes large white gaps.
8 # * texinfo: add support for @pagesize
9
10 # todo: dimension handling (all the x2y) is clumsy. (tca: Thats
11 #       because the values are taken directly from texinfo.tex,
12 #       geometry.sty and article.cls. Give me a hint, and I'll
13 #       fix it.)
14
15 #
16 # TODO: magnification support should also work for texinfo -> html: eg. add as option to dvips. 
17
18
19 # This is was the idea for handling of comments:
20 #       Multiline comments, @ignore .. @end ignore is scanned for
21 #       in read_doc_file, and the chunks are marked as 'ignore', so
22 #       lilypond-book will not touch them any more. The content of the
23 #       chunks are written to the output file. Also 'include' and 'input'
24 #       regex has to check if they are commented out.
25 #
26 #       Then it is scanned for 'lilypond', 'lilypond-file' and 'lilypond-block'.
27 #       These three regex's has to check if they are on a commented line,
28 #       % for latex, @c for texinfo.
29 #
30 #       Then lines that are commented out with % (latex) and @c (Texinfo)
31 #       are put into chunks marked 'ignore'. This cannot be done before
32 #       searching for the lilypond-blocks because % is also the comment character
33 #       for lilypond.
34 #
35 #       The the rest of the rexeces are searched for. They don't have to test
36 #       if they are on a commented out line.
37
38
39
40 import os
41 import stat
42 import string
43 import getopt
44 import sys
45 import __main__
46
47 # Handle bug in Python 1.6-2.1
48 #
49 # there are recursion limits for some patterns in Python 1.6 til 2.1. 
50 # fix this by importing the 1.5.2 implementation pre instead. Fix by Mats.
51
52 if float (sys.version[0:3]) < 2.2:
53         try:
54                 import pre
55                 re = pre
56                 del pre
57         except ImportError:
58                 import re
59 else:
60         import re
61
62 # Attempt to fix problems with limited stack size set by Python!
63 # Sets unlimited stack size. Note that the resource module only
64 # is available on UNIX.
65 try:
66        import resource
67        resource.setrlimit (resource.RLIMIT_STACK, (-1, -1))
68 except:
69        pass
70
71 errorport = sys.stderr
72 verbose_p = 0
73
74
75
76 try:
77         import gettext
78         gettext.bindtextdomain ('lilypond', localedir)
79         gettext.textdomain ('lilypond')
80         _ = gettext.gettext
81 except:
82         def _ (s):
83                 return s
84
85 def progress (s):
86         errorport.write (s + '\n')
87
88
89 program_version = '@TOPLEVEL_VERSION@'
90 if program_version == '@' + 'TOPLEVEL_VERSION' + '@':
91         program_version = '1.5.53'
92
93 # if set, LILYPONDPREFIX must take prevalence
94 # if datadir is not set, we're doing a build and LILYPONDPREFIX 
95 datadir = '@local_lilypond_datadir@'
96
97 if os.environ.has_key ('LILYPONDPREFIX') :
98         datadir = os.environ['LILYPONDPREFIX']
99 else:
100         datadir = '@local_lilypond_datadir@'
101
102 while datadir[-1] == os.sep:
103         datadir= datadir[:-1]
104
105 kpse = os.popen ('kpsexpand \$TEXMF').read()
106 kpse = re.sub('[ \t\n]+$','', kpse)
107 type1_paths = os.popen ('kpsewhich -expand-path=\$T1FONTS').read ()
108
109 environment = {
110         # TODO: * prevent multiple addition.
111         #       * clean TEXINPUTS, MFINPUTS, TFMFONTS,
112         #         as these take prevalence over $TEXMF
113         #         and thus may break tex run?
114         'TEXMF' : "{%s,%s}" % (datadir, kpse) ,
115         'GS_FONTPATH' : type1_paths,
116         'GS_LIB' : datadir + '/ps',
117 }
118
119 # tex needs lots of memory, more than it gets by default on Debian
120 non_path_environment = {
121         'extra_mem_top' : '1000000',
122         'extra_mem_bottom' : '1000000',
123         'pool_size' : '250000',
124 }
125
126 def setup_environment ():
127         # $TEXMF is special, previous value is already taken care of
128         if os.environ.has_key ('TEXMF'):
129                 del os.environ['TEXMF']
130  
131         for key in environment.keys ():
132                 val = environment[key]
133                 if os.environ.has_key (key):
134                         val = val + os.pathsep + os.environ[key]
135                 os.environ[key] = val
136
137         for key in non_path_environment.keys ():
138                 val = non_path_environment[key]
139                 os.environ[key] = val
140
141 include_path = [os.getcwd()]
142
143
144 # g_ is for global (?)
145 g_extra_opts = ''
146 g_here_dir = os.getcwd ()
147 g_dep_prefix = ''
148 g_outdir = ''
149 g_force_music_fontsize = 0
150 g_read_lys = 0
151 g_do_pictures = 1
152 g_do_music = 1
153
154 format = ''
155 g_run_lilypond = 1
156 no_match = 'a\ba'
157
158 default_music_fontsize = 16
159 default_text_fontsize = 12
160 paperguru = None
161
162 class LatexPaper:
163         def __init__(self):
164                 self.m_document_preamble = []
165                 self.m_num_cols = 1
166                 self.m_multicols = 1
167         def find_latex_dims(self):
168                 if g_outdir:
169                         fname = os.path.join(g_outdir, "lily-tmp.tex")
170                 else:
171                         fname = "lily-tmp.tex"
172                 try:
173                         f = open(fname, "w")
174                 except IOError:
175                         error ("Error creating temporary file '%s'" % fname)
176                 for s in self.m_document_preamble:
177                         f.write(s)
178                 f.write(r"""
179 \begin{document}
180 \typeout{---}
181 \typeout{\columnsep \the\columnsep}
182 \typeout{\textwidth \the\textwidth}
183 \typeout{---}
184 \end{document}
185                 """)
186                 f.close()
187                 re_dim = re.compile(r"\\(\w+)\s+(\d+\.\d+)")
188                 p = os.popen("latex %s" % fname)
189                 ln = p.readline()
190                 while ln:
191                         ln = string.strip(ln)
192                         m = re_dim.match(ln)
193                         if m:
194                                 if m.groups()[0] in ('textwidth', 'columnsep'):
195                                         self.__dict__['m_%s' % m.groups()[0]] = float(m.groups()[1])
196                         ln = p.readline()
197                 try:
198                         os.remove (fname)
199                         os.remove (os.path.splitext(fname)[0]+".aux")
200                         os.remove (os.path.splitext(fname)[0]+".log")
201                 except:
202                         pass
203         def get_linewidth(self):
204                 if self.m_num_cols == 1:
205                         w = self.m_textwidth
206                 else:
207                         w = (self.m_textwidth - self.m_columnsep)/2
208                 if self.m_multicols > 1:
209                         return (w - self.m_columnsep*(self.m_multicols-1)) \
210                            / self.m_multicols
211                 return w
212
213
214 class HtmlPaper:
215         def __init__(self):
216                 self.m_papersize = 'letterpaper'
217                 self.m_fontsize = 12
218         def get_linewidth(self):
219                 return html_linewidths[self.m_papersize][self.m_fontsize]
220
221 class TexiPaper:
222         def __init__(self):
223                 self.m_papersize = 'letterpaper'
224                 self.m_fontsize = 12
225         def get_linewidth(self):
226                 return texi_linewidths[self.m_papersize][self.m_fontsize]
227
228 def mm2pt(x):
229         return x * 2.8452756
230 def in2pt(x):
231         return x * 72.26999
232 def em2pt(x, fontsize = 10):
233         return {10: 10.00002, 11: 10.8448, 12: 11.74988}[fontsize] * x
234 def ex2pt(x, fontsize = 10):
235         return {10: 4.30554, 11: 4.7146, 12: 5.16667}[fontsize] * x
236
237 def pt2pt(x):
238         return x
239
240 dimension_conversion_dict ={
241         'mm': mm2pt,
242         'cm': lambda x: mm2pt(10*x),
243         'in': in2pt,
244         'em': em2pt,
245         'ex': ex2pt,
246         'pt': pt2pt
247         }
248
249 # Convert numeric values, with or without specific dimension, to floats.
250 # Keep other strings
251 def conv_dimen_to_float(value):
252         if type(value) == type(""):
253                 m = re.match ("([0-9.]+)(cm|in|pt|mm|em|ex)",value)
254                 if m:
255                         unit = m.group (2)
256                         num = string.atof(m.group (1))
257                         conv =  dimension_conversion_dict[m.group(2)]
258                         
259                         value = conv(num)
260                 
261                 elif re.match ("^[0-9.]+$",value):
262                         value = float(value)
263
264         return value
265
266 texi_linewidths = {
267         'afourpaper': {12: mm2pt(160)},
268         'afourwide': {12: in2pt(6.5)},
269         'afourlatex': {12: mm2pt(150)},
270         'smallbook': {12: in2pt(5)},
271         'letterpaper': {12: in2pt(6)}}
272
273 html_linewidths = {
274         'afourpaper': {12: mm2pt(160)},
275         'afourwide': {12: in2pt(6.5)},
276         'afourlatex': {12: mm2pt(150)},
277         'smallbook': {12: in2pt(5)},
278         'letterpaper': {12: in2pt(6)}}
279
280 option_definitions = [
281         ('EXT', 'f', 'format', 'use output format EXT (texi [default], latex, html)'),
282         ('DIM',  '', 'default-music-fontsize', 'default fontsize for music.  DIM is assumed to be in points'),
283         ('DIM',  '', 'default-lilypond-fontsize', 'deprecated, use --default-music-fontsize'),
284         ('OPT', '', 'extra-options' , 'Pass OPT quoted to the lilypond command line'),
285         ('DIM', '', 'force-music-fontsize', 'force fontsize for all inline lilypond. DIM is assumed be to in points'),
286         ('DIM', '', 'force-lilypond-fontsize', 'deprecated, use --force-music-fontsize'),
287         ('', 'h', 'help', 'this help'),
288         ('DIR', 'I', 'include', 'include path'),
289         ('', 'M', 'dependencies', 'write dependencies'),
290         ('PREF', '',  'dep-prefix', 'prepend PREF before each -M dependency'),
291         ('', 'n', 'no-lily', 'don\'t run lilypond'),
292         ('', '', 'no-pictures', "don\'t generate pictures"),
293         ('', '', 'no-music', "strip all lilypond blocks from output"),  
294         ('', '', 'read-lys', "don't write ly files."),
295         ('FILE', 'o', 'outname', 'filename main output file'),
296         ('FILE', '', 'outdir', "where to place generated files"),
297         ('', 'V', 'verbose', 'verbose' ),
298         ('', 'v', 'version', 'print version information' ),
299         ]
300
301 # format specific strings, ie. regex-es for input, and % strings for output
302 output_dict= {
303         'html' : {'output-lilypond': '''<lilypond%s>
304 %s
305 </lilypond>''',
306                 'output-filename' : r'''
307 <!-- %s >
308 <a href="%s">
309 <pre>%s</pre></a>:''',    
310                   'output-lilypond-fragment': '''<lilypond%s>
311 \context Staff\context Voice{ %s }
312 </lilypond>''',
313                   'output-noinline': r'''
314 <!-- generated: %(fn)s.png !-->
315 ''',
316                   ## maybe <hr> ?
317                   'pagebreak': None,
318                   'output-verbatim': r'''<pre>
319 %s
320 </pre>''',
321                   'output-small-verbatim': r'''<font size=-1><pre>
322 %s
323 </pre></font>''',
324
325                   ## Ugh we need to differentiate on origin:
326                   ## lilypond-block origin wants an extra <p>, but
327                   ## inline music doesn't.
328                   ## possibly other center options?
329                   'output-all': r'''
330 <a href="%(fn)s.png">
331 <img align="center" valign="center" border="0" src="%(fn)s.png" alt="[picture of music]"></a>
332 ''',
333                   },
334         'latex': {
335                 'output-lilypond-fragment' : r'''\begin[eps,singleline,%s]{lilypond}
336   \context Staff <
337     \context Voice{
338       %s
339     }
340   >
341 \end{lilypond}''',
342                 'output-filename' : r'''
343 \verb+%s+:
344 %% %s
345 %% %s
346 ''',
347                 'output-lilypond': r'''\begin[%s]{lilypond}
348 %s
349 \end{lilypond}
350 ''',
351                 'output-verbatim': r'''\begin{verbatim}%s\end{verbatim}%%
352 ''',
353                 'output-small-verbatim': r'''{\small\begin{verbatim}%s\end{verbatim}}%%''',
354                 'output-default-post': "\\def\postLilypondExample{}\n",
355                 'output-default-pre': "\\def\preLilypondExample{}\n",
356                 'usepackage-graphics': '\\usepackage{graphics}\n',
357                 'output-eps': '\\noindent\\parbox{\\lilypondepswidth{%(fn)s.eps}}{\includegraphics{%(fn)s}}',
358                 'output-noinline': r'''
359 %% generated: %(fn)s.eps
360 ''',
361                 'output-tex': '{\\preLilypondExample \\input %(fn)s.tex \\postLilypondExample\n}',
362                 'pagebreak': r'\pagebreak',
363                 },
364         
365         'texi' : {'output-lilypond': '''@lilypond[%s]
366 %s
367 @end lilypond 
368 ''',
369                 'output-filename' : r'''
370 @ifnothtml
371 @file{%s}:
372 @end ifnothtml
373 @ifhtml
374 @uref{%s,@file{%s}}
375 @end ifhtml
376 ''',      
377                   'output-lilypond-fragment': '''@lilypond[%s]
378 \context Staff\context Voice{ %s }
379 @end lilypond ''',
380                   'output-noinline': r'''
381 @c generated: %(fn)s.png                  
382 ''',
383                   'pagebreak': None,
384                   'output-small-verbatim': r'''@smallexample
385 %s
386 @end smallexample
387 ''',
388                   'output-verbatim': r'''@example
389 %s
390 @end example
391 ''',
392
393 # do some tweaking: @ is needed in some ps stuff.
394 # override EndLilyPondOutput, since @tex is done
395 # in a sandbox, you can't do \input lilyponddefs at the
396 # top of the document.
397
398 # should also support fragment in
399
400 # ugh, the <p> below breaks inline images...
401                   
402                   'output-all': r'''
403 @tex
404 \catcode`\@=12
405 \input lilyponddefs
406 \def\EndLilyPondOutput{}
407 \input %(fn)s.tex
408 \catcode`\@=0
409 @end tex
410 @html
411 <p>
412 <a href="%(fn)s.png">
413 <img border=0 src="%(fn)s.png" alt="[picture of music]">
414 </a>
415 @end html
416 ''',
417                 }
418         
419         }
420
421 def output_verbatim (body, small):
422         if __main__.format == 'html':
423                 body = re.sub ('&', '&amp;', body)
424                 body = re.sub ('>', '&gt;', body)
425                 body = re.sub ('<', '&lt;', body)
426         elif __main__.format == 'texi':
427                 body = re.sub ('([@{}])', '@\\1', body)
428
429         if small:
430                 key = 'output-small-verbatim'
431         else:
432                 key = 'output-verbatim'
433         return get_output (key) % body
434
435
436 #warning: this uses extended regular expressions. Tread with care.
437
438 # legenda
439
440 # (?P  -- name parameter
441 # *? -- match non-greedily.
442 # (?m)  -- ?  
443 re_dict = {
444         'html': {
445                  'include':  no_match,
446                  'input': no_match,
447                  'header': no_match,
448                  'preamble-end': no_match,
449                  'landscape': no_match,
450                  'verbatim': r'''(?s)(?P<code><pre>\s.*?</pre>\s)''',
451                  'verb': r'''(?P<code><pre>.*?</pre>)''',
452                  'lilypond-file': r'(?m)(?P<match><lilypondfile(?P<options>[^>]+)?>\s*(?P<filename>[^<]+)\s*</lilypondfile>)',
453                  'lilypond' : '(?m)(?P<match><lilypond((?P<options>[^:]*):)(?P<code>.*?)/>)',
454                  'lilypond-block': r'''(?ms)(?P<match><lilypond(?P<options>[^>]+)?>(?P<code>.*?)</lilypond>)''',
455                   'option-sep' : '\s*',
456                   'intertext': r',?\s*intertext=\".*?\"',
457                   'multiline-comment': r"(?sm)\s*(?!@c\s+)(?P<code><!--\s.*?!-->)\s",
458                   'singleline-comment': no_match,
459                   'numcols': no_match,
460                   'multicols': no_match,
461                  },
462         
463         'latex': {'input': r'(?m)^[^%\n]*?(?P<match>\\mbinput{?([^}\t \n}]*))',
464                   'include': r'(?m)^[^%\n]*?(?P<match>\\mbinclude{(?P<filename>[^}]+)})',
465                   'option-sep' : ',\s*',
466                   'header': r"\n*\\documentclass\s*(\[.*?\])?",
467                   'preamble-end': r'(?P<code>\\begin{document})',
468                   'verbatim': r"(?s)(?P<code>\\begin{verbatim}.*?\\end{verbatim})",
469                   'verb': r"(?P<code>\\verb(?P<del>.).*?(?P=del))",
470                   'lilypond-file': r'(?m)^[^%\n]*?(?P<match>\\lilypondfile\s*(\[(?P<options>.*?)\])?\s*\{(?P<filename>.+)})',
471                   'lilypond' : r'(?m)^[^%\n]*?(?P<match>\\lilypond\s*(\[(?P<options>.*?)\])?\s*{(?P<code>.*?)})',
472                   'lilypond-block': r"(?sm)^[^%\n]*?(?P<match>\\begin\s*(\[(?P<options>.*?)\])?\s*{lilypond}(?P<code>.*?)\\end{lilypond})",
473                   'def-post-re': r"\\def\\postLilypondExample",
474                   'def-pre-re': r"\\def\\preLilypondExample",
475                   'usepackage-graphics': r"\usepackage{graphics}",
476                   'intertext': r',?\s*intertext=\".*?\"',
477                   'multiline-comment': no_match,
478                   'singleline-comment': r"(?m)^.*?(?P<match>(?P<code>^%.*$\n+))",
479                   'numcols': r"(?P<code>\\(?P<num>one|two)column)",
480                   'multicols': r"(?P<code>\\(?P<be>begin|end){multicols}({(?P<num>\d+)?})?)",
481                   },
482
483
484         # why do we have distinction between @mbinclude and @include?
485
486         
487         'texi': {
488                  'include':  '(?m)^[^%\n]*?(?P<match>@mbinclude[ \n\t]+(?P<filename>[^\t \n]*))',
489                  'input': no_match,
490                  'header': no_match,
491                  'preamble-end': no_match,
492                  'landscape': no_match,
493                  'verbatim': r'''(?s)(?P<code>@example\s.*?@end example\s)''',
494                  'verb': r'''(?P<code>@code{.*?})''',
495                  'lilypond-file': '(?m)^(?P<match>@lilypondfile(\[(?P<options>[^]]*)\])?{(?P<filename>[^}]+)})',
496                  'lilypond' : '(?m)^(?P<match>@lilypond(\[(?P<options>[^]]*)\])?{(?P<code>.*?)})',
497                  'lilypond-block': r'''(?ms)^(?P<match>@lilypond(\[(?P<options>[^]]*)\])?\s(?P<code>.*?)@end +lilypond)\s''',
498                  'option-sep' : ',\s*',
499                  'intertext': r',?\s*intertext=\".*?\"',
500                  'multiline-comment': r"(?sm)^\s*(?!@c\s+)(?P<code>@ignore\s.*?@end ignore)\s",
501                  'singleline-comment': r"(?m)^.*?(?P<match>(?P<code>@c.*$\n+))",
502                  'numcols': no_match,
503                  'multicols': no_match,
504                  }
505         }
506
507
508 for r in re_dict.keys ():
509         olddict = re_dict[r]
510         newdict = {}
511         for k in olddict.keys ():
512                 try:
513                         newdict[k] = re.compile (olddict[k])
514                 except:
515                         print 'invalid regexp: %s' % olddict[k]
516
517                         # we'd like to catch and reraise a more detailed  error, but
518                         # alas, the exceptions changed across the 1.5/2.1 boundary.
519                         raise "Invalid re"
520         re_dict[r] = newdict
521
522         
523 def uniq (list):
524         list.sort ()
525         s = list
526         list = []
527         for x in s:
528                 if x not in list:
529                         list.append (x)
530         return list
531                 
532
533 def get_output (name):
534         return  output_dict[format][name]
535
536 def get_re (name):
537         return  re_dict[format][name]
538
539 def bounding_box_dimensions(fname):
540         if g_outdir:
541                 fname = os.path.join(g_outdir, fname)
542         try:
543                 fd = open(fname)
544         except IOError:
545                 error ("Error opening `%s'" % fname)
546         str = fd.read ()
547         s = re.search('%%BoundingBox: ([0-9]+) ([0-9]+) ([0-9]+) ([0-9]+)', str)
548         if s:
549                 
550                 gs = map (lambda x: string.atoi (x), s.groups ())
551                 return (int (gs[2] - gs[0] + 0.5),
552                         int (gs[3] - gs[1] + 0.5))
553         else:
554                 return (0,0)
555
556 def error (str):
557         sys.stderr.write (str + "\n  Exiting ... \n\n")
558         raise 'Exiting.'
559
560
561 def compose_full_body (body, opts):
562         '''Construct the lilypond code to send to Lilypond.
563         Add stuff to BODY using OPTS as options.'''
564         music_size = default_music_fontsize
565         if g_force_music_fontsize:
566                 music_size = g_force_music_fontsize
567         indent = ''
568         linewidth = ''
569         for o in opts:
570                 if not g_force_music_fontsize:
571                         m = re.match ('([0-9]+)pt', o)
572                         if m:
573                                 music_size = string.atoi(m.group (1))
574
575                 m = re.match ('indent=([-.0-9]+)(cm|in|mm|pt)', o)
576                 if m:
577                         f = float (m.group (1))
578                         indent = 'indent = %f\\%s' % (f, m.group (2))
579                         
580                 m = re.match ('linewidth=([-.0-9]+)(cm|in|mm|pt)', o)
581                 if m:
582                         f = float (m.group (1))
583                         linewidth = 'linewidth = %f\\%s' % (f, m.group (2))
584
585         if re.search ('\\\\score', body):
586                 is_fragment = 0
587         else:
588                 is_fragment = 1
589         if 'fragment' in opts:
590                 is_fragment = 1
591         if 'nofragment' in opts:
592                 is_fragment = 0
593
594         if is_fragment and not 'multiline' in opts:
595                 opts.append('singleline')
596                 
597         if 'singleline' in opts:
598                 linewidth = 'linewidth = -1.0'
599         elif not linewidth:
600                 l = __main__.paperguru.get_linewidth ()
601                 linewidth = 'linewidth = %f\pt' % l
602
603         if 'noindent' in opts:
604                 indent = 'indent = 0.0\mm'
605
606         for o in opts:
607                 m= re.search ('relative(.*)', o)
608                 v = 0
609                 if m:
610                         try:
611                                 v = string.atoi (m.group (1))
612                         except ValueError:
613                                 pass
614
615                         v = v + 1
616                         pitch = 'c'
617                         if v < 0:
618                                 pitch = pitch + '\,' * v
619                         elif v > 0:
620                                 pitch = pitch + '\'' * v
621
622                         body = '\\relative %s { %s }' %(pitch, body)
623         
624         if is_fragment:
625                 body = r'''\score { 
626  \notes { %s }
627   \paper { }  
628 }''' % body
629
630         opts = uniq (opts)
631         optstring = string.join (opts, ' ')
632         optstring = re.sub ('\n', ' ', optstring)
633         body = r'''
634 %% Generated automatically by: lilypond-book.py
635 %% options are %s  
636 \include "paper%d.ly"
637 \paper  {
638   %s
639   %s
640
641 ''' % (optstring, music_size, linewidth, indent) + body
642
643         # ughUGH not original options
644         return body
645
646 def scan_html_preamble (chunks):
647         return
648
649 def scan_latex_preamble(chunks):
650         # First we want to scan the \documentclass line
651         # it should be the first non-comment line.
652         # The only thing we really need to know about the \documentclass line
653         # is if there are one or two columns to begin with.
654         idx = 0
655         while 1:
656                 if chunks[idx][0] == 'ignore':
657                         idx = idx + 1
658                         continue
659                 m = get_re ('header').match(chunks[idx][1])
660                 if not m:
661                         error ("Latex documents must start with a \documentclass command")
662                 if m.group (1):
663                         options = re.split (',[\n \t]*', m.group(1)[1:-1])
664                 else:
665                         options = []
666                 if 'twocolumn' in options:
667                         paperguru.m_num_cols = 2
668                 break
669
670         # Then we add everythin before \begin{document} to
671         # paperguru.m_document_preamble so that we can later write this header
672         # to a temporary file in find_latex_dims() to find textwidth.
673         while idx < len(chunks) and chunks[idx][0] != 'preamble-end':
674                 if chunks[idx] == 'ignore':
675                         idx = idx + 1
676                         continue
677                 paperguru.m_document_preamble.append(chunks[idx][1])
678                 idx = idx + 1
679         paperguru.find_latex_dims()
680
681 def scan_texi_preamble (chunks):
682         # this is not bulletproof..., it checks the first 10 chunks
683         for c in chunks[:10]:
684                 if c[0] == 'input':
685                         for s in ('afourpaper', 'afourwide', 'letterpaper',
686                                   'afourlatex', 'smallbook'):
687                                 if string.find(c[1], "@%s" % s) != -1:
688                                         paperguru.m_papersize = s
689
690
691 def scan_preamble (chunks):
692         if __main__.format == 'html':
693                 scan_html_preamble (chunks)
694         elif __main__.format == 'latex':
695                 scan_latex_preamble (chunks)
696         elif __main__.format == 'texi':
697                 scan_texi_preamble (chunks)
698                 
699
700 def completize_preamble (chunks):
701         if __main__.format != 'latex':
702                 return chunks
703         pre_b = post_b = graphics_b = None
704         for chunk in chunks:
705                 if chunk[0] == 'preamble-end':
706                         break
707                 if chunk[0] == 'input':
708                         m = get_re('def-pre-re').search(chunk[1])
709                         if m:
710                                 pre_b = 1
711                 if chunk[0] == 'input':
712                         m = get_re('def-post-re').search(chunk[1])
713                         if m:
714                                 post_b = 1
715                                 
716                 if chunk[0] == 'input':
717                         m = get_re('usepackage-graphics').search(chunk[1])
718                         if m:
719                                 graphics_b = 1
720         x = 0
721         while x < len (chunks) and   chunks[x][0] != 'preamble-end':
722                 x = x + 1
723
724         if x == len(chunks):
725                 return chunks
726         
727         if not pre_b:
728                 chunks.insert(x, ('input', get_output ('output-default-pre')))
729         if not post_b:
730                 chunks.insert(x, ('input', get_output ('output-default-post')))
731         if not graphics_b:
732                 chunks.insert(x, ('input', get_output ('usepackage-graphics')))
733
734         return chunks
735
736
737 read_files = []
738 def find_file (name):
739         '''
740         Search the include path for NAME. If found, return the (CONTENTS, PATH) of the file.
741         '''
742
743         if name == '-':
744                 return (sys.stdin.read (), '<stdin>')
745         f = None
746         nm = ''
747         for a in include_path:
748                 try:
749                         nm = os.path.join (a, name)
750                         f = open (nm)
751                         __main__.read_files.append (nm)
752                         break
753                 except IOError:
754                         pass
755         if f:
756                 sys.stderr.write ("Reading `%s'\n" % nm)
757                 return (f.read (), nm)
758         else:
759                 error ("File not found `%s'\n" % name)
760                 return ('', '')
761
762 def do_ignore(match_object):
763         return [('ignore', match_object.group('code'))]
764 def do_preamble_end(match_object):
765         return [('preamble-end', match_object.group('code'))]
766
767 def make_verbatim(match_object):
768         return [('verbatim', match_object.group('code'))]
769
770 def make_verb(match_object):
771         return [('verb', match_object.group('code'))]
772
773 def do_include_file(m):
774         "m: MatchObject"
775         return [('input', get_output ('pagebreak'))] \
776              + read_doc_file(m.group('filename')) \
777              + [('input', get_output ('pagebreak'))] 
778
779 def do_input_file(m):
780         return read_doc_file(m.group('filename'))
781
782 def make_lilypond(m):
783         if m.group('options'):
784                 options = m.group('options')
785         else:
786                 options = ''
787         return [('input', get_output('output-lilypond-fragment') % 
788                         (options, m.group('code')))]
789
790 def make_lilypond_file(m):
791         '''
792
793         Find @lilypondfile{bla.ly} occurences and substitute bla.ly
794         into a @lilypond .. @end lilypond block.
795         
796         '''
797         
798         if m.group('options'):
799                 options = m.group('options')
800         else:
801                 options = ''
802         (content, nm) = find_file(m.group('filename'))
803         options = "filename=%s," % nm + options
804
805         return [('input', get_output('output-lilypond') %
806                         (options, content))]
807
808 def make_lilypond_block(m):
809         if not g_do_music:
810                 return []
811         
812         if m.group('options'):
813                 options = get_re('option-sep').split (m.group('options'))
814         else:
815             options = []
816         options = filter(lambda s: s != '', options)
817         return [('lilypond', m.group('code'), options)]
818
819 def do_columns(m):
820         if __main__.format != 'latex':
821                 return []
822         if m.group('num') == 'one':
823                 return [('numcols', m.group('code'), 1)]
824         if m.group('num') == 'two':
825                 return [('numcols', m.group('code'), 2)]
826
827 def do_multicols(m):
828         if __main__.format != 'latex':
829                 return []
830         if m.group('be') == 'begin':
831                 return [('multicols', m.group('code'), int(m.group('num')))]
832         else:
833                 return [('multicols', m.group('code'), 1)]
834         return []
835
836 def chop_chunks(chunks, re_name, func, use_match=0):
837         newchunks = []
838         for c in chunks:
839                 if c[0] == 'input':
840                         str = c[1]
841                         while str:
842                                 m = get_re (re_name).search (str)
843                                 if m == None:
844                                         newchunks.append (('input', str))
845                                         str = ''
846                                 else:
847                                         if use_match:
848                                                 newchunks.append (('input', str[:m.start ('match')]))
849                                         else:
850                                                 newchunks.append (('input', str[:m.start (0)]))
851                                         #newchunks.extend(func(m))
852                                         # python 1.5 compatible:
853                                         newchunks = newchunks + func(m)
854                                         str = str [m.end(0):]
855                 else:
856                         newchunks.append(c)
857         return newchunks
858
859 def determine_format (str):
860         if __main__.format == '':
861                 
862                 html = re.search ('(?i)<[dh]tml', str[:200])
863                 latex = re.search (r'''\\document''', str[:200])
864                 texi = re.search ('@node|@setfilename', str[:200])
865
866                 f = ''
867                 g = None
868                 
869                 if html and not latex and not texi:
870                         f = 'html'
871                 elif latex and not html and not texi:
872                         f = 'latex'
873                 elif texi and not html and not latex:
874                         f = 'texi'
875                 else:
876                         error ("can't determine format, please specify")
877                 __main__.format = f
878
879         if __main__.paperguru == None:
880                 if __main__.format == 'html':
881                         g = HtmlPaper ()
882                 elif __main__.format == 'latex':
883                         g = LatexPaper ()
884                 elif __main__.format == 'texi':
885                         g = TexiPaper ()
886                         
887                 __main__.paperguru = g
888
889
890 def read_doc_file (filename):
891         '''Read the input file, find verbatim chunks and do \input and \include
892         '''
893         (str, path) = find_file(filename)
894         determine_format (str)
895         
896         chunks = [('input', str)]
897         
898         # we have to check for verbatim before doing include,
899         # because we don't want to include files that are mentioned
900         # inside a verbatim environment
901         chunks = chop_chunks(chunks, 'verbatim', make_verbatim)
902         chunks = chop_chunks(chunks, 'verb', make_verb)
903         chunks = chop_chunks(chunks, 'multiline-comment', do_ignore)
904         #ugh fix input
905         chunks = chop_chunks(chunks, 'include', do_include_file, 1)
906         chunks = chop_chunks(chunks, 'input', do_input_file, 1)
907         return chunks
908
909
910 taken_file_names = {}
911 def schedule_lilypond_block (chunk):
912         '''Take the body and options from CHUNK, figure out how the
913         real .ly should look, and what should be left MAIN_STR (meant
914         for the main file).  The .ly is written, and scheduled in
915         TODO.
916
917         Return: a chunk (TYPE_STR, MAIN_STR, OPTIONS, TODO, BASE)
918
919         TODO has format [basename, extension, extension, ... ]
920         
921         '''
922         (type, body, opts) = chunk
923         assert type == 'lilypond'
924         file_body = compose_full_body (body, opts)
925         ## Hmm, we should hash only lilypond source, and skip the
926         ## %options are ...
927         ## comment line
928         basename = 'lily-' + `abs(hash (file_body))`
929         for o in opts:
930                 m = re.search ('filename="(.*?)"', o)
931                 if m:
932                         basename = m.group (1)
933                         if not taken_file_names.has_key(basename):
934                                 taken_file_names[basename] = 0
935                         else:
936                                 taken_file_names[basename] = taken_file_names[basename] + 1
937                                 basename = basename + "-%i" % taken_file_names[basename]
938         if not g_read_lys:
939                 update_file(file_body, os.path.join(g_outdir, basename) + '.ly')
940         needed_filetypes = ['tex']
941
942         if format == 'html' or format == 'texi':
943                 needed_filetypes.append ('eps')
944                 needed_filetypes.append ('png')
945         if 'eps' in opts and not ('eps' in needed_filetypes):
946                 needed_filetypes.append('eps')
947         pathbase = os.path.join (g_outdir, basename)
948         def f (base, ext1, ext2):
949                 a = os.path.isfile(base + ext2)
950                 if (os.path.isfile(base + ext1) and
951                     os.path.isfile(base + ext2) and
952                                 os.stat(base+ext1)[stat.ST_MTIME] >
953                                 os.stat(base+ext2)[stat.ST_MTIME]) or \
954                                 not os.path.isfile(base + ext2):
955                         return 1
956         todo = []
957         if 'tex' in needed_filetypes and f(pathbase, '.ly', '.tex'):
958                 todo.append('tex')
959         if 'eps' in needed_filetypes and f(pathbase, '.tex', '.eps'):
960                 todo.append('eps')
961         if 'png' in needed_filetypes and f(pathbase, '.eps', '.png'):
962                 todo.append('png')
963         newbody = ''
964
965         if 'printfilename' in opts:
966                 for o in opts:
967                         m= re.match ("filename=(.*)", o)
968                         if m:
969                                 newbody = newbody + get_output ("output-filename") % (m.group(1), basename + '.ly', m.group(1))
970                                 break
971                 
972
973         if 'smallverbatim' in opts:
974                 newbody = newbody + output_verbatim (body, 1)
975         elif 'verbatim' in opts:
976                 newbody = newbody + output_verbatim (body, 0)
977
978         for o in opts:
979                 m = re.search ('intertext="(.*?)"', o)
980                 if m:
981                         newbody = newbody  + m.group (1) + "\n\n"
982         
983         if 'noinline' in opts:
984                 s = 'output-noinline'
985         elif format == 'latex':
986                 if 'eps' in opts:
987                         s = 'output-eps'
988                 else:
989                         s = 'output-tex'
990         else: # format == 'html' or format == 'texi':
991                 s = 'output-all'
992         newbody = newbody + get_output (s) % {'fn': basename }
993         return ('lilypond', newbody, opts, todo, basename)
994
995 def process_lilypond_blocks(chunks):#ugh rename
996         newchunks = []
997         # Count sections/chapters.
998         for c in chunks:
999                 if c[0] == 'lilypond':
1000                         c = schedule_lilypond_block (c)
1001                 elif c[0] == 'numcols':
1002                         paperguru.m_num_cols = c[2]
1003                 elif c[0] == 'multicols':
1004                         paperguru.m_multicols = c[2]
1005                 newchunks.append (c)
1006         return newchunks
1007
1008
1009
1010 def system (cmd):
1011         sys.stderr.write ("invoking `%s'\n" % cmd)
1012         st = os.system (cmd)
1013         if st:
1014                 error ('Error command exited with value %d\n' % st)
1015         return st
1016
1017 def quiet_system (cmd, name):
1018         if not verbose_p:
1019                 progress ( _("Running %s...") % name)
1020                 cmd = cmd + ' 1> /dev/null 2> /dev/null'
1021
1022         return system (cmd)
1023
1024 def get_bbox (filename):
1025         system ('gs -sDEVICE=bbox -q  -sOutputFile=- -dNOPAUSE %s -c quit > %s.bbox 2>&1 ' % (filename, filename))
1026
1027         box = open (filename + '.bbox').read()
1028         m = re.match ('^%%BoundingBox: ([0-9]+) ([0-9]+) ([0-9]+) ([0-9]+)', box)
1029         gr = []
1030         if m:
1031                 gr = map (string.atoi, m.groups ())
1032         
1033         return gr
1034
1035 def make_pixmap (name):
1036         bbox = get_bbox (name + '.eps')
1037         margin = 0
1038         fo = open (name + '.trans.eps' , 'w')
1039         fo.write ('%d %d translate\n' % (-bbox[0]+margin, -bbox[1]+margin))
1040         fo.close ()
1041         
1042         res = 90
1043
1044         x = (2* margin + bbox[2] - bbox[0]) * res / 72.
1045         y = (2* margin + bbox[3] - bbox[1]) * res / 72.
1046
1047         cmd = r'''gs -g%dx%d -sDEVICE=pnggray  -dTextAlphaBits=4 -dGraphicsAlphaBits=4  -q -sOutputFile=- -r%d -dNOPAUSE %s %s -c quit  > %s'''
1048         
1049         cmd = cmd % (x, y, res, name + '.trans.eps', name + '.eps',name + '.png')
1050         status = 0
1051         try:
1052                 status = system (cmd)
1053         except:
1054                 status = -1
1055
1056         if status:
1057                 os.unlink (name + '.png')
1058                 error ("Removing output file")
1059
1060 def compile_all_files (chunks):
1061         global foutn
1062         eps = []
1063         tex = []
1064         png = []
1065
1066         for c in chunks:
1067                 if c[0] != 'lilypond':
1068                         continue
1069                 base  = c[4]
1070                 exts = c[3]
1071                 for e in exts:
1072                         if e == 'eps':
1073                                 eps.append (base)
1074                         elif e == 'tex':
1075                                 #ugh
1076                                 if base + '.ly' not in tex:
1077                                         tex.append (base + '.ly')
1078                         elif e == 'png' and g_do_pictures:
1079                                 png.append (base)
1080         d = os.getcwd()
1081         if g_outdir:
1082                 os.chdir(g_outdir)
1083         if tex:
1084                 # fixme: be sys-independent.
1085                 def incl_opt (x):
1086                         if g_outdir and x[0] != '/' :
1087                                 x = os.path.join (g_here_dir, x)
1088                         return ' -I %s' % x
1089
1090                 incs = map (incl_opt, include_path)
1091                 lilyopts = string.join (incs, ' ' )
1092                 if do_deps:
1093                         lilyopts = lilyopts + ' --dependencies '
1094                         if g_outdir:
1095                                 lilyopts = lilyopts + '--dep-prefix=' + g_outdir + '/'
1096                 texfiles = string.join (tex, ' ')
1097                 cmd = 'lilypond --header=texidoc %s %s %s' \
1098                       % (lilyopts, g_extra_opts, texfiles)
1099
1100                 system (cmd)
1101
1102                 #
1103                 # Ugh, fixing up dependencies for .tex generation
1104                 #
1105                 if do_deps:
1106                         depfiles=map (lambda x: re.sub ('(.*)\.ly', '\\1.dep', x), tex)
1107                         for i in depfiles:
1108                                 f =open (i)
1109                                 text=f.read ()
1110                                 f.close ()
1111                                 text=re.sub ('\n([^:\n]*):', '\n' + foutn + ':', text)
1112                                 f = open (i, 'w')
1113                                 f.write (text)
1114                                 f.close ()
1115
1116         for e in eps:
1117                 cmd = r"echo $TEXMF; tex '\nonstopmode \input %s'" % e
1118                 quiet_system (cmd, 'TeX')
1119                 
1120                 cmd = r"dvips -E -o %s %s" % (e + '.eps', e)
1121                 quiet_system (cmd, 'dvips')
1122                 
1123         for g in png:
1124                 make_pixmap (g)
1125                 
1126         os.chdir (d)
1127
1128
1129 def update_file (body, name):
1130         '''
1131         write the body if it has changed
1132         '''
1133         same = 0
1134         try:
1135                 f = open (name)
1136                 fs = f.read (-1)
1137                 same = (fs == body)
1138         except:
1139                 pass
1140
1141         if not same:
1142                 f = open (name , 'w')
1143                 f.write (body)
1144                 f.close ()
1145         
1146         return not same
1147
1148
1149 def getopt_args (opts):
1150         "Construct arguments (LONG, SHORT) for getopt from  list of options."
1151         short = ''
1152         long = []
1153         for o in opts:
1154                 if o[1]:
1155                         short = short + o[1]
1156                         if o[0]:
1157                                 short = short + ':'
1158                 if o[2]:
1159                         l = o[2]
1160                         if o[0]:
1161                                 l = l + '='
1162                         long.append (l)
1163         return (short, long)
1164
1165 def option_help_str (o):
1166         "Transform one option description (4-tuple ) into neatly formatted string"
1167         sh = '  '       
1168         if o[1]:
1169                 sh = '-%s' % o[1]
1170
1171         sep = ' '
1172         if o[1] and o[2]:
1173                 sep = ','
1174                 
1175         long = ''
1176         if o[2]:
1177                 long= '--%s' % o[2]
1178
1179         arg = ''
1180         if o[0]:
1181                 if o[2]:
1182                         arg = '='
1183                 arg = arg + o[0]
1184         return '  ' + sh + sep + long + arg
1185
1186
1187 def options_help_str (opts):
1188         "Convert a list of options into a neatly formatted string"
1189         w = 0
1190         strs =[]
1191         helps = []
1192
1193         for o in opts:
1194                 s = option_help_str (o)
1195                 strs.append ((s, o[3]))
1196                 if len (s) > w:
1197                         w = len (s)
1198
1199         str = ''
1200         for s in strs:
1201                 str = str + '%s%s%s\n' % (s[0], ' ' * (w - len(s[0])  + 3), s[1])
1202         return str
1203
1204 def help():
1205         sys.stdout.write('''Usage: lilypond-book [options] FILE\n
1206 Generate hybrid LaTeX input from Latex + lilypond
1207 Options:
1208 ''')
1209         sys.stdout.write (options_help_str (option_definitions))
1210         sys.stdout.write (r'''Warning all output is written in the CURRENT directory
1211
1212
1213
1214 Report bugs to bug-lilypond@gnu.org.
1215
1216 Written by Tom Cato Amundsen <tca@gnu.org> and
1217 Han-Wen Nienhuys <hanwen@cs.uu.nl>
1218 ''')
1219
1220         sys.exit (0)
1221
1222
1223 def write_deps (fn, target, chunks):
1224         global read_files
1225         sys.stderr.write('Writing `%s\'\n' % os.path.join(g_outdir, fn))
1226         f = open (os.path.join(g_outdir, fn), 'w')
1227         f.write ('%s%s: ' % (g_dep_prefix, target))
1228         for d in read_files:
1229                 f.write ('%s ' %  d)
1230         basenames=[]
1231         for c in chunks:
1232                 if c[0] == 'lilypond':
1233                         (type, body, opts, todo, basename) = c;
1234                         basenames.append (basename)
1235         for d in basenames:
1236                 if g_outdir:
1237                         d=g_outdir + '/' + d
1238                 if g_dep_prefix:
1239                         #if not os.isfile (d): # thinko?
1240                         if not re.search ('/', d):
1241                                 d = g_dep_prefix + d
1242                 f.write ('%s.tex ' %  d)
1243         f.write ('\n')
1244         #if len (basenames):
1245         #       for d in basenames:
1246         #               f.write ('%s.ly ' %  d)
1247         #       f.write (' : %s' % target)
1248         f.write ('\n')
1249         f.close ()
1250         read_files = []
1251
1252 def identify (stream):
1253         stream.write ('lilypond-book (GNU LilyPond) %s\n' % program_version)
1254
1255 def print_version ():
1256         identify (sys.stdout)
1257         sys.stdout.write (r'''Copyright 1998--1999
1258 Distributed under terms of the GNU General Public License. It comes with
1259 NO WARRANTY.
1260 ''')
1261
1262
1263 def check_texidoc (chunks):
1264         n = []
1265         for c in chunks:
1266                 if c[0] == 'lilypond':
1267                         (type, body, opts, todo, basename) = c;
1268                         pathbase = os.path.join (g_outdir, basename)
1269                         if os.path.isfile (pathbase + '.texidoc'):
1270                                 body = '\n@include %s.texidoc\n' % basename + body
1271                                 c = (type, body, opts, todo, basename)
1272                 n.append (c)
1273         return n
1274
1275
1276 ## what's this? Docme --hwn
1277 ##
1278 def fix_epswidth (chunks):
1279         newchunks = []
1280         for c in chunks:
1281                 if c[0] != 'lilypond' or 'eps' not in c[2]:
1282                         newchunks.append (c)
1283                         continue
1284
1285                 mag = 1.0
1286                 for o in c[2]:
1287                         m  = re.match ('magnification=([0-9.]+)', o)
1288                         if m:
1289                                 mag = string.atof (m.group (1))
1290
1291                 def replace_eps_dim (match, lmag = mag):
1292                         filename = match.group (1)
1293                         dims = bounding_box_dimensions (filename)
1294
1295                         return '%fpt' % (dims[0] *lmag)
1296         
1297                 body = re.sub (r'''\\lilypondepswidth{(.*?)}''', replace_eps_dim, c[1])
1298                 newchunks.append(('lilypond', body, c[2], c[3], c[4]))
1299                         
1300         return newchunks
1301
1302
1303 ##docme: why global?
1304 foutn=""
1305 def do_file(input_filename):
1306
1307         chunks = read_doc_file(input_filename)
1308         chunks = chop_chunks(chunks, 'lilypond', make_lilypond, 1)
1309         chunks = chop_chunks(chunks, 'lilypond-file', make_lilypond_file, 1)
1310         chunks = chop_chunks(chunks, 'lilypond-block', make_lilypond_block, 1)
1311         chunks = chop_chunks(chunks, 'singleline-comment', do_ignore, 1)
1312         chunks = chop_chunks(chunks, 'preamble-end', do_preamble_end)
1313         chunks = chop_chunks(chunks, 'numcols', do_columns)
1314         chunks = chop_chunks(chunks, 'multicols', do_multicols)
1315         #print "-" * 50
1316         #for c in chunks: print "c:", c;
1317         #sys.exit()
1318         scan_preamble(chunks)
1319         chunks = process_lilypond_blocks(chunks)
1320
1321         # Do It.
1322         if __main__.g_run_lilypond:
1323                 compile_all_files (chunks)
1324                 chunks = fix_epswidth (chunks)
1325
1326         if __main__.format == 'texi':
1327                 chunks = check_texidoc (chunks)
1328
1329         x = 0
1330         chunks = completize_preamble (chunks)
1331
1332
1333         global foutn
1334
1335         if outname:
1336                 my_outname = outname
1337         elif input_filename == '-' or input_filename == "/dev/stdin":
1338                 my_outname = '-'
1339         else:
1340                 my_outname = os.path.basename (os.path.splitext(input_filename)[0]) + '.' + format
1341         my_depname = my_outname + '.dep'                
1342         
1343         if my_outname == '-' or my_outname == '/dev/stdout':
1344                 fout = sys.stdout
1345                 foutn = "<stdout>"
1346                 __main__.do_deps = 0
1347         else:
1348                 foutn = os.path.join (g_outdir, my_outname)
1349                 sys.stderr.write ("Writing `%s'\n" % foutn)
1350                 fout = open (foutn, 'w')
1351         for c in chunks:
1352                 fout.write (c[1])
1353         fout.close ()
1354         # should chmod -w
1355
1356         if do_deps:
1357                 write_deps (my_depname, foutn, chunks)
1358
1359 outname = ''
1360 try:
1361         (sh, long) = getopt_args (__main__.option_definitions)
1362         (options, files) = getopt.getopt(sys.argv[1:], sh, long)
1363 except getopt.error, msg:
1364         sys.stderr.write("error: %s" % msg)
1365         sys.exit(1)
1366
1367 do_deps = 0
1368 for opt in options:     
1369         o = opt[0]
1370         a = opt[1]
1371
1372         if o == '--include' or o == '-I':
1373                 include_path.append (a)
1374         elif o == '--version' or o == '-v':
1375                 print_version ()
1376                 sys.exit  (0)
1377         elif o == '--verbose' or o == '-V':
1378                 __main__.verbose_p = 1
1379         elif o == '--format' or o == '-f':
1380                 __main__.format = a
1381         elif o == '--outname' or o == '-o':
1382                 if len(files) > 1:
1383                         #HACK
1384                         sys.stderr.write("Lilypond-book is confused by --outname on multiple files")
1385                         sys.exit(1)
1386                 outname = a
1387         elif o == '--help' or o == '-h':
1388                 help ()
1389         elif o == '--no-lily' or o == '-n':
1390                 __main__.g_run_lilypond = 0
1391         elif o == '--dependencies' or o == '-M':
1392                 do_deps = 1
1393         elif o == '--default-music-fontsize':
1394                 default_music_fontsize = string.atoi (a)
1395         elif o == '--default-lilypond-fontsize':
1396                 print "--default-lilypond-fontsize is deprecated, use --default-music-fontsize"
1397                 default_music_fontsize = string.atoi (a)
1398         elif o == '--extra-options':
1399                 g_extra_opts = a
1400         elif o == '--force-music-fontsize':
1401                 g_force_music_fontsize = string.atoi(a)
1402         elif o == '--force-lilypond-fontsize':
1403                 print "--force-lilypond-fontsize is deprecated, use --default-lilypond-fontsize"
1404                 g_force_music_fontsize = string.atoi(a)
1405         elif o == '--dep-prefix':
1406                 g_dep_prefix = a
1407         elif o == '--no-pictures':
1408                 g_do_pictures = 0
1409         elif o == '--no-music':
1410                 g_do_music = 0
1411         elif o == '--read-lys':
1412                 g_read_lys = 1
1413         elif o == '--outdir':
1414                 g_outdir = a
1415
1416 identify (sys.stderr)
1417 if g_outdir:
1418         if os.path.isfile(g_outdir):
1419                 error ("outdir is a file: %s" % g_outdir)
1420         if not os.path.exists(g_outdir):
1421                 os.mkdir(g_outdir)
1422 setup_environment ()
1423 for input_filename in files:
1424         do_file(input_filename)
1425         
1426 #
1427 # Petr, ik zou willen dat ik iets zinvoller deed,
1428 # maar wat ik kan ik doen, het verandert toch niets?
1429 #   --hwn 20/aug/99