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