| 
									
										
										
										
											1998-03-27 05:25:43 +00:00
										 |  |  | #! /usr/bin/env python | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | __version__ = '$Revision$' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-10-16 15:30:17 +00:00
										 |  |  | import os.path | 
					
						
							| 
									
										
										
										
											1998-03-27 05:25:43 +00:00
										 |  |  | import re | 
					
						
							|  |  |  | import string | 
					
						
							|  |  |  | import sys | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-12-26 19:55:14 +00:00
										 |  |  | bang_join = "!".join | 
					
						
							|  |  |  | null_join = "".join | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-03-27 05:25:43 +00:00
										 |  |  | class Node: | 
					
						
							|  |  |  |     __rmjunk = re.compile("<#\d+#>") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-03 04:19:14 +00:00
										 |  |  |     continuation = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-03-27 05:25:43 +00:00
										 |  |  |     def __init__(self, link, str, seqno): | 
					
						
							|  |  |  |         self.links = [link] | 
					
						
							|  |  |  |         self.seqno = seqno | 
					
						
							|  |  |  |         # remove <#\d+#> left in by moving the data out of LaTeX2HTML | 
					
						
							|  |  |  |         str = self.__rmjunk.sub('', str) | 
					
						
							|  |  |  |         # build up the text | 
					
						
							| 
									
										
										
										
											1998-04-08 23:12:51 +00:00
										 |  |  |         self.text = split_entry_text(str) | 
					
						
							|  |  |  |         self.key = split_entry_key(str) | 
					
						
							| 
									
										
										
										
											1998-03-27 05:25:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __cmp__(self, other): | 
					
						
							|  |  |  |         """Comparison operator includes sequence number, for use with
 | 
					
						
							|  |  |  |         list.sort()."""
 | 
					
						
							|  |  |  |         return self.cmp_entry(other) or cmp(self.seqno, other.seqno) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def cmp_entry(self, other): | 
					
						
							|  |  |  |         """Comparison 'operator' that ignores sequence number.""" | 
					
						
							| 
									
										
										
										
											1998-04-08 23:12:51 +00:00
										 |  |  |         c = 0 | 
					
						
							| 
									
										
										
										
											1998-03-27 05:25:43 +00:00
										 |  |  |         for i in range(min(len(self.key), len(other.key))): | 
					
						
							| 
									
										
										
										
											1998-04-08 23:12:51 +00:00
										 |  |  |             c = (cmp_part(self.key[i], other.key[i]) | 
					
						
							|  |  |  |                  or cmp_part(self.text[i], other.text[i])) | 
					
						
							| 
									
										
										
										
											1998-03-27 05:25:43 +00:00
										 |  |  |             if c: | 
					
						
							| 
									
										
										
										
											1998-04-08 23:12:51 +00:00
										 |  |  |                 break | 
					
						
							|  |  |  |         return c or cmp(self.key, other.key) or cmp(self.text, other.text) | 
					
						
							| 
									
										
										
										
											1998-03-27 05:25:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __repr__(self): | 
					
						
							| 
									
										
										
										
											2001-12-26 19:55:14 +00:00
										 |  |  |         return "<Node for %s (%s)>" % (bang_join(self.text), self.seqno) | 
					
						
							| 
									
										
										
										
											1998-03-27 05:25:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __str__(self): | 
					
						
							| 
									
										
										
										
											2001-12-26 19:55:14 +00:00
										 |  |  |         return bang_join(self.key) | 
					
						
							| 
									
										
										
										
											1998-03-27 05:25:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def dump(self): | 
					
						
							| 
									
										
										
										
											1998-04-08 23:12:51 +00:00
										 |  |  |         return "%s\1%s###%s\n" \ | 
					
						
							| 
									
										
										
										
											2002-10-16 15:30:17 +00:00
										 |  |  |                % ("\1".join(self.links), | 
					
						
							| 
									
										
										
										
											2001-12-26 19:55:14 +00:00
										 |  |  |                   bang_join(self.text), | 
					
						
							| 
									
										
										
										
											1998-03-27 05:25:43 +00:00
										 |  |  |                   self.seqno) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-08 23:12:51 +00:00
										 |  |  | def cmp_part(s1, s2): | 
					
						
							|  |  |  |     result = cmp(s1, s2) | 
					
						
							|  |  |  |     if result == 0: | 
					
						
							|  |  |  |         return 0 | 
					
						
							| 
									
										
										
										
											2001-12-26 19:55:14 +00:00
										 |  |  |     l1 = s1.lower() | 
					
						
							|  |  |  |     l2 = s2.lower() | 
					
						
							| 
									
										
										
										
											1998-04-08 23:12:51 +00:00
										 |  |  |     minlen = min(len(s1), len(s2)) | 
					
						
							|  |  |  |     if len(s1) < len(s2) and l1 == l2[:len(s1)]: | 
					
						
							|  |  |  |         result = -1 | 
					
						
							|  |  |  |     elif len(s2) < len(s1) and l2 == l1[:len(s2)]: | 
					
						
							|  |  |  |         result = 1 | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         result = cmp(l1, l2) or cmp(s1, s2) | 
					
						
							|  |  |  |     return result | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def split_entry(str, which): | 
					
						
							|  |  |  |     stuff = [] | 
					
						
							| 
									
										
										
										
											2001-12-26 19:55:14 +00:00
										 |  |  |     parts = str.split('!') | 
					
						
							|  |  |  |     parts = [part.split('@') for part in parts] | 
					
						
							| 
									
										
										
										
											1998-04-08 23:12:51 +00:00
										 |  |  |     for entry in parts: | 
					
						
							|  |  |  |         if len(entry) != 1: | 
					
						
							|  |  |  |             key = entry[which] | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             key = entry[0] | 
					
						
							|  |  |  |         stuff.append(key) | 
					
						
							|  |  |  |     return stuff | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-03 04:19:14 +00:00
										 |  |  | _rmtt = re.compile(r"""(.*)<tt(?: class=['"][a-z0-9]+["'])?>(.*)</tt>(.*)$""", | 
					
						
							| 
									
										
										
										
											1999-02-18 16:11:12 +00:00
										 |  |  |                    re.IGNORECASE) | 
					
						
							| 
									
										
										
										
											1998-04-08 23:12:51 +00:00
										 |  |  | _rmparens = re.compile(r"\(\)") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def split_entry_key(str): | 
					
						
							|  |  |  |     parts = split_entry(str, 1) | 
					
						
							|  |  |  |     for i in range(len(parts)): | 
					
						
							|  |  |  |         m = _rmtt.match(parts[i]) | 
					
						
							|  |  |  |         if m: | 
					
						
							| 
									
										
										
										
											2001-12-26 19:55:14 +00:00
										 |  |  |             parts[i] = null_join(m.group(1, 2, 3)) | 
					
						
							| 
									
										
										
										
											1998-04-08 23:12:51 +00:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2001-12-26 19:55:14 +00:00
										 |  |  |             parts[i] = parts[i].lower() | 
					
						
							| 
									
										
										
										
											1998-04-08 23:12:51 +00:00
										 |  |  |         # remove '()' from the key: | 
					
						
							|  |  |  |         parts[i] = _rmparens.sub('', parts[i]) | 
					
						
							|  |  |  |     return map(trim_ignored_letters, parts) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def split_entry_text(str): | 
					
						
							|  |  |  |     if '<' in str: | 
					
						
							|  |  |  |         m = _rmtt.match(str) | 
					
						
							|  |  |  |         if m: | 
					
						
							| 
									
										
										
										
											2001-12-26 19:55:14 +00:00
										 |  |  |             str = null_join(m.group(1, 2, 3)) | 
					
						
							| 
									
										
										
										
											1998-04-08 23:12:51 +00:00
										 |  |  |     return split_entry(str, 1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-03-27 05:25:43 +00:00
										 |  |  | def load(fp): | 
					
						
							|  |  |  |     nodes = [] | 
					
						
							| 
									
										
										
										
											1998-04-08 23:12:51 +00:00
										 |  |  |     rx = re.compile("(.*)\1(.*)###(.*)$") | 
					
						
							| 
									
										
										
										
											1998-03-27 05:25:43 +00:00
										 |  |  |     while 1: | 
					
						
							|  |  |  |         line = fp.readline() | 
					
						
							|  |  |  |         if not line: | 
					
						
							|  |  |  |             break | 
					
						
							|  |  |  |         m = rx.match(line) | 
					
						
							|  |  |  |         if m: | 
					
						
							|  |  |  |             link, str, seqno = m.group(1, 2, 3) | 
					
						
							|  |  |  |             nodes.append(Node(link, str, seqno)) | 
					
						
							|  |  |  |     return nodes | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-08 23:12:51 +00:00
										 |  |  | def trim_ignored_letters(s): | 
					
						
							| 
									
										
										
										
											1999-01-04 22:00:56 +00:00
										 |  |  |     # ignore $ to keep environment variables with the | 
					
						
							|  |  |  |     # leading letter from the name | 
					
						
							| 
									
										
										
										
											2001-12-26 19:55:14 +00:00
										 |  |  |     if s.startswith("$"): | 
					
						
							|  |  |  |         return s[1:].lower() | 
					
						
							| 
									
										
										
										
											1999-01-04 22:00:56 +00:00
										 |  |  |     else: | 
					
						
							| 
									
										
										
										
											2001-12-26 19:55:14 +00:00
										 |  |  |         return s.lower() | 
					
						
							| 
									
										
										
										
											1998-04-08 23:12:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def get_first_letter(s): | 
					
						
							| 
									
										
										
										
											2001-12-26 19:55:14 +00:00
										 |  |  |     if s.startswith("<tex2html_percent_mark>"): | 
					
						
							|  |  |  |         return "%" | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         return trim_ignored_letters(s)[0] | 
					
						
							| 
									
										
										
										
											1998-04-08 23:12:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-03-27 05:25:43 +00:00
										 |  |  | def split_letters(nodes): | 
					
						
							|  |  |  |     letter_groups = [] | 
					
						
							|  |  |  |     if nodes: | 
					
						
							| 
									
										
										
										
											1998-04-08 23:12:51 +00:00
										 |  |  |         group = [] | 
					
						
							|  |  |  |         append = group.append | 
					
						
							|  |  |  |         letter = get_first_letter(nodes[0].text[0]) | 
					
						
							| 
									
										
										
										
											1998-03-27 05:25:43 +00:00
										 |  |  |         letter_groups.append((letter, group)) | 
					
						
							|  |  |  |         for node in nodes: | 
					
						
							| 
									
										
										
										
											1998-04-08 23:12:51 +00:00
										 |  |  |             nletter = get_first_letter(node.text[0]) | 
					
						
							| 
									
										
										
										
											1998-03-27 05:25:43 +00:00
										 |  |  |             if letter != nletter: | 
					
						
							|  |  |  |                 letter = nletter | 
					
						
							|  |  |  |                 group = [] | 
					
						
							|  |  |  |                 letter_groups.append((letter, group)) | 
					
						
							|  |  |  |                 append = group.append | 
					
						
							|  |  |  |             append(node) | 
					
						
							|  |  |  |     return letter_groups | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-12-26 19:55:14 +00:00
										 |  |  | def group_symbols(groups): | 
					
						
							|  |  |  |     entries = [] | 
					
						
							|  |  |  |     ident_letters = string.ascii_letters + "_" | 
					
						
							|  |  |  |     while groups[0][0] not in ident_letters: | 
					
						
							|  |  |  |         entries += groups[0][1] | 
					
						
							|  |  |  |         del groups[0] | 
					
						
							|  |  |  |     if entries: | 
					
						
							|  |  |  |         groups.insert(0, ("Symbols", entries)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-08-07 19:50:13 +00:00
										 |  |  | # need a function to separate the nodes into columns... | 
					
						
							|  |  |  | def split_columns(nodes, columns=1): | 
					
						
							|  |  |  |     if columns <= 1: | 
					
						
							| 
									
										
										
										
											1998-08-07 20:49:54 +00:00
										 |  |  |         return [nodes] | 
					
						
							| 
									
										
										
										
											1998-08-07 19:50:13 +00:00
										 |  |  |     # This is a rough height; we may have to increase to avoid breaks before | 
					
						
							|  |  |  |     # a subitem. | 
					
						
							| 
									
										
										
										
											2001-12-26 19:55:14 +00:00
										 |  |  |     colheight = int(len(nodes) / columns) | 
					
						
							|  |  |  |     numlong = int(len(nodes) % columns) | 
					
						
							| 
									
										
										
										
											1998-08-07 19:50:13 +00:00
										 |  |  |     if numlong: | 
					
						
							|  |  |  |         colheight = colheight + 1 | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         numlong = columns | 
					
						
							|  |  |  |     cols = [] | 
					
						
							|  |  |  |     for i in range(numlong): | 
					
						
							|  |  |  |         start = i * colheight | 
					
						
							|  |  |  |         end = start + colheight | 
					
						
							|  |  |  |         cols.append(nodes[start:end]) | 
					
						
							|  |  |  |     del nodes[:end] | 
					
						
							|  |  |  |     colheight = colheight - 1 | 
					
						
							|  |  |  |     try: | 
					
						
							| 
									
										
										
										
											2001-12-26 19:55:14 +00:00
										 |  |  |         numshort = int(len(nodes) / colheight) | 
					
						
							| 
									
										
										
										
											1998-08-07 19:50:13 +00:00
										 |  |  |     except ZeroDivisionError: | 
					
						
							|  |  |  |         cols = cols + (columns - len(cols)) * [[]] | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         for i in range(numshort): | 
					
						
							|  |  |  |             start = i * colheight | 
					
						
							|  |  |  |             end = start + colheight | 
					
						
							|  |  |  |             cols.append(nodes[start:end]) | 
					
						
							| 
									
										
										
										
											2000-04-03 04:19:14 +00:00
										 |  |  |     # | 
					
						
							|  |  |  |     # If items continue across columns, make sure they are marked | 
					
						
							|  |  |  |     # as continuations so the user knows to look at the previous column. | 
					
						
							|  |  |  |     # | 
					
						
							|  |  |  |     for i in range(len(cols) - 1): | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             prev = cols[i][-1] | 
					
						
							|  |  |  |             next = cols[i + 1][0] | 
					
						
							|  |  |  |         except IndexError: | 
					
						
							|  |  |  |             return cols | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             n = min(len(prev.key), len(next.key)) | 
					
						
							|  |  |  |             for j in range(n): | 
					
						
							|  |  |  |                 if prev.key[j] != next.key[j]: | 
					
						
							|  |  |  |                     break | 
					
						
							|  |  |  |                 next.continuation = j + 1 | 
					
						
							| 
									
										
										
										
											1998-08-07 20:49:54 +00:00
										 |  |  |     return cols | 
					
						
							| 
									
										
										
										
											1998-08-07 19:50:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-08 23:12:51 +00:00
										 |  |  | DL_LEVEL_INDENT = "  " | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-08-07 19:50:13 +00:00
										 |  |  | def format_column(nodes): | 
					
						
							| 
									
										
										
										
											1998-03-27 05:25:43 +00:00
										 |  |  |     strings = ["<dl compact>"] | 
					
						
							|  |  |  |     append = strings.append | 
					
						
							| 
									
										
										
										
											1998-08-07 19:50:13 +00:00
										 |  |  |     level = 0 | 
					
						
							| 
									
										
										
										
											1998-04-08 23:12:51 +00:00
										 |  |  |     previous = [] | 
					
						
							| 
									
										
										
										
											1998-03-27 05:25:43 +00:00
										 |  |  |     for node in nodes: | 
					
						
							| 
									
										
										
										
											1998-04-08 23:12:51 +00:00
										 |  |  |         current = node.text | 
					
						
							|  |  |  |         count = 0 | 
					
						
							|  |  |  |         for i in range(min(len(current), len(previous))): | 
					
						
							|  |  |  |             if previous[i] != current[i]: | 
					
						
							|  |  |  |                 break | 
					
						
							|  |  |  |             count = i + 1 | 
					
						
							|  |  |  |         if count > level: | 
					
						
							|  |  |  |             append("<dl compact>" * (count - level) + "\n") | 
					
						
							|  |  |  |             level = count | 
					
						
							|  |  |  |         elif level > count: | 
					
						
							|  |  |  |             append("\n") | 
					
						
							|  |  |  |             append(level * DL_LEVEL_INDENT) | 
					
						
							|  |  |  |             append("</dl>" * (level - count)) | 
					
						
							|  |  |  |             level = count | 
					
						
							|  |  |  |         # else: level == count | 
					
						
							|  |  |  |         for i in range(count, len(current) - 1): | 
					
						
							|  |  |  |             term = node.text[i] | 
					
						
							|  |  |  |             level = level + 1 | 
					
						
							| 
									
										
										
										
											2000-04-03 04:19:14 +00:00
										 |  |  |             if node.continuation > i: | 
					
						
							|  |  |  |                 extra = " (continued)" | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 extra = "" | 
					
						
							|  |  |  |             append("\n<dt>%s%s\n<dd>\n%s<dl compact>" | 
					
						
							|  |  |  |                    % (term, extra, level * DL_LEVEL_INDENT)) | 
					
						
							| 
									
										
										
										
											1998-04-08 23:12:51 +00:00
										 |  |  |         append("\n%s<dt>%s%s</a>" | 
					
						
							|  |  |  |                % (level * DL_LEVEL_INDENT, node.links[0], node.text[-1])) | 
					
						
							| 
									
										
										
										
											1998-03-27 05:25:43 +00:00
										 |  |  |         for link in node.links[1:]: | 
					
						
							| 
									
										
										
										
											1998-04-08 23:12:51 +00:00
										 |  |  |             append(",\n%s    %s[Link]</a>" % (level * DL_LEVEL_INDENT, link)) | 
					
						
							|  |  |  |         previous = current | 
					
						
							|  |  |  |     append("\n") | 
					
						
							| 
									
										
										
										
											1998-04-11 16:26:02 +00:00
										 |  |  |     append("</dl>" * (level + 1)) | 
					
						
							| 
									
										
										
										
											2001-12-26 19:55:14 +00:00
										 |  |  |     return null_join(strings) | 
					
						
							| 
									
										
										
										
											1998-08-07 19:50:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def format_nodes(nodes, columns=1): | 
					
						
							|  |  |  |     strings = [] | 
					
						
							|  |  |  |     append = strings.append | 
					
						
							|  |  |  |     if columns > 1: | 
					
						
							|  |  |  |         colnos = range(columns) | 
					
						
							| 
									
										
										
										
											2001-12-26 19:55:14 +00:00
										 |  |  |         colheight = int(len(nodes) / columns) | 
					
						
							| 
									
										
										
										
											1998-08-07 19:50:13 +00:00
										 |  |  |         if len(nodes) % columns: | 
					
						
							|  |  |  |             colheight = colheight + 1 | 
					
						
							| 
									
										
										
										
											2001-12-26 19:55:14 +00:00
										 |  |  |         colwidth = int(100 / columns) | 
					
						
							| 
									
										
										
										
											1998-08-07 19:50:13 +00:00
										 |  |  |         append('<table width="100%"><tr valign="top">') | 
					
						
							|  |  |  |         for col in split_columns(nodes, columns): | 
					
						
							|  |  |  |             append('<td width="%d%%">\n' % colwidth) | 
					
						
							|  |  |  |             append(format_column(col)) | 
					
						
							|  |  |  |             append("\n</td>") | 
					
						
							|  |  |  |         append("\n</tr></table>") | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         append(format_column(nodes)) | 
					
						
							| 
									
										
										
										
											1998-04-11 16:26:02 +00:00
										 |  |  |     append("\n<p>\n") | 
					
						
							| 
									
										
										
										
											2001-12-26 19:55:14 +00:00
										 |  |  |     return null_join(strings) | 
					
						
							| 
									
										
										
										
											1998-03-27 05:25:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def format_letter(letter): | 
					
						
							|  |  |  |     if letter == '.': | 
					
						
							|  |  |  |         lettername = ". (dot)" | 
					
						
							|  |  |  |     elif letter == '_': | 
					
						
							|  |  |  |         lettername = "_ (underscore)" | 
					
						
							|  |  |  |     else: | 
					
						
							| 
									
										
										
										
											2001-12-26 19:55:14 +00:00
										 |  |  |         lettername = letter.capitalize() | 
					
						
							| 
									
										
										
										
											1998-04-08 23:12:51 +00:00
										 |  |  |     return "\n<hr>\n<h2><a name=\"letter-%s\">%s</a></h2>\n\n" \ | 
					
						
							| 
									
										
										
										
											1998-03-27 05:25:43 +00:00
										 |  |  |            % (letter, lettername) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-12-26 19:55:14 +00:00
										 |  |  | def format_html_letters(nodes, columns, group_symbol_nodes): | 
					
						
							| 
									
										
										
										
											1998-03-27 05:25:43 +00:00
										 |  |  |     letter_groups = split_letters(nodes) | 
					
						
							| 
									
										
										
										
											2001-12-26 19:55:14 +00:00
										 |  |  |     if group_symbol_nodes: | 
					
						
							|  |  |  |         group_symbols(letter_groups) | 
					
						
							| 
									
										
										
										
											1998-03-27 05:25:43 +00:00
										 |  |  |     items = [] | 
					
						
							|  |  |  |     for letter, nodes in letter_groups: | 
					
						
							|  |  |  |         s = "<b><a href=\"#letter-%s\">%s</a></b>" % (letter, letter) | 
					
						
							|  |  |  |         items.append(s) | 
					
						
							| 
									
										
										
										
											2002-10-16 15:30:17 +00:00
										 |  |  |     s = ["<hr><center>\n%s</center>\n" % " |\n".join(items)] | 
					
						
							| 
									
										
										
										
											1998-03-27 05:25:43 +00:00
										 |  |  |     for letter, nodes in letter_groups: | 
					
						
							| 
									
										
										
										
											1998-04-08 23:12:51 +00:00
										 |  |  |         s.append(format_letter(letter)) | 
					
						
							| 
									
										
										
										
											1998-08-07 19:50:13 +00:00
										 |  |  |         s.append(format_nodes(nodes, columns)) | 
					
						
							| 
									
										
										
										
											2001-12-26 19:55:14 +00:00
										 |  |  |     return null_join(s) | 
					
						
							| 
									
										
										
										
											1998-03-27 05:25:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-08-07 20:49:54 +00:00
										 |  |  | def format_html(nodes, columns): | 
					
						
							|  |  |  |     return format_nodes(nodes, columns) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-03-27 05:25:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def collapse(nodes): | 
					
						
							|  |  |  |     """Collapse sequences of nodes with matching keys into a single node.
 | 
					
						
							|  |  |  |     Destructive."""
 | 
					
						
							|  |  |  |     if len(nodes) < 2: | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  |     prev = nodes[0] | 
					
						
							|  |  |  |     i = 1 | 
					
						
							|  |  |  |     while i < len(nodes): | 
					
						
							|  |  |  |         node = nodes[i] | 
					
						
							|  |  |  |         if not node.cmp_entry(prev): | 
					
						
							|  |  |  |             prev.links.append(node.links[0]) | 
					
						
							|  |  |  |             del nodes[i] | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             i = i + 1 | 
					
						
							|  |  |  |             prev = node | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def dump(nodes, fp): | 
					
						
							|  |  |  |     for node in nodes: | 
					
						
							|  |  |  |         fp.write(node.dump()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-12-26 19:55:14 +00:00
										 |  |  | def process_nodes(nodes, columns, letters=0, group_symbol_nodes=0): | 
					
						
							| 
									
										
										
										
											1999-02-24 16:36:48 +00:00
										 |  |  |     nodes.sort() | 
					
						
							|  |  |  |     collapse(nodes) | 
					
						
							|  |  |  |     if letters: | 
					
						
							| 
									
										
										
										
											2001-12-26 19:55:14 +00:00
										 |  |  |         return format_html_letters(nodes, columns, group_symbol_nodes) | 
					
						
							| 
									
										
										
										
											1999-02-24 16:36:48 +00:00
										 |  |  |     else: | 
					
						
							|  |  |  |         return format_html(nodes, columns) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-03-27 05:25:43 +00:00
										 |  |  | def main(): | 
					
						
							| 
									
										
										
										
											1998-04-08 23:12:51 +00:00
										 |  |  |     import getopt | 
					
						
							|  |  |  |     ifn = "-" | 
					
						
							|  |  |  |     ofn = "-" | 
					
						
							| 
									
										
										
										
											1998-08-07 19:50:13 +00:00
										 |  |  |     columns = 1 | 
					
						
							| 
									
										
										
										
											1998-08-07 20:49:54 +00:00
										 |  |  |     letters = 0 | 
					
						
							| 
									
										
										
										
											2001-12-26 19:55:14 +00:00
										 |  |  |     group_symbol_nodes = 1 | 
					
						
							| 
									
										
										
										
											1998-08-07 20:49:54 +00:00
										 |  |  |     opts, args = getopt.getopt(sys.argv[1:], "c:lo:", | 
					
						
							| 
									
										
										
										
											2001-12-26 19:55:14 +00:00
										 |  |  |                                ["columns=", "dont-group-symbols", | 
					
						
							|  |  |  |                                 "group-symbols", "letters", "output="]) | 
					
						
							| 
									
										
										
										
											1998-04-08 23:12:51 +00:00
										 |  |  |     for opt, val in opts: | 
					
						
							|  |  |  |         if opt in ("-o", "--output"): | 
					
						
							|  |  |  |             ofn = val | 
					
						
							| 
									
										
										
										
											1998-08-07 19:50:13 +00:00
										 |  |  |         elif opt in ("-c", "--columns"): | 
					
						
							| 
									
										
										
										
											2001-12-26 19:55:14 +00:00
										 |  |  |             columns = int(val, 10) | 
					
						
							| 
									
										
										
										
											1998-08-07 20:49:54 +00:00
										 |  |  |         elif opt in ("-l", "--letters"): | 
					
						
							|  |  |  |             letters = 1 | 
					
						
							| 
									
										
										
										
											2001-12-26 19:55:14 +00:00
										 |  |  |         elif opt == "--group-symbols": | 
					
						
							|  |  |  |             group_symbol_nodes = 1 | 
					
						
							|  |  |  |         elif opt == "--dont-group-symbols": | 
					
						
							|  |  |  |             group_symbol_nodes = 0 | 
					
						
							| 
									
										
										
										
											1998-04-08 23:12:51 +00:00
										 |  |  |     if not args: | 
					
						
							|  |  |  |         args = [ifn] | 
					
						
							|  |  |  |     nodes = [] | 
					
						
							|  |  |  |     for fn in args: | 
					
						
							|  |  |  |         nodes = nodes + load(open(fn)) | 
					
						
							| 
									
										
										
										
											1998-12-28 20:46:53 +00:00
										 |  |  |     num_nodes = len(nodes) | 
					
						
							| 
									
										
										
										
											2001-12-26 19:55:14 +00:00
										 |  |  |     html = process_nodes(nodes, columns, letters, group_symbol_nodes) | 
					
						
							| 
									
										
										
										
											1998-12-28 20:46:53 +00:00
										 |  |  |     program = os.path.basename(sys.argv[0]) | 
					
						
							| 
									
										
										
										
											1998-04-08 23:12:51 +00:00
										 |  |  |     if ofn == "-": | 
					
						
							|  |  |  |         sys.stdout.write(html) | 
					
						
							| 
									
										
										
										
											1998-12-28 20:46:53 +00:00
										 |  |  |         sys.stderr.write("\n%s: %d index nodes" % (program, num_nodes)) | 
					
						
							| 
									
										
										
										
											1998-04-08 23:12:51 +00:00
										 |  |  |     else: | 
					
						
							|  |  |  |         open(ofn, "w").write(html) | 
					
						
							| 
									
										
										
										
											1998-12-28 20:46:53 +00:00
										 |  |  |         print | 
					
						
							|  |  |  |         print "%s: %d index nodes" % (program, num_nodes) | 
					
						
							| 
									
										
										
										
											1998-03-27 05:25:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if __name__ == "__main__": | 
					
						
							|  |  |  |     main() |