1 #!/usr/bin/env python
2 # -*- coding: utf-8
3 #
4 # snippets.py - Creates html/css highlighted Snippets out of normal
5 # source files.
6 #
7 # Copyright (C) 2007 Stefan Hacker
8 #
9 # This program is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; either version 2 of the License, or
12 # (at your option) any later version.
13 #
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
18 #
19 # You should have received a copy of the GNU General Public License along
20 # with this program; if not, write to the Free Software Foundation, Inc.,
21 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22
23 import codecs
24 from pygments import highlight
25 from pygments.lexers import *
26 from pygments.formatters import HtmlFormatter
27 from time import ctime, time
28
29 """
30 Config options
31 """
32 #Name of the stylesheet to create/use
33 stylesheet = "highlight.css"
34
35 #Definition of all snippets to process
36 snippets = {
37 'snippets.html':{
38 'description':"snippets is a small script I use to create "\
39 "codesnippets like this one.",
40 'title':"Snippet creator",
41 'files':{'snippets.py':PythonLexer}
42 },
43 'gltext.html':{
44 'description':"gltext utilizes wxpython to enable the user "\
45 "to easily display system fonts in an pyopengl "\
46 "environment.",
47 'title':"wxpython/opengl easy text to texture class - gltext.py",
48 'files':{'gltext.py':PythonLexer}
49 },
50
51 'jabber_post_commit_hook.html':{
52 'description':"xmpp_pc is a simple post-commit hook script "\
53 "which is able to inform a fixed set of "\
54 "xmpp/jabber users of a recent commit.",
55 'title':"XMPP/Jabber svn post commit hook",
56 'files':{'post-commit':BashLexer,
57 'xmpp_pc.py':PythonLexer}
58 },
59
60 'xmpp_bot.html':{
61 'description':"xmpp_bot is a minimal, extendable bot which "\
62 "provides easy function integration as well as "\
63 "a basic rights management.",
64 'title':"Simple XMPP/Jabber bot",
65 'files':{'bot.py':PythonLexer,
66 'xmpp_bot.py':PythonLexer}
67 },
68 'grabxkcd.html':{
69 'description':"grabxk is a small script to keep up to date with all xkcd "\
70 "webcomics. Downloads all up to the current one into current folder.",
71 'title':"xkcd webcomic grabber",
72 'files': {'grabxkcd.py':PythonLexer}
73 }
74 }
75
76 #Template for the head of the file
77 head = u"""<?xml version="1.0" encoding="utf-8"?>
78 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
79 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
80 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
81
82 <head>
83 <title>%(title)s</title>
84 <meta http-equiv="content-type"
85 content="text/html;charset=utf-8" />
86 <meta http-equiv="Content-Style-Type" content="text/css" />
87 <link rel="stylesheet" type="text/css" href="%(stylesheet)s"/>
88 </head>
89 <body>
90 <h1>%(title)s</h1>
91 <div>
92 <b>Description:</b> %(description)s<br/>
93 <b>Raw download:</b> %(downloads)s<br/>
94 <b>Jump to:</b> %(jumps)s<br/>
95 </div>
96 """
97
98 #Template for a download link (inserted into $(downloads) variable
99 downloadatom = u"<a href='%(path)s'>%(path)s</a>"
100
101 #Template for a jump link (inserted into $(jumps) vairable
102 jumpatom = u"<a href='#%(path)s'>%(path)s</a>"
103
104 #Template for a file (inserted after body)
105 bodyatom = u"""<h2 id="%(path)s">%(path)s (<a href="%(path)s">Raw</a>)</h2>
106 %(highlighted)s
107 <div><br/></div>
108 """
109
110 #Template for the end of the file
111 tail = u"""<div><i>Created on %(time)s using <a href="http://pygments.org/">pygments</a>.</i></div></body>
112 </html>
113 """
114
115 if __name__ == "__main__":
116 errors = False
117
118 print "Creating stylesheet '%s': " % stylesheet,
119 try:
120 mfile = open(stylesheet, 'w')
121 except IOError:
122 print "Failed"
123 exit(1)
124
125 print>>mfile, HtmlFormatter().get_style_defs()
126 print "Done"
127
128 print "Creating snippets..."
129 for snippet, spec in snippets.iteritems():
130 print "Processing '%s':" % snippet
131 try:
132 mfile = codecs.open(snippet, "w","utf-8")
133 except IOError:
134 print "Open file in write mode failed"
135 errors = True
136 continue
137
138 #Insert file head
139 print " Insert head: ",
140
141 #Create raw download/jump links
142 downloads = ''
143 jumps = ''
144 first = True
145 for path, lexer in spec['files'].iteritems():
146 if not first:
147 downloads += ' / '
148 jumps += ' / '
149 else: first = False
150
151 downloads += downloadatom % {'path':path, 'type':lexer.name}
152 jumps += jumpatom % {'path':path, 'type':lexer.name}
153
154 #Append it to the specs ;-)
155 spec['downloads'] = downloads
156 spec['jumps'] = jumps
157 spec['stylesheet']= stylesheet
158
159 print>>mfile, head % spec
160 print "Done"
161
162
163
164 #Processing files
165 print " Processing files:"
166 for path, lexer in spec['files'].iteritems():
167 print " %s (%s): " % (path, lexer.name),
168 try:
169 code = open(path, "r").read()
170 except IOError:
171 print "Failed to open file"
172 errors = True
173 continue
174
175 highlighted = highlight(code, lexer(), HtmlFormatter(linenos='inline'))
176 print>>mfile, bodyatom % {'path':path,
177 'highlighted':highlighted}
178 print "Done"
179
180 #Insert tail
181 print " Insert tail: ",
182 print>>mfile, tail % {'time':ctime(time())}
183 print "Done"
184
185 if errors:
186 print "======================================================================"
187 print "WARNING: ONE OR MORE ERRORS OCCURED DURING THE EXECUTION OF THE SCRIPT"
188 print "======================================================================"
189 else:
190 print "All snippets processed"
191 print "Goodbye"