Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 1 | #! /usr/bin/env python |
| 2 | |
Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 3 | __version__ = '$Revision$' |
| 4 | |
Fred Drake | 071972e | 2002-10-16 15:30:17 +0000 | [diff] [blame] | 5 | import os.path |
Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 6 | import re |
| 7 | import string |
| 8 | import sys |
| 9 | |
Fred Drake | 3972457 | 2003-11-25 16:21:00 +0000 | [diff] [blame] | 10 | from xml.sax.saxutils import quoteattr |
| 11 | |
Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 12 | |
Fred Drake | 3d42266 | 2001-12-26 19:55:14 +0000 | [diff] [blame] | 13 | bang_join = "!".join |
| 14 | null_join = "".join |
| 15 | |
Fred Drake | 63a0191 | 2004-07-08 03:56:12 +0000 | [diff] [blame] | 16 | REPLACEMENTS = [ |
| 17 | # Hackish way to deal with macros replaced with simple text |
| 18 | (re.compile(r"\\ABC\b"), "ABC"), |
| 19 | (re.compile(r"\\ASCII\b"), "ASCII"), |
| 20 | (re.compile(r"\\Cpp\b"), "C++"), |
| 21 | (re.compile(r"\\EOF\b"), "EOF"), |
| 22 | (re.compile(r"\\NULL\b"), "NULL"), |
| 23 | (re.compile(r"\\POSIX\b"), "POSIX"), |
| 24 | (re.compile(r"\\UNIX\b"), "Unix"), |
| 25 | # deal with turds left over from LaTeX2HTML |
| 26 | (re.compile(r"<#\d+#>"), ""), |
| 27 | ] |
Fred Drake | 3d42266 | 2001-12-26 19:55:14 +0000 | [diff] [blame] | 28 | |
Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 29 | class Node: |
Fred Drake | ba82878 | 2000-04-03 04:19:14 +0000 | [diff] [blame] | 30 | continuation = 0 |
| 31 | |
Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 32 | def __init__(self, link, str, seqno): |
| 33 | self.links = [link] |
| 34 | self.seqno = seqno |
Fred Drake | 63a0191 | 2004-07-08 03:56:12 +0000 | [diff] [blame] | 35 | for pattern, replacement in REPLACEMENTS: |
| 36 | str = pattern.sub(replacement, str) |
Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 37 | # build up the text |
Fred Drake | 058068d | 1998-04-08 23:12:51 +0000 | [diff] [blame] | 38 | self.text = split_entry_text(str) |
Guido van Rossum | 992d4a3 | 2007-07-11 13:09:30 +0000 | [diff] [blame] | 39 | self.key = list(split_entry_key(str)) |
| 40 | |
Collin Winter | 65d09d4 | 2007-03-21 02:11:39 +0000 | [diff] [blame] | 41 | def __eq__(self, other): |
| 42 | return cmp(self, other) == 0 |
Guido van Rossum | 992d4a3 | 2007-07-11 13:09:30 +0000 | [diff] [blame] | 43 | |
Collin Winter | 65d09d4 | 2007-03-21 02:11:39 +0000 | [diff] [blame] | 44 | def __lt__(self, other): |
| 45 | return cmp(self, other) == -1 |
Guido van Rossum | 992d4a3 | 2007-07-11 13:09:30 +0000 | [diff] [blame] | 46 | |
Collin Winter | 65d09d4 | 2007-03-21 02:11:39 +0000 | [diff] [blame] | 47 | def __gt__(self, other): |
| 48 | return cmp(self, other) == 1 |
Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 49 | |
| 50 | def __cmp__(self, other): |
| 51 | """Comparison operator includes sequence number, for use with |
| 52 | list.sort().""" |
| 53 | return self.cmp_entry(other) or cmp(self.seqno, other.seqno) |
| 54 | |
| 55 | def cmp_entry(self, other): |
| 56 | """Comparison 'operator' that ignores sequence number.""" |
Fred Drake | 058068d | 1998-04-08 23:12:51 +0000 | [diff] [blame] | 57 | c = 0 |
Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 58 | for i in range(min(len(self.key), len(other.key))): |
Fred Drake | 058068d | 1998-04-08 23:12:51 +0000 | [diff] [blame] | 59 | c = (cmp_part(self.key[i], other.key[i]) |
| 60 | or cmp_part(self.text[i], other.text[i])) |
Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 61 | if c: |
Fred Drake | 058068d | 1998-04-08 23:12:51 +0000 | [diff] [blame] | 62 | break |
| 63 | return c or cmp(self.key, other.key) or cmp(self.text, other.text) |
Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 64 | |
| 65 | def __repr__(self): |
Fred Drake | 3d42266 | 2001-12-26 19:55:14 +0000 | [diff] [blame] | 66 | return "<Node for %s (%s)>" % (bang_join(self.text), self.seqno) |
Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 67 | |
| 68 | def __str__(self): |
Fred Drake | 3d42266 | 2001-12-26 19:55:14 +0000 | [diff] [blame] | 69 | return bang_join(self.key) |
Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 70 | |
| 71 | def dump(self): |
Fred Drake | 058068d | 1998-04-08 23:12:51 +0000 | [diff] [blame] | 72 | return "%s\1%s###%s\n" \ |
Fred Drake | 071972e | 2002-10-16 15:30:17 +0000 | [diff] [blame] | 73 | % ("\1".join(self.links), |
Fred Drake | 3d42266 | 2001-12-26 19:55:14 +0000 | [diff] [blame] | 74 | bang_join(self.text), |
Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 75 | self.seqno) |
| 76 | |
| 77 | |
Fred Drake | 058068d | 1998-04-08 23:12:51 +0000 | [diff] [blame] | 78 | def cmp_part(s1, s2): |
| 79 | result = cmp(s1, s2) |
| 80 | if result == 0: |
| 81 | return 0 |
Fred Drake | 3d42266 | 2001-12-26 19:55:14 +0000 | [diff] [blame] | 82 | l1 = s1.lower() |
| 83 | l2 = s2.lower() |
Fred Drake | 058068d | 1998-04-08 23:12:51 +0000 | [diff] [blame] | 84 | minlen = min(len(s1), len(s2)) |
| 85 | if len(s1) < len(s2) and l1 == l2[:len(s1)]: |
| 86 | result = -1 |
| 87 | elif len(s2) < len(s1) and l2 == l1[:len(s2)]: |
| 88 | result = 1 |
| 89 | else: |
| 90 | result = cmp(l1, l2) or cmp(s1, s2) |
| 91 | return result |
| 92 | |
| 93 | |
| 94 | def split_entry(str, which): |
| 95 | stuff = [] |
Fred Drake | 3d42266 | 2001-12-26 19:55:14 +0000 | [diff] [blame] | 96 | parts = str.split('!') |
| 97 | parts = [part.split('@') for part in parts] |
Fred Drake | 058068d | 1998-04-08 23:12:51 +0000 | [diff] [blame] | 98 | for entry in parts: |
| 99 | if len(entry) != 1: |
| 100 | key = entry[which] |
| 101 | else: |
| 102 | key = entry[0] |
| 103 | stuff.append(key) |
| 104 | return stuff |
| 105 | |
| 106 | |
Fred Drake | ba82878 | 2000-04-03 04:19:14 +0000 | [diff] [blame] | 107 | _rmtt = re.compile(r"""(.*)<tt(?: class=['"][a-z0-9]+["'])?>(.*)</tt>(.*)$""", |
Fred Drake | 4cc902f | 1999-02-18 16:11:12 +0000 | [diff] [blame] | 108 | re.IGNORECASE) |
Fred Drake | 058068d | 1998-04-08 23:12:51 +0000 | [diff] [blame] | 109 | _rmparens = re.compile(r"\(\)") |
| 110 | |
| 111 | def split_entry_key(str): |
| 112 | parts = split_entry(str, 1) |
| 113 | for i in range(len(parts)): |
| 114 | m = _rmtt.match(parts[i]) |
| 115 | if m: |
Fred Drake | 3d42266 | 2001-12-26 19:55:14 +0000 | [diff] [blame] | 116 | parts[i] = null_join(m.group(1, 2, 3)) |
Fred Drake | 058068d | 1998-04-08 23:12:51 +0000 | [diff] [blame] | 117 | else: |
Fred Drake | 3d42266 | 2001-12-26 19:55:14 +0000 | [diff] [blame] | 118 | parts[i] = parts[i].lower() |
Fred Drake | 058068d | 1998-04-08 23:12:51 +0000 | [diff] [blame] | 119 | # remove '()' from the key: |
| 120 | parts[i] = _rmparens.sub('', parts[i]) |
| 121 | return map(trim_ignored_letters, parts) |
| 122 | |
| 123 | |
| 124 | def split_entry_text(str): |
| 125 | if '<' in str: |
| 126 | m = _rmtt.match(str) |
| 127 | if m: |
Fred Drake | 3d42266 | 2001-12-26 19:55:14 +0000 | [diff] [blame] | 128 | str = null_join(m.group(1, 2, 3)) |
Fred Drake | 058068d | 1998-04-08 23:12:51 +0000 | [diff] [blame] | 129 | return split_entry(str, 1) |
| 130 | |
| 131 | |
Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 132 | def load(fp): |
| 133 | nodes = [] |
Fred Drake | 058068d | 1998-04-08 23:12:51 +0000 | [diff] [blame] | 134 | rx = re.compile("(.*)\1(.*)###(.*)$") |
Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 135 | while 1: |
| 136 | line = fp.readline() |
| 137 | if not line: |
| 138 | break |
| 139 | m = rx.match(line) |
| 140 | if m: |
| 141 | link, str, seqno = m.group(1, 2, 3) |
| 142 | nodes.append(Node(link, str, seqno)) |
| 143 | return nodes |
| 144 | |
| 145 | |
Fred Drake | 058068d | 1998-04-08 23:12:51 +0000 | [diff] [blame] | 146 | def trim_ignored_letters(s): |
Fred Drake | 3b07480 | 1999-01-04 22:00:56 +0000 | [diff] [blame] | 147 | # ignore $ to keep environment variables with the |
| 148 | # leading letter from the name |
Fred Drake | 3d42266 | 2001-12-26 19:55:14 +0000 | [diff] [blame] | 149 | if s.startswith("$"): |
| 150 | return s[1:].lower() |
Fred Drake | 3b07480 | 1999-01-04 22:00:56 +0000 | [diff] [blame] | 151 | else: |
Fred Drake | 3d42266 | 2001-12-26 19:55:14 +0000 | [diff] [blame] | 152 | return s.lower() |
Fred Drake | 058068d | 1998-04-08 23:12:51 +0000 | [diff] [blame] | 153 | |
| 154 | def get_first_letter(s): |
Fred Drake | 3d42266 | 2001-12-26 19:55:14 +0000 | [diff] [blame] | 155 | if s.startswith("<tex2html_percent_mark>"): |
| 156 | return "%" |
| 157 | else: |
| 158 | return trim_ignored_letters(s)[0] |
Fred Drake | 058068d | 1998-04-08 23:12:51 +0000 | [diff] [blame] | 159 | |
| 160 | |
Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 161 | def split_letters(nodes): |
| 162 | letter_groups = [] |
Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 163 | if nodes: |
Fred Drake | 058068d | 1998-04-08 23:12:51 +0000 | [diff] [blame] | 164 | group = [] |
| 165 | append = group.append |
| 166 | letter = get_first_letter(nodes[0].text[0]) |
Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 167 | letter_groups.append((letter, group)) |
| 168 | for node in nodes: |
Fred Drake | 058068d | 1998-04-08 23:12:51 +0000 | [diff] [blame] | 169 | nletter = get_first_letter(node.text[0]) |
Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 170 | if letter != nletter: |
| 171 | letter = nletter |
| 172 | group = [] |
| 173 | letter_groups.append((letter, group)) |
| 174 | append = group.append |
| 175 | append(node) |
| 176 | return letter_groups |
| 177 | |
| 178 | |
Fred Drake | 3d42266 | 2001-12-26 19:55:14 +0000 | [diff] [blame] | 179 | def group_symbols(groups): |
| 180 | entries = [] |
| 181 | ident_letters = string.ascii_letters + "_" |
| 182 | while groups[0][0] not in ident_letters: |
| 183 | entries += groups[0][1] |
| 184 | del groups[0] |
| 185 | if entries: |
| 186 | groups.insert(0, ("Symbols", entries)) |
| 187 | |
| 188 | |
Fred Drake | 7cbf462 | 1998-08-07 19:50:13 +0000 | [diff] [blame] | 189 | # need a function to separate the nodes into columns... |
| 190 | def split_columns(nodes, columns=1): |
| 191 | if columns <= 1: |
Fred Drake | 077fffa | 1998-08-07 20:49:54 +0000 | [diff] [blame] | 192 | return [nodes] |
Fred Drake | 7cbf462 | 1998-08-07 19:50:13 +0000 | [diff] [blame] | 193 | # This is a rough height; we may have to increase to avoid breaks before |
| 194 | # a subitem. |
Fred Drake | 3d42266 | 2001-12-26 19:55:14 +0000 | [diff] [blame] | 195 | colheight = int(len(nodes) / columns) |
| 196 | numlong = int(len(nodes) % columns) |
Fred Drake | 7cbf462 | 1998-08-07 19:50:13 +0000 | [diff] [blame] | 197 | if numlong: |
| 198 | colheight = colheight + 1 |
| 199 | else: |
| 200 | numlong = columns |
| 201 | cols = [] |
| 202 | for i in range(numlong): |
| 203 | start = i * colheight |
| 204 | end = start + colheight |
| 205 | cols.append(nodes[start:end]) |
| 206 | del nodes[:end] |
| 207 | colheight = colheight - 1 |
| 208 | try: |
Fred Drake | 3d42266 | 2001-12-26 19:55:14 +0000 | [diff] [blame] | 209 | numshort = int(len(nodes) / colheight) |
Fred Drake | 7cbf462 | 1998-08-07 19:50:13 +0000 | [diff] [blame] | 210 | except ZeroDivisionError: |
| 211 | cols = cols + (columns - len(cols)) * [[]] |
| 212 | else: |
| 213 | for i in range(numshort): |
| 214 | start = i * colheight |
| 215 | end = start + colheight |
| 216 | cols.append(nodes[start:end]) |
Fred Drake | ba82878 | 2000-04-03 04:19:14 +0000 | [diff] [blame] | 217 | # |
| 218 | # If items continue across columns, make sure they are marked |
| 219 | # as continuations so the user knows to look at the previous column. |
| 220 | # |
| 221 | for i in range(len(cols) - 1): |
| 222 | try: |
| 223 | prev = cols[i][-1] |
| 224 | next = cols[i + 1][0] |
| 225 | except IndexError: |
| 226 | return cols |
| 227 | else: |
| 228 | n = min(len(prev.key), len(next.key)) |
| 229 | for j in range(n): |
| 230 | if prev.key[j] != next.key[j]: |
| 231 | break |
| 232 | next.continuation = j + 1 |
Fred Drake | 077fffa | 1998-08-07 20:49:54 +0000 | [diff] [blame] | 233 | return cols |
Fred Drake | 7cbf462 | 1998-08-07 19:50:13 +0000 | [diff] [blame] | 234 | |
| 235 | |
Fred Drake | 058068d | 1998-04-08 23:12:51 +0000 | [diff] [blame] | 236 | DL_LEVEL_INDENT = " " |
| 237 | |
Fred Drake | 7cbf462 | 1998-08-07 19:50:13 +0000 | [diff] [blame] | 238 | def format_column(nodes): |
Fred Drake | 3972457 | 2003-11-25 16:21:00 +0000 | [diff] [blame] | 239 | strings = ["<dl compact='compact'>"] |
Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 240 | append = strings.append |
Fred Drake | 7cbf462 | 1998-08-07 19:50:13 +0000 | [diff] [blame] | 241 | level = 0 |
Fred Drake | 058068d | 1998-04-08 23:12:51 +0000 | [diff] [blame] | 242 | previous = [] |
Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 243 | for node in nodes: |
Fred Drake | 058068d | 1998-04-08 23:12:51 +0000 | [diff] [blame] | 244 | current = node.text |
| 245 | count = 0 |
| 246 | for i in range(min(len(current), len(previous))): |
| 247 | if previous[i] != current[i]: |
| 248 | break |
| 249 | count = i + 1 |
| 250 | if count > level: |
Fred Drake | 3972457 | 2003-11-25 16:21:00 +0000 | [diff] [blame] | 251 | append("<dl compact='compact'>" * (count - level) + "\n") |
Fred Drake | 058068d | 1998-04-08 23:12:51 +0000 | [diff] [blame] | 252 | level = count |
| 253 | elif level > count: |
| 254 | append("\n") |
| 255 | append(level * DL_LEVEL_INDENT) |
| 256 | append("</dl>" * (level - count)) |
| 257 | level = count |
| 258 | # else: level == count |
| 259 | for i in range(count, len(current) - 1): |
| 260 | term = node.text[i] |
| 261 | level = level + 1 |
Fred Drake | ba82878 | 2000-04-03 04:19:14 +0000 | [diff] [blame] | 262 | if node.continuation > i: |
| 263 | extra = " (continued)" |
| 264 | else: |
| 265 | extra = "" |
Fred Drake | 3972457 | 2003-11-25 16:21:00 +0000 | [diff] [blame] | 266 | append("\n<dt>%s%s\n<dd>\n%s<dl compact='compact'>" |
Fred Drake | ba82878 | 2000-04-03 04:19:14 +0000 | [diff] [blame] | 267 | % (term, extra, level * DL_LEVEL_INDENT)) |
Fred Drake | 058068d | 1998-04-08 23:12:51 +0000 | [diff] [blame] | 268 | append("\n%s<dt>%s%s</a>" |
| 269 | % (level * DL_LEVEL_INDENT, node.links[0], node.text[-1])) |
Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 270 | for link in node.links[1:]: |
Fred Drake | 058068d | 1998-04-08 23:12:51 +0000 | [diff] [blame] | 271 | append(",\n%s %s[Link]</a>" % (level * DL_LEVEL_INDENT, link)) |
| 272 | previous = current |
| 273 | append("\n") |
Fred Drake | 2b8c95e | 1998-04-11 16:26:02 +0000 | [diff] [blame] | 274 | append("</dl>" * (level + 1)) |
Fred Drake | 3d42266 | 2001-12-26 19:55:14 +0000 | [diff] [blame] | 275 | return null_join(strings) |
Fred Drake | 7cbf462 | 1998-08-07 19:50:13 +0000 | [diff] [blame] | 276 | |
| 277 | |
| 278 | def format_nodes(nodes, columns=1): |
| 279 | strings = [] |
| 280 | append = strings.append |
| 281 | if columns > 1: |
| 282 | colnos = range(columns) |
Fred Drake | 3d42266 | 2001-12-26 19:55:14 +0000 | [diff] [blame] | 283 | colheight = int(len(nodes) / columns) |
Fred Drake | 7cbf462 | 1998-08-07 19:50:13 +0000 | [diff] [blame] | 284 | if len(nodes) % columns: |
| 285 | colheight = colheight + 1 |
Fred Drake | 3d42266 | 2001-12-26 19:55:14 +0000 | [diff] [blame] | 286 | colwidth = int(100 / columns) |
Fred Drake | 7cbf462 | 1998-08-07 19:50:13 +0000 | [diff] [blame] | 287 | append('<table width="100%"><tr valign="top">') |
| 288 | for col in split_columns(nodes, columns): |
| 289 | append('<td width="%d%%">\n' % colwidth) |
| 290 | append(format_column(col)) |
| 291 | append("\n</td>") |
| 292 | append("\n</tr></table>") |
| 293 | else: |
| 294 | append(format_column(nodes)) |
Fred Drake | 3d42266 | 2001-12-26 19:55:14 +0000 | [diff] [blame] | 295 | return null_join(strings) |
Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 296 | |
| 297 | |
| 298 | def format_letter(letter): |
| 299 | if letter == '.': |
| 300 | lettername = ". (dot)" |
| 301 | elif letter == '_': |
| 302 | lettername = "_ (underscore)" |
| 303 | else: |
Fred Drake | 3d42266 | 2001-12-26 19:55:14 +0000 | [diff] [blame] | 304 | lettername = letter.capitalize() |
Fred Drake | 3972457 | 2003-11-25 16:21:00 +0000 | [diff] [blame] | 305 | return "\n<hr />\n<h2 id=%s>%s</h2>\n\n" \ |
| 306 | % (quoteattr("letter-" + letter), lettername) |
Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 307 | |
| 308 | |
Fred Drake | 3d42266 | 2001-12-26 19:55:14 +0000 | [diff] [blame] | 309 | def format_html_letters(nodes, columns, group_symbol_nodes): |
Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 310 | letter_groups = split_letters(nodes) |
Fred Drake | 3d42266 | 2001-12-26 19:55:14 +0000 | [diff] [blame] | 311 | if group_symbol_nodes: |
| 312 | group_symbols(letter_groups) |
Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 313 | items = [] |
| 314 | for letter, nodes in letter_groups: |
| 315 | s = "<b><a href=\"#letter-%s\">%s</a></b>" % (letter, letter) |
| 316 | items.append(s) |
Fred Drake | 3972457 | 2003-11-25 16:21:00 +0000 | [diff] [blame] | 317 | s = ["<hr /><center>\n%s</center>\n" % " |\n".join(items)] |
Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 318 | for letter, nodes in letter_groups: |
Fred Drake | 058068d | 1998-04-08 23:12:51 +0000 | [diff] [blame] | 319 | s.append(format_letter(letter)) |
Fred Drake | 7cbf462 | 1998-08-07 19:50:13 +0000 | [diff] [blame] | 320 | s.append(format_nodes(nodes, columns)) |
Fred Drake | 3d42266 | 2001-12-26 19:55:14 +0000 | [diff] [blame] | 321 | return null_join(s) |
Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 322 | |
Fred Drake | 077fffa | 1998-08-07 20:49:54 +0000 | [diff] [blame] | 323 | def format_html(nodes, columns): |
| 324 | return format_nodes(nodes, columns) |
| 325 | |
Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 326 | |
| 327 | def collapse(nodes): |
| 328 | """Collapse sequences of nodes with matching keys into a single node. |
| 329 | Destructive.""" |
| 330 | if len(nodes) < 2: |
| 331 | return |
| 332 | prev = nodes[0] |
| 333 | i = 1 |
| 334 | while i < len(nodes): |
| 335 | node = nodes[i] |
| 336 | if not node.cmp_entry(prev): |
| 337 | prev.links.append(node.links[0]) |
| 338 | del nodes[i] |
Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 339 | else: |
| 340 | i = i + 1 |
| 341 | prev = node |
| 342 | |
| 343 | |
| 344 | def dump(nodes, fp): |
| 345 | for node in nodes: |
| 346 | fp.write(node.dump()) |
| 347 | |
| 348 | |
Fred Drake | 3d42266 | 2001-12-26 19:55:14 +0000 | [diff] [blame] | 349 | def process_nodes(nodes, columns, letters=0, group_symbol_nodes=0): |
Fred Drake | 711fe02 | 1999-02-24 16:36:48 +0000 | [diff] [blame] | 350 | nodes.sort() |
| 351 | collapse(nodes) |
| 352 | if letters: |
Fred Drake | 3d42266 | 2001-12-26 19:55:14 +0000 | [diff] [blame] | 353 | return format_html_letters(nodes, columns, group_symbol_nodes) |
Fred Drake | 711fe02 | 1999-02-24 16:36:48 +0000 | [diff] [blame] | 354 | else: |
| 355 | return format_html(nodes, columns) |
| 356 | |
| 357 | |
Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 358 | def main(): |
Fred Drake | 058068d | 1998-04-08 23:12:51 +0000 | [diff] [blame] | 359 | import getopt |
| 360 | ifn = "-" |
| 361 | ofn = "-" |
Fred Drake | 7cbf462 | 1998-08-07 19:50:13 +0000 | [diff] [blame] | 362 | columns = 1 |
Fred Drake | 077fffa | 1998-08-07 20:49:54 +0000 | [diff] [blame] | 363 | letters = 0 |
Fred Drake | 3d42266 | 2001-12-26 19:55:14 +0000 | [diff] [blame] | 364 | group_symbol_nodes = 1 |
Fred Drake | 077fffa | 1998-08-07 20:49:54 +0000 | [diff] [blame] | 365 | opts, args = getopt.getopt(sys.argv[1:], "c:lo:", |
Fred Drake | 3d42266 | 2001-12-26 19:55:14 +0000 | [diff] [blame] | 366 | ["columns=", "dont-group-symbols", |
| 367 | "group-symbols", "letters", "output="]) |
Fred Drake | 058068d | 1998-04-08 23:12:51 +0000 | [diff] [blame] | 368 | for opt, val in opts: |
| 369 | if opt in ("-o", "--output"): |
| 370 | ofn = val |
Fred Drake | 7cbf462 | 1998-08-07 19:50:13 +0000 | [diff] [blame] | 371 | elif opt in ("-c", "--columns"): |
Fred Drake | 3d42266 | 2001-12-26 19:55:14 +0000 | [diff] [blame] | 372 | columns = int(val, 10) |
Fred Drake | 077fffa | 1998-08-07 20:49:54 +0000 | [diff] [blame] | 373 | elif opt in ("-l", "--letters"): |
| 374 | letters = 1 |
Fred Drake | 3d42266 | 2001-12-26 19:55:14 +0000 | [diff] [blame] | 375 | elif opt == "--group-symbols": |
| 376 | group_symbol_nodes = 1 |
| 377 | elif opt == "--dont-group-symbols": |
| 378 | group_symbol_nodes = 0 |
Fred Drake | 058068d | 1998-04-08 23:12:51 +0000 | [diff] [blame] | 379 | if not args: |
| 380 | args = [ifn] |
| 381 | nodes = [] |
| 382 | for fn in args: |
| 383 | nodes = nodes + load(open(fn)) |
Fred Drake | 03a0235 | 1998-12-28 20:46:53 +0000 | [diff] [blame] | 384 | num_nodes = len(nodes) |
Fred Drake | 3d42266 | 2001-12-26 19:55:14 +0000 | [diff] [blame] | 385 | html = process_nodes(nodes, columns, letters, group_symbol_nodes) |
Fred Drake | 03a0235 | 1998-12-28 20:46:53 +0000 | [diff] [blame] | 386 | program = os.path.basename(sys.argv[0]) |
Fred Drake | 058068d | 1998-04-08 23:12:51 +0000 | [diff] [blame] | 387 | if ofn == "-": |
| 388 | sys.stdout.write(html) |
Fred Drake | 03a0235 | 1998-12-28 20:46:53 +0000 | [diff] [blame] | 389 | sys.stderr.write("\n%s: %d index nodes" % (program, num_nodes)) |
Fred Drake | 058068d | 1998-04-08 23:12:51 +0000 | [diff] [blame] | 390 | else: |
| 391 | open(ofn, "w").write(html) |
Collin Winter | 65d09d4 | 2007-03-21 02:11:39 +0000 | [diff] [blame] | 392 | print() |
| 393 | print("%s: %d index nodes" % (program, num_nodes)) |
Fred Drake | ec56109 | 1998-03-27 05:25:43 +0000 | [diff] [blame] | 394 | |
| 395 | |
| 396 | if __name__ == "__main__": |
| 397 | main() |