]> git.donarmstrong.com Git - lilypond.git/blob - scripts/ly2dvi.py
81011a87ab46e558412f5307da618fe02fe04036
[lilypond.git] / scripts / ly2dvi.py
1 #!@PYTHON@
2 # Run lilypond, latex, dvips.
3 #
4 # This is the third incarnation of ly2dvi.
5 #
6 # Earlier incarnations of ly2dvi were written by
7 # Jeffrey B. Reed<daboys@austin.rr.com> (Python version)
8 # Jan Arne Fagertun <Jan.A.Fagertun@@energy.sintef.no> (Bourne shell script)
9 #
10
11
12
13 # TODO: should allow to set a central pk cache directory from the command line.
14 # TODO: should allow to switch off pk cache.
15 #
16
17
18 # Note: gettext work best if we use ' for docstrings and "
19 # for gettextable strings
20
21 '''
22 TODO:
23
24   * figure out which set of command line options should make ly2dvi:
25
26       na: create tex only?  
27       na: create latex only? 
28       na: create tex and latex
29       default: create dvi only
30       na: create tex, latex and dvi
31       -P: create dvi and ps
32       na: * create ps only
33
34      etc.
35
36      for foo.ly, rename ly2dvi.dir to out-ly2dvi, foo.ly2dvi, foo.dir ?
37      
38   * move versatile taglines, 
39   
40      \header {
41         beginfooter=\mutopiaPD
42         endfooter=\tagline  -> 'lily was here <version>'
43      }
44
45      lilytagline (->lily was here), usertagline, copyright etc.
46
47   * head/header tagline/endfooter
48
49   * dvi from lilypond .tex output?  This is hairy, because we create dvi
50     from lilypond .tex *and* header output.
51
52   * multiple \score blocks?
53   
54 '''
55
56
57 import os
58 import stat
59 import string
60 import re
61 import getopt
62 import sys
63 import shutil
64 import __main__
65 import operator
66 import tempfile
67
68 datadir = '@datadir@'
69 sys.path.append (datadir + '/python')
70 try:
71         import gettext
72         gettext.bindtextdomain ('lilypond', '@localedir@')
73         gettext.textdomain('lilypond')
74         _ = gettext.gettext
75 except:
76         def _ (s):
77                 return s
78
79
80 layout_fields = ['dedication', 'title', 'subtitle', 'subsubtitle',
81           'footer', 'head', 'composer', 'arranger', 'instrument',
82           'opus', 'piece', 'metre', 'meter', 'poet', 'texttranslator']
83
84
85 # init to empty; values here take precedence over values in the file
86
87 ## TODO: change name.
88 extra_init = {
89         'language' : [],
90         'latexheaders' : [],
91         'latexpackages' :  ['geometry'],
92         'latexoptions' : [],
93         'papersize' : [],
94         'pagenumber' : [1],
95         'textheight' : [], 
96         'linewidth' : [],
97         'orientation' : []
98 }
99
100 extra_fields = extra_init.keys ()
101
102 fields = layout_fields + extra_fields
103 program_name = 'ly2dvi'
104 help_summary = _ ("Generate .dvi with LaTeX for LilyPond")
105
106 include_path = ['.']
107 lily_p = 1
108 paper_p = 1
109 cache_pks_p = 1
110
111 PK_PATTERN='feta.*\.[0-9]+pk'
112
113 output_name = ''
114 targets = {
115         'DVI' : 0,
116         'LATEX' : 0,
117         'MIDI' : 0,
118         'TEX' : 0,
119         }
120
121 track_dependencies_p = 0
122 dependency_files = []
123
124
125 # lily_py.py -- options and stuff
126
127 # source file of the GNU LilyPond music typesetter
128
129 # BEGIN Library for these?
130 # cut-n-paste from ly2dvi
131
132 program_version = '@TOPLEVEL_VERSION@'
133 if program_version == '@' + 'TOPLEVEL_VERSION' + '@':
134         program_version = '1.3.148'
135
136
137 original_dir = os.getcwd ()
138 temp_dir = os.path.join (original_dir,  '%s.dir' % program_name)
139
140 keep_temp_dir_p = 0
141 verbose_p = 0
142
143 #
144 # Try to cater for bad installations of LilyPond, that have
145 # broken TeX setup.  Just hope this doesn't hurt good TeX
146 # setups.  Maybe we should check if kpsewhich can find
147 # feta16.{afm,mf,tex,tfm}, and only set env upon failure.
148 #
149 environment = {
150         'MFINPUTS' : ':' + datadir + '/mf',
151         'TEXINPUTS': ':' + datadir + '/tex:' + datadir + '/ps',
152         'TFMFONTS' : ':' + datadir + '/tfm',
153         'GS_FONTPATH' : datadir + '/afm:' + datadir + '/pfa',
154         'GS_LIB' : datadir + '/ps',
155 }
156
157 def setup_environment ():
158         for key in environment.keys ():
159                 val = environment[key]
160                 if os.environ.has_key (key):
161                         val = os.environ[key] + os.pathsep + val 
162                 os.environ[key] = val
163
164 def identify ():
165         sys.stdout.write ('%s (GNU LilyPond) %s\n' % (program_name, program_version))
166
167 def warranty ():
168         identify ()
169         sys.stdout.write ('\n')
170         sys.stdout.write (_ ('Copyright (c) %s by' % ' 2001'))
171         sys.stdout.write ('\n')
172         sys.stdout.write ('  Han-Wen Nienhuys')
173         sys.stdout.write ('  Jan Nieuwenhuizen')
174         sys.stdout.write ('\n')
175         sys.stdout.write (_ (r'''
176 Distributed under terms of the GNU General Public License. It comes with
177 NO WARRANTY.'''))
178         sys.stdout.write ('\n')
179
180 if ( os.name == 'posix' ):
181         errorport=sys.stderr
182 else:
183         errorport=sys.stdout
184
185 def progress (s):
186         errorport.write (s + '\n')
187
188 def warning (s):
189         progress (_ ("warning: ") + s)
190                 
191 def error (s):
192
193
194         """Report the error S.  Exit by raising an exception. Please
195         do not abuse by trying to catch this error. If you donn't want
196         a stack trace, write to the output directly.
197
198         RETURN VALUE
199
200         None
201         
202         """
203         
204         progress (_ ("error: ") + s)
205         raise _ ("Exiting ... ")
206
207 def getopt_args (opts):
208         '''Construct arguments (LONG, SHORT) for getopt from  list of options.'''
209         short = ''
210         long = []
211         for o in opts:
212                 if o[1]:
213                         short = short + o[1]
214                         if o[0]:
215                                 short = short + ':'
216                 if o[2]:
217                         l = o[2]
218                         if o[0]:
219                                 l = l + '='
220                         long.append (l)
221         return (short, long)
222
223 def option_help_str (o):
224         '''Transform one option description (4-tuple ) into neatly formatted string'''
225         sh = '  '       
226         if o[1]:
227                 sh = '-%s' % o[1]
228
229         sep = ' '
230         if o[1] and o[2]:
231                 sep = ','
232                 
233         long = ''
234         if o[2]:
235                 long= '--%s' % o[2]
236
237         arg = ''
238         if o[0]:
239                 if o[2]:
240                         arg = '='
241                 arg = arg + o[0]
242         return '  ' + sh + sep + long + arg
243
244
245 def options_help_str (opts):
246         '''Convert a list of options into a neatly formatted string'''
247         w = 0
248         strs =[]
249         helps = []
250
251         for o in opts:
252                 s = option_help_str (o)
253                 strs.append ((s, o[3]))
254                 if len (s) > w:
255                         w = len (s)
256
257         str = ''
258         for s in strs:
259                 str = str + '%s%s%s\n' % (s[0], ' ' * (w - len(s[0])  + 3), s[1])
260         return str
261
262 def help ():
263         ls = [(_ ("Usage: %s [OPTION]... FILE") % program_name),
264                 ('\n\n'),
265                 (help_summary),
266                 ('\n\n'),
267                 (_ ("Options:")),
268                 ('\n'),
269                 (options_help_str (option_definitions)),
270                 ('\n\n'),
271                 (_ ("Report bugs to %s") % 'bug-gnu-music@gnu.org'),
272                 ('\n')]
273         map (sys.stdout.write, ls)
274         
275 def setup_temp ():
276         """
277         Create a temporary directory, and return its name. 
278         """
279         global temp_dir
280         if not keep_temp_dir_p:
281                 temp_dir = tempfile.mktemp (program_name)
282         try:
283                 os.mkdir (temp_dir, 0777)
284         except OSError:
285                 pass
286
287         return temp_dir
288
289
290 def system (cmd, ignore_error = 0):
291         """Run CMD. If IGNORE_ERROR is set, don't complain when CMD returns non zero.
292
293         RETURN VALUE
294
295         Exit status of CMD
296         """
297         
298         if ( os.name != 'posix' ):
299                 cmd = re.sub (r'''\\''', r'''\\\\\\''', cmd)
300                 cmd = "sh -c \'%s\'" % cmd
301
302                 
303         if verbose_p:
304                 progress (_ ("Invoking `%s\'") % cmd)
305         st = os.system (cmd)
306         if st:
307                 name = re.match ('[ \t]*([^ \t]*)', cmd).group (1)
308                 msg = name + ': ' + _ ("command exited with value %d") % st
309                 if ignore_error:
310                         warning (msg + ' ' + _ ("(ignored)") + ' ')
311                 else:
312                         error (msg)
313
314         return st
315
316
317 def cleanup_temp ():
318         if not keep_temp_dir_p:
319                 if verbose_p:
320                         progress (_ ("Cleaning %s...") % temp_dir)
321                 shutil.rmtree (temp_dir)
322
323
324 #what a name.
325 def set_setting (dict, key, val):
326         try:
327                 val = string.atof (val)
328         except ValueError:
329                 #warning (_ ("invalid value: %s") % `val`)
330                 pass
331
332         try:
333                 dict[key].append (val)
334         except KeyError:
335                 warning (_ ("no such setting: %s") % `key`)
336                 dict[key] = [val]
337
338
339 def strip_extension (f, ext):
340         (p, e) = os.path.splitext (f)
341         if e == ext:
342                 e = ''
343         return p + e
344
345 # END Library
346
347 option_definitions = [
348         ('', 'd', 'dependencies', _ ("write Makefile dependencies for every input file")),
349         ('', 'h', 'help', _ ("this help")),
350         (_ ("DIR"), 'I', 'include', _ ("add DIR to LilyPond's search path")),
351         ('', 'k', 'keep', _ ("keep all output, and name the directory %s.dir") % program_name),
352         ('', '', 'no-lily', _ ("don't run LilyPond")),
353         ('', 'm', 'no-paper', _ ("produce MIDI output only")),
354         (_ ("FILE"), 'o', 'output', _ ("write ouput to FILE")),
355         # why capital P?
356         ('', 'P', 'postscript', _ ("generate PostScript output")),
357         (_ ("KEY=VAL"), 's', 'set', _ ("change global setting KEY to VAL")),
358         ('', 'V', 'verbose', _ ("verbose")),
359         ('', 'v', 'version', _ ("print version number")),
360         ('', 'w', 'warranty', _ ("show warranty and copyright")),
361         ]
362
363 def run_lilypond (files, outbase, dep_prefix):
364         opts = ''
365 #       opts = opts + '--output=%s.tex' % outbase
366         opts = opts + ' ' + string.join (map (lambda x : '-I ' + x,
367                                               include_path))
368         if paper_p:
369                 opts = opts + ' ' + string.join (map (lambda x : '-H ' + x,
370                                                       fields))
371         else:
372                 opts = opts + ' --no-paper'
373                 
374         if track_dependencies_p:
375                 opts = opts + " --dependencies"
376                 if dep_prefix:
377                         opts = opts + ' --dep-prefix=%s' % dep_prefix
378
379         fs = string.join (files)
380
381         if not verbose_p:
382                 progress ( _("Running %s...") % 'LilyPond')
383                 # cmd = cmd + ' 1> /dev/null 2> /dev/null'
384         else:
385                 opts = opts + ' --verbose'
386         
387         system ('lilypond %s %s ' % (opts, fs))
388
389 def analyse_lilypond_output (filename, extra):
390         
391         # urg
392         '''Grep FILENAME for interesting stuff, and
393         put relevant info into EXTRA.'''
394         filename = filename+'.tex'
395         progress (_ ("Analyzing %s...") % filename)
396         s = open (filename).read ()
397
398         # search only the first 10k
399         s = s[:10240]
400         for x in ('textheight', 'linewidth', 'papersize', 'orientation'):
401                 m = re.search (r'\\def\\lilypondpaper%s{([^}]*)}'%x, s)
402                 if m:
403                         set_setting (extra, x, m.group (1))
404
405 def find_tex_files_for_base (base, extra):
406
407         """
408         Find the \header fields dumped from BASE.
409         """
410         
411         headerfiles = {}
412         for f in layout_fields:
413                 if os.path.exists (base + '.' + f):
414                         headerfiles[f] = base+'.'+f
415
416         if os.path.exists (base  +'.dep'):
417                 dependency_files.append (base + '.dep')
418
419         for f in extra_fields:
420                 if os.path.exists (base + '.' + f):
421                         extra[f].append (open (base + '.' + f).read ())
422         
423         return (base  +'.tex',headerfiles)
424          
425
426 def find_tex_files (files, extra):
427         """
428         Find all .tex files whose prefixes start with some name in FILES. 
429
430         """
431         
432         tfiles = []
433         
434         for f in files:
435                 x = 0
436                 while 1:
437                         fname = os.path.basename (f)
438                         fname = strip_extension (fname, '.ly')
439                         if x:
440                                 fname = fname + '-%d' % x
441
442                         if os.path.exists (fname + '.tex'):
443                                 tfiles.append (find_tex_files_for_base (fname, extra))
444                                 analyse_lilypond_output (fname, extra)
445                         else:
446                                 break
447
448                         x = x + 1
449         if not x:
450                 fstr = string.join (files, ', ')
451                 warning (_ ("no lilypond output found for %s") % fstr)
452         return tfiles
453
454 def one_latex_definition (defn, first):
455         s = '\n'
456         for (k,v) in defn[1].items ():
457                 val = open (v).read ()
458                 if (string.strip (val)):
459                         s = s + r'''\def\lilypond%s{%s}''' % (k, val)
460                 else:
461                         s = s + r'''\let\lilypond%s\relax''' % k
462                 s = s + '\n'
463
464         if first:
465                 s = s + '\\def\\mustmakelilypondtitle{}\n'
466         else:
467                 s = s + '\\def\\mustmakelilypondpiecetitle{}\n'
468                 
469         s = s + '\\input %s\n' % defn[0] # The final \n seems important here. It ensures that the footers and taglines end up on the right page.
470         return s
471
472
473 ly_paper_to_latexpaper =  {
474         'a4' : 'a4paper',
475         'letter' : 'letterpaper', 
476 }
477
478 def global_latex_definition (tfiles, extra):
479
480         '''construct preamble from EXTRA, dump Latex stuff for each
481 lily output file in TFILES after that, and return the Latex file constructed.  '''
482
483
484         s = ""
485         s = s + '% generation tag\n'
486
487         options = ''
488
489         if extra['papersize']:
490                 try:
491                         options = '%s' % ly_paper_to_latexpaper[extra['papersize'][0]]
492                 except KeyError:
493                         warning (_ ("invalid value: %s") % `extra['papersize'][0]`)
494                         pass
495
496         if extra['latexoptions']:
497                 options = options + ',' + extra['latexoptions'][-1]
498
499         s = s + '\\documentclass[%s]{article}\n' % options
500
501         if extra['language']:
502                 s = s + r'\usepackage[%s]{babel}\n' % extra['language'][-1]
503
504
505         s = s + '\\usepackage{%s}\n' \
506                 % string.join (extra['latexpackages'], ',')
507
508         if extra['latexheaders']:
509                 s = s + '\\include{%s}\n' \
510                         % string.join (extra['latexheaders'], '}\n\\include{')
511
512         textheight = ''
513         if extra['textheight']:
514                 textheight = ',textheight=%fpt' % extra['textheight'][0]
515
516         orientation = 'portrait'
517         if extra['orientation']:
518                 orientation = extra['orientation'][0]
519
520         # set sane geometry width (a4-width) for linewidth = -1.
521         maxlw = max (extra['linewidth'] + [-1])
522         if maxlw < 0:
523                 # who the hell is 597 ?
524                 linewidth = '597'
525         else:
526                 linewidth = maxlw
527         s = s + '\geometry{width=%spt%s,headheight=2mm,footskip=2mm,%s}\n' % (linewidth, textheight, orientation)
528
529         if extra['latexoptions']:
530                 s = s + '\geometry{twosideshift=4mm}\n'
531
532         s = s + r'''
533 \usepackage[latin1]{inputenc}
534 \input{titledefs}
535 \makeatletter
536 \renewcommand{\@oddfoot}{\parbox{\textwidth}{\mbox{}\thefooter}}%
537 \renewcommand{\@evenfoot}{\parbox{\textwidth}{\mbox{}\thefooter}}%
538 '''
539         
540         if extra['pagenumber'] and extra['pagenumber'][-1] and extra['pagenumber'][-1] != 'no':
541                 s = s + r'''
542 \renewcommand{\@evenhead}{\hbox to\textwidth{\textbf{\thepage}\hfill{\small\theheader}}}
543 \renewcommand{\@oddhead}{\hbox to \textwidth{{\small\theheader}\hfill\textbf{\thepage}}}
544 '''
545         else:
546                 s = s + '\\pagestyle{empty}\n'
547
548         s = s + '\\makeatother\n'
549         s = s + '\\begin{document}\n'
550
551
552         first = 1
553         for t in tfiles:
554                 s = s + one_latex_definition (t, first)
555                 first = 0
556
557         s = s + r'''
558 %% I do not see why we want to clobber the footer here
559 %% \vfill\hfill\parbox{\textwidth}{\mbox{}\makelilypondtagline}
560 %% Well, maybe you don't submit music to mutopia?
561 %% I would not object to this kind of change, but I don't know how
562 %% to get the last mutopia tagline right (ie: no footer on last page)
563 %% Please check that mutopia footers and endfooter are OK before changing
564 %% this again. -- jcn
565 % the \mbox{} helps latex if people do stupid things in tagline
566 \makeatletter
567 \if@twoside
568   \ifodd\thepage
569    \renewcommand{\@oddfoot}{\parbox{\textwidth}{\mbox{}\makelilypondtagline}}%
570   \else
571    \renewcommand{\@evenfoot}{\parbox{\textwidth}{\mbox{}\makelilypondtagline}}%
572   \fi
573  \else
574   \renewcommand{\@thefoot}{\parbox{\textwidth}{\mbox{}\makelilypondtagline}}%
575 \fi
576 \makeatother
577 '''
578         s = s + '\\end{document}'
579
580         return s
581
582 def run_latex (files, outbase, extra):
583
584         """Construct latex file, for FILES and EXTRA, dump it into
585 OUTBASE.latex. Run LaTeX on it.
586
587 RETURN VALUE
588
589 None
590         """
591         latex_fn = outbase + '.latex'
592         
593         wfs = find_tex_files (files, extra)
594         s = global_latex_definition (wfs, extra)
595
596         f = open (latex_fn, 'w')
597         f.write (s)
598         f.close ()
599
600         cmd = 'latex \\\\nonstopmode \\\\input %s' % latex_fn
601
602         if not verbose_p and os.name == 'posix':
603                 progress ( _("Running %s...") % 'LaTeX')
604                 cmd = cmd + ' 1> /dev/null 2> /dev/null'
605
606         system (cmd)
607
608 def run_dvips (outbase, extra):
609
610
611         """Run dvips using the correct options taken from EXTRA,
612 leaving a PS file in OUTBASE.ps
613
614 RETURN VALUE
615
616 None.
617 """
618         opts = ''
619         if extra['papersize']:
620                 opts = opts + ' -t%s' % extra['papersize'][0]
621
622         if extra['orientation'] and extra['orientation'][0] == 'landscape':
623                 opts = opts + ' -tlandscape'
624
625         cmd = 'dvips %s -o%s %s' % (opts, outbase + '.ps', outbase + '.dvi')
626         
627         if not verbose_p and os.name == 'posix':
628                 progress ( _("Running %s...") % 'dvips')
629                 cmd = cmd + ' 1> /dev/null 2> /dev/null'
630                 
631         system (cmd)
632
633 def generate_dependency_file (depfile, outname):
634         df = open (depfile, 'w')
635         df.write (outname + ':' )
636         
637         for d in dependency_files:
638                 s = open (d).read ()
639                 s = re.sub ('#[^\n]*\n', '', s)
640                 s = re.sub (r'\\\n', ' ', s)
641                 m = re.search ('.*:(.*)\n', s)
642
643                 # ugh. Different targets?
644                 if m:
645                         df.write ( m.group (1)  + ' ' )
646
647         df.write ('\n')
648         df.close ();
649
650 (sh, long) = getopt_args (__main__.option_definitions)
651 try:
652         (options, files) = getopt.getopt(sys.argv[1:], sh, long)
653 except getopt.error, s: 
654         errorport.write ("\nerror: getopt says `%s\'\n\n" % s)
655         help ()
656         sys.exit (2)
657         
658 for opt in options:     
659         o = opt[0]
660         a = opt[1]
661
662         if 0:
663                 pass
664         elif o == '--help' or o == '-h':
665                 help ()
666                 sys.exit (0)
667         elif o == '--include' or o == '-I':
668                 include_path.append (a)
669         elif o == '--postscript' or o == '-P':
670                 targets['PS'] = 0
671         elif o == '--keep' or o == '-k':
672                 keep_temp_dir_p = 1
673         elif o == '--no-lily':
674                 lily_p = 0
675         elif o == '--no-paper' or o == '-m':
676                 targets = {}
677                 targets['MIDI'] = 0
678                 paper_p = 0
679         elif o == '--output' or o == '-o':
680                 output_name = a
681         elif o == '--set' or o == '-s':
682                 ss = string.split (a, '=')
683                 set_setting (extra_init, ss[0], ss[1])
684         elif o == '--dependencies' or o == '-d':
685                 track_dependencies_p = 1
686         elif o == '--verbose' or o == '-V':
687                 verbose_p = 1
688         elif o == '--version' or o == '-v':
689                 identify ()
690                 sys.exit (0)
691         elif o == '--warranty' or o == '-w':
692                 status = system ('lilypond -w', ignore_error = 1)
693                 if status:
694                         warranty ()
695
696                 sys.exit (0)
697
698
699 def cp_to_dir (pattern, dir):
700         "Copy files matching re PATTERN from cwd to DIR"
701         # Duh.  Python style portable: cp *.EXT OUTDIR
702         # system ('cp *.%s %s' % (ext, outdir), 1)
703         files = filter (lambda x, p=pattern: re.match (p, x), os.listdir ('.'))
704         map (lambda x, d=dir: shutil.copy2 (x, os.path.join (d, x)), files)
705
706 # Python < 1.5.2 compatibility
707 #
708 # On most platforms, this is equivalent to
709 #`normpath(join(os.getcwd()), PATH)'.  *Added in Python version 1.5.2*
710 if os.path.__dict__.has_key ('abspath'):
711         abspath = os.path.abspath
712 else:
713         def abspath (path):
714                 return os.path.normpath (os.path.join (os.getcwd (), path))
715
716 if os.__dict__.has_key ('makedirs'):
717         makedirs = os.makedirs
718 else:
719         def makedirs (dir, mode=0777):
720                 system ('mkdir -p %s' % dir)
721
722 def mkdir_p (dir, mode=0777):
723         if not os.path.isdir (dir):
724                 makedirs (dir, mode)
725
726 include_path = map (abspath, include_path)
727
728 original_output = output_name
729
730 if files and files[0] != '-':
731
732         files = map (lambda x: strip_extension (x, '.ly'), files)
733
734         (outdir, outbase) = ('','')
735         if not output_name:
736                 outbase = os.path.basename (files[0])
737                 outdir = abspath('.')
738         elif output_name[-1] == os.sep:
739                 outdir = abspath (output_name)
740                 outbase = os.path.basename (files[0])
741         else:
742                 (outdir, outbase) = os.path.split (abspath (output_name))
743
744         for i in ('.dvi', '.latex', '.ly', '.ps', '.tex'):
745                 output_name = strip_extension (output_name, i)
746
747         files = map (abspath, files) 
748
749         if os.path.dirname (output_name) != '.':
750                 dep_prefix = os.path.dirname (output_name)
751         else:
752                 dep_prefix = 0
753
754         reldir = os.path.dirname (output_name)
755         if outdir != '.' and (track_dependencies_p or targets.keys ()):
756                 mkdir_p (outdir, 0777)
757
758         setup_environment ()
759         tmpdir = setup_temp ()
760         if cache_pks_p :
761                 os.chdir (outdir)
762                 cp_to_dir (PK_PATTERN, tmpdir)
763
764         os.chdir (tmpdir)
765         
766         extra = extra_init
767         
768         if lily_p:
769 ##              try:
770                         run_lilypond (files, outbase, dep_prefix)
771 ## #            except:
772 ##                      # TODO: friendly message about LilyPond setup/failing?
773 ##                      #
774 ##                      # TODO: lilypond should fail with different
775 ##                      # error codes for:
776 ##                      #   - guile setup/startup failure
777 ##                      #   - font setup failure
778 ##                      #   - init.ly setup failure
779 ##                      #   - parse error in .ly
780 ##                      #   - unexpected: assert/core dump
781 ## #                    targets = {}
782
783         if targets.has_key ('DVI') or targets.has_key ('PS'):
784 #               try:
785                         run_latex (files, outbase, extra)
786                         # unless: add --tex, or --latex?
787                         del targets['TEX']
788                         del targets['LATEX']
789 #               except Foobar:
790 #                       # TODO: friendly message about TeX/LaTeX setup,
791 #                       # trying to run tex/latex by hand
792 #                       if targets.has_key ('DVI'):
793 #                               del targets['DVI']
794 #                       if targets.has_key ('PS'):
795 #                               del targets['PS']
796
797         # TODO: does dvips ever fail?
798         if targets.has_key ('PS'):
799                 run_dvips (outbase, extra)
800
801         # add DEP to targets?
802         if track_dependencies_p:
803                 depfile = os.path.join (outdir, outbase + '.dep')
804                 generate_dependency_file (depfile, depfile)
805                 if os.path.isfile (depfile):
806                         progress (_ ("dependencies output to `%s'...") % depfile)
807
808         for i in targets.keys ():
809                 ext = string.lower (i)
810                 cp_to_dir ('.*\.%s$' % ext, outdir)
811                 outname = outbase + '.' + string.lower (i)
812                 abs = os.path.join (outdir, outname)
813                 if reldir != '.':
814                         outname = os.path.join (reldir, outname)
815                 if os.path.isfile (abs):
816                         progress (_ ("%s output to `%s'...") % (i, outname))
817                 elif verbose_p:
818                         warning (_ ("can't find file: `%s'") % outname)
819                         
820                 if cache_pks_p:
821                         cp_to_dir (PK_PATTERN, outdir)
822                 
823         os.chdir (original_dir)
824         cleanup_temp ()
825         
826 else:
827         # FIXME
828         help ()
829         errorport.write ("ly2dvi: " + _ ("error: ") + _ ("no files specified on command line.") + '\n')
830         sys.exit (2)
831
832
833