44__author__ = 'Raymond Hettinger'
55
66import keyword , tokenize , cgi , re , functools
7+ try :
8+ import builtins
9+ except ImportError :
10+ import __builtin__ as builtins
711
812#### Analyze Python Source #################################
913
1014def is_builtin (s ):
1115 'Return True if s is the name of a builtin'
12- return hasattr (__builtins__ , s )
16+ return hasattr (builtins , s )
1317
1418def combine_range (lines , start , end ):
1519 'Join content from a range of lines between start and end'
@@ -21,9 +25,7 @@ def combine_range(lines, start, end):
2125
2226def analyze_python (source ):
2327 '''Generate and classify chunks of Python for syntax highlighting.
24- Yields tuples in the form: (leadin_text, category, categorized_text).
25- The final tuple has empty strings for the category and categorized text.
26-
28+ Yields tuples in the form: (category, categorized_text).
2729 '''
2830 lines = source .splitlines (True )
2931 lines .append ('' )
@@ -37,7 +39,7 @@ def analyze_python(source):
3739 kind = ''
3840 if tok_type == tokenize .COMMENT :
3941 kind = 'comment'
40- elif tok_type == tokenize .OP and tok_str [:1 ] not in '{}[](),.:;' :
42+ elif tok_type == tokenize .OP and tok_str [:1 ] not in '{}[](),.:;@ ' :
4143 kind = 'operator'
4244 elif tok_type == tokenize .STRING :
4345 kind = 'string'
@@ -53,22 +55,20 @@ def analyze_python(source):
5355 elif is_builtin (tok_str ) and prev_tok_str != '.' :
5456 kind = 'builtin'
5557 if kind :
56- line_upto_token , written = combine_range (lines , written , (srow , scol ))
57- line_thru_token , written = combine_range (lines , written , (erow , ecol ))
58- yield line_upto_token , kind , line_thru_token
58+ text , written = combine_range (lines , written , (srow , scol ))
59+ yield '' , text
60+ text , written = combine_range (lines , written , (erow , ecol ))
61+ yield kind , text
5962 line_upto_token , written = combine_range (lines , written , (erow , ecol ))
60- yield line_upto_token , '' , ''
63+ yield '' , line_upto_token
6164
6265#### Raw Output ###########################################
6366
6467def raw_highlight (classified_text ):
6568 'Straight text display of text classifications'
6669 result = []
67- for line_upto_token , kind , line_thru_token in classified_text :
68- if line_upto_token :
69- result .append (' plain: %r\n ' % line_upto_token )
70- if line_thru_token :
71- result .append ('%15s: %r\n ' % (kind , line_thru_token ))
70+ for kind , text in classified_text :
71+ result .append ('%15s: %r\n ' % (kind or 'plain' , text ))
7272 return '' .join (result )
7373
7474#### ANSI Output ###########################################
@@ -88,26 +88,23 @@ def ansi_highlight(classified_text, colors=default_ansi):
8888 'Add syntax highlighting to source code using ANSI escape sequences'
8989 # http://en.wikipedia.org/wiki/ANSI_escape_code
9090 result = []
91- for line_upto_token , kind , line_thru_token in classified_text :
91+ for kind , text in classified_text :
9292 opener , closer = colors .get (kind , ('' , '' ))
93- result += [line_upto_token , opener , line_thru_token , closer ]
93+ result += [opener , text , closer ]
9494 return '' .join (result )
9595
9696#### HTML Output ###########################################
9797
9898def html_highlight (classified_text ,opener = '<pre class="python">\n ' , closer = '</pre>\n ' ):
9999 'Convert classified text to an HTML fragment'
100100 result = [opener ]
101- for line_upto_token , kind , line_thru_token in classified_text :
101+ for kind , text in classified_text :
102+ if kind :
103+ result .append ('<span class="%s">' % kind )
104+ result .append (cgi .escape (text ))
102105 if kind :
103- result += [cgi .escape (line_upto_token ),
104- '<span class="%s">' % kind ,
105- cgi .escape (line_thru_token ),
106- '</span>' ]
107- else :
108- result += [cgi .escape (line_upto_token ),
109- cgi .escape (line_thru_token )]
110- result += [closer ]
106+ result .append ('</span>' )
107+ result .append (closer )
111108 return '' .join (result )
112109
113110default_css = {
@@ -188,15 +185,12 @@ def latex_highlight(classified_text, title = 'python',
188185 document = default_latex_document ):
189186 'Create a complete LaTeX document with colorized source code'
190187 result = []
191- for line_upto_token , kind , line_thru_token in classified_text :
188+ for kind , text in classified_text :
189+ if kind :
190+ result .append (r'{\color{%s}' % colors [kind ])
191+ result .append (latex_escape (text ))
192192 if kind :
193- result += [latex_escape (line_upto_token ),
194- r'{\color{%s}' % colors [kind ],
195- latex_escape (line_thru_token ),
196- '}' ]
197- else :
198- result += [latex_escape (line_upto_token ),
199- latex_escape (line_thru_token )]
193+ result .append ('}' )
200194 return default_latex_document % dict (title = title , body = '' .join (result ))
201195
202196
0 commit comments