1 2import re, time 3 4class Node: 5 def __init__(self, name): 6 self.name = name 7 self.body = "" 8 self.index = "" 9 self.indexname = "" 10 self.tag = "" 11 self.nodes = [] 12 def Sorted(self): 13 names = [] 14 for n in self.nodes: 15 names += [n.name] 16 names.sort() 17 new_list = [] 18 for name in names: 19 for n in self.nodes: 20 if n.name == name: 21 new_list += [n] 22 break 23 self.nodes = new_list 24 return self 25 26# tags 27group_tag = "@GROUP" 28function_tag = "@FUNCTION" 29option_tag = "@OPTION" 30body_tag = "@BODY" 31tags = [function_tag, option_tag, body_tag] 32end_tag = "@END" 33 34class DocInfo: 35 def __init__(self): 36 self.name = "" 37 self.copyright = "" 38 self.logo = "" 39 40class Output: 41 def __init__(self, filename, docinfo): 42 self.filename = filename 43 self.docinfo = docinfo 44 45 def output_name(self): 46 return self.filename 47 48 def render_node_index(self, cur): 49 if len(cur.index): 50 print >>self.file, self.index_node_begin(cur) 51 for node in cur.nodes: 52 self.render_node_index(node) 53 if len(cur.index): 54 print >>self.file, self.index_node_end(cur) 55 def render_node(self, cur): 56 if len(cur.index): 57 print >>self.file, self.format_header(cur) 58 print >>self.file, self.format_body(cur) 59 for node in cur.nodes: 60 self.render_node(node) 61 62 def index_nodes(self, cur, index=""): 63 for i in xrange(0, len(cur.nodes)): 64 if len(index): 65 cur.nodes[i].index = index + "." + str(i+1) 66 else: 67 cur.nodes[i].index = str(i+1) 68 69 cur.nodes[i].indexname = cur.nodes[i].name 70 if cur.nodes[i].tag == function_tag: 71 cur.nodes[i].indexname = cur.nodes[i].indexname.split("(")[0].strip() 72 self.index_nodes(cur.nodes[i], cur.nodes[i].index) 73 74 def render(self, rootnode): 75 self.index_nodes(rootnode) 76 print >>self.file, self.render_begin() 77 78 print >>self.file, self.index_begin() 79 self.render_node_index(rootnode) 80 print >>self.file, self.index_end() 81 82 self.render_node(rootnode) 83 print >>self.file, self.render_end() 84 85class HTMLOutput(Output): 86 def render_begin(self): 87 img = "" 88 if len(self.docinfo.logo): 89 img = '<img src="%s"/>'%self.docinfo.logo 90 91 # large part of the style sheet is stolen from luas documentation 92 return ''' 93 <head> 94 <title>Bam Manual</title> 95 96 <style type="text/css"><!-- 97 98 body { 99 color: #000000 ; 100 background-color: #FFFFFF ; 101 font-family: sans-serif ; 102 text-align: justify ; 103 margin-right: 20px ; 104 margin-left: 20px ; 105 } 106 107 h1, h2, h3, h4, h5 { 108 font-weight: normal ; 109 font-style: italic ; 110 } 111 112 a:link { 113 color: #000080 ; 114 background-color: inherit ; 115 text-decoration: none ; 116 } 117 118 a:visited { 119 background-color: inherit ; 120 text-decoration: none ; 121 } 122 123 a:link:hover, a:visited:hover { 124 color: #000080 ; 125 background-color: #E0E0FF ; 126 } 127 128 a:link:active, a:visited:active { 129 color: #FF0000 ; 130 } 131 132 hr { 133 border: 0 ; 134 height: 1px ; 135 color: #a0a0a0 ; 136 background-color: #a0a0a0 ; 137 } 138 139 pre { 140 padding: 5px ; 141 background-color: #eeeeee ; 142 } 143 144 td { 145 border-width: 1px; 146 border-style: dotted; 147 padding: 2px; 148 } 149 150 .identifier { 151 font-family: monospace ; 152 } 153 154 li { 155 list-style-type: none; 156 } 157 158 --></style> 159 </head> 160 <body> 161 <!-- COMMENTS "BASE" --> 162 <hr/> 163 %s<h1>%s</h1> 164 <small>%s</small> 165 166 <hr/> 167 %s 168 ''' %(img, self.docinfo.name, self.docinfo.note, self.docinfo.copyright) 169 def render_end(self): 170 return ''' 171 <hr/> 172 <small>Generated at %s.</small> 173 </body> 174 ''' % (time.asctime()) 175 176 def index_begin(self): return '<h2>Contents</h2><ul>' 177 def index_end(self): return '</ul><hr/>' 178 def index_node_begin(self, node): 179 return '<li><a href="#%s">%s - %s</a></li><ul>'%(node.index,node.index,node.indexname) 180 def index_node_end(self, node): 181 if len(node.index) == 1: 182 return '</ul><p></p>' 183 return '</ul>' 184 185 def format_header(self, node): 186 i = (len(node.index)-1)/2 + 1 187 header = '<h%d><a name="%s"></a><a name="%s">%s</a> - <a name="%s">%s</a></h%d>'%(i,node.indexname,node.index,node.index,node.name,node.name,i) 188 if node.tag == function_tag: 189 header = '<hr/>' + header 190 return header 191 192 def format_body(self, node): 193 body = node.body 194 body = re.sub('\^(?P<ident>[^\^]+)\^', '<span class="identifier">\g<ident></span>', body) 195 body = re.sub('\[(?P<ident>[^\]]+)\]', '<a href="#\g<ident>">\g<ident></a>', body) 196 body = re.sub('{{{{', '<pre>', body) 197 body = re.sub('}}}}', '</pre>', body) 198 body = re.sub('!IMG (?P<filename>.+)', '<img src="\g<filename>"/>', body) 199 body = re.sub('\\\\t', ' ', body) 200 body = re.sub('\n\n', '</p><p>', body) 201 202 203 body = '<p class="body">' + body + '</p>\n' 204 body += '\n<!-- COMMENTS "%s" -->\n' % (node.indexname) 205 return body 206 207def ParseTextFile(rootnode, filename, addbr=False): 208 group = rootnode 209 for line in file(filename): 210 if group_tag in line: 211 group_name = line.split(group_tag)[-1].split(end_tag)[0].strip() 212 group = Node(group_name) 213 rootnode.nodes += [group] 214 else: 215 if addbr: 216 group.body += line.strip() + "<br/>\n" 217 else: 218 group.body += line.strip() + "\n" 219 220 return rootnode 221 222def ParseFile(rootnode, filename): 223 # 0 = scaning for start tag 224 # 1 = scaning for end tag, 225 # 2 = outputting function decl 226 state = 0 227 group = rootnode 228 for line in file(filename): 229 if state == 0: 230 if group_tag in line: 231 group_name = line.split(group_tag)[-1].split(end_tag)[0].strip() 232 group = Node(group_name) 233 rootnode.nodes += [group] 234 else: 235 for t in tags: 236 if t in line: 237 title = line.split(t)[-1].strip() 238 tag = t 239 body = "" 240 state = 1 241 break 242 elif state == 1: 243 if end_tag in line: 244 state = 3 245 elif "@PAUSE" in line: 246 state = 2 247 else: 248 body += line.strip() + "\n" 249 elif state == 2: 250 if "@RESUME" in line: 251 state = 1 252 else: 253 if tag == function_tag: 254 if len(title) == 0: 255 title = line.replace("function", "").strip() 256 title = title.replace("(", " (") 257 node = Node(title) 258 node.body = body 259 node.tag = tag 260 group.nodes += [node] 261 state = 0 262 return rootnode 263