5 from cStringIO
import StringIO
9 'python': 'script.png',
11 'shell': 'script.png',
14 'assembler': 'binary.png',
15 'binary': 'binary.png',
20 ICONSDIR
= os
.path
.join (os
.path
.dirname (__file__
), 'icons')
22 def ident_file_type (filename
):
23 '''Returns an icon based on the contents of filename.'''
24 if os
.path
.exists (filename
):
25 quoted_filename
= shell_quote (filename
)
26 fileinfo
= commands
.getoutput('file -b %s' % quoted_filename
)
27 for filetype
, iconname
in KNOWN_FILE_TYPES
.iteritems():
28 if filetype
in fileinfo
.lower():
32 # Fallback for modified files of an unknown type
35 def get_icon (filename
):
36 '''Returns the full path to an icon file corresponding to
37 filename's contents.'''
38 icon_file
= ident_file_type (filename
)
39 return os
.path
.join (ICONSDIR
, icon_file
)
41 def get_staged_icon (filename
):
42 '''Special-case method for staged items. These are only
43 ever 'staged' and 'removed' items in the staged list.'''
45 if os
.path
.exists (filename
):
46 return os
.path
.join (ICONSDIR
, 'staged.png')
48 return os
.path
.join (ICONSDIR
, 'removed.png')
50 def get_untracked_icon():
51 return os
.path
.join (ICONSDIR
, 'untracked.png')
53 def get_directory_icon():
54 return os
.path
.join (ICONSDIR
, 'dir.png')
57 return os
.path
.join (ICONSDIR
, 'generic.png')
59 def shell_quote (*inputs
):
60 '''Quote strings so that they can be suitably martialled
61 off to the shell. This method supports POSIX sh syntax.
62 This is crucial to properly handle command line arguments
63 with spaces, quotes, double-quotes, etc.'''
65 regex
= re
.compile ('[^\w!%+,\-./:@^]')
66 quote_regex
= re
.compile ("((?:'\\''){2,})")
74 raise AssertionError, ('No way to quote strings '
75 'containing null (\\000) bytes')
77 # = does need quoting else in command position it's a
78 # program-local environment setting
79 match
= regex
.search (input)
82 input = input.replace ("'", "'\\''")
84 # make multiple ' in a row look simpler
85 # '\'''\'''\'' -> '"'''"'
86 quote_match
= quote_regex
.match (input)
88 quotes
= match
.group (1)
89 input.replace (quotes
,
90 ("'" * (len(quotes
)/4)) + "\"'")
92 input = "'%s'" % input
93 if input.startswith ("''"):
96 if input.endswith ("''"):
101 ANSI_BACKGROUND_COLOR
= '41'
114 def ansi_to_html (ansi
):
115 '''Converts a block of ANSI text into an equivalent html fragment.'''
118 regex
= re
.compile ('(.*?)\x1b\[(\d*)m')
120 for line
in ansi
.split ('\n'):
122 linecopy
= html_encode(line
)
123 match
= regex
.match (linecopy
)
127 start
, end
= match
.span()
129 prefix
= match
.group (1)
130 middle
= match
.group (2)
131 postfix
= linecopy
[end
:]
133 if middle
in ANSI_TABLE
:
134 color
= ANSI_TABLE
[middle
]
135 middle
= '<span style="color: %s">' % color
138 elif middle
== ANSI_BACKGROUND_COLOR
:
139 middle
= '<span style="background-color:red">'
148 linecopy
= prefix
+ middle
+ postfix
149 match
= regex
.match (linecopy
)
151 html
.write (linecopy
)
154 return html
.getvalue()
156 def html_header (header
):
158 <p style="color: black;
159 background-color: yellow">
163 def html_encode (ascii
):
164 '''HTML-encodes text. This method explicitly avoids encoding
165 alphanumeric and ANSI-escape sequences.'''
173 # There is no HTML equivalent to a tab, so just
174 # insert eight spaces
175 html
.write ( ' ' * 8 )
177 elif char
== '\x1b' or char
== '[':
178 # Don't encode ANSI characters since these
179 # are stripped out during ansi_to_html
183 html
.write (ENTITIES
[char
])
185 return html
.getvalue()
187 # Keep this at the bottom of the file since it's generated output.
188 # Generated by html2py.pl from HTML::Entities on Wed Dec 5 16:28:55 PST 2007
351 chr(161) : '¡',
353 chr(163) : '£',
354 chr(164) : '¤',
356 chr(166) : '¦',
361 chr(171) : '«',
367 chr(177) : '±',
370 chr(180) : '´',
371 chr(181) : 'µ',
373 chr(183) : '·',
374 chr(184) : '¸',
377 chr(187) : '»',
378 chr(188) : '¼',
379 chr(189) : '½',
380 chr(190) : '¾',
381 chr(191) : '¿',
382 chr(192) : 'À',
383 chr(193) : 'Á',
384 chr(194) : 'Â',
385 chr(195) : 'Ã',
387 chr(197) : 'Å',
388 chr(198) : 'Æ',
389 chr(199) : 'Ç',
390 chr(200) : 'È',
391 chr(201) : 'É',
392 chr(202) : 'Ê',
394 chr(204) : 'Ì',
395 chr(205) : 'Í',
396 chr(206) : 'Î',
399 chr(209) : 'Ñ',
400 chr(210) : 'Ò',
401 chr(211) : 'Ó',
402 chr(212) : 'Ô',
403 chr(213) : 'Õ',
405 chr(215) : '×',
406 chr(216) : 'Ø',
407 chr(217) : 'Ù',
408 chr(218) : 'Ú',
409 chr(219) : 'Û',
411 chr(221) : 'Ý',
412 chr(222) : 'Þ',
413 chr(223) : 'ß',
414 chr(224) : 'à',
415 chr(225) : 'á',
416 chr(226) : 'â',
417 chr(227) : 'ã',
419 chr(229) : 'å',
420 chr(230) : 'æ',
421 chr(231) : 'ç',
422 chr(232) : 'è',
423 chr(233) : 'é',
424 chr(234) : 'ê',
426 chr(236) : 'ì',
427 chr(237) : 'í',
428 chr(238) : 'î',
431 chr(241) : 'ñ',
432 chr(242) : 'ò',
433 chr(243) : 'ó',
434 chr(244) : 'ô',
435 chr(245) : 'õ',
437 chr(247) : '÷',
438 chr(248) : 'ø',
439 chr(249) : 'ù',
440 chr(250) : 'ú',
441 chr(251) : 'û',
443 chr(253) : 'ý',
444 chr(254) : 'þ',