]> Pileus Git - ~andy/gtk/blob - docs/make-todo
stylecontext: Do invalidation on first resize container
[~andy/gtk] / docs / make-todo
1 #!/usr/bin/python
2
3 import xmllib;
4 import sys;
5 import string
6 import re
7
8 def html_subst(s):
9     if s.group(1) != None:
10         return s.group(0)
11     elif s.group(2) != None:
12         return '<a href="' + s.group(0) + '">' + s.group(0) + '</a>'
13     elif s.group(3) != None:
14         return '<a href="mailto:' + s.group(0) + '">' + s.group(0) + '</a>'
15         
16 def htmlify(str): 
17     return re.sub ("(<[^>]*>)|(http://[~.:/\w-]+)|([\w._!-]+@[\w_-]+).[\w_-]+", html_subst, str)
18
19 def bug_subst(s):
20     if s.group(1) != None:
21         return s.group(0)
22     else:
23         n = s.group(2)
24         return '<a href="http://bugs.gnome.org/db/%s/%s.html">#%s</a>' % (n[0:2], n, n)
25
26 def bugify(str):
27     str =  re.sub ("(<[^>]*>)|#(\d+)", bug_subst, str)
28     return htmlify(str)
29
30 def make_id(str):
31     return re.sub ("[^a-z]","-", string.lower(str))
32
33 class ParseError (Exception):
34     pass
35
36 class Entry:
37     def __init__(self):
38         self.description = None
39         self.title = None
40         self.url = None
41         self.contact = None
42         self.bugs = None
43
44     def set_size(self, size):
45         size = string.lower(size)
46         if size == "small":
47             self.size = "Small"
48         elif size == "medium":
49             self.size = "Medium"
50         elif size == "big":
51             self.size = "Big"
52         else:
53             raise ParseError, 'size must be "small", "medium", or "big"'
54
55     def output(self):
56         if self.size == "Big":
57             bgcolor = "#88bb88"
58         elif self.size == "Medium":
59             bgcolor = "#b4d4b4"
60         else:
61             bgcolor = "#d0e0d0"
62         
63         print '''<table cellspacing="0" cellpadding="2" width="97%%" border="0" bgcolor="#000000">
64         <tbody><tr><td colspan=2>
65         <table cellspacing="0" cellpadding="5" width="100%%" border="0" bgcolor="#ffffff">
66         <tbody>
67           <tr bgcolor="%s">
68              <td align="left"><font size="+1">%s</font></font></td>
69              <td align="left" width="20%%"><b>Size</b>: %s</td>
70              <td align="center" width="20%%"><b>Status</b>: %s</td>
71              <td align="right" width="20%%"><b>Target Version</b>: %s</td>
72           </tr>
73           <tr>
74              <td colspan=4>
75              %s
76              <table cellspacing="0" cellpadding="0">
77                <tbody>''' % (bgcolor, self.title, self.size, self.status, self.target, htmlify(self.description))
78
79         if self.url != None:
80             print '''<tr><td width="0"><b>More Info</b>:</td>
81                      <td>%s</td>
82                      </tr>''' % htmlify (self.url)
83
84         if self.bugs != None:
85             print '''<tr><td width="0"><b>Bug Reports</b>:</td>
86                      <td>%s</td>
87                      </tr>''' % bugify (self.bugs)
88
89         if self.contact != None:
90             print '''<tr><td width="0"><b>Contact</b>:</td>
91                      <td>%s</td>
92                      </tr>''' % htmlify (self.contact)
93
94         print '''</tbody>
95              </table>
96              </td>
97          </tr>
98         </tbody></table>
99         </td></tr></tbody></table>
100 '''
101
102 class Section:
103     def __init__(self):
104         self.title = None
105         self.entries = []
106
107     def output(self):
108
109         print '<h2><a name="%s">%s</a></h2>' % (make_id(self.title), self.title)
110         
111         first = 1
112         for entry in self.entries:
113             if not first:
114                 print "<br>"
115             first = 0
116             entry.output()
117
118 class TodoParser (xmllib.XMLParser):
119     def __init__(self):
120         xmllib.XMLParser.__init__(self)
121         
122         self.in_todo = 0
123         self.in_data = 0
124         self.data = ""
125         self.section = None
126         self.entry = None
127         self.logourl = None
128         self.title = None
129         self.sections = []
130
131         self.entitydefs = {}
132
133     def start_todo(self,attributes):
134         if self.in_todo:
135             raise ParseError, "<todo> tags may not be nested"
136         if attributes.has_key ("logourl"):
137             self.logourl = attributes["logourl"]
138         self.in_todo = 1
139
140     def end_todo(self):
141         self.in_todo = 0
142
143     def start_section(self,attributes):
144         if self.section:
145             raise ParseError, "<section> tags may not be nested"
146         
147         self.section = Section()
148
149     def end_section(self):
150         if self.section.title == None:
151             raise ParseError, "<section> requires <title>"
152             
153         self.sections.append(self.section)
154         self.section = None
155
156     def start_title(self,attributes):
157         if not self.in_todo:
158             raise ParseError, "<title> tag must be in <todo>, <section> or <entry>"
159         if self.in_data:
160             raise ParseError, "Unexpected <title> tag in content"
161         self.in_data = 1
162     
163     def end_title(self):
164         self.in_data = 0
165         if self.entry:
166             self.entry.title = self.data
167         elif self.section:
168             self.section.title = self.data
169         else:
170             self.title = self.data
171         self.data = ""
172             
173     def start_description(self,attributes):
174         if not self.entry:
175             raise ParseError, "<description> tag must be in <entry>"
176         if self.in_data:
177             raise ParseError, "Unexpected <description> tag in content"
178         self.in_data = 1
179     
180     def end_description(self):
181         self.in_data = 0
182         self.entry.description = self.data
183         self.data = ""
184             
185     def start_url(self,attributes):
186         if not self.entry:
187             raise ParseError, "<url> tag must be in <entry>"
188         if self.in_data:
189             raise ParseError, "Unexpected <url> tag in content"
190         self.in_data = 1
191     
192     def end_url(self):
193         self.in_data = 0
194         self.entry.url = self.data
195         self.data = ""
196             
197     def start_contact(self,attributes):
198         if not self.entry:
199             raise ParseError, "<contact> tag must be in <entry>"
200         if self.in_data:
201             raise ParseError, "Unexpected <contact> tag in content"
202         self.in_data = 1
203     
204     def end_contact(self):
205         self.in_data = 0
206         self.entry.contact = self.data
207         self.data = ""
208             
209     def start_bugs(self,attributes):
210         if not self.entry:
211             raise ParseError, "<bugs> tag must be in <bugs>"
212         if self.in_data:
213             raise ParseError, "Unexpected <bugs> tag in content"
214         self.in_data = 1
215     
216     def end_bugs(self):
217         self.in_data = 0
218         self.entry.bugs = self.data
219         self.data = ""
220             
221     def start_entry(self,attributes):
222         if not self.section:
223             raise ParseError, "<entry> tag must be in <section>"
224         if self.entry:
225             raise ParseError, "<entry> tags may not be nested"
226
227         self.entry = Entry()
228
229         if not attributes.has_key("size"):
230             raise ParseError, '"size" attribute required for entry'
231         self.entry.set_size(attributes["size"])
232
233         if not attributes.has_key("status"):
234             raise ParseError, '"status" attribute (completion percentage) required for entry'
235         self.entry.status=attributes["status"]
236
237         if not attributes.has_key("target"):
238             raise ParseError, '"target" attribute (target version) required for entry'
239         self.entry.target=attributes["target"]
240
241     def end_entry(self):
242         if self.entry.title == None:
243             raise ParseError, "<entry> requires <title>"
244             
245         if self.entry.description == None:
246             raise ParseError, "<entry> requires <description>"
247             
248         self.section.entries.append(self.entry)
249         self.entry = None
250
251     def handle_data(self,data):
252         if self.in_data:
253             self.data = self.data + data
254         
255     def unknown_starttag(self,tag,attributes):
256         if not self.in_data:
257             raise ParseError, "Unexpected start tag: " + tag
258         else:
259             self.data = self.data + "<" + tag
260             for (key,val) in attributes.items():
261                 self.data = self.data + ' %s="%s"' % (key,val)
262             self.data = self.data + ">"
263
264     def unknown_endtag(self,tag):
265         if not self.in_data:
266             raise ParseError, "Unexpected end tag: " + tag
267         else:
268             self.data = self.data + "</%s>" % tag
269
270     def syntax_error(self, err):
271         if re.match("reference to unknown entity", err):
272             pass
273         else:
274             xmllib.XMLParser.syntax_error (self, err)
275             
276     def unknown_entityref(self,ref):
277         if not self.in_data:
278             raise ParseError, "Unknown entity &" + ref + ";"
279         else:
280             self.data = self.data + "&" + ref + ";"
281
282 file = open(sys.argv[1])
283 parser = TodoParser()
284
285 lineno = 1
286 while 1:
287     line = file.readline()
288     if line == "":
289         break
290
291     try:
292         parser.feed(line)
293     except ParseError, err:
294         sys.stderr.write("Parse error at line " + `lineno` + ": " + err.__str__() + "\n")
295         sys.exit(1)
296     except RuntimeError, err:
297         sys.stderr.write(err.__str__() + "\n")
298         sys.exit(1)
299
300     lineno = lineno + 1
301
302 parser.close()
303 if parser.title == None:
304     sys.stderr.write ("<todo> Document must have a <title>\n")
305     sys.exit (1)
306
307 print '''<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
308 <html>
309 <head>
310 <title>%s</title>
311 </head>
312 <body bgcolor="#ffffff">
313 <table width="100%%" cellspacing="0" cellpadding="0" border="0">
314   <tbody>
315     <tr valign="top">
316       <td>
317         <h1>%s</h1>''' % (parser.title, parser.title)
318
319
320 for section in parser.sections:
321     ntasks = len(section.entries)
322     id = make_id (section.title)
323     if ntasks == 1:
324         print '<a href="#%s">%s</a> (1 item)<br>' % (id,section.title)
325     else:
326         print '<a href="#%s">%s</a> (%d items)<br>' % (id,section.title,ntasks)
327
328 print '''
329       </td>'''
330 if parser.logourl != None:
331     print '''      <td align="right">
332        <img src="%s" alt="Logo"></img>
333       </td>''' % parser.logourl
334 print '''
335     </tr>
336   </tbody>
337 </table>
338 ''' 
339
340 first = 1
341 for section in parser.sections:
342     if not first:
343         print "<br><br>"
344     first = 0
345     section.output()
346
347 print '''</body>
348 </html>'''
349     
350