-- limodou [2004-09-13 01:21:13]
Contents
1. Python 源代码转成Html
现在有许多的Python源码转成Html的程序,这个是从Moin中修改而来的
1.1. 关于
现在有许多的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.2. 代码
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, \
"start", srow,scol, "end", erow,ecol, "<br>"
95
96 # calculate new positions
97 oldpos = self.pos
98 newpos = self.lines[srow] + scol
99 self.pos = newpos + len(toktext)
100
101 # handle newlines
102 if toktype in [token.NEWLINE, tokenize.NL]:
103 self.result.append('\n')
104 return
105
106 # send the original whitespace, if needed
107 if newpos > oldpos:
108 self.result.append(self.raw[oldpos:newpos])
109
110 # skip indenting tokens
111 if toktype in [token.INDENT, token.DEDENT]:
112 self.pos = newpos
113 return
114
115 # map token type to a color group
116 if token.LPAR <= toktype and toktype <= token.OP:
117 toktype = token.OP
118 elif toktype == token.NAME and keyword.iskeyword(toktext):
119 toktype = _KEYWORD
120 color = _colors.get(toktype, _colors[_TEXT])
121
122 style = ''
123 if toktype == token.ERRORTOKEN:
124 style = ' style="border: solid 1.5pt #FF0000;"'
125
126 # send text
127 self.result.append('<font color="%s"%s>' % (color, style))
128 if toktype == _KEYWORD:
129 self.result.append('<b>')
130 self.result.append(cgi.escape(toktext))
131 if toktype == _KEYWORD:
132 self.result.append('</b>')
133 self.result.append('</font>')
134
135 if __name__ == "__main__":
136 import os
137 print "Formatting..."
138
139 # open own source
140 source = open('colourize.py').read()
141
142 # write colorized version to "python.html"
143 file('colourize.html', 'w').write(Parser(source).format(False))
format中的linenumber可以控制是否要生成行号。