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