]> git.donarmstrong.com Git - lilypond.git/blob - python/lilylib.py
f9cbff2c60a84ee84a3ebeb772e6eacc720b9adc
[lilypond.git] / python / lilylib.py
1 ###############################################################
2 # lilylib.py -- options and stuff
3
4 # source file of the GNU LilyPond music typesetter
5 #
6 # (c) 1998--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 #                 Jan Nieuwenhuizen <janneke@gnu.org>
8
9 import __main__
10 import glob
11 import os
12 import re
13 import shutil
14 import sys
15 import optparse
16
17 ################################################################
18 # Users of python modules should include this snippet
19 # and customize variables below.
20
21 # We'll suffer this path init stuff as long as we don't install our
22 # python packages in <prefix>/lib/pythonx.y (and don't kludge around
23 # it as we do with teTeX on Red Hat Linux: set some environment var
24 # (PYTHONPATH) in profile)
25
26 # If set, LILYPOND_DATADIR must take prevalence
27 # if datadir is not set, we're doing a build and LILYPOND_DATADIR
28
29 datadir = '@local_lilypond_datadir@'
30 if not os.path.isdir (datadir):
31     datadir = '@lilypond_datadir@'
32 if os.environ.has_key ('LILYPOND_DATADIR') :
33     datadir = os.environ['LILYPOND_DATADIR']
34     while datadir[-1] == os.sep:
35         datadir= datadir[:-1]
36
37 sys.path.insert (0, os.path.join (datadir, 'python'))
38
39
40 # Python 2.5 only accepts strings with proper Python internal encoding
41 # (i.e. ASCII or Unicode) when writing to stdout/stderr, so we must
42 # use ugettext iso gettext, and encode the string when writing to
43 # stdout/stderr
44
45 localedir = '@localedir@'
46 try:
47     import gettext
48     t = gettext.translation ('lilypond', localedir)
49     _ = t.ugettext
50 except:
51     def _ (s):
52         return s
53 underscore = _
54
55 # Urg, Python 2.4 does not define stderr/stdout encoding
56 # Maybe guess encoding from LANG/LC_ALL/LC_CTYPE?
57
58 def encoded_write(f, s):
59     f.write (s.encode (f.encoding or 'utf_8'))
60
61 # ugh, Python 2.5 optparse requires Unicode strings in some argument
62 # functions, and refuse them in some other places
63 def display_encode (s):
64     return s.encode (sys.stderr.encoding or 'utf_8')
65
66 def stderr_write (s):
67     encoded_write (sys.stderr, s)
68
69 progress = stderr_write
70
71 # Modified version of the commands.mkarg(x), which always uses 
72 # double quotes (since Windows can't handle the single quotes:
73 def mkarg(x):
74     s = ' "'
75     for c in x:
76         if c in '\\$"`':
77             s = s + '\\'
78         s = s + c
79     s = s + '"'
80     return s
81
82 def command_name (cmd):
83     # Strip all stuf after command,
84     # deal with "((latex ) >& 1 ) .." too
85     cmd = re.match ('([\(\)]*)([^\\\ ]*)', cmd).group (2)
86     return os.path.basename (cmd)
87
88 def subprocess_system (cmd,
89                        ignore_error=False,
90                        progress_p=True,
91                        be_verbose=False,
92                        log_file=None):
93     import subprocess
94
95     show_progress= progress_p 
96     name = command_name (cmd)
97     error_log_file = ''
98
99     if be_verbose:
100         show_progress = 1
101         progress (_ ("Invoking `%s\'") % cmd)
102     else:
103         progress ( _("Running %s...") % name)
104
105
106     stdout_setting = None
107     if not show_progress:
108         stdout_setting = subprocess.PIPE
109
110     proc = subprocess.Popen (cmd,
111                              shell=True,
112                              universal_newlines=True,
113                              stdout=stdout_setting,
114                              stderr=stdout_setting)
115
116     log = ''
117
118     if show_progress:
119         retval = proc.wait()
120     else:
121         log = proc.communicate ()
122         retval = proc.returncode
123
124
125     if retval:
126         print >>sys.stderr, 'command failed:', cmd
127         if retval < 0:
128             print >>sys.stderr, "Child was terminated by signal", -retval
129         elif retval > 0:
130             print >>sys.stderr, "Child returned", retval
131
132         if ignore_error:
133             print >>sys.stderr, "Error ignored"
134         else:
135             if not show_progress:
136                 print log[0]
137                 print log[1]
138             sys.exit (1)
139
140     return abs (retval)
141
142 def ossystem_system (cmd,
143                      ignore_error=False,
144                      progress_p=True,
145                      be_verbose=False,
146                      log_file=None):
147
148
149     name = command_name (cmd)
150     if be_verbose:
151         show_progress = 1
152         progress (_ ("Invoking `%s\'") % cmd)
153     else:
154         progress ( _("Running %s...") % name)
155
156     retval = os.system (cmd)
157     if retval:
158         print >>sys.stderr, 'command failed:', cmd
159         if retval < 0:
160             print >>sys.stderr, "Child was terminated by signal", -retval
161         elif retval > 0:
162             print >>sys.stderr, "Child returned", retval
163
164         if ignore_error:
165             print >>sys.stderr, "Error ignored"
166         else:
167             sys.exit (1)
168
169     return abs (retval)
170
171
172 system = subprocess_system
173 if sys.platform == 'mingw32':
174     
175     ## subprocess x-compile doesn't work.
176     system = ossystem_system
177
178 def strip_extension (f, ext):
179     (p, e) = os.path.splitext (f)
180     if e == ext:
181         e = ''
182     return p + e
183
184
185 def search_exe_path (name):
186     p = os.environ['PATH']
187     exe_paths = p.split (':')
188     for e in exe_paths:
189         full = os.path.join (e, name)
190         if os.path.exists (full):
191             return full
192     return None
193
194
195 def print_environment ():
196     for (k,v) in os.environ.items ():
197         sys.stderr.write ("%s=\"%s\"\n" % (k, v)) 
198
199 class NonDentedHeadingFormatter (optparse.IndentedHelpFormatter):
200     def format_heading(self, heading):
201         if heading:
202             return heading[0].upper() + heading[1:] + ':\n'
203         return ''
204     def format_option_strings(self, option):
205         sep = ' '
206         if option._short_opts and option._long_opts:
207             sep = ','
208
209         metavar = ''
210         if option.takes_value():
211             metavar = '=%s' % option.metavar or option.dest.upper()
212
213         return "%3s%s %s%s" % (" ".join (option._short_opts),
214                                sep,
215                                " ".join (option._long_opts),
216                                metavar)
217
218     def format_usage(self, usage):
219         return _("Usage: %s") % usage + '\n'
220
221     def format_description(self, description):
222         return description
223
224 def get_option_parser (*args, **kwargs): 
225     p = optparse.OptionParser (*args, **kwargs)
226     p.formatter = NonDentedHeadingFormatter () 
227     return p