3 __version__
= '$Revision$'
16 __rmjunk
= re
.compile("<#\d+#>")
20 def __init__(self
, link
, str, seqno
):
23 # remove <#\d+#> left in by moving the data out of LaTeX2HTML
24 str = self
.__rmjunk
.sub('', str)
26 self
.text
= split_entry_text(str)
27 self
.key
= split_entry_key(str)
29 def __cmp__(self
, other
):
30 """Comparison operator includes sequence number, for use with
32 return self
.cmp_entry(other
) or cmp(self
.seqno
, other
.seqno
)
34 def cmp_entry(self
, other
):
35 """Comparison 'operator' that ignores sequence number."""
37 for i
in range(min(len(self
.key
), len(other
.key
))):
38 c
= (cmp_part(self
.key
[i
], other
.key
[i
])
39 or cmp_part(self
.text
[i
], other
.text
[i
]))
42 return c
or cmp(self
.key
, other
.key
) or cmp(self
.text
, other
.text
)
45 return "<Node for %s (%s)>" % (bang_join(self
.text
), self
.seqno
)
48 return bang_join(self
.key
)
51 return "%s\1%s###%s\n" \
52 % ("\1".join(self
.links
),
63 minlen
= min(len(s1
), len(s2
))
64 if len(s1
) < len(s2
) and l1
== l2
[:len(s1
)]:
66 elif len(s2
) < len(s1
) and l2
== l1
[:len(s2
)]:
69 result
= cmp(l1
, l2
) or cmp(s1
, s2
)
73 def split_entry(str, which
):
75 parts
= str.split('!')
76 parts
= [part
.split('@') for part
in parts
]
86 _rmtt
= re
.compile(r
"""(.*)<tt(?: class=['"][a-z0-9]+["'])?>(.*)</tt>(.*)$""",
88 _rmparens
= re
.compile(r
"\(\)")
90 def split_entry_key(str):
91 parts
= split_entry(str, 1)
92 for i
in range(len(parts
)):
93 m
= _rmtt
.match(parts
[i
])
95 parts
[i
] = null_join(m
.group(1, 2, 3))
97 parts
[i
] = parts
[i
].lower()
98 # remove '()' from the key:
99 parts
[i
] = _rmparens
.sub('', parts
[i
])
100 return map(trim_ignored_letters
, parts
)
103 def split_entry_text(str):
107 str = null_join(m
.group(1, 2, 3))
108 return split_entry(str, 1)
113 rx
= re
.compile("(.*)\1(.*)###(.*)$")
120 link
, str, seqno
= m
.group(1, 2, 3)
121 nodes
.append(Node(link
, str, seqno
))
125 def trim_ignored_letters(s
):
126 # ignore $ to keep environment variables with the
127 # leading letter from the name
128 if s
.startswith("$"):
133 def get_first_letter(s
):
134 if s
.startswith("<tex2html_percent_mark>"):
137 return trim_ignored_letters(s
)[0]
140 def split_letters(nodes
):
144 append
= group
.append
145 letter
= get_first_letter(nodes
[0].text
[0])
146 letter_groups
.append((letter
, group
))
148 nletter
= get_first_letter(node
.text
[0])
149 if letter
!= nletter
:
152 letter_groups
.append((letter
, group
))
153 append
= group
.append
158 def group_symbols(groups
):
160 ident_letters
= string
.ascii_letters
+ "_"
161 while groups
[0][0] not in ident_letters
:
162 entries
+= groups
[0][1]
165 groups
.insert(0, ("Symbols", entries
))
168 # need a function to separate the nodes into columns...
169 def split_columns(nodes
, columns
=1):
172 # This is a rough height; we may have to increase to avoid breaks before
174 colheight
= int(len(nodes
) / columns
)
175 numlong
= int(len(nodes
) % columns
)
177 colheight
= colheight
+ 1
181 for i
in range(numlong
):
182 start
= i
* colheight
183 end
= start
+ colheight
184 cols
.append(nodes
[start
:end
])
186 colheight
= colheight
- 1
188 numshort
= int(len(nodes
) / colheight
)
189 except ZeroDivisionError:
190 cols
= cols
+ (columns
- len(cols
)) * [[]]
192 for i
in range(numshort
):
193 start
= i
* colheight
194 end
= start
+ colheight
195 cols
.append(nodes
[start
:end
])
197 # If items continue across columns, make sure they are marked
198 # as continuations so the user knows to look at the previous column.
200 for i
in range(len(cols
) - 1):
203 next
= cols
[i
+ 1][0]
207 n
= min(len(prev
.key
), len(next
.key
))
209 if prev
.key
[j
] != next
.key
[j
]:
211 next
.continuation
= j
+ 1
215 DL_LEVEL_INDENT
= " "
217 def format_column(nodes
):
218 strings
= ["<dl compact>"]
219 append
= strings
.append
225 for i
in range(min(len(current
), len(previous
))):
226 if previous
[i
] != current
[i
]:
230 append("<dl compact>" * (count
- level
) + "\n")
234 append(level
* DL_LEVEL_INDENT
)
235 append("</dl>" * (level
- count
))
237 # else: level == count
238 for i
in range(count
, len(current
) - 1):
241 if node
.continuation
> i
:
242 extra
= " (continued)"
245 append("\n<dt>%s%s\n<dd>\n%s<dl compact>"
246 % (term
, extra
, level
* DL_LEVEL_INDENT
))
247 append("\n%s<dt>%s%s</a>"
248 % (level
* DL_LEVEL_INDENT
, node
.links
[0], node
.text
[-1]))
249 for link
in node
.links
[1:]:
250 append(",\n%s %s[Link]</a>" % (level
* DL_LEVEL_INDENT
, link
))
253 append("</dl>" * (level
+ 1))
254 return null_join(strings
)
257 def format_nodes(nodes
, columns
=1):
259 append
= strings
.append
261 colnos
= range(columns
)
262 colheight
= int(len(nodes
) / columns
)
263 if len(nodes
) % columns
:
264 colheight
= colheight
+ 1
265 colwidth
= int(100 / columns
)
266 append('<table width="100%"><tr valign="top">')
267 for col
in split_columns(nodes
, columns
):
268 append('<td width="%d%%">\n' % colwidth
)
269 append(format_column(col
))
271 append("\n</tr></table>")
273 append(format_column(nodes
))
275 return null_join(strings
)
278 def format_letter(letter
):
280 lettername
= ". (dot)"
282 lettername
= "_ (underscore)"
284 lettername
= letter
.capitalize()
285 return "\n<hr>\n<h2><a name=\"letter-%s\">%s</a></h2>\n\n" \
286 % (letter
, lettername
)
289 def format_html_letters(nodes
, columns
, group_symbol_nodes
):
290 letter_groups
= split_letters(nodes
)
291 if group_symbol_nodes
:
292 group_symbols(letter_groups
)
294 for letter
, nodes
in letter_groups
:
295 s
= "<b><a href=\"#letter-%s\">%s</a></b>" % (letter
, letter
)
297 s
= ["<hr><center>\n%s</center>\n" % " |\n".join(items
)]
298 for letter
, nodes
in letter_groups
:
299 s
.append(format_letter(letter
))
300 s
.append(format_nodes(nodes
, columns
))
303 def format_html(nodes
, columns
):
304 return format_nodes(nodes
, columns
)
308 """Collapse sequences of nodes with matching keys into a single node.
314 while i
< len(nodes
):
316 if not node
.cmp_entry(prev
):
317 prev
.links
.append(node
.links
[0])
326 fp
.write(node
.dump())
329 def process_nodes(nodes
, columns
, letters
=0, group_symbol_nodes
=0):
333 return format_html_letters(nodes
, columns
, group_symbol_nodes
)
335 return format_html(nodes
, columns
)
344 group_symbol_nodes
= 1
345 opts
, args
= getopt
.getopt(sys
.argv
[1:], "c:lo:",
346 ["columns=", "dont-group-symbols",
347 "group-symbols", "letters", "output="])
348 for opt
, val
in opts
:
349 if opt
in ("-o", "--output"):
351 elif opt
in ("-c", "--columns"):
352 columns
= int(val
, 10)
353 elif opt
in ("-l", "--letters"):
355 elif opt
== "--group-symbols":
356 group_symbol_nodes
= 1
357 elif opt
== "--dont-group-symbols":
358 group_symbol_nodes
= 0
363 nodes
= nodes
+ load(open(fn
))
364 num_nodes
= len(nodes
)
365 html
= process_nodes(nodes
, columns
, letters
, group_symbol_nodes
)
366 program
= os
.path
.basename(sys
.argv
[0])
368 sys
.stdout
.write(html
)
369 sys
.stderr
.write("\n%s: %d index nodes" % (program
, num_nodes
))
371 open(ofn
, "w").write(html
)
373 print "%s: %d index nodes" % (program
, num_nodes
)
376 if __name__
== "__main__":