ThirdParty/Pygments/pygments/cmdline.py

changeset 0
de9c2efb9d02
child 12
1d8dd9706f46
equal deleted inserted replaced
-1:000000000000 0:de9c2efb9d02
1 # -*- coding: utf-8 -*-
2 """
3 pygments.cmdline
4 ~~~~~~~~~~~~~~~~
5
6 Command line interface.
7
8 :copyright: Copyright 2006-2009 by the Pygments team, see AUTHORS.
9 :license: BSD, see LICENSE for details.
10 """
11 import sys
12 import getopt
13 from textwrap import dedent
14
15 from pygments import __version__, highlight
16 from pygments.util import ClassNotFound, OptionError, docstring_headline
17 from pygments.lexers import get_all_lexers, get_lexer_by_name, get_lexer_for_filename, \
18 find_lexer_class, guess_lexer, TextLexer
19 from pygments.formatters import get_all_formatters, get_formatter_by_name, \
20 get_formatter_for_filename, find_formatter_class, \
21 TerminalFormatter # pylint:disable-msg=E0611
22 from pygments.filters import get_all_filters, find_filter_class
23 from pygments.styles import get_all_styles, get_style_by_name
24
25
26 USAGE = """\
27 Usage: %s [-l <lexer> | -g] [-F <filter>[:<options>]] [-f <formatter>]
28 [-O <options>] [-P <option=value>] [-o <outfile>] [<infile>]
29
30 %s -S <style> -f <formatter> [-a <arg>] [-O <options>] [-P <option=value>]
31 %s -L [<which> ...]
32 %s -N <filename>
33 %s -H <type> <name>
34 %s -h | -V
35
36 Highlight the input file and write the result to <outfile>.
37
38 If no input file is given, use stdin, if -o is not given, use stdout.
39
40 <lexer> is a lexer name (query all lexer names with -L). If -l is not
41 given, the lexer is guessed from the extension of the input file name
42 (this obviously doesn't work if the input is stdin). If -g is passed,
43 attempt to guess the lexer from the file contents, or pass through as
44 plain text if this fails (this can work for stdin).
45
46 Likewise, <formatter> is a formatter name, and will be guessed from
47 the extension of the output file name. If no output file is given,
48 the terminal formatter will be used by default.
49
50 With the -O option, you can give the lexer and formatter a comma-
51 separated list of options, e.g. ``-O bg=light,python=cool``.
52
53 The -P option adds lexer and formatter options like the -O option, but
54 you can only give one option per -P. That way, the option value may
55 contain commas and equals signs, which it can't with -O, e.g.
56 ``-P "heading=Pygments, the Python highlighter".
57
58 With the -F option, you can add filters to the token stream, you can
59 give options in the same way as for -O after a colon (note: there must
60 not be spaces around the colon).
61
62 The -O, -P and -F options can be given multiple times.
63
64 With the -S option, print out style definitions for style <style>
65 for formatter <formatter>. The argument given by -a is formatter
66 dependent.
67
68 The -L option lists lexers, formatters, styles or filters -- set
69 `which` to the thing you want to list (e.g. "styles"), or omit it to
70 list everything.
71
72 The -N option guesses and prints out a lexer name based solely on
73 the given filename. It does not take input or highlight anything.
74 If no specific lexer can be determined "text" is returned.
75
76 The -H option prints detailed help for the object <name> of type <type>,
77 where <type> is one of "lexer", "formatter" or "filter".
78
79 The -h option prints this help.
80 The -V option prints the package version.
81 """
82
83
84 def _parse_options(o_strs):
85 opts = {}
86 if not o_strs:
87 return opts
88 for o_str in o_strs:
89 if not o_str:
90 continue
91 o_args = o_str.split(',')
92 for o_arg in o_args:
93 o_arg = o_arg.strip()
94 try:
95 o_key, o_val = o_arg.split('=')
96 o_key = o_key.strip()
97 o_val = o_val.strip()
98 except ValueError:
99 opts[o_arg] = True
100 else:
101 opts[o_key] = o_val
102 return opts
103
104
105 def _parse_filters(f_strs):
106 filters = []
107 if not f_strs:
108 return filters
109 for f_str in f_strs:
110 if ':' in f_str:
111 fname, fopts = f_str.split(':', 1)
112 filters.append((fname, _parse_options([fopts])))
113 else:
114 filters.append((f_str, {}))
115 return filters
116
117
118 def _print_help(what, name):
119 try:
120 if what == 'lexer':
121 cls = find_lexer_class(name)
122 print "Help on the %s lexer:" % cls.name
123 print dedent(cls.__doc__)
124 elif what == 'formatter':
125 cls = find_formatter_class(name)
126 print "Help on the %s formatter:" % cls.name
127 print dedent(cls.__doc__)
128 elif what == 'filter':
129 cls = find_filter_class(name)
130 print "Help on the %s filter:" % name
131 print dedent(cls.__doc__)
132 except AttributeError:
133 print >>sys.stderr, "%s not found!" % what
134
135
136 def _print_list(what):
137 if what == 'lexer':
138 print
139 print "Lexers:"
140 print "~~~~~~~"
141
142 info = []
143 for fullname, names, exts, _ in get_all_lexers():
144 tup = (', '.join(names)+':', fullname,
145 exts and '(filenames ' + ', '.join(exts) + ')' or '')
146 info.append(tup)
147 info.sort()
148 for i in info:
149 print ('* %s\n %s %s') % i
150
151 elif what == 'formatter':
152 print
153 print "Formatters:"
154 print "~~~~~~~~~~~"
155
156 info = []
157 for cls in get_all_formatters():
158 doc = docstring_headline(cls)
159 tup = (', '.join(cls.aliases) + ':', doc, cls.filenames and
160 '(filenames ' + ', '.join(cls.filenames) + ')' or '')
161 info.append(tup)
162 info.sort()
163 for i in info:
164 print ('* %s\n %s %s') % i
165
166 elif what == 'filter':
167 print
168 print "Filters:"
169 print "~~~~~~~~"
170
171 for name in get_all_filters():
172 cls = find_filter_class(name)
173 print "* " + name + ':'
174 print " %s" % docstring_headline(cls)
175
176 elif what == 'style':
177 print
178 print "Styles:"
179 print "~~~~~~~"
180
181 for name in get_all_styles():
182 cls = get_style_by_name(name)
183 print "* " + name + ':'
184 print " %s" % docstring_headline(cls)
185
186
187 def main(args=sys.argv):
188 """
189 Main command line entry point.
190 """
191 # pylint: disable-msg=R0911,R0912,R0915
192
193 usage = USAGE % ((args[0],) * 6)
194
195 try:
196 popts, args = getopt.getopt(args[1:], "l:f:F:o:O:P:LS:a:N:hVHg")
197 except getopt.GetoptError, err:
198 print >>sys.stderr, usage
199 return 2
200 opts = {}
201 O_opts = []
202 P_opts = []
203 F_opts = []
204 for opt, arg in popts:
205 if opt == '-O':
206 O_opts.append(arg)
207 elif opt == '-P':
208 P_opts.append(arg)
209 elif opt == '-F':
210 F_opts.append(arg)
211 opts[opt] = arg
212
213 if not opts and not args:
214 print usage
215 return 0
216
217 if opts.pop('-h', None) is not None:
218 print usage
219 return 0
220
221 if opts.pop('-V', None) is not None:
222 print 'Pygments version %s, (c) 2006-2008 by Georg Brandl.' % __version__
223 return 0
224
225 # handle ``pygmentize -L``
226 L_opt = opts.pop('-L', None)
227 if L_opt is not None:
228 if opts:
229 print >>sys.stderr, usage
230 return 2
231
232 # print version
233 main(['', '-V'])
234 if not args:
235 args = ['lexer', 'formatter', 'filter', 'style']
236 for arg in args:
237 _print_list(arg.rstrip('s'))
238 return 0
239
240 # handle ``pygmentize -H``
241 H_opt = opts.pop('-H', None)
242 if H_opt is not None:
243 if opts or len(args) != 2:
244 print >>sys.stderr, usage
245 return 2
246
247 what, name = args
248 if what not in ('lexer', 'formatter', 'filter'):
249 print >>sys.stderr, usage
250 return 2
251
252 _print_help(what, name)
253 return 0
254
255 # parse -O options
256 parsed_opts = _parse_options(O_opts)
257 opts.pop('-O', None)
258
259 # parse -P options
260 for p_opt in P_opts:
261 try:
262 name, value = p_opt.split('=', 1)
263 except ValueError:
264 parsed_opts[p_opt] = True
265 else:
266 parsed_opts[name] = value
267 opts.pop('-P', None)
268
269 # handle ``pygmentize -N``
270 infn = opts.pop('-N', None)
271 if infn is not None:
272 try:
273 lexer = get_lexer_for_filename(infn, **parsed_opts)
274 except ClassNotFound, err:
275 lexer = TextLexer()
276 except OptionError, err:
277 print >>sys.stderr, 'Error:', err
278 return 1
279
280 print lexer.aliases[0]
281 return 0
282
283 # handle ``pygmentize -S``
284 S_opt = opts.pop('-S', None)
285 a_opt = opts.pop('-a', None)
286 if S_opt is not None:
287 f_opt = opts.pop('-f', None)
288 if not f_opt:
289 print >>sys.stderr, usage
290 return 2
291 if opts or args:
292 print >>sys.stderr, usage
293 return 2
294
295 try:
296 parsed_opts['style'] = S_opt
297 fmter = get_formatter_by_name(f_opt, **parsed_opts)
298 except ClassNotFound, err:
299 print >>sys.stderr, err
300 return 1
301
302 arg = a_opt or ''
303 try:
304 print fmter.get_style_defs(arg)
305 except Exception, err:
306 print >>sys.stderr, 'Error:', err
307 return 1
308 return 0
309
310 # if no -S is given, -a is not allowed
311 if a_opt is not None:
312 print >>sys.stderr, usage
313 return 2
314
315 # parse -F options
316 F_opts = _parse_filters(F_opts)
317 opts.pop('-F', None)
318
319 # select formatter
320 outfn = opts.pop('-o', None)
321 fmter = opts.pop('-f', None)
322 if fmter:
323 try:
324 fmter = get_formatter_by_name(fmter, **parsed_opts)
325 except (OptionError, ClassNotFound), err:
326 print >>sys.stderr, 'Error:', err
327 return 1
328
329 if outfn:
330 if not fmter:
331 try:
332 fmter = get_formatter_for_filename(outfn, **parsed_opts)
333 except (OptionError, ClassNotFound), err:
334 print >>sys.stderr, 'Error:', err
335 return 1
336 try:
337 outfile = open(outfn, 'wb')
338 except Exception, err:
339 print >>sys.stderr, 'Error: cannot open outfile:', err
340 return 1
341 else:
342 if not fmter:
343 fmter = TerminalFormatter(**parsed_opts)
344 outfile = sys.stdout
345
346 # select lexer
347 lexer = opts.pop('-l', None)
348 if lexer:
349 try:
350 lexer = get_lexer_by_name(lexer, **parsed_opts)
351 except (OptionError, ClassNotFound), err:
352 print >>sys.stderr, 'Error:', err
353 return 1
354
355 if args:
356 if len(args) > 1:
357 print >>sys.stderr, usage
358 return 2
359
360 infn = args[0]
361 try:
362 code = open(infn, 'rb').read()
363 except Exception, err:
364 print >>sys.stderr, 'Error: cannot read infile:', err
365 return 1
366
367 if not lexer:
368 try:
369 lexer = get_lexer_for_filename(infn, code, **parsed_opts)
370 except ClassNotFound, err:
371 if '-g' in opts:
372 try:
373 lexer = guess_lexer(code)
374 except ClassNotFound:
375 lexer = TextLexer()
376 else:
377 print >>sys.stderr, 'Error:', err
378 return 1
379 except OptionError, err:
380 print >>sys.stderr, 'Error:', err
381 return 1
382
383 else:
384 if '-g' in opts:
385 code = sys.stdin.read()
386 try:
387 lexer = guess_lexer(code)
388 except ClassNotFound:
389 lexer = TextLexer()
390 elif not lexer:
391 print >>sys.stderr, 'Error: no lexer name given and reading ' + \
392 'from stdin (try using -g or -l <lexer>)'
393 return 2
394 else:
395 code = sys.stdin.read()
396
397 # No encoding given? Use latin1 if output file given,
398 # stdin/stdout encoding otherwise.
399 # (This is a compromise, I'm not too happy with it...)
400 if 'encoding' not in parsed_opts and 'outencoding' not in parsed_opts:
401 if outfn:
402 # encoding pass-through
403 fmter.encoding = 'latin1'
404 else:
405 if sys.version_info < (3,):
406 # use terminal encoding; Python 3's terminals already do that
407 lexer.encoding = getattr(sys.stdin, 'encoding',
408 None) or 'ascii'
409 fmter.encoding = getattr(sys.stdout, 'encoding',
410 None) or 'ascii'
411
412 # ... and do it!
413 try:
414 # process filters
415 for fname, fopts in F_opts:
416 lexer.add_filter(fname, **fopts)
417 highlight(code, lexer, fmter, outfile)
418 except Exception, err:
419 import traceback
420 info = traceback.format_exception(*sys.exc_info())
421 msg = info[-1].strip()
422 if len(info) >= 3:
423 # extract relevant file and position info
424 msg += '\n (f%s)' % info[-2].split('\n')[0].strip()[1:]
425 print >>sys.stderr
426 print >>sys.stderr, '*** Error while highlighting:'
427 print >>sys.stderr, msg
428 return 1
429
430 return 0

eric ide

mercurial