blob: 22aa1fb834a70ce0a17e38fa78b5f04066cdc0c8 [file] [log] [blame]
Guido van Rossum26a9d371995-03-15 11:26:05 +00001#! /usr/local/bin/python
2
3# Convert GNU texinfo files into HTML, one file per node.
4# Based on Texinfo 2.14.
Guido van Rossum06f42891995-08-28 03:01:00 +00005# Usage: texi2html [-d] [-d] [-c] inputfile outputdirectory
Guido van Rossum26a9d371995-03-15 11:26:05 +00006# The input file must be a complete texinfo file, e.g. emacs.texi.
7# This creates many files (one per info node) in the output directory,
8# overwriting existing files of the same name. All files created have
9# ".html" as their extension.
10
11
12# XXX To do:
13# - handle @comment*** correctly
14# - handle @xref {some words} correctly
15# - handle @ftable correctly (items aren't indexed?)
16# - handle @itemx properly
17# - handle @exdent properly
18# - add links directly to the proper line from indices
19# - check against the definitive list of @-cmds; we still miss (among others):
Guido van Rossum26a9d371995-03-15 11:26:05 +000020# - @defindex (hard)
21# - @c(omment) in the middle of a line (rarely used)
22# - @this* (not really needed, only used in headers anyway)
23# - @today{} (ever used outside title page?)
24
Guido van Rossum06f42891995-08-28 03:01:00 +000025# More consistent handling of chapters/sections/etc.
26# Lots of documentation
27# Many more options:
28# -top designate top node
29# -links customize which types of links are included
30# -split split at chapters or sections instead of nodes
31# -name Allow different types of filename handling. Non unix systems
32# will have problems with long node names
33# ...
34# Support the most recent texinfo version and take a good look at HTML 3.0
35# More debugging output (customizable) and more fexible error handling
36# How about icons ?
Guido van Rossum26a9d371995-03-15 11:26:05 +000037
38import os
39import regex
40import regsub
41import string
42
43MAGIC = '\\input texinfo'
44
45cmprog = regex.compile('^@\([a-z]+\)\([ \t]\|$\)') # Command (line-oriented)
46blprog = regex.compile('^[ \t]*$') # Blank line
47kwprog = regex.compile('@[a-z]+') # Keyword (embedded, usually with {} args)
48spprog = regex.compile('[\n@{}&<>]') # Special characters in running text
49miprog = regex.compile( \
50 '^\* \([^:]*\):\(:\|[ \t]*\([^\t,\n.]+\)\([^ \t\n]*\)\)[ \t\n]*')
Fred Drake02827261996-10-09 19:05:12 +000051 # menu item (Yuck!)
Guido van Rossum26a9d371995-03-15 11:26:05 +000052
Guido van Rossum06f42891995-08-28 03:01:00 +000053
Fred Drake02827261996-10-09 19:05:12 +000054class HTMLNode:
55 """Some of the parser's functionality is separated into this class.
Guido van Rossum06f42891995-08-28 03:01:00 +000056
57 A Node accumulates its contents, takes care of links to other Nodes
Fred Drake02827261996-10-09 19:05:12 +000058 and saves itself when it is finished and all links are resolved.
59 """
Fred Drakea39a25e1996-09-13 14:44:34 +000060
Fred Drake02827261996-10-09 19:05:12 +000061 DOCTYPE = '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">'
62
63 type = 0
64 cont = ''
65 epilogue = '</BODY></HTML>\n'
66
67 def __init__(self, dir, name, topname, title, next, prev, up):
Guido van Rossum06f42891995-08-28 03:01:00 +000068 self.dirname = dir
69 self.name = name
70 if topname:
71 self.topname = topname
72 else:
73 self.topname = name
74 self.title = title
75 self.next = next
76 self.prev = prev
77 self.up = up
78 self.lines = []
Fred Drakea39a25e1996-09-13 14:44:34 +000079
Fred Drake02827261996-10-09 19:05:12 +000080 def write(self, *lines):
Guido van Rossum29901ff1996-08-09 21:46:34 +000081 map(self.lines.append, lines)
Guido van Rossum06f42891995-08-28 03:01:00 +000082
Fred Drake02827261996-10-09 19:05:12 +000083 def flush(self):
84 fp = open(self.dirname + '/' + makefile(self.name), 'w')
85 fp.write(self.prologue)
86 fp.write(self.text)
87 fp.write(self.epilogue)
88 fp.close()
Guido van Rossum06f42891995-08-28 03:01:00 +000089
Fred Drake02827261996-10-09 19:05:12 +000090 def link(self, label, nodename, rel=None, rev=None):
Guido van Rossum06f42891995-08-28 03:01:00 +000091 if nodename:
92 if string.lower(nodename) == '(dir)':
93 addr = '../dir.html'
Fred Drake02827261996-10-09 19:05:12 +000094 title = ''
Guido van Rossum06f42891995-08-28 03:01:00 +000095 else:
96 addr = makefile(nodename)
Fred Drake02827261996-10-09 19:05:12 +000097 title = ' TITLE="%s"' % nodename
98 self.write(label, ': <A HREF="', addr, '"', \
99 rel and (' REL=' + rel) or "", \
100 rev and (' REV=' + rev) or "", \
101 title, '>', nodename, '</A> \n')
Fred Drakea39a25e1996-09-13 14:44:34 +0000102
Guido van Rossum06f42891995-08-28 03:01:00 +0000103 def finalize(self):
Fred Drake02827261996-10-09 19:05:12 +0000104 length = len(self.lines)
105 self.text = string.joinfields(self.lines, '')
Guido van Rossum06f42891995-08-28 03:01:00 +0000106 self.lines = []
Fred Drake02827261996-10-09 19:05:12 +0000107 self.open_links()
108 self.output_links()
109 self.close_links()
Guido van Rossum29901ff1996-08-09 21:46:34 +0000110 links = string.joinfields(self.lines, '')
Guido van Rossum06f42891995-08-28 03:01:00 +0000111 self.lines = []
Fred Drakea39a25e1996-09-13 14:44:34 +0000112
Fred Drake02827261996-10-09 19:05:12 +0000113 self.prologue = (
114 self.DOCTYPE +
115 '\n<HTML><HEAD>\n'
116 ' <!-- Converted with texi2html and Python -->\n'
117 ' <TITLE>' + self.title + '</TITLE>\n'
118 ' <LINK REL=Next HREF="'
119 + makefile(self.next) + '" TITLE="' + self.next + '">\n'
120 ' <LINK REL=Previous HREF="'
121 + makefile(self.prev) + '" TITLE="' + self.prev + '">\n'
122 ' <LINK REL=Up HREF="'
123 + makefile(self.up) + '" TITLE="' + self.up + '">\n'
124 '</HEAD><BODY>\n' +
125 links)
Guido van Rossum06f42891995-08-28 03:01:00 +0000126 if length > 20:
Fred Drake02827261996-10-09 19:05:12 +0000127 self.epilogue = '<P>\n%s</BODY></HTML>\n' % links
128
129 def open_links(self):
130 self.write('<HR>\n')
131
132 def close_links(self):
133 self.write('<HR>\n')
134
135 def output_links(self):
136 if self.cont != self.next:
137 self.link(' Cont', self.cont)
138 self.link(' Next', self.next, rel='Next')
139 self.link(' Prev', self.prev, rel='Previous')
140 self.link(' Up', self.up, rel='Up')
141 if self.name <> self.topname:
142 self.link(' Top', self.topname)
143
144
145class HTML3Node(HTMLNode):
146
147 DOCTYPE = '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML Level 3//EN//3.0">'
148
149 def open_links(self):
Fred Drake22f7f9e1996-10-11 16:54:00 +0000150 self.write('<DIV CLASS=Navigation>\n <HR>\n')
Fred Drake02827261996-10-09 19:05:12 +0000151
152 def close_links(self):
153 self.write(' <HR>\n</DIV>\n')
Fred Drakea39a25e1996-09-13 14:44:34 +0000154
Guido van Rossum06f42891995-08-28 03:01:00 +0000155
Guido van Rossum26a9d371995-03-15 11:26:05 +0000156class TexinfoParser:
157
Fred Drake02827261996-10-09 19:05:12 +0000158 COPYRIGHT_SYMBOL = "&copy;"
159 FN_ID_PATTERN = "(%(id)s)"
160 FN_SOURCE_PATTERN = '<A NAME=footnoteref%(id)s' \
161 ' HREF="#footnotetext%(id)s">' \
162 + FN_ID_PATTERN + '</A>'
163 FN_TARGET_PATTERN = '<A NAME=footnotetext%(id)s' \
164 ' HREF="#footnoteref%(id)s">' \
165 + FN_ID_PATTERN + '</A>\n%(text)s<P>\n'
Fred Drake22f7f9e1996-10-11 16:54:00 +0000166 FN_HEADER = '\n<P>\n<HR NOSHADE SIZE=1 WIDTH=200>\n' \
Fred Drake02827261996-10-09 19:05:12 +0000167 '<STRONG><EM>Footnotes</EM></STRONG>\n<P>'
168
169
170 Node = HTMLNode
171
Fred Drakea39a25e1996-09-13 14:44:34 +0000172 # Initialize an instance
173 def __init__(self):
174 self.unknown = {} # statistics about unknown @-commands
175 self.filenames = {} # Check for identical filenames
176 self.debugging = 0 # larger values produce more output
Fred Drake02827261996-10-09 19:05:12 +0000177 self.print_headers = 0 # always print headers?
Fred Drakea39a25e1996-09-13 14:44:34 +0000178 self.nodefp = None # open file we're writing to
179 self.nodelineno = 0 # Linenumber relative to node
180 self.links = None # Links from current node
181 self.savetext = None # If not None, save text head instead
182 self.savestack = [] # If not None, save text head instead
183 self.dirname = 'tmp' # directory where files are created
184 self.includedir = '.' # directory to search @include files
185 self.nodename = '' # name of current node
186 self.topname = '' # name of top node (first node seen)
187 self.title = '' # title of this whole Texinfo tree
188 self.resetindex() # Reset all indices
189 self.contents = [] # Reset table of contents
190 self.numbering = [] # Reset section numbering counters
191 self.nofill = 0 # Normal operation: fill paragraphs
192 self.values={'html': 1} # Names that should be parsed in ifset
193 self.stackinfo={} # Keep track of state in the stack
194 # XXX The following should be reset per node?!
195 self.footnotes = [] # Reset list of footnotes
196 self.itemarg = None # Reset command used by @item
197 self.itemnumber = None # Reset number for @item in @enumerate
198 self.itemindex = None # Reset item index name
199 self.node = None
200 self.nodestack = []
201 self.cont = 0
202 self.includedepth = 0
203 # Set (output) directory name
204 def setdirname(self, dirname):
205 self.dirname = dirname
Guido van Rossum26a9d371995-03-15 11:26:05 +0000206
Fred Drakea39a25e1996-09-13 14:44:34 +0000207 # Set include directory name
208 def setincludedir(self, includedir):
209 self.includedir = includedir
Guido van Rossum26a9d371995-03-15 11:26:05 +0000210
Fred Drakea39a25e1996-09-13 14:44:34 +0000211 # Parse the contents of an entire file
212 def parse(self, fp):
213 line = fp.readline()
214 lineno = 1
215 while line and (line[0] == '%' or blprog.match(line) >= 0):
216 line = fp.readline()
217 lineno = lineno + 1
218 if line[:len(MAGIC)] <> MAGIC:
219 raise SyntaxError, 'file does not begin with '+`MAGIC`
220 self.parserest(fp, lineno)
Guido van Rossum26a9d371995-03-15 11:26:05 +0000221
Fred Drakea39a25e1996-09-13 14:44:34 +0000222 # Parse the contents of a file, not expecting a MAGIC header
223 def parserest(self, fp, initial_lineno):
224 lineno = initial_lineno
225 self.done = 0
226 self.skip = 0
227 self.stack = []
228 accu = []
229 while not self.done:
230 line = fp.readline()
231 self.nodelineno = self.nodelineno + 1
232 if not line:
233 if accu:
234 if not self.skip: self.process(accu)
235 accu = []
236 if initial_lineno > 0:
237 print '*** EOF before @bye'
238 break
239 lineno = lineno + 1
240 if cmprog.match(line) >= 0:
Guido van Rossum26a9d371995-03-15 11:26:05 +0000241 a, b = cmprog.regs[1]
242 cmd = line[a:b]
Fred Drakea39a25e1996-09-13 14:44:34 +0000243 if cmd in ('noindent', 'refill'):
244 accu.append(line)
245 else:
246 if accu:
247 if not self.skip:
248 self.process(accu)
249 accu = []
250 self.command(line)
251 elif blprog.match(line) >= 0 and \
252 'format' not in self.stack and \
253 'example' not in self.stack:
254 if accu:
255 if not self.skip:
256 self.process(accu)
Fred Drake02827261996-10-09 19:05:12 +0000257 if self.nofill:
258 self.write('\n')
259 else:
260 self.write('<P>\n')
Fred Drakea39a25e1996-09-13 14:44:34 +0000261 accu = []
262 else:
263 # Append the line including trailing \n!
264 accu.append(line)
265 #
266 if self.skip:
267 print '*** Still skipping at the end'
268 if self.stack:
269 print '*** Stack not empty at the end'
270 print '***', self.stack
271 if self.includedepth == 0:
272 while self.nodestack:
Fred Drake02827261996-10-09 19:05:12 +0000273 self.nodestack[-1].finalize()
274 self.nodestack[-1].flush()
275 del self.nodestack[-1]
Fred Drakea39a25e1996-09-13 14:44:34 +0000276
277 # Start saving text in a buffer instead of writing it to a file
278 def startsaving(self):
279 if self.savetext <> None:
Fred Drake02827261996-10-09 19:05:12 +0000280 self.savestack.append(self.savetext)
Fred Drakea39a25e1996-09-13 14:44:34 +0000281 # print '*** Recursively saving text, expect trouble'
282 self.savetext = ''
283
284 # Return the text saved so far and start writing to file again
285 def collectsavings(self):
286 savetext = self.savetext
Fred Drake02827261996-10-09 19:05:12 +0000287 if len(self.savestack) > 0:
Fred Drakea39a25e1996-09-13 14:44:34 +0000288 self.savetext = self.savestack[-1]
289 del self.savestack[-1]
290 else:
291 self.savetext = None
292 return savetext or ''
293
294 # Write text to file, or save it in a buffer, or ignore it
295 def write(self, *args):
296 try:
297 text = string.joinfields(args, '')
298 except:
299 print args
300 raise TypeError
301 if self.savetext <> None:
302 self.savetext = self.savetext + text
303 elif self.nodefp:
304 self.nodefp.write(text)
305 elif self.node:
Fred Drake02827261996-10-09 19:05:12 +0000306 self.node.write(text)
Fred Drakea39a25e1996-09-13 14:44:34 +0000307 # Complete the current node -- write footnotes and close file
308 def endnode(self):
309 if self.savetext <> None:
310 print '*** Still saving text at end of node'
311 dummy = self.collectsavings()
312 if self.footnotes:
313 self.writefootnotes()
314 if self.nodefp:
315 if self.nodelineno > 20:
Fred Drake02827261996-10-09 19:05:12 +0000316 self.write('<HR>\n')
Fred Drakea39a25e1996-09-13 14:44:34 +0000317 [name, next, prev, up] = self.nodelinks[:4]
318 self.link('Next', next)
319 self.link('Prev', prev)
320 self.link('Up', up)
321 if self.nodename <> self.topname:
322 self.link('Top', self.topname)
Fred Drake02827261996-10-09 19:05:12 +0000323 self.write('<HR>\n')
Fred Drakea39a25e1996-09-13 14:44:34 +0000324 self.write('</BODY>\n')
325 self.nodefp.close()
326 self.nodefp = None
327 elif self.node:
328 if not self.cont and \
329 (not self.node.type or \
330 (self.node.next and self.node.prev and self.node.up)):
Fred Drake02827261996-10-09 19:05:12 +0000331 self.node.finalize()
332 self.node.flush()
Fred Drakea39a25e1996-09-13 14:44:34 +0000333 else:
Fred Drake02827261996-10-09 19:05:12 +0000334 self.nodestack.append(self.node)
Fred Drakea39a25e1996-09-13 14:44:34 +0000335 self.node = None
336 self.nodename = ''
337
338 # Process a list of lines, expanding embedded @-commands
339 # This mostly distinguishes between menus and normal text
340 def process(self, accu):
341 if self.debugging > 1:
342 print self.skip, self.stack,
343 if accu: print accu[0][:30],
344 if accu[0][30:] or accu[1:]: print '...',
345 print
346 if self.stack and self.stack[-1] == 'menu':
347 # XXX should be done differently
348 for line in accu:
349 if miprog.match(line) < 0:
350 line = string.strip(line) + '\n'
351 self.expand(line)
352 continue
353 (bgn, end), (a, b), (c, d), (e, f), (g, h) = \
354 miprog.regs[:5]
355 label = line[a:b]
356 nodename = line[c:d]
357 if nodename[0] == ':': nodename = label
358 else: nodename = line[e:f]
359 punct = line[g:h]
Fred Drake02827261996-10-09 19:05:12 +0000360 self.write(' <LI><A HREF="',
Fred Drakea39a25e1996-09-13 14:44:34 +0000361 makefile(nodename),
362 '">', nodename,
363 '</A>', punct, '\n')
364 self.expand(line[end:])
365 else:
366 text = string.joinfields(accu, '')
367 self.expand(text)
368
369 # Write a string, expanding embedded @-commands
370 def expand(self, text):
371 stack = []
372 i = 0
373 n = len(text)
374 while i < n:
375 start = i
376 i = spprog.search(text, i)
377 if i < 0:
378 self.write(text[start:])
379 break
380 self.write(text[start:i])
381 c = text[i]
382 i = i+1
383 if c == '\n':
Fred Drake02827261996-10-09 19:05:12 +0000384 self.write('\n')
Fred Drakea39a25e1996-09-13 14:44:34 +0000385 continue
386 if c == '<':
387 self.write('&lt;')
388 continue
389 if c == '>':
390 self.write('&gt;')
391 continue
392 if c == '&':
393 self.write('&amp;')
394 continue
395 if c == '{':
396 stack.append('')
397 continue
398 if c == '}':
399 if not stack:
400 print '*** Unmatched }'
401 self.write('}')
402 continue
403 cmd = stack[-1]
404 del stack[-1]
Guido van Rossum26a9d371995-03-15 11:26:05 +0000405 try:
Fred Drakea39a25e1996-09-13 14:44:34 +0000406 method = getattr(self, 'close_' + cmd)
Guido van Rossum26a9d371995-03-15 11:26:05 +0000407 except AttributeError:
Fred Drakea39a25e1996-09-13 14:44:34 +0000408 self.unknown_close(cmd)
409 continue
410 method()
411 continue
412 if c <> '@':
413 # Cannot happen unless spprog is changed
414 raise RuntimeError, 'unexpected funny '+`c`
415 start = i
416 while i < n and text[i] in string.letters: i = i+1
417 if i == start:
418 # @ plus non-letter: literal next character
419 i = i+1
420 c = text[start:i]
421 if c == ':':
422 # `@:' means no extra space after
423 # preceding `.', `?', `!' or `:'
424 pass
Guido van Rossum26a9d371995-03-15 11:26:05 +0000425 else:
Fred Drakea39a25e1996-09-13 14:44:34 +0000426 # `@.' means a sentence-ending period;
427 # `@@', `@{', `@}' quote `@', `{', `}'
428 self.write(c)
429 continue
430 cmd = text[start:i]
431 if i < n and text[i] == '{':
432 i = i+1
433 stack.append(cmd)
434 try:
435 method = getattr(self, 'open_' + cmd)
436 except AttributeError:
437 self.unknown_open(cmd)
438 continue
439 method()
440 continue
441 try:
442 method = getattr(self, 'handle_' + cmd)
443 except AttributeError:
444 self.unknown_handle(cmd)
445 continue
446 method()
447 if stack:
448 print '*** Stack not empty at para:', stack
Guido van Rossum26a9d371995-03-15 11:26:05 +0000449
Fred Drakea39a25e1996-09-13 14:44:34 +0000450 # --- Handle unknown embedded @-commands ---
451
452 def unknown_open(self, cmd):
453 print '*** No open func for @' + cmd + '{...}'
454 cmd = cmd + '{'
455 self.write('@', cmd)
456 if not self.unknown.has_key(cmd):
457 self.unknown[cmd] = 1
458 else:
459 self.unknown[cmd] = self.unknown[cmd] + 1
460
461 def unknown_close(self, cmd):
462 print '*** No close func for @' + cmd + '{...}'
463 cmd = '}' + cmd
464 self.write('}')
465 if not self.unknown.has_key(cmd):
466 self.unknown[cmd] = 1
467 else:
468 self.unknown[cmd] = self.unknown[cmd] + 1
469
470 def unknown_handle(self, cmd):
471 print '*** No handler for @' + cmd
472 self.write('@', cmd)
473 if not self.unknown.has_key(cmd):
474 self.unknown[cmd] = 1
475 else:
476 self.unknown[cmd] = self.unknown[cmd] + 1
477
478 # XXX The following sections should be ordered as the texinfo docs
479
480 # --- Embedded @-commands without {} argument list --
481
482 def handle_noindent(self): pass
483
484 def handle_refill(self): pass
485
486 # --- Include file handling ---
487
488 def do_include(self, args):
489 file = args
490 file = os.path.join(self.includedir, file)
491 try:
492 fp = open(file, 'r')
493 except IOError, msg:
494 print '*** Can\'t open include file', `file`
495 return
496 if self.debugging:
497 print '--> file', `file`
498 save_done = self.done
499 save_skip = self.skip
500 save_stack = self.stack
501 self.includedepth = self.includedepth + 1
502 self.parserest(fp, 0)
503 self.includedepth = self.includedepth - 1
504 fp.close()
505 self.done = save_done
506 self.skip = save_skip
507 self.stack = save_stack
508 if self.debugging:
509 print '<-- file', `file`
510
511 # --- Special Insertions ---
512
513 def open_dmn(self): pass
514 def close_dmn(self): pass
515
516 def open_dots(self): self.write('...')
517 def close_dots(self): pass
518
519 def open_bullet(self): pass
520 def close_bullet(self): pass
521
522 def open_TeX(self): self.write('TeX')
523 def close_TeX(self): pass
524
Fred Drake02827261996-10-09 19:05:12 +0000525 def handle_copyright(self): self.write(self.COPYRIGHT_SYMBOL)
526 def open_copyright(self): self.write(self.COPYRIGHT_SYMBOL)
Fred Drakea39a25e1996-09-13 14:44:34 +0000527 def close_copyright(self): pass
528
529 def open_minus(self): self.write('-')
530 def close_minus(self): pass
531
532 # --- Special Glyphs for Examples ---
533
534 def open_result(self): self.write('=&gt;')
535 def close_result(self): pass
536
537 def open_expansion(self): self.write('==&gt;')
538 def close_expansion(self): pass
539
540 def open_print(self): self.write('-|')
541 def close_print(self): pass
542
543 def open_error(self): self.write('error--&gt;')
544 def close_error(self): pass
545
546 def open_equiv(self): self.write('==')
547 def close_equiv(self): pass
548
549 def open_point(self): self.write('-!-')
550 def close_point(self): pass
551
552 # --- Cross References ---
553
554 def open_pxref(self):
555 self.write('see ')
556 self.startsaving()
557 def close_pxref(self):
558 self.makeref()
559
560 def open_xref(self):
561 self.write('See ')
562 self.startsaving()
563 def close_xref(self):
564 self.makeref()
565
566 def open_ref(self):
567 self.startsaving()
568 def close_ref(self):
569 self.makeref()
570
571 def open_inforef(self):
572 self.write('See info file ')
573 self.startsaving()
574 def close_inforef(self):
575 text = self.collectsavings()
576 args = string.splitfields(text, ',')
577 n = len(args)
578 for i in range(n):
579 args[i] = string.strip(args[i])
580 while len(args) < 3: args.append('')
581 node = args[0]
582 file = args[2]
583 self.write('`', file, '\', node `', node, '\'')
584
585 def makeref(self):
586 text = self.collectsavings()
587 args = string.splitfields(text, ',')
588 n = len(args)
589 for i in range(n):
590 args[i] = string.strip(args[i])
591 while len(args) < 5: args.append('')
592 nodename = label = args[0]
593 if args[2]: label = args[2]
594 file = args[3]
595 title = args[4]
596 href = makefile(nodename)
597 if file:
598 href = '../' + file + '/' + href
599 self.write('<A HREF="', href, '">', label, '</A>')
600
601 # --- Marking Words and Phrases ---
602
603 # --- Other @xxx{...} commands ---
604
605 def open_(self): pass # Used by {text enclosed in braces}
606 def close_(self): pass
607
608 open_asis = open_
609 close_asis = close_
610
611 def open_cite(self): self.write('<CITE>')
612 def close_cite(self): self.write('</CITE>')
613
614 def open_code(self): self.write('<CODE>')
615 def close_code(self): self.write('</CODE>')
616
Fred Drake02827261996-10-09 19:05:12 +0000617 def open_t(self): self.write('<TT>')
618 def close_t(self): self.write('</TT>')
Fred Drakea39a25e1996-09-13 14:44:34 +0000619
620 def open_dfn(self): self.write('<DFN>')
621 def close_dfn(self): self.write('</DFN>')
622
623 def open_emph(self): self.write('<EM>')
624 def close_emph(self): self.write('</EM>')
625
Fred Drake02827261996-10-09 19:05:12 +0000626 def open_i(self): self.write('<I>')
627 def close_i(self): self.write('</I>')
Fred Drakea39a25e1996-09-13 14:44:34 +0000628
629 def open_footnote(self):
630 # if self.savetext <> None:
631 # print '*** Recursive footnote -- expect weirdness'
632 id = len(self.footnotes) + 1
Fred Drake02827261996-10-09 19:05:12 +0000633 self.write(self.FN_SOURCE_PATTERN % {'id': `id`})
634 self.startsaving()
Fred Drakea39a25e1996-09-13 14:44:34 +0000635
636 def close_footnote(self):
637 id = len(self.footnotes) + 1
Fred Drake02827261996-10-09 19:05:12 +0000638 self.footnotes.append(id, self.collectsavings())
Fred Drakea39a25e1996-09-13 14:44:34 +0000639
640 def writefootnotes(self):
Fred Drake02827261996-10-09 19:05:12 +0000641 self.write(self.FN_HEADER)
Fred Drakea39a25e1996-09-13 14:44:34 +0000642 for id, text in self.footnotes:
Fred Drake02827261996-10-09 19:05:12 +0000643 self.write(self.FN_TARGET_PATTERN
644 % {'id': `id`, 'text': text})
Fred Drakea39a25e1996-09-13 14:44:34 +0000645 self.footnotes = []
646
647 def open_file(self): self.write('<CODE>')
648 def close_file(self): self.write('</CODE>')
649
650 def open_kbd(self): self.write('<KBD>')
651 def close_kbd(self): self.write('</KBD>')
652
653 def open_key(self): self.write('<KEY>')
654 def close_key(self): self.write('</KEY>')
655
656 def open_r(self): self.write('<R>')
657 def close_r(self): self.write('</R>')
658
659 def open_samp(self): self.write('`<SAMP>')
660 def close_samp(self): self.write('</SAMP>\'')
661
662 def open_sc(self): self.write('<SMALLCAPS>')
663 def close_sc(self): self.write('</SMALLCAPS>')
664
Fred Drake02827261996-10-09 19:05:12 +0000665 def open_strong(self): self.write('<STRONG>')
666 def close_strong(self): self.write('</STRONG>')
Fred Drakea39a25e1996-09-13 14:44:34 +0000667
Fred Drake02827261996-10-09 19:05:12 +0000668 def open_b(self): self.write('<B>')
669 def close_b(self): self.write('</B>')
Fred Drakea39a25e1996-09-13 14:44:34 +0000670
671 def open_var(self): self.write('<VAR>')
672 def close_var(self): self.write('</VAR>')
673
674 def open_w(self): self.write('<NOBREAK>')
675 def close_w(self): self.write('</NOBREAK>')
676
677 open_titlefont = open_
678 close_titlefont = close_
679
680 def open_small(self): pass
681 def close_small(self): pass
682
683 def command(self, line):
684 a, b = cmprog.regs[1]
685 cmd = line[a:b]
686 args = string.strip(line[b:])
687 if self.debugging > 1:
688 print self.skip, self.stack, '@' + cmd, args
689 try:
690 func = getattr(self, 'do_' + cmd)
691 except AttributeError:
692 try:
693 func = getattr(self, 'bgn_' + cmd)
694 except AttributeError:
695 # don't complain if we are skipping anyway
696 if not self.skip:
697 self.unknown_cmd(cmd, args)
698 return
699 self.stack.append(cmd)
700 func(args)
701 return
702 if not self.skip or cmd == 'end':
703 func(args)
704
705 def unknown_cmd(self, cmd, args):
706 print '*** unknown', '@' + cmd, args
707 if not self.unknown.has_key(cmd):
708 self.unknown[cmd] = 1
709 else:
710 self.unknown[cmd] = self.unknown[cmd] + 1
711
712 def do_end(self, args):
713 words = string.split(args)
714 if not words:
715 print '*** @end w/o args'
716 else:
717 cmd = words[0]
718 if not self.stack or self.stack[-1] <> cmd:
719 print '*** @end', cmd, 'unexpected'
720 else:
721 del self.stack[-1]
722 try:
723 func = getattr(self, 'end_' + cmd)
724 except AttributeError:
725 self.unknown_end(cmd)
726 return
727 func()
728
729 def unknown_end(self, cmd):
730 cmd = 'end ' + cmd
731 print '*** unknown', '@' + cmd
732 if not self.unknown.has_key(cmd):
733 self.unknown[cmd] = 1
734 else:
735 self.unknown[cmd] = self.unknown[cmd] + 1
736
737 # --- Comments ---
738
739 def do_comment(self, args): pass
740 do_c = do_comment
741
742 # --- Conditional processing ---
743
744 def bgn_ifinfo(self, args): pass
745 def end_ifinfo(self): pass
746
747 def bgn_iftex(self, args): self.skip = self.skip + 1
748 def end_iftex(self): self.skip = self.skip - 1
749
750 def bgn_ignore(self, args): self.skip = self.skip + 1
751 def end_ignore(self): self.skip = self.skip - 1
752
753 def bgn_tex(self, args): self.skip = self.skip + 1
754 def end_tex(self): self.skip = self.skip - 1
755
756 def do_set(self, args):
Fred Drake02827261996-10-09 19:05:12 +0000757 fields = string.splitfields(args, ' ')
Fred Drakea39a25e1996-09-13 14:44:34 +0000758 key = fields[0]
759 if len(fields) == 1:
760 value = 1
761 else:
Fred Drake02827261996-10-09 19:05:12 +0000762 value = string.joinfields(fields[1:], ' ')
763 self.values[key] = value
Fred Drakea39a25e1996-09-13 14:44:34 +0000764 print self.values
765
766 def do_clear(self, args):
767 self.values[args] = None
768
769 def bgn_ifset(self, args):
770 if args not in self.values.keys() \
771 or self.values[args] is None:
772 self.skip = self.skip + 1
773 self.stackinfo[len(self.stack)] = 1
774 else:
775 self.stackinfo[len(self.stack)] = 0
776 def end_ifset(self):
777 print self.stack
778 print self.stackinfo
779 if self.stackinfo[len(self.stack) + 1]:
780 self.skip = self.skip - 1
781 del self.stackinfo[len(self.stack) + 1]
782
783 def bgn_ifclear(self, args):
784 if args in self.values.keys() \
785 and self.values[args] is not None:
786 self.skip = self.skip + 1
787 self.stackinfo[len(self.stack)] = 1
788 else:
789 self.stackinfo[len(self.stack)] = 0
790
791 end_ifclear = end_ifset
792
793 def open_value(self):
794 self.startsaving()
795
796 def close_value(self):
Fred Drake02827261996-10-09 19:05:12 +0000797 key = self.collectsavings()
Fred Drakea39a25e1996-09-13 14:44:34 +0000798 if key in self.values.keys():
Fred Drake02827261996-10-09 19:05:12 +0000799 self.write(self.values[key])
Fred Drakea39a25e1996-09-13 14:44:34 +0000800 else:
801 print '*** Undefined value: ', key
802
803 # --- Beginning a file ---
804
805 do_finalout = do_comment
806 do_setchapternewpage = do_comment
807 do_setfilename = do_comment
808
809 def do_settitle(self, args):
810 print args
811 self.startsaving()
Fred Drake02827261996-10-09 19:05:12 +0000812 self.expand(args)
813 self.title = self.collectsavings()
Fred Drakea39a25e1996-09-13 14:44:34 +0000814 print self.title
815 def do_parskip(self, args): pass
816
817 # --- Ending a file ---
818
819 def do_bye(self, args):
Fred Drake02827261996-10-09 19:05:12 +0000820 self.endnode()
Fred Drakea39a25e1996-09-13 14:44:34 +0000821 self.done = 1
822
823 # --- Title page ---
824
825 def bgn_titlepage(self, args): self.skip = self.skip + 1
826 def end_titlepage(self): self.skip = self.skip - 1
827 def do_shorttitlepage(self, args): pass
828
829 def do_center(self, args):
830 # Actually not used outside title page...
831 self.write('<H1>')
Fred Drake02827261996-10-09 19:05:12 +0000832 self.expand(args)
833 self.write('</H1>\n')
Fred Drakea39a25e1996-09-13 14:44:34 +0000834 do_title = do_center
835 do_subtitle = do_center
836 do_author = do_center
837
838 do_vskip = do_comment
839 do_vfill = do_comment
840 do_smallbook = do_comment
841
842 do_paragraphindent = do_comment
843 do_setchapternewpage = do_comment
844 do_headings = do_comment
845 do_footnotestyle = do_comment
846
847 do_evenheading = do_comment
848 do_evenfooting = do_comment
849 do_oddheading = do_comment
850 do_oddfooting = do_comment
851 do_everyheading = do_comment
852 do_everyfooting = do_comment
853
854 # --- Nodes ---
855
856 def do_node(self, args):
857 self.endnode()
858 self.nodelineno = 0
859 parts = string.splitfields(args, ',')
860 while len(parts) < 4: parts.append('')
861 for i in range(4): parts[i] = string.strip(parts[i])
862 self.nodelinks = parts
863 [name, next, prev, up] = parts[:4]
864 file = self.dirname + '/' + makefile(name)
865 if self.filenames.has_key(file):
866 print '*** Filename already in use: ', file
867 else:
868 if self.debugging: print '--- writing', file
869 self.filenames[file] = 1
870 # self.nodefp = open(file, 'w')
871 self.nodename = name
872 if self.cont and self.nodestack:
873 self.nodestack[-1].cont = self.nodename
874 if not self.topname: self.topname = name
875 title = name
876 if self.title: title = title + ' -- ' + self.title
Fred Drake02827261996-10-09 19:05:12 +0000877 self.node = self.Node(self.dirname, self.nodename, self.topname,
878 title, next, prev, up)
Fred Drakea39a25e1996-09-13 14:44:34 +0000879
880 def link(self, label, nodename):
881 if nodename:
882 if string.lower(nodename) == '(dir)':
883 addr = '../dir.html'
884 else:
885 addr = makefile(nodename)
Fred Drake02827261996-10-09 19:05:12 +0000886 self.write(label, ': <A HREF="', addr, '" TYPE="',
887 label, '">', nodename, '</A> \n')
Fred Drakea39a25e1996-09-13 14:44:34 +0000888
889 # --- Sectioning commands ---
890
Fred Drake02827261996-10-09 19:05:12 +0000891 def popstack(self, type):
Fred Drakea39a25e1996-09-13 14:44:34 +0000892 if (self.node):
893 self.node.type = type
894 while self.nodestack:
895 if self.nodestack[-1].type > type:
Fred Drake02827261996-10-09 19:05:12 +0000896 self.nodestack[-1].finalize()
897 self.nodestack[-1].flush()
898 del self.nodestack[-1]
Fred Drakea39a25e1996-09-13 14:44:34 +0000899 elif self.nodestack[-1].type == type:
900 if not self.nodestack[-1].next:
901 self.nodestack[-1].next = self.node.name
902 if not self.node.prev:
903 self.node.prev = self.nodestack[-1].name
Fred Drake02827261996-10-09 19:05:12 +0000904 self.nodestack[-1].finalize()
905 self.nodestack[-1].flush()
906 del self.nodestack[-1]
Guido van Rossum26a9d371995-03-15 11:26:05 +0000907 else:
Fred Drakea39a25e1996-09-13 14:44:34 +0000908 if type > 1 and not self.node.up:
909 self.node.up = self.nodestack[-1].name
910 break
Guido van Rossum26a9d371995-03-15 11:26:05 +0000911
Fred Drakea39a25e1996-09-13 14:44:34 +0000912 def do_chapter(self, args):
913 self.heading('H1', args, 0)
Fred Drake02827261996-10-09 19:05:12 +0000914 self.popstack(1)
Guido van Rossum26a9d371995-03-15 11:26:05 +0000915
Fred Drakea39a25e1996-09-13 14:44:34 +0000916 def do_unnumbered(self, args):
917 self.heading('H1', args, -1)
Fred Drake02827261996-10-09 19:05:12 +0000918 self.popstack(1)
Fred Drakea39a25e1996-09-13 14:44:34 +0000919 def do_appendix(self, args):
920 self.heading('H1', args, -1)
Fred Drake02827261996-10-09 19:05:12 +0000921 self.popstack(1)
Fred Drakea39a25e1996-09-13 14:44:34 +0000922 def do_top(self, args):
923 self.heading('H1', args, -1)
924 def do_chapheading(self, args):
925 self.heading('H1', args, -1)
926 def do_majorheading(self, args):
927 self.heading('H1', args, -1)
Guido van Rossum26a9d371995-03-15 11:26:05 +0000928
Fred Drakea39a25e1996-09-13 14:44:34 +0000929 def do_section(self, args):
930 self.heading('H1', args, 1)
Fred Drake02827261996-10-09 19:05:12 +0000931 self.popstack(2)
Guido van Rossum26a9d371995-03-15 11:26:05 +0000932
Fred Drakea39a25e1996-09-13 14:44:34 +0000933 def do_unnumberedsec(self, args):
934 self.heading('H1', args, -1)
Fred Drake02827261996-10-09 19:05:12 +0000935 self.popstack(2)
Fred Drakea39a25e1996-09-13 14:44:34 +0000936 def do_appendixsec(self, args):
937 self.heading('H1', args, -1)
Fred Drake02827261996-10-09 19:05:12 +0000938 self.popstack(2)
Fred Drakea39a25e1996-09-13 14:44:34 +0000939 do_appendixsection = do_appendixsec
940 def do_heading(self, args):
941 self.heading('H1', args, -1)
Guido van Rossum26a9d371995-03-15 11:26:05 +0000942
Fred Drakea39a25e1996-09-13 14:44:34 +0000943 def do_subsection(self, args):
944 self.heading('H2', args, 2)
Fred Drake02827261996-10-09 19:05:12 +0000945 self.popstack(3)
Fred Drakea39a25e1996-09-13 14:44:34 +0000946 def do_unnumberedsubsec(self, args):
947 self.heading('H2', args, -1)
Fred Drake02827261996-10-09 19:05:12 +0000948 self.popstack(3)
Fred Drakea39a25e1996-09-13 14:44:34 +0000949 def do_appendixsubsec(self, args):
950 self.heading('H2', args, -1)
Fred Drake02827261996-10-09 19:05:12 +0000951 self.popstack(3)
Fred Drakea39a25e1996-09-13 14:44:34 +0000952 def do_subheading(self, args):
953 self.heading('H2', args, -1)
Guido van Rossum26a9d371995-03-15 11:26:05 +0000954
Fred Drakea39a25e1996-09-13 14:44:34 +0000955 def do_subsubsection(self, args):
956 self.heading('H3', args, 3)
Fred Drake02827261996-10-09 19:05:12 +0000957 self.popstack(4)
Fred Drakea39a25e1996-09-13 14:44:34 +0000958 def do_unnumberedsubsubsec(self, args):
959 self.heading('H3', args, -1)
Fred Drake02827261996-10-09 19:05:12 +0000960 self.popstack(4)
Fred Drakea39a25e1996-09-13 14:44:34 +0000961 def do_appendixsubsubsec(self, args):
962 self.heading('H3', args, -1)
Fred Drake02827261996-10-09 19:05:12 +0000963 self.popstack(4)
Fred Drakea39a25e1996-09-13 14:44:34 +0000964 def do_subsubheading(self, args):
965 self.heading('H3', args, -1)
Guido van Rossum26a9d371995-03-15 11:26:05 +0000966
Fred Drakea39a25e1996-09-13 14:44:34 +0000967 def heading(self, type, args, level):
968 if level >= 0:
969 while len(self.numbering) <= level:
970 self.numbering.append(0)
971 del self.numbering[level+1:]
972 self.numbering[level] = self.numbering[level] + 1
973 x = ''
974 for i in self.numbering:
975 x = x + `i` + '.'
976 args = x + ' ' + args
977 self.contents.append(level, args, self.nodename)
978 self.write('<', type, '>')
979 self.expand(args)
980 self.write('</', type, '>\n')
Fred Drake02827261996-10-09 19:05:12 +0000981 if self.debugging or self.print_headers:
Fred Drakea39a25e1996-09-13 14:44:34 +0000982 print '---', args
Guido van Rossum26a9d371995-03-15 11:26:05 +0000983
Fred Drakea39a25e1996-09-13 14:44:34 +0000984 def do_contents(self, args):
985 # pass
986 self.listcontents('Table of Contents', 999)
Guido van Rossum26a9d371995-03-15 11:26:05 +0000987
Fred Drakea39a25e1996-09-13 14:44:34 +0000988 def do_shortcontents(self, args):
989 pass
990 # self.listcontents('Short Contents', 0)
991 do_summarycontents = do_shortcontents
Guido van Rossuma12bbff1995-05-03 14:17:36 +0000992
Fred Drakea39a25e1996-09-13 14:44:34 +0000993 def listcontents(self, title, maxlevel):
994 self.write('<H1>', title, '</H1>\n<UL COMPACT PLAIN>\n')
995 prevlevels = [0]
996 for level, title, node in self.contents:
997 if level > maxlevel:
998 continue
999 if level > prevlevels[-1]:
1000 # can only advance one level at a time
1001 self.write(' '*prevlevels[-1], '<UL PLAIN>\n')
1002 prevlevels.append(level)
1003 elif level < prevlevels[-1]:
1004 # might drop back multiple levels
1005 while level < prevlevels[-1]:
1006 del prevlevels[-1]
1007 self.write(' '*prevlevels[-1],
1008 '</UL>\n')
1009 self.write(' '*level, '<LI> <A HREF="',
1010 makefile(node), '">')
1011 self.expand(title)
1012 self.write('</A>\n')
1013 self.write('</UL>\n' * len(prevlevels))
Guido van Rossum06f42891995-08-28 03:01:00 +00001014
Fred Drakea39a25e1996-09-13 14:44:34 +00001015 # --- Page lay-out ---
Guido van Rossum06f42891995-08-28 03:01:00 +00001016
Fred Drakea39a25e1996-09-13 14:44:34 +00001017 # These commands are only meaningful in printed text
Guido van Rossum26a9d371995-03-15 11:26:05 +00001018
Fred Drakea39a25e1996-09-13 14:44:34 +00001019 def do_page(self, args): pass
Guido van Rossum26a9d371995-03-15 11:26:05 +00001020
Fred Drakea39a25e1996-09-13 14:44:34 +00001021 def do_need(self, args): pass
Guido van Rossum26a9d371995-03-15 11:26:05 +00001022
Fred Drakea39a25e1996-09-13 14:44:34 +00001023 def bgn_group(self, args): pass
1024 def end_group(self): pass
Guido van Rossum26a9d371995-03-15 11:26:05 +00001025
Fred Drakea39a25e1996-09-13 14:44:34 +00001026 # --- Line lay-out ---
Guido van Rossum26a9d371995-03-15 11:26:05 +00001027
Fred Drakea39a25e1996-09-13 14:44:34 +00001028 def do_sp(self, args):
Fred Drake02827261996-10-09 19:05:12 +00001029 if self.nofill:
1030 self.write('\n')
Fred Drakea39a25e1996-09-13 14:44:34 +00001031 else:
Fred Drake02827261996-10-09 19:05:12 +00001032 self.write('<P>\n')
Guido van Rossum26a9d371995-03-15 11:26:05 +00001033
Fred Drakea39a25e1996-09-13 14:44:34 +00001034 def do_hline(self, args):
Fred Drake02827261996-10-09 19:05:12 +00001035 self.write('<HR>')
Guido van Rossum26a9d371995-03-15 11:26:05 +00001036
Fred Drakea39a25e1996-09-13 14:44:34 +00001037 # --- Function and variable definitions ---
Guido van Rossum26a9d371995-03-15 11:26:05 +00001038
Fred Drakea39a25e1996-09-13 14:44:34 +00001039 def bgn_deffn(self, args):
1040 self.write('<DL>')
Fred Drake02827261996-10-09 19:05:12 +00001041 self.do_deffnx(args)
Guido van Rossum26a9d371995-03-15 11:26:05 +00001042
Fred Drakea39a25e1996-09-13 14:44:34 +00001043 def end_deffn(self):
1044 self.write('</DL>\n')
Guido van Rossum26a9d371995-03-15 11:26:05 +00001045
Fred Drakea39a25e1996-09-13 14:44:34 +00001046 def do_deffnx(self, args):
1047 self.write('<DT>')
1048 words = splitwords(args, 2)
1049 [category, name], rest = words[:2], words[2:]
Fred Drake02827261996-10-09 19:05:12 +00001050 self.expand('@b{%s}' % name)
Fred Drakea39a25e1996-09-13 14:44:34 +00001051 for word in rest: self.expand(' ' + makevar(word))
Fred Drake02827261996-10-09 19:05:12 +00001052 #self.expand(' -- ' + category)
1053 self.write('\n<DD>')
Fred Drakea39a25e1996-09-13 14:44:34 +00001054 self.index('fn', name)
Guido van Rossum26a9d371995-03-15 11:26:05 +00001055
Fred Drakea39a25e1996-09-13 14:44:34 +00001056 def bgn_defun(self, args): self.bgn_deffn('Function ' + args)
1057 end_defun = end_deffn
1058 def do_defunx(self, args): self.do_deffnx('Function ' + args)
Guido van Rossum26a9d371995-03-15 11:26:05 +00001059
Fred Drakea39a25e1996-09-13 14:44:34 +00001060 def bgn_defmac(self, args): self.bgn_deffn('Macro ' + args)
1061 end_defmac = end_deffn
1062 def do_defmacx(self, args): self.do_deffnx('Macro ' + args)
Guido van Rossum06f42891995-08-28 03:01:00 +00001063
Fred Drakea39a25e1996-09-13 14:44:34 +00001064 def bgn_defspec(self, args): self.bgn_deffn('{Special Form} ' + args)
1065 end_defspec = end_deffn
1066 def do_defspecx(self, args): self.do_deffnx('{Special Form} ' + args)
Guido van Rossum06f42891995-08-28 03:01:00 +00001067
Fred Drakea39a25e1996-09-13 14:44:34 +00001068 def bgn_defvr(self, args):
1069 self.write('<DL>')
Fred Drake02827261996-10-09 19:05:12 +00001070 self.do_defvrx(args)
Guido van Rossum26a9d371995-03-15 11:26:05 +00001071
Fred Drakea39a25e1996-09-13 14:44:34 +00001072 end_defvr = end_deffn
Guido van Rossum06f42891995-08-28 03:01:00 +00001073
Fred Drakea39a25e1996-09-13 14:44:34 +00001074 def do_defvrx(self, args):
1075 self.write('<DT>')
1076 words = splitwords(args, 2)
1077 [category, name], rest = words[:2], words[2:]
Fred Drake02827261996-10-09 19:05:12 +00001078 self.expand('@code{%s}' % name)
Fred Drakea39a25e1996-09-13 14:44:34 +00001079 # If there are too many arguments, show them
1080 for word in rest: self.expand(' ' + word)
Fred Drake02827261996-10-09 19:05:12 +00001081 #self.expand(' -- ' + category)
1082 self.write('\n<DD>')
Fred Drakea39a25e1996-09-13 14:44:34 +00001083 self.index('vr', name)
Guido van Rossum26a9d371995-03-15 11:26:05 +00001084
Fred Drakea39a25e1996-09-13 14:44:34 +00001085 def bgn_defvar(self, args): self.bgn_defvr('Variable ' + args)
1086 end_defvar = end_defvr
1087 def do_defvarx(self, args): self.do_defvrx('Variable ' + args)
Guido van Rossum26a9d371995-03-15 11:26:05 +00001088
Fred Drakea39a25e1996-09-13 14:44:34 +00001089 def bgn_defopt(self, args): self.bgn_defvr('{User Option} ' + args)
1090 end_defopt = end_defvr
1091 def do_defoptx(self, args): self.do_defvrx('{User Option} ' + args)
Guido van Rossum26a9d371995-03-15 11:26:05 +00001092
Fred Drakea39a25e1996-09-13 14:44:34 +00001093 # --- Ditto for typed languages ---
Guido van Rossum26a9d371995-03-15 11:26:05 +00001094
Fred Drakea39a25e1996-09-13 14:44:34 +00001095 def bgn_deftypefn(self, args):
1096 self.write('<DL>')
Fred Drake02827261996-10-09 19:05:12 +00001097 self.do_deftypefnx(args)
Guido van Rossum26a9d371995-03-15 11:26:05 +00001098
Fred Drakea39a25e1996-09-13 14:44:34 +00001099 end_deftypefn = end_deffn
Guido van Rossum26a9d371995-03-15 11:26:05 +00001100
Fred Drakea39a25e1996-09-13 14:44:34 +00001101 def do_deftypefnx(self, args):
1102 self.write('<DT>')
1103 words = splitwords(args, 3)
1104 [category, datatype, name], rest = words[:3], words[3:]
Fred Drake02827261996-10-09 19:05:12 +00001105 self.expand('@code{%s} @b{%s}' % (datatype, name))
Fred Drakea39a25e1996-09-13 14:44:34 +00001106 for word in rest: self.expand(' ' + makevar(word))
Fred Drake02827261996-10-09 19:05:12 +00001107 #self.expand(' -- ' + category)
1108 self.write('\n<DD>')
Fred Drakea39a25e1996-09-13 14:44:34 +00001109 self.index('fn', name)
Guido van Rossum26a9d371995-03-15 11:26:05 +00001110
Guido van Rossum26a9d371995-03-15 11:26:05 +00001111
Fred Drakea39a25e1996-09-13 14:44:34 +00001112 def bgn_deftypefun(self, args): self.bgn_deftypefn('Function ' + args)
1113 end_deftypefun = end_deftypefn
1114 def do_deftypefunx(self, args): self.do_deftypefnx('Function ' + args)
Guido van Rossum26a9d371995-03-15 11:26:05 +00001115
Fred Drakea39a25e1996-09-13 14:44:34 +00001116 def bgn_deftypevr(self, args):
1117 self.write('<DL>')
Fred Drake02827261996-10-09 19:05:12 +00001118 self.do_deftypevrx(args)
Guido van Rossum26a9d371995-03-15 11:26:05 +00001119
Fred Drakea39a25e1996-09-13 14:44:34 +00001120 end_deftypevr = end_deftypefn
Guido van Rossum26a9d371995-03-15 11:26:05 +00001121
Fred Drakea39a25e1996-09-13 14:44:34 +00001122 def do_deftypevrx(self, args):
1123 self.write('<DT>')
1124 words = splitwords(args, 3)
1125 [category, datatype, name], rest = words[:3], words[3:]
Fred Drake02827261996-10-09 19:05:12 +00001126 self.expand('@code{%s} @b{%s}' % (datatype, name))
Fred Drakea39a25e1996-09-13 14:44:34 +00001127 # If there are too many arguments, show them
1128 for word in rest: self.expand(' ' + word)
Fred Drake02827261996-10-09 19:05:12 +00001129 #self.expand(' -- ' + category)
1130 self.write('\n<DD>')
Fred Drakea39a25e1996-09-13 14:44:34 +00001131 self.index('fn', name)
Guido van Rossum26a9d371995-03-15 11:26:05 +00001132
Fred Drakea39a25e1996-09-13 14:44:34 +00001133 def bgn_deftypevar(self, args):
1134 self.bgn_deftypevr('Variable ' + args)
1135 end_deftypevar = end_deftypevr
1136 def do_deftypevarx(self, args):
1137 self.do_deftypevrx('Variable ' + args)
Guido van Rossum26a9d371995-03-15 11:26:05 +00001138
Fred Drakea39a25e1996-09-13 14:44:34 +00001139 # --- Ditto for object-oriented languages ---
Guido van Rossum26a9d371995-03-15 11:26:05 +00001140
Fred Drakea39a25e1996-09-13 14:44:34 +00001141 def bgn_defcv(self, args):
1142 self.write('<DL>')
1143 self.do_defcvx(args)
Guido van Rossum26a9d371995-03-15 11:26:05 +00001144
Fred Drakea39a25e1996-09-13 14:44:34 +00001145 end_defcv = end_deftypevr
Guido van Rossum26a9d371995-03-15 11:26:05 +00001146
Fred Drakea39a25e1996-09-13 14:44:34 +00001147 def do_defcvx(self, args):
1148 self.write('<DT>')
1149 words = splitwords(args, 3)
1150 [category, classname, name], rest = words[:3], words[3:]
Fred Drake02827261996-10-09 19:05:12 +00001151 self.expand('@b{%s}' % name)
Fred Drakea39a25e1996-09-13 14:44:34 +00001152 # If there are too many arguments, show them
1153 for word in rest: self.expand(' ' + word)
Fred Drake02827261996-10-09 19:05:12 +00001154 #self.expand(' -- %s of @code{%s}' % (category, classname))
1155 self.write('\n<DD>')
1156 self.index('vr', '%s @r{on %s}' % (name, classname))
Guido van Rossum26a9d371995-03-15 11:26:05 +00001157
Fred Drakea39a25e1996-09-13 14:44:34 +00001158 def bgn_defivar(self, args):
1159 self.bgn_defcv('{Instance Variable} ' + args)
1160 end_defivar = end_defcv
1161 def do_defivarx(self, args):
1162 self.do_defcvx('{Instance Variable} ' + args)
Guido van Rossuma12bbff1995-05-03 14:17:36 +00001163
Fred Drakea39a25e1996-09-13 14:44:34 +00001164 def bgn_defop(self, args):
1165 self.write('<DL>')
Fred Drake02827261996-10-09 19:05:12 +00001166 self.do_defopx(args)
Guido van Rossum26a9d371995-03-15 11:26:05 +00001167
Fred Drakea39a25e1996-09-13 14:44:34 +00001168 end_defop = end_defcv
Guido van Rossum26a9d371995-03-15 11:26:05 +00001169
Fred Drakea39a25e1996-09-13 14:44:34 +00001170 def do_defopx(self, args):
1171 self.write('<DT>')
1172 words = splitwords(args, 3)
1173 [category, classname, name], rest = words[:3], words[3:]
Fred Drake02827261996-10-09 19:05:12 +00001174 self.expand('@b{%s}' % name)
Fred Drakea39a25e1996-09-13 14:44:34 +00001175 for word in rest: self.expand(' ' + makevar(word))
Fred Drake02827261996-10-09 19:05:12 +00001176 #self.expand(' -- %s of @code{%s}' % (category, classname))
1177 self.write('\n<DD>')
1178 self.index('fn', '%s @r{on %s}' % (name, classname))
Guido van Rossum26a9d371995-03-15 11:26:05 +00001179
Fred Drakea39a25e1996-09-13 14:44:34 +00001180 def bgn_defmethod(self, args):
1181 self.bgn_defop('Method ' + args)
1182 end_defmethod = end_defop
1183 def do_defmethodx(self, args):
1184 self.do_defopx('Method ' + args)
Guido van Rossum26a9d371995-03-15 11:26:05 +00001185
Fred Drakea39a25e1996-09-13 14:44:34 +00001186 # --- Ditto for data types ---
Guido van Rossum26a9d371995-03-15 11:26:05 +00001187
Fred Drakea39a25e1996-09-13 14:44:34 +00001188 def bgn_deftp(self, args):
1189 self.write('<DL>')
1190 self.do_deftpx(args)
Guido van Rossum06f42891995-08-28 03:01:00 +00001191
Fred Drakea39a25e1996-09-13 14:44:34 +00001192 end_deftp = end_defcv
Guido van Rossum06f42891995-08-28 03:01:00 +00001193
Fred Drakea39a25e1996-09-13 14:44:34 +00001194 def do_deftpx(self, args):
1195 self.write('<DT>')
1196 words = splitwords(args, 2)
1197 [category, name], rest = words[:2], words[2:]
Fred Drake02827261996-10-09 19:05:12 +00001198 self.expand('@b{%s}' % name)
Fred Drakea39a25e1996-09-13 14:44:34 +00001199 for word in rest: self.expand(' ' + word)
Fred Drake02827261996-10-09 19:05:12 +00001200 #self.expand(' -- ' + category)
1201 self.write('\n<DD>')
Fred Drakea39a25e1996-09-13 14:44:34 +00001202 self.index('tp', name)
Guido van Rossum26a9d371995-03-15 11:26:05 +00001203
Fred Drakea39a25e1996-09-13 14:44:34 +00001204 # --- Making Lists and Tables
Guido van Rossum26a9d371995-03-15 11:26:05 +00001205
Fred Drakea39a25e1996-09-13 14:44:34 +00001206 def bgn_enumerate(self, args):
1207 if not args:
1208 self.write('<OL>\n')
1209 self.stackinfo[len(self.stack)] = '</OL>\n'
1210 else:
1211 self.itemnumber = args
1212 self.write('<UL>\n')
1213 self.stackinfo[len(self.stack)] = '</UL>\n'
1214 def end_enumerate(self):
1215 self.itemnumber = None
1216 self.write(self.stackinfo[len(self.stack) + 1])
1217 del self.stackinfo[len(self.stack) + 1]
Guido van Rossum26a9d371995-03-15 11:26:05 +00001218
Fred Drakea39a25e1996-09-13 14:44:34 +00001219 def bgn_itemize(self, args):
1220 self.itemarg = args
1221 self.write('<UL>\n')
1222 def end_itemize(self):
1223 self.itemarg = None
1224 self.write('</UL>\n')
Guido van Rossum26a9d371995-03-15 11:26:05 +00001225
Fred Drakea39a25e1996-09-13 14:44:34 +00001226 def bgn_table(self, args):
1227 self.itemarg = args
1228 self.write('<DL>\n')
1229 def end_table(self):
1230 self.itemarg = None
1231 self.write('</DL>\n')
Guido van Rossum26a9d371995-03-15 11:26:05 +00001232
Fred Drakea39a25e1996-09-13 14:44:34 +00001233 def bgn_ftable(self, args):
1234 self.itemindex = 'fn'
1235 self.bgn_table(args)
1236 def end_ftable(self):
1237 self.itemindex = None
1238 self.end_table()
Guido van Rossum26a9d371995-03-15 11:26:05 +00001239
Fred Drakea39a25e1996-09-13 14:44:34 +00001240 def do_item(self, args):
1241 if self.itemindex: self.index(self.itemindex, args)
1242 if self.itemarg:
1243 if self.itemarg[0] == '@' and self.itemarg[1:2] and \
1244 self.itemarg[1] in string.letters:
1245 args = self.itemarg + '{' + args + '}'
1246 else:
1247 # some other character, e.g. '-'
1248 args = self.itemarg + ' ' + args
1249 if self.itemnumber <> None:
1250 args = self.itemnumber + '. ' + args
1251 self.itemnumber = increment(self.itemnumber)
1252 if self.stack and self.stack[-1] == 'table':
1253 self.write('<DT>')
1254 self.expand(args)
Fred Drake02827261996-10-09 19:05:12 +00001255 self.write('\n<DD>')
Fred Drakea39a25e1996-09-13 14:44:34 +00001256 else:
1257 self.write('<LI>')
1258 self.expand(args)
1259 self.write(' ')
1260 do_itemx = do_item # XXX Should suppress leading blank line
Guido van Rossum26a9d371995-03-15 11:26:05 +00001261
Fred Drakea39a25e1996-09-13 14:44:34 +00001262 # --- Enumerations, displays, quotations ---
1263 # XXX Most of these should increase the indentation somehow
Guido van Rossum26a9d371995-03-15 11:26:05 +00001264
Fred Drakea39a25e1996-09-13 14:44:34 +00001265 def bgn_quotation(self, args): self.write('<BLOCKQUOTE>')
1266 def end_quotation(self): self.write('</BLOCKQUOTE>\n')
Guido van Rossum26a9d371995-03-15 11:26:05 +00001267
Fred Drakea39a25e1996-09-13 14:44:34 +00001268 def bgn_example(self, args):
1269 self.nofill = self.nofill + 1
1270 self.write('<PRE>')
1271 def end_example(self):
Fred Drakeabcb3821996-10-25 22:13:59 +00001272 self.write('</PRE>\n')
Fred Drakea39a25e1996-09-13 14:44:34 +00001273 self.nofill = self.nofill - 1
Guido van Rossum26a9d371995-03-15 11:26:05 +00001274
Fred Drakea39a25e1996-09-13 14:44:34 +00001275 bgn_lisp = bgn_example # Synonym when contents are executable lisp code
1276 end_lisp = end_example
Guido van Rossum26a9d371995-03-15 11:26:05 +00001277
Fred Drakea39a25e1996-09-13 14:44:34 +00001278 bgn_smallexample = bgn_example # XXX Should use smaller font
1279 end_smallexample = end_example
Guido van Rossum26a9d371995-03-15 11:26:05 +00001280
Fred Drakea39a25e1996-09-13 14:44:34 +00001281 bgn_smalllisp = bgn_lisp # Ditto
1282 end_smalllisp = end_lisp
Guido van Rossum26a9d371995-03-15 11:26:05 +00001283
Fred Drakea39a25e1996-09-13 14:44:34 +00001284 bgn_display = bgn_example
1285 end_display = end_example
Guido van Rossum26a9d371995-03-15 11:26:05 +00001286
Fred Drakea39a25e1996-09-13 14:44:34 +00001287 bgn_format = bgn_display
1288 end_format = end_display
Guido van Rossum26a9d371995-03-15 11:26:05 +00001289
Fred Drakea39a25e1996-09-13 14:44:34 +00001290 def do_exdent(self, args): self.expand(args + '\n')
1291 # XXX Should really mess with indentation
Guido van Rossum26a9d371995-03-15 11:26:05 +00001292
Fred Drakea39a25e1996-09-13 14:44:34 +00001293 def bgn_flushleft(self, args):
1294 self.nofill = self.nofill + 1
1295 self.write('<PRE>\n')
1296 def end_flushleft(self):
1297 self.write('</PRE>\n')
1298 self.nofill = self.nofill - 1
Guido van Rossum26a9d371995-03-15 11:26:05 +00001299
Fred Drakea39a25e1996-09-13 14:44:34 +00001300 def bgn_flushright(self, args):
1301 self.nofill = self.nofill + 1
1302 self.write('<ADDRESS COMPACT>\n')
1303 def end_flushright(self):
1304 self.write('</ADDRESS>\n')
1305 self.nofill = self.nofill - 1
Guido van Rossum26a9d371995-03-15 11:26:05 +00001306
Fred Drakea39a25e1996-09-13 14:44:34 +00001307 def bgn_menu(self, args):
1308 self.write('<DIR>\n')
1309 self.write(' <STRONG><EM>Menu</EM></STRONG><P>\n')
Fred Drake02827261996-10-09 19:05:12 +00001310 def end_menu(self):
1311 self.write('</DIR>\n')
Guido van Rossum26a9d371995-03-15 11:26:05 +00001312
Fred Drakea39a25e1996-09-13 14:44:34 +00001313 def bgn_cartouche(self, args): pass
1314 def end_cartouche(self): pass
Guido van Rossum26a9d371995-03-15 11:26:05 +00001315
Fred Drakea39a25e1996-09-13 14:44:34 +00001316 # --- Indices ---
Guido van Rossum26a9d371995-03-15 11:26:05 +00001317
Fred Drakea39a25e1996-09-13 14:44:34 +00001318 def resetindex(self):
1319 self.noncodeindices = ['cp']
1320 self.indextitle = {}
1321 self.indextitle['cp'] = 'Concept'
1322 self.indextitle['fn'] = 'Function'
1323 self.indextitle['ky'] = 'Keyword'
1324 self.indextitle['pg'] = 'Program'
1325 self.indextitle['tp'] = 'Type'
1326 self.indextitle['vr'] = 'Variable'
1327 #
1328 self.whichindex = {}
1329 for name in self.indextitle.keys():
1330 self.whichindex[name] = []
Guido van Rossum26a9d371995-03-15 11:26:05 +00001331
Fred Drakea39a25e1996-09-13 14:44:34 +00001332 def user_index(self, name, args):
1333 if self.whichindex.has_key(name):
1334 self.index(name, args)
1335 else:
1336 print '*** No index named', `name`
Guido van Rossum26a9d371995-03-15 11:26:05 +00001337
Fred Drakea39a25e1996-09-13 14:44:34 +00001338 def do_cindex(self, args): self.index('cp', args)
1339 def do_findex(self, args): self.index('fn', args)
1340 def do_kindex(self, args): self.index('ky', args)
1341 def do_pindex(self, args): self.index('pg', args)
1342 def do_tindex(self, args): self.index('tp', args)
1343 def do_vindex(self, args): self.index('vr', args)
Guido van Rossum26a9d371995-03-15 11:26:05 +00001344
Fred Drakea39a25e1996-09-13 14:44:34 +00001345 def index(self, name, args):
1346 self.whichindex[name].append(args, self.nodename)
Guido van Rossum26a9d371995-03-15 11:26:05 +00001347
Fred Drakea39a25e1996-09-13 14:44:34 +00001348 def do_synindex(self, args):
1349 words = string.split(args)
1350 if len(words) <> 2:
1351 print '*** bad @synindex', args
1352 return
1353 [old, new] = words
1354 if not self.whichindex.has_key(old) or \
1355 not self.whichindex.has_key(new):
1356 print '*** bad key(s) in @synindex', args
1357 return
1358 if old <> new and \
1359 self.whichindex[old] is not self.whichindex[new]:
1360 inew = self.whichindex[new]
1361 inew[len(inew):] = self.whichindex[old]
1362 self.whichindex[old] = inew
1363 do_syncodeindex = do_synindex # XXX Should use code font
Guido van Rossum26a9d371995-03-15 11:26:05 +00001364
Fred Drakea39a25e1996-09-13 14:44:34 +00001365 def do_printindex(self, args):
1366 words = string.split(args)
1367 for name in words:
1368 if self.whichindex.has_key(name):
1369 self.prindex(name)
1370 else:
1371 print '*** No index named', `name`
Guido van Rossum26a9d371995-03-15 11:26:05 +00001372
Fred Drakea39a25e1996-09-13 14:44:34 +00001373 def prindex(self, name):
1374 iscodeindex = (name not in self.noncodeindices)
1375 index = self.whichindex[name]
1376 if not index: return
1377 if self.debugging:
1378 print '--- Generating', self.indextitle[name], 'index'
1379 # The node already provides a title
1380 index1 = []
1381 junkprog = regex.compile('^\(@[a-z]+\)?{')
1382 for key, node in index:
1383 sortkey = string.lower(key)
1384 # Remove leading `@cmd{' from sort key
1385 # -- don't bother about the matching `}'
1386 oldsortkey = sortkey
1387 while 1:
1388 i = junkprog.match(sortkey)
1389 if i < 0: break
1390 sortkey = sortkey[i:]
1391 index1.append(sortkey, key, node)
1392 del index[:]
1393 index1.sort()
1394 self.write('<DL COMPACT>\n')
1395 prevkey = prevnode = None
1396 for sortkey, key, node in index1:
1397 if (key, node) == (prevkey, prevnode):
1398 continue
1399 if self.debugging > 1: print key, ':', node
1400 self.write('<DT>')
1401 if iscodeindex: key = '@code{' + key + '}'
1402 if key != prevkey:
1403 self.expand(key)
Fred Drake02827261996-10-09 19:05:12 +00001404 self.write('\n<DD><A HREF="%s">%s</A>\n' % (makefile(node), node))
Fred Drakea39a25e1996-09-13 14:44:34 +00001405 prevkey, prevnode = key, node
1406 self.write('</DL>\n')
Guido van Rossum26a9d371995-03-15 11:26:05 +00001407
Fred Drakea39a25e1996-09-13 14:44:34 +00001408 # --- Final error reports ---
Guido van Rossum26a9d371995-03-15 11:26:05 +00001409
Fred Drakea39a25e1996-09-13 14:44:34 +00001410 def report(self):
1411 if self.unknown:
1412 print '--- Unrecognized commands ---'
1413 cmds = self.unknown.keys()
1414 cmds.sort()
1415 for cmd in cmds:
1416 print string.ljust(cmd, 20), self.unknown[cmd]
Guido van Rossum26a9d371995-03-15 11:26:05 +00001417
1418
Fred Drake02827261996-10-09 19:05:12 +00001419class TexinfoParserHTML3(TexinfoParser):
1420
1421 COPYRIGHT_SYMBOL = "&copy;"
1422 FN_ID_PATTERN = "[%(id)s]"
1423 FN_SOURCE_PATTERN = '<A ID=footnoteref%(id)s ' \
1424 'HREF="#footnotetext%(id)s">' + FN_ID_PATTERN + '</A>'
1425 FN_TARGET_PATTERN = '<FN ID=footnotetext%(id)s>\n' \
1426 '<P><A HREF="#footnoteref%(id)s">' + FN_ID_PATTERN \
1427 + '</A>\n%(text)s</P></FN>\n'
1428 FN_HEADER = '<DIV CLASS=footnotes>\n <HR NOSHADE WIDTH=200>\n' \
1429 ' <STRONG><EM>Footnotes</EM></STRONG>\n <P>\n'
1430
1431 Node = HTML3Node
1432
1433 def bgn_quotation(self, args): self.write('<BQ>')
1434 def end_quotation(self): self.write('</BQ>\n')
1435
1436 def bgn_example(self, args):
Fred Drakeabcb3821996-10-25 22:13:59 +00001437 # this use of <CODE> would not be legal in HTML 2.0,
1438 # but is in more recent DTDs.
Fred Drake02827261996-10-09 19:05:12 +00001439 self.nofill = self.nofill + 1
Fred Drakeabcb3821996-10-25 22:13:59 +00001440 self.write('<PRE CLASS=example><CODE>')
1441 def end_example(self):
1442 self.write("</CODE></PRE>\n")
1443 self.nofill = self.nofill - 1
Fred Drake02827261996-10-09 19:05:12 +00001444
1445 def bgn_flushleft(self, args):
1446 self.nofill = self.nofill + 1
1447 self.write('<PRE CLASS=flushleft>\n')
1448
1449 def bgn_flushright(self, args):
1450 self.nofill = self.nofill + 1
1451 self.write('<DIV ALIGN=right CLASS=flushright><ADDRESS COMPACT>\n')
1452 def end_flushright(self):
1453 self.write('</ADDRESS></DIV>\n')
1454 self.nofill = self.nofill - 1
1455
1456 def bgn_menu(self, args):
1457 self.write('<UL PLAIN CLASS=menu>\n')
1458 self.write(' <LH>Menu</LH>\n')
1459 def end_menu(self):
1460 self.write('</UL>\n')
1461
1462
Guido van Rossum26a9d371995-03-15 11:26:05 +00001463# Put @var{} around alphabetic substrings
1464def makevar(str):
Fred Drakea39a25e1996-09-13 14:44:34 +00001465 return '@var{'+str+'}'
Guido van Rossum26a9d371995-03-15 11:26:05 +00001466
1467
1468# Split a string in "words" according to findwordend
1469def splitwords(str, minlength):
Fred Drakea39a25e1996-09-13 14:44:34 +00001470 words = []
1471 i = 0
1472 n = len(str)
1473 while i < n:
1474 while i < n and str[i] in ' \t\n': i = i+1
1475 if i >= n: break
1476 start = i
1477 i = findwordend(str, i, n)
1478 words.append(str[start:i])
1479 while len(words) < minlength: words.append('')
1480 return words
Guido van Rossum26a9d371995-03-15 11:26:05 +00001481
1482
1483# Find the end of a "word", matching braces and interpreting @@ @{ @}
1484fwprog = regex.compile('[@{} ]')
1485def findwordend(str, i, n):
Fred Drakea39a25e1996-09-13 14:44:34 +00001486 level = 0
1487 while i < n:
1488 i = fwprog.search(str, i)
1489 if i < 0: break
1490 c = str[i]; i = i+1
1491 if c == '@': i = i+1 # Next character is not special
1492 elif c == '{': level = level+1
1493 elif c == '}': level = level-1
1494 elif c == ' ' and level <= 0: return i-1
1495 return n
Guido van Rossum26a9d371995-03-15 11:26:05 +00001496
1497
1498# Convert a node name into a file name
1499def makefile(nodename):
Fred Drakea39a25e1996-09-13 14:44:34 +00001500 return fixfunnychars(nodename) + '.html'
Guido van Rossum26a9d371995-03-15 11:26:05 +00001501
1502
1503# Characters that are perfectly safe in filenames and hyperlinks
Guido van Rossum06f42891995-08-28 03:01:00 +00001504goodchars = string.letters + string.digits + '!@-=+.'
Guido van Rossum26a9d371995-03-15 11:26:05 +00001505
Guido van Rossum06f42891995-08-28 03:01:00 +00001506# Replace characters that aren't perfectly safe by dashes
1507# Underscores are bad since Cern HTTPD treats them as delimiters for
1508# encoding times, so you get mismatches if you compress your files:
1509# a.html.gz will map to a_b.html.gz
Guido van Rossum26a9d371995-03-15 11:26:05 +00001510def fixfunnychars(addr):
Fred Drakea39a25e1996-09-13 14:44:34 +00001511 i = 0
1512 while i < len(addr):
1513 c = addr[i]
1514 if c not in goodchars:
1515 c = '-'
1516 addr = addr[:i] + c + addr[i+1:]
1517 i = i + len(c)
1518 return addr
Guido van Rossum26a9d371995-03-15 11:26:05 +00001519
1520
1521# Increment a string used as an enumeration
1522def increment(s):
Fred Drakea39a25e1996-09-13 14:44:34 +00001523 if not s:
1524 return '1'
1525 for sequence in string.digits, string.lowercase, string.uppercase:
1526 lastc = s[-1]
1527 if lastc in sequence:
1528 i = string.index(sequence, lastc) + 1
1529 if i >= len(sequence):
1530 if len(s) == 1:
1531 s = sequence[0]*2
1532 if s == '00':
1533 s = '10'
1534 else:
1535 s = increment(s[:-1]) + sequence[0]
1536 else:
1537 s = s[:-1] + sequence[i]
1538 return s
1539 return s # Don't increment
Guido van Rossum26a9d371995-03-15 11:26:05 +00001540
1541
1542def test():
Fred Drakea39a25e1996-09-13 14:44:34 +00001543 import sys
Fred Drake02827261996-10-09 19:05:12 +00001544 debugging = 0
1545 print_headers = 0
1546 cont = 0
1547 html3 = 0
1548
Fred Drakea39a25e1996-09-13 14:44:34 +00001549 while sys.argv[1:2] == ['-d']:
Fred Drake02827261996-10-09 19:05:12 +00001550 debugging = debugging + 1
Fred Drakea39a25e1996-09-13 14:44:34 +00001551 del sys.argv[1:2]
Fred Drake02827261996-10-09 19:05:12 +00001552 if sys.argv[1] == '-p':
1553 print_headers = 1
1554 del sys.argv[1]
Fred Drakea39a25e1996-09-13 14:44:34 +00001555 if sys.argv[1] == '-c':
Fred Drake02827261996-10-09 19:05:12 +00001556 cont = 1
1557 del sys.argv[1]
1558 if sys.argv[1] == '-3':
1559 html3 = 1
Fred Drakea39a25e1996-09-13 14:44:34 +00001560 del sys.argv[1]
1561 if len(sys.argv) <> 3:
Fred Drake02827261996-10-09 19:05:12 +00001562 print 'usage: texi2html [-d [-d]] [-p] [-c] inputfile outputdirectory'
Fred Drakea39a25e1996-09-13 14:44:34 +00001563 sys.exit(2)
Fred Drake02827261996-10-09 19:05:12 +00001564
1565 if html3:
1566 parser = TexinfoParserHTML3()
1567 else:
1568 parser = TexinfoParser()
1569 parser.cont = cont
1570 parser.debugging = debugging
1571 parser.print_headers = print_headers
1572
Fred Drakea39a25e1996-09-13 14:44:34 +00001573 file = sys.argv[1]
1574 parser.setdirname(sys.argv[2])
1575 if file == '-':
1576 fp = sys.stdin
1577 else:
1578 parser.setincludedir(os.path.dirname(file))
1579 try:
1580 fp = open(file, 'r')
1581 except IOError, msg:
1582 print file, ':', msg
1583 sys.exit(1)
1584 parser.parse(fp)
1585 fp.close()
1586 parser.report()
Guido van Rossum26a9d371995-03-15 11:26:05 +00001587
1588
Fred Drakea39a25e1996-09-13 14:44:34 +00001589if __name__ == "__main__":
1590 test()