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