-- limodou [2004-09-13 01:21:13]
Contents
Python 源代码转成Html
现在有许多的Python源码转成Html的程序,这个是从Moin中修改而来的
关于
现在有许多的Python源码转成Html的程序,就我所知就有Moin, Twisted, DiveIntoPython带了一个,可能还有别的,我没有再查过。
本来PyTextile是可以将Python转成Html的,但它用的是twisted.python.htmlizer,不过在程序它将导入位置改为了:
import htmlizer
结果要你将htmlizer从twisted中拷贝出来才可以,但现在的htmlizer还要调用别的模块。因些我放弃了。当然,改一下是行的,不过没这么做。
DiveIntoPython的作者Mark Pilgrim写的,也是要用到别的东西。因此还是放弃了。
最后选定了Moin中的python.py。不过,与老版本不同,它使用了wiki的一个应用模块,主要是进行特殊字符的html处理,我改成了cgi模块。但还是发现,对传入的文本是unicode时,处理有问题,没办法改吧。最后形成了这个版本,已经不再是原来的东西了。
代码
1 # -*- coding: iso-8859-1 -*-
2 """
3 MoinMoin - Python Source Parser
4
5 @copyright: 2001 by J黵gen Hermann <[email protected]>
6 @license: GNU GPL, see COPYING for details.
7 """
8
9 # Imports
10 import cStringIO
11 import keyword, token, tokenize
12 import cgi
13 import types
14
15 #############################################################################
16 ### Python Source Parser (does Hilighting)
17 #############################################################################
18
19 _KEYWORD = token.NT_OFFSET + 1
20 _TEXT = token.NT_OFFSET + 2
21
22 _colors = {
23 token.NUMBER: '#0080C0',
24 token.OP: '#0000C0',
25 token.STRING: '#804000',
26 tokenize.COMMENT: '#008000',
27 token.NAME: '#000000',
28 token.ERRORTOKEN: '#FF8080',
29 _KEYWORD: '#0000FF',
30 _TEXT: '#000000',
31 }
32
33
34 class Parser:
35 """ Send colored python source.
36 """
37
38 def __init__(self, raw):
39 """ Store the source text.
40 """
41 self.raw = raw.expandtabs().rstrip()
42 self.unicode = False
43 self.result = []
44
45 def format(self, linenumber=True):
46 """ Parse and send the colored source.
47 """
48 # store line offsets in self.lines
49 if isinstance(self.raw, types.UnicodeType):
50 self.raw = self.raw.encode('utf-8')
51 self.unicode = True
52
53 self.lines = [0, 0]
54 pos = 0
55 while 1:
56 pos = self.raw.find('\n', pos) + 1
57 if not pos: break
58 self.lines.append(pos)
59 self.lines.append(len(self.raw))
60
61 # write line numbers
62 if linenumber:
63 self.result.append('<table border="0"><tr><td align="right" valign="top">')
64 self.result.append('<td align="right" valign="top"><pre><font face="Lucida,Courier New" color="%s">' % _colors[_TEXT])
65 for idx in range(1, len(self.lines)-1):
66 self.result.append('%3d \n' % idx)
67 self.result.append('</font></pre></td><td valign="top">')
68
69 # parse the source and write it
70 self.pos = 0
71 text = cStringIO.StringIO(self.raw)
72 self.result.append('<pre><font face="Lucida,Courier New">')
73 try:
74 tokenize.tokenize(text.readline, self)
75 except tokenize.TokenError, ex:
76 msg = ex[0]
77 line = ex[1][0]
78 self.result.append("<h3>ERROR: %s</h3>%s\n" % (
79 msg, self.raw[self.lines[line]:]))
80 self.result.append('</font></pre>')
81
82 # close table
83 if linenumber:
84 self.result.append('</td></tr></table>')
85
86 text = ''.join(self.result)
87 if self.unicode:
88 text = unicode(text, 'utf-8')
89 return text
90
91 def __call__(self, toktype, toktext, (srow,scol), (erow,ecol), line):
92 """ Token handler.
93 """
94 if 0: print "type", toktype, token.tok_name[toktype], "text", toktext, \
95 "start", srow,scol, "end", erow,ecol, "<br>"
96
97 # calculate new positions
98 oldpos = self.pos
99 newpos = self.lines[srow] + scol
100 self.pos = newpos + len(toktext)
101
102 # handle newlines
103 if toktype in [token.NEWLINE, tokenize.NL]:
104 self.result.append('\n')
105 return
106
107 # send the original whitespace, if needed
108 if newpos > oldpos:
109 self.result.append(self.raw[oldpos:newpos])
110
111 # skip indenting tokens
112 if toktype in [token.INDENT, token.DEDENT]:
113 self.pos = newpos
114 return
115
116 # map token type to a color group
117 if token.LPAR <= toktype and toktype <= token.OP:
118 toktype = token.OP
119 elif toktype == token.NAME and keyword.iskeyword(toktext):
120 toktype = _KEYWORD
121 color = _colors.get(toktype, _colors[_TEXT])
122
123 style = ''
124 if toktype == token.ERRORTOKEN:
125 style = ' style="border: solid 1.5pt #FF0000;"'
126
127 # send text
128 self.result.append('<font color="%s"%s>' % (color, style))
129 if toktype == _KEYWORD:
130 self.result.append('<b>')
131 self.result.append(cgi.escape(toktext))
132 if toktype == _KEYWORD:
133 self.result.append('</b>')
134 self.result.append('</font>')
135
136 if __name__ == "__main__":
137 import os
138 print "Formatting..."
139
140 # open own source
141 source = open('colourize.py').read()
142
143 # write colorized version to "python.html"
144 file('colourize.html', 'w').write(Parser(source).format(False))
format中的linenumber可以控制是否要生成行号。