/usr/lib64/python2.7/Tools/scripts
NameSizeModeActions
analyze_dxp.py42050755editdlrm
analyze_dxp.pyc47480644editdlrm
analyze_dxp.pyo47480644editdlrm
byext.py39440755editdlrm
byext.pyc45210644editdlrm
byext.pyo45210644editdlrm
byteyears.py16370755editdlrm
byteyears.pyc13980644editdlrm
byteyears.pyo13980644editdlrm
checkappend.py46570755editdlrm
checkappend.pyc48860644editdlrm
checkappend.pyo48860644editdlrm
checkpip.py7570755editdlrm
checkpip.pyc10440644editdlrm
checkpip.pyo10440644editdlrm
checkpyc.py20100755editdlrm
checkpyc.pyc19760644editdlrm
checkpyc.pyo19760644editdlrm
classfix.py59520755editdlrm
classfix.pyc41890644editdlrm
classfix.pyo41890644editdlrm
cleanfuture.py85770755editdlrm
cleanfuture.pyc73940644editdlrm
cleanfuture.pyo73610644editdlrm
combinerefs.py43800755editdlrm
combinerefs.pyc42560644editdlrm
combinerefs.pyo42230644editdlrm
copytime.py6630755editdlrm
copytime.pyc9370644editdlrm
copytime.pyo9370644editdlrm
crlf.py6100755editdlrm
crlf.pyc8550644editdlrm
crlf.pyo8550644editdlrm
cvsfiles.py17860755editdlrm
cvsfiles.pyc21630644editdlrm
cvsfiles.pyo21630644editdlrm
db2pickle.py35700755editdlrm
db2pickle.pyc34970644editdlrm
db2pickle.pyo34970644editdlrm
diff.py20660755editdlrm
diff.pyc23860644editdlrm
diff.pyo23860644editdlrm
dutree.py16150755editdlrm
dutree.pyc22300644editdlrm
dutree.pyo22300644editdlrm
eptags.py14830755editdlrm
eptags.pyc18760644editdlrm
eptags.pyo18760644editdlrm
finddiv.py25170755editdlrm
finddiv.pyc32960644editdlrm
finddiv.pyo32960644editdlrm
findlinksto.py10690755editdlrm
findlinksto.pyc14250644editdlrm
findlinksto.pyo14250644editdlrm
findnocoding.py28080755editdlrm
findnocoding.pyc32010644editdlrm
findnocoding.pyo32010644editdlrm
find_recursionlimit.py34730755editdlrm
find_recursionlimit.pyc56730644editdlrm
find_recursionlimit.pyo56730644editdlrm
fixcid.py99950755editdlrm
fixcid.pyc78510644editdlrm
fixcid.pyo78510644editdlrm
fixdiv.py138410755editdlrm
fixdiv.pyc138490644editdlrm
fixdiv.pyo137660644editdlrm
fixheader.py11890755editdlrm
fixheader.pyc14710644editdlrm
fixheader.pyo14710644editdlrm
fixnotice.py30510755editdlrm
fixnotice.pyc35000644editdlrm
fixnotice.pyo35000644editdlrm
fixps.py8930755editdlrm
fixps.pyc9690644editdlrm
fixps.pyo9690644editdlrm
google.py5190755editdlrm
google.pyc7920644editdlrm
google.pyo7920644editdlrm
gprof2html.py21670755editdlrm
gprof2html.pyc22770644editdlrm
gprof2html.pyo22770644editdlrm
h2py.py59530755editdlrm
h2py.pyc43920644editdlrm
h2py.pyo43920644editdlrm
hotshotmain.py14830755editdlrm
hotshotmain.pyc18630644editdlrm
hotshotmain.pyo18630644editdlrm
ifdef.py37180755editdlrm
ifdef.pyc22650644editdlrm
ifdef.pyo22650644editdlrm
lfcr.py6180755editdlrm
lfcr.pyc8800644editdlrm
lfcr.pyo8800644editdlrm
linktree.py24240755editdlrm
linktree.pyc20250644editdlrm
linktree.pyo20250644editdlrm
lll.py7420755editdlrm
lll.pyc9420644editdlrm
lll.pyo9420644editdlrm
logmerge.py55750755editdlrm
logmerge.pyc50830644editdlrm
logmerge.pyo50830644editdlrm
mailerdaemon.py79420755editdlrm
mailerdaemon.pyc73640644editdlrm
mailerdaemon.pyo73640644editdlrm
md5sum.py23850755editdlrm
md5sum.pyc29170644editdlrm
md5sum.pyo29170644editdlrm
methfix.py54620755editdlrm
methfix.pyc41250644editdlrm
methfix.pyo41250644editdlrm
mkreal.py16270755editdlrm
mkreal.pyc19800644editdlrm
mkreal.pyo19800644editdlrm
ndiff.py38080755editdlrm
ndiff.pyc38590644editdlrm
ndiff.pyo38590644editdlrm
nm2def.py24430755editdlrm
nm2def.pyc29600644editdlrm
nm2def.pyo29600644editdlrm
objgraph.py60170755editdlrm
objgraph.pyc49330644editdlrm
objgraph.pyo49330644editdlrm
parseentities.py17190755editdlrm
parseentities.pyc20770644editdlrm
parseentities.pyo20770644editdlrm
patchcheck.py76790755editdlrm
patchcheck.pyc91280644editdlrm
patchcheck.pyo91280644editdlrm
pathfix.py43290755editdlrm
pathfix.pyc38380644editdlrm
pathfix.pyo38380644editdlrm
pdeps.py39360755editdlrm
pdeps.pyc32200644editdlrm
pdeps.pyo32200644editdlrm
pickle2db.py39420755editdlrm
pickle2db.pyc38190644editdlrm
pickle2db.pyo38190644editdlrm
pindent.py171700755editdlrm
pindent.pyc115590644editdlrm
pindent.pyo115590644editdlrm
ptags.py12240755editdlrm
ptags.pyc14070644editdlrm
ptags.pyo14070644editdlrm
pysource.py38460755editdlrm
pysource.pyc40090644editdlrm
pysource.pyo40090644editdlrm
redemo.py57920755editdlrm
redemo.pyc52490644editdlrm
redemo.pyo52490644editdlrm
reindent-rst.py2780755editdlrm
reindent-rst.pyc4810644editdlrm
reindent-rst.pyo4810644editdlrm
reindent.py114170755editdlrm
reindent.pyc96290644editdlrm
reindent.pyo95900644editdlrm
rgrep.py14920755editdlrm
rgrep.pyc18810644editdlrm
rgrep.pyo18810644editdlrm
serve.py11470755editdlrm
serve.pyc15970644editdlrm
serve.pyo15970644editdlrm
setup.py4210644editdlrm
setup.pyc5480644editdlrm
setup.pyo5480644editdlrm
suff.py6210755editdlrm
suff.pyc9040644editdlrm
suff.pyo9040644editdlrm
svneol.py29300755editdlrm
svneol.pyc29040644editdlrm
svneol.pyo28250644editdlrm
texcheck.py92560644editdlrm
texcheck.pyc83760644editdlrm
texcheck.pyo83760644editdlrm
texi2html.py698250755editdlrm
texi2html.pyc833230644editdlrm
texi2html.pyo833230644editdlrm
treesync.py57830755editdlrm
treesync.pyc59900644editdlrm
treesync.pyo59900644editdlrm
untabify.py12150755editdlrm
untabify.pyc15830644editdlrm
untabify.pyo15830644editdlrm
which.py16300755editdlrm
which.pyc16320644editdlrm
which.pyo16320644editdlrm
win_add2path.py16200644editdlrm
win_add2path.pyc20690644editdlrm
win_add2path.pyo20690644editdlrm
xxci.py27970755editdlrm
xxci.pyc40170644editdlrm
xxci.pyo40170644editdlrm
Edit: /usr/lib64/python2.7/Tools/scripts/texi2html.py (69825B)
#! /usr/bin/python2.7 # Convert GNU texinfo files into HTML, one file per node. # Based on Texinfo 2.14. # Usage: texi2html [-d] [-d] [-c] inputfile outputdirectory # The input file must be a complete texinfo file, e.g. emacs.texi. # This creates many files (one per info node) in the output directory, # overwriting existing files of the same name. All files created have # ".html" as their extension. # XXX To do: # - handle @comment*** correctly # - handle @xref {some words} correctly # - handle @ftable correctly (items aren't indexed?) # - handle @itemx properly # - handle @exdent properly # - add links directly to the proper line from indices # - check against the definitive list of @-cmds; we still miss (among others): # - @defindex (hard) # - @c(omment) in the middle of a line (rarely used) # - @this* (not really needed, only used in headers anyway) # - @today{} (ever used outside title page?) # More consistent handling of chapters/sections/etc. # Lots of documentation # Many more options: # -top designate top node # -links customize which types of links are included # -split split at chapters or sections instead of nodes # -name Allow different types of filename handling. Non unix systems # will have problems with long node names # ... # Support the most recent texinfo version and take a good look at HTML 3.0 # More debugging output (customizable) and more flexible error handling # How about icons ? # rpyron 2002-05-07 # Robert Pyron # 1. BUGFIX: In function makefile(), strip blanks from the nodename. # This is necessary to match the behavior of parser.makeref() and # parser.do_node(). # 2. BUGFIX fixed KeyError in end_ifset (well, I may have just made # it go away, rather than fix it) # 3. BUGFIX allow @menu and menu items inside @ifset or @ifclear # 4. Support added for: # @uref URL reference # @image image file reference (see note below) # @multitable output an HTML table # @vtable # 5. Partial support for accents, to match MAKEINFO output # 6. I added a new command-line option, '-H basename', to specify # HTML Help output. This will cause three files to be created # in the current directory: # `basename`.hhp HTML Help Workshop project file # `basename`.hhc Contents file for the project # `basename`.hhk Index file for the project # When fed into HTML Help Workshop, the resulting file will be # named `basename`.chm. # 7. A new class, HTMLHelp, to accomplish item 6. # 8. Various calls to HTMLHelp functions. # A NOTE ON IMAGES: Just as 'outputdirectory' must exist before # running this program, all referenced images must already exist # in outputdirectory. import os import sys import string import re MAGIC = '\\input texinfo' cmprog = re.compile('^@([a-z]+)([ \t]|$)') # Command (line-oriented) blprog = re.compile('^[ \t]*$') # Blank line kwprog = re.compile('@[a-z]+') # Keyword (embedded, usually # with {} args) spprog = re.compile('[\n@{}&<>]') # Special characters in # running text # # menu item (Yuck!) miprog = re.compile('^\* ([^:]*):(:|[ \t]*([^\t,\n.]+)([^ \t\n]*))[ \t\n]*') # 0 1 1 2 3 34 42 0 # ----- ---------- --------- # -|----------------------------- # ----------------------------------------------------- class HTMLNode: """Some of the parser's functionality is separated into this class. A Node accumulates its contents, takes care of links to other Nodes and saves itself when it is finished and all links are resolved. """ DOCTYPE = '' type = 0 cont = '' epilogue = '\n' def __init__(self, dir, name, topname, title, next, prev, up): self.dirname = dir self.name = name if topname: self.topname = topname else: self.topname = name self.title = title self.next = next self.prev = prev self.up = up self.lines = [] def write(self, *lines): map(self.lines.append, lines) def flush(self): fp = open(self.dirname + '/' + makefile(self.name), 'w') fp.write(self.prologue) fp.write(self.text) fp.write(self.epilogue) fp.close() def link(self, label, nodename, rel=None, rev=None): if nodename: if nodename.lower() == '(dir)': addr = '../dir.html' title = '' else: addr = makefile(nodename) title = ' TITLE="%s"' % nodename self.write(label, ': ', nodename, ' \n') def finalize(self): length = len(self.lines) self.text = ''.join(self.lines) self.lines = [] self.open_links() self.output_links() self.close_links() links = ''.join(self.lines) self.lines = [] self.prologue = ( self.DOCTYPE + '\n\n' ' \n' ' ' + self.title + '\n' ' \n' ' \n' ' \n' '\n' + links) if length > 20: self.epilogue = '

\n%s\n' % links def open_links(self): self.write('


\n') def close_links(self): self.write('
\n') def output_links(self): if self.cont != self.next: self.link(' Cont', self.cont) self.link(' Next', self.next, rel='Next') self.link(' Prev', self.prev, rel='Previous') self.link(' Up', self.up, rel='Up') if self.name <> self.topname: self.link(' Top', self.topname) class HTML3Node(HTMLNode): DOCTYPE = '' def open_links(self): self.write('\n') class TexinfoParser: COPYRIGHT_SYMBOL = "©" FN_ID_PATTERN = "(%(id)s)" FN_SOURCE_PATTERN = '' \ + FN_ID_PATTERN + '' FN_TARGET_PATTERN = '' \ + FN_ID_PATTERN + '\n%(text)s

\n' FN_HEADER = '\n

\n


\n' \ 'Footnotes\n

' Node = HTMLNode # Initialize an instance def __init__(self): self.unknown = {} # statistics about unknown @-commands self.filenames = {} # Check for identical filenames self.debugging = 0 # larger values produce more output self.print_headers = 0 # always print headers? self.nodefp = None # open file we're writing to self.nodelineno = 0 # Linenumber relative to node self.links = None # Links from current node self.savetext = None # If not None, save text head instead self.savestack = [] # If not None, save text head instead self.htmlhelp = None # html help data self.dirname = 'tmp' # directory where files are created self.includedir = '.' # directory to search @include files self.nodename = '' # name of current node self.topname = '' # name of top node (first node seen) self.title = '' # title of this whole Texinfo tree self.resetindex() # Reset all indices self.contents = [] # Reset table of contents self.numbering = [] # Reset section numbering counters self.nofill = 0 # Normal operation: fill paragraphs self.values={'html': 1} # Names that should be parsed in ifset self.stackinfo={} # Keep track of state in the stack # XXX The following should be reset per node?! self.footnotes = [] # Reset list of footnotes self.itemarg = None # Reset command used by @item self.itemnumber = None # Reset number for @item in @enumerate self.itemindex = None # Reset item index name self.node = None self.nodestack = [] self.cont = 0 self.includedepth = 0 # Set htmlhelp helper class def sethtmlhelp(self, htmlhelp): self.htmlhelp = htmlhelp # Set (output) directory name def setdirname(self, dirname): self.dirname = dirname # Set include directory name def setincludedir(self, includedir): self.includedir = includedir # Parse the contents of an entire file def parse(self, fp): line = fp.readline() lineno = 1 while line and (line[0] == '%' or blprog.match(line)): line = fp.readline() lineno = lineno + 1 if line[:len(MAGIC)] <> MAGIC: raise SyntaxError, 'file does not begin with %r' % (MAGIC,) self.parserest(fp, lineno) # Parse the contents of a file, not expecting a MAGIC header def parserest(self, fp, initial_lineno): lineno = initial_lineno self.done = 0 self.skip = 0 self.stack = [] accu = [] while not self.done: line = fp.readline() self.nodelineno = self.nodelineno + 1 if not line: if accu: if not self.skip: self.process(accu) accu = [] if initial_lineno > 0: print '*** EOF before @bye' break lineno = lineno + 1 mo = cmprog.match(line) if mo: a, b = mo.span(1) cmd = line[a:b] if cmd in ('noindent', 'refill'): accu.append(line) else: if accu: if not self.skip: self.process(accu) accu = [] self.command(line, mo) elif blprog.match(line) and \ 'format' not in self.stack and \ 'example' not in self.stack: if accu: if not self.skip: self.process(accu) if self.nofill: self.write('\n') else: self.write('

\n') accu = [] else: # Append the line including trailing \n! accu.append(line) # if self.skip: print '*** Still skipping at the end' if self.stack: print '*** Stack not empty at the end' print '***', self.stack if self.includedepth == 0: while self.nodestack: self.nodestack[-1].finalize() self.nodestack[-1].flush() del self.nodestack[-1] # Start saving text in a buffer instead of writing it to a file def startsaving(self): if self.savetext <> None: self.savestack.append(self.savetext) # print '*** Recursively saving text, expect trouble' self.savetext = '' # Return the text saved so far and start writing to file again def collectsavings(self): savetext = self.savetext if len(self.savestack) > 0: self.savetext = self.savestack[-1] del self.savestack[-1] else: self.savetext = None return savetext or '' # Write text to file, or save it in a buffer, or ignore it def write(self, *args): try: text = ''.join(args) except: print args raise TypeError if self.savetext <> None: self.savetext = self.savetext + text elif self.nodefp: self.nodefp.write(text) elif self.node: self.node.write(text) # Complete the current node -- write footnotes and close file def endnode(self): if self.savetext <> None: print '*** Still saving text at end of node' dummy = self.collectsavings() if self.footnotes: self.writefootnotes() if self.nodefp: if self.nodelineno > 20: self.write('


\n') [name, next, prev, up] = self.nodelinks[:4] self.link('Next', next) self.link('Prev', prev) self.link('Up', up) if self.nodename <> self.topname: self.link('Top', self.topname) self.write('
\n') self.write('\n') self.nodefp.close() self.nodefp = None elif self.node: if not self.cont and \ (not self.node.type or \ (self.node.next and self.node.prev and self.node.up)): self.node.finalize() self.node.flush() else: self.nodestack.append(self.node) self.node = None self.nodename = '' # Process a list of lines, expanding embedded @-commands # This mostly distinguishes between menus and normal text def process(self, accu): if self.debugging > 1: print '!'*self.debugging, 'process:', self.skip, self.stack, if accu: print accu[0][:30], if accu[0][30:] or accu[1:]: print '...', print if self.inmenu(): # XXX should be done differently for line in accu: mo = miprog.match(line) if not mo: line = line.strip() + '\n' self.expand(line) continue bgn, end = mo.span(0) a, b = mo.span(1) c, d = mo.span(2) e, f = mo.span(3) g, h = mo.span(4) label = line[a:b] nodename = line[c:d] if nodename[0] == ':': nodename = label else: nodename = line[e:f] punct = line[g:h] self.write('
  • ', nodename, '', punct, '\n') self.htmlhelp.menuitem(nodename) self.expand(line[end:]) else: text = ''.join(accu) self.expand(text) # find 'menu' (we might be inside 'ifset' or 'ifclear') def inmenu(self): #if 'menu' in self.stack: # print 'inmenu :', self.skip, self.stack, self.stackinfo stack = self.stack while stack and stack[-1] in ('ifset','ifclear'): try: if self.stackinfo[len(stack)]: return 0 except KeyError: pass stack = stack[:-1] return (stack and stack[-1] == 'menu') # Write a string, expanding embedded @-commands def expand(self, text): stack = [] i = 0 n = len(text) while i < n: start = i mo = spprog.search(text, i) if mo: i = mo.start() else: self.write(text[start:]) break self.write(text[start:i]) c = text[i] i = i+1 if c == '\n': self.write('\n') continue if c == '<': self.write('<') continue if c == '>': self.write('>') continue if c == '&': self.write('&') continue if c == '{': stack.append('') continue if c == '}': if not stack: print '*** Unmatched }' self.write('}') continue cmd = stack[-1] del stack[-1] try: method = getattr(self, 'close_' + cmd) except AttributeError: self.unknown_close(cmd) continue method() continue if c <> '@': # Cannot happen unless spprog is changed raise RuntimeError, 'unexpected funny %r' % c start = i while i < n and text[i] in string.ascii_letters: i = i+1 if i == start: # @ plus non-letter: literal next character i = i+1 c = text[start:i] if c == ':': # `@:' means no extra space after # preceding `.', `?', `!' or `:' pass else: # `@.' means a sentence-ending period; # `@@', `@{', `@}' quote `@', `{', `}' self.write(c) continue cmd = text[start:i] if i < n and text[i] == '{': i = i+1 stack.append(cmd) try: method = getattr(self, 'open_' + cmd) except AttributeError: self.unknown_open(cmd) continue method() continue try: method = getattr(self, 'handle_' + cmd) except AttributeError: self.unknown_handle(cmd) continue method() if stack: print '*** Stack not empty at para:', stack # --- Handle unknown embedded @-commands --- def unknown_open(self, cmd): print '*** No open func for @' + cmd + '{...}' cmd = cmd + '{' self.write('@', cmd) if not self.unknown.has_key(cmd): self.unknown[cmd] = 1 else: self.unknown[cmd] = self.unknown[cmd] + 1 def unknown_close(self, cmd): print '*** No close func for @' + cmd + '{...}' cmd = '}' + cmd self.write('}') if not self.unknown.has_key(cmd): self.unknown[cmd] = 1 else: self.unknown[cmd] = self.unknown[cmd] + 1 def unknown_handle(self, cmd): print '*** No handler for @' + cmd self.write('@', cmd) if not self.unknown.has_key(cmd): self.unknown[cmd] = 1 else: self.unknown[cmd] = self.unknown[cmd] + 1 # XXX The following sections should be ordered as the texinfo docs # --- Embedded @-commands without {} argument list -- def handle_noindent(self): pass def handle_refill(self): pass # --- Include file handling --- def do_include(self, args): file = args file = os.path.join(self.includedir, file) try: fp = open(file, 'r') except IOError, msg: print '*** Can\'t open include file', repr(file) return print '!'*self.debugging, '--> file', repr(file) save_done = self.done save_skip = self.skip save_stack = self.stack self.includedepth = self.includedepth + 1 self.parserest(fp, 0) self.includedepth = self.includedepth - 1 fp.close() self.done = save_done self.skip = save_skip self.stack = save_stack print '!'*self.debugging, '<-- file', repr(file) # --- Special Insertions --- def open_dmn(self): pass def close_dmn(self): pass def open_dots(self): self.write('...') def close_dots(self): pass def open_bullet(self): pass def close_bullet(self): pass def open_TeX(self): self.write('TeX') def close_TeX(self): pass def handle_copyright(self): self.write(self.COPYRIGHT_SYMBOL) def open_copyright(self): self.write(self.COPYRIGHT_SYMBOL) def close_copyright(self): pass def open_minus(self): self.write('-') def close_minus(self): pass # --- Accents --- # rpyron 2002-05-07 # I would like to do at least as well as makeinfo when # it is producing HTML output: # # input output # @"o @"o umlaut accent # @'o 'o acute accent # @,{c} @,{c} cedilla accent # @=o @=o macron/overbar accent # @^o @^o circumflex accent # @`o `o grave accent # @~o @~o tilde accent # @dotaccent{o} @dotaccent{o} overdot accent # @H{o} @H{o} long Hungarian umlaut # @ringaccent{o} @ringaccent{o} ring accent # @tieaccent{oo} @tieaccent{oo} tie-after accent # @u{o} @u{o} breve accent # @ubaraccent{o} @ubaraccent{o} underbar accent # @udotaccent{o} @udotaccent{o} underdot accent # @v{o} @v{o} hacek or check accent # @exclamdown{} ¡ upside-down ! # @questiondown{} ¿ upside-down ? # @aa{},@AA{} å,Å a,A with circle # @ae{},@AE{} æ,Æ ae,AE ligatures # @dotless{i} @dotless{i} dotless i # @dotless{j} @dotless{j} dotless j # @l{},@L{} l/,L/ suppressed-L,l # @o{},@O{} ø,Ø O,o with slash # @oe{},@OE{} oe,OE oe,OE ligatures # @ss{} ß es-zet or sharp S # # The following character codes and approximations have been # copied from makeinfo's HTML output. def open_exclamdown(self): self.write('¡') # upside-down ! def close_exclamdown(self): pass def open_questiondown(self): self.write('¿') # upside-down ? def close_questiondown(self): pass def open_aa(self): self.write('å') # a with circle def close_aa(self): pass def open_AA(self): self.write('Å') # A with circle def close_AA(self): pass def open_ae(self): self.write('æ') # ae ligatures def close_ae(self): pass def open_AE(self): self.write('Æ') # AE ligatures def close_AE(self): pass def open_o(self): self.write('ø') # o with slash def close_o(self): pass def open_O(self): self.write('Ø') # O with slash def close_O(self): pass def open_ss(self): self.write('ß') # es-zet or sharp S def close_ss(self): pass def open_oe(self): self.write('oe') # oe ligatures def close_oe(self): pass def open_OE(self): self.write('OE') # OE ligatures def close_OE(self): pass def open_l(self): self.write('l/') # suppressed-l def close_l(self): pass def open_L(self): self.write('L/') # suppressed-L def close_L(self): pass # --- Special Glyphs for Examples --- def open_result(self): self.write('=>') def close_result(self): pass def open_expansion(self): self.write('==>') def close_expansion(self): pass def open_print(self): self.write('-|') def close_print(self): pass def open_error(self): self.write('error-->') def close_error(self): pass def open_equiv(self): self.write('==') def close_equiv(self): pass def open_point(self): self.write('-!-') def close_point(self): pass # --- Cross References --- def open_pxref(self): self.write('see ') self.startsaving() def close_pxref(self): self.makeref() def open_xref(self): self.write('See ') self.startsaving() def close_xref(self): self.makeref() def open_ref(self): self.startsaving() def close_ref(self): self.makeref() def open_inforef(self): self.write('See info file ') self.startsaving() def close_inforef(self): text = self.collectsavings() args = [s.strip() for s in text.split(',')] while len(args) < 3: args.append('') node = args[0] file = args[2] self.write('`', file, '\', node `', node, '\'') def makeref(self): text = self.collectsavings() args = [s.strip() for s in text.split(',')] while len(args) < 5: args.append('') nodename = label = args[0] if args[2]: label = args[2] file = args[3] title = args[4] href = makefile(nodename) if file: href = '../' + file + '/' + href self.write('', label, '') # rpyron 2002-05-07 uref support def open_uref(self): self.startsaving() def close_uref(self): text = self.collectsavings() args = [s.strip() for s in text.split(',')] while len(args) < 2: args.append('') href = args[0] label = args[1] if not label: label = href self.write('', label, '') # rpyron 2002-05-07 image support # GNU makeinfo producing HTML output tries `filename.png'; if # that does not exist, it tries `filename.jpg'. If that does # not exist either, it complains. GNU makeinfo does not handle # GIF files; however, I include GIF support here because # MySQL documentation uses GIF files. def open_image(self): self.startsaving() def close_image(self): self.makeimage() def makeimage(self): text = self.collectsavings() args = [s.strip() for s in text.split(',')] while len(args) < 5: args.append('') filename = args[0] width = args[1] height = args[2] alt = args[3] ext = args[4] # The HTML output will have a reference to the image # that is relative to the HTML output directory, # which is what 'filename' gives us. However, we need # to find it relative to our own current directory, # so we construct 'imagename'. imagelocation = self.dirname + '/' + filename if os.path.exists(imagelocation+'.png'): filename += '.png' elif os.path.exists(imagelocation+'.jpg'): filename += '.jpg' elif os.path.exists(imagelocation+'.gif'): # MySQL uses GIF files filename += '.gif' else: print "*** Cannot find image " + imagelocation #TODO: what is 'ext'? self.write('' ) self.htmlhelp.addimage(imagelocation) # --- Marking Words and Phrases --- # --- Other @xxx{...} commands --- def open_(self): pass # Used by {text enclosed in braces} def close_(self): pass open_asis = open_ close_asis = close_ def open_cite(self): self.write('') def close_cite(self): self.write('') def open_code(self): self.write('') def close_code(self): self.write('') def open_t(self): self.write('') def close_t(self): self.write('') def open_dfn(self): self.write('') def close_dfn(self): self.write('') def open_emph(self): self.write('') def close_emph(self): self.write('') def open_i(self): self.write('') def close_i(self): self.write('') def open_footnote(self): # if self.savetext <> None: # print '*** Recursive footnote -- expect weirdness' id = len(self.footnotes) + 1 self.write(self.FN_SOURCE_PATTERN % {'id': repr(id)}) self.startsaving() def close_footnote(self): id = len(self.footnotes) + 1 self.footnotes.append((id, self.collectsavings())) def writefootnotes(self): self.write(self.FN_HEADER) for id, text in self.footnotes: self.write(self.FN_TARGET_PATTERN % {'id': repr(id), 'text': text}) self.footnotes = [] def open_file(self): self.write('') def close_file(self): self.write('') def open_kbd(self): self.write('') def close_kbd(self): self.write('') def open_key(self): self.write('') def close_key(self): self.write('') def open_r(self): self.write('') def close_r(self): self.write('') def open_samp(self): self.write('`') def close_samp(self): self.write('\'') def open_sc(self): self.write('') def close_sc(self): self.write('') def open_strong(self): self.write('') def close_strong(self): self.write('') def open_b(self): self.write('') def close_b(self): self.write('') def open_var(self): self.write('') def close_var(self): self.write('') def open_w(self): self.write('') def close_w(self): self.write('') def open_url(self): self.startsaving() def close_url(self): text = self.collectsavings() self.write('', text, '') def open_email(self): self.startsaving() def close_email(self): text = self.collectsavings() self.write('', text, '') open_titlefont = open_ close_titlefont = close_ def open_small(self): pass def close_small(self): pass def command(self, line, mo): a, b = mo.span(1) cmd = line[a:b] args = line[b:].strip() if self.debugging > 1: print '!'*self.debugging, 'command:', self.skip, self.stack, \ '@' + cmd, args try: func = getattr(self, 'do_' + cmd) except AttributeError: try: func = getattr(self, 'bgn_' + cmd) except AttributeError: # don't complain if we are skipping anyway if not self.skip: self.unknown_cmd(cmd, args) return self.stack.append(cmd) func(args) return if not self.skip or cmd == 'end': func(args) def unknown_cmd(self, cmd, args): print '*** unknown', '@' + cmd, args if not self.unknown.has_key(cmd): self.unknown[cmd] = 1 else: self.unknown[cmd] = self.unknown[cmd] + 1 def do_end(self, args): words = args.split() if not words: print '*** @end w/o args' else: cmd = words[0] if not self.stack or self.stack[-1] <> cmd: print '*** @end', cmd, 'unexpected' else: del self.stack[-1] try: func = getattr(self, 'end_' + cmd) except AttributeError: self.unknown_end(cmd) return func() def unknown_end(self, cmd): cmd = 'end ' + cmd print '*** unknown', '@' + cmd if not self.unknown.has_key(cmd): self.unknown[cmd] = 1 else: self.unknown[cmd] = self.unknown[cmd] + 1 # --- Comments --- def do_comment(self, args): pass do_c = do_comment # --- Conditional processing --- def bgn_ifinfo(self, args): pass def end_ifinfo(self): pass def bgn_iftex(self, args): self.skip = self.skip + 1 def end_iftex(self): self.skip = self.skip - 1 def bgn_ignore(self, args): self.skip = self.skip + 1 def end_ignore(self): self.skip = self.skip - 1 def bgn_tex(self, args): self.skip = self.skip + 1 def end_tex(self): self.skip = self.skip - 1 def do_set(self, args): fields = args.split(' ') key = fields[0] if len(fields) == 1: value = 1 else: value = ' '.join(fields[1:]) self.values[key] = value def do_clear(self, args): self.values[args] = None def bgn_ifset(self, args): if args not in self.values.keys() \ or self.values[args] is None: self.skip = self.skip + 1 self.stackinfo[len(self.stack)] = 1 else: self.stackinfo[len(self.stack)] = 0 def end_ifset(self): try: if self.stackinfo[len(self.stack) + 1]: self.skip = self.skip - 1 del self.stackinfo[len(self.stack) + 1] except KeyError: print '*** end_ifset: KeyError :', len(self.stack) + 1 def bgn_ifclear(self, args): if args in self.values.keys() \ and self.values[args] is not None: self.skip = self.skip + 1 self.stackinfo[len(self.stack)] = 1 else: self.stackinfo[len(self.stack)] = 0 def end_ifclear(self): try: if self.stackinfo[len(self.stack) + 1]: self.skip = self.skip - 1 del self.stackinfo[len(self.stack) + 1] except KeyError: print '*** end_ifclear: KeyError :', len(self.stack) + 1 def open_value(self): self.startsaving() def close_value(self): key = self.collectsavings() if key in self.values.keys(): self.write(self.values[key]) else: print '*** Undefined value: ', key # --- Beginning a file --- do_finalout = do_comment do_setchapternewpage = do_comment do_setfilename = do_comment def do_settitle(self, args): self.startsaving() self.expand(args) self.title = self.collectsavings() def do_parskip(self, args): pass # --- Ending a file --- def do_bye(self, args): self.endnode() self.done = 1 # --- Title page --- def bgn_titlepage(self, args): self.skip = self.skip + 1 def end_titlepage(self): self.skip = self.skip - 1 def do_shorttitlepage(self, args): pass def do_center(self, args): # Actually not used outside title page... self.write('

    ') self.expand(args) self.write('

    \n') do_title = do_center do_subtitle = do_center do_author = do_center do_vskip = do_comment do_vfill = do_comment do_smallbook = do_comment do_paragraphindent = do_comment do_setchapternewpage = do_comment do_headings = do_comment do_footnotestyle = do_comment do_evenheading = do_comment do_evenfooting = do_comment do_oddheading = do_comment do_oddfooting = do_comment do_everyheading = do_comment do_everyfooting = do_comment # --- Nodes --- def do_node(self, args): self.endnode() self.nodelineno = 0 parts = [s.strip() for s in args.split(',')] while len(parts) < 4: parts.append('') self.nodelinks = parts [name, next, prev, up] = parts[:4] file = self.dirname + '/' + makefile(name) if self.filenames.has_key(file): print '*** Filename already in use: ', file else: if self.debugging: print '!'*self.debugging, '--- writing', file self.filenames[file] = 1 # self.nodefp = open(file, 'w') self.nodename = name if self.cont and self.nodestack: self.nodestack[-1].cont = self.nodename if not self.topname: self.topname = name title = name if self.title: title = title + ' -- ' + self.title self.node = self.Node(self.dirname, self.nodename, self.topname, title, next, prev, up) self.htmlhelp.addnode(self.nodename,next,prev,up,file) def link(self, label, nodename): if nodename: if nodename.lower() == '(dir)': addr = '../dir.html' else: addr = makefile(nodename) self.write(label, ': ', nodename, ' \n') # --- Sectioning commands --- def popstack(self, type): if (self.node): self.node.type = type while self.nodestack: if self.nodestack[-1].type > type: self.nodestack[-1].finalize() self.nodestack[-1].flush() del self.nodestack[-1] elif self.nodestack[-1].type == type: if not self.nodestack[-1].next: self.nodestack[-1].next = self.node.name if not self.node.prev: self.node.prev = self.nodestack[-1].name self.nodestack[-1].finalize() self.nodestack[-1].flush() del self.nodestack[-1] else: if type > 1 and not self.node.up: self.node.up = self.nodestack[-1].name break def do_chapter(self, args): self.heading('H1', args, 0) self.popstack(1) def do_unnumbered(self, args): self.heading('H1', args, -1) self.popstack(1) def do_appendix(self, args): self.heading('H1', args, -1) self.popstack(1) def do_top(self, args): self.heading('H1', args, -1) def do_chapheading(self, args): self.heading('H1', args, -1) def do_majorheading(self, args): self.heading('H1', args, -1) def do_section(self, args): self.heading('H1', args, 1) self.popstack(2) def do_unnumberedsec(self, args): self.heading('H1', args, -1) self.popstack(2) def do_appendixsec(self, args): self.heading('H1', args, -1) self.popstack(2) do_appendixsection = do_appendixsec def do_heading(self, args): self.heading('H1', args, -1) def do_subsection(self, args): self.heading('H2', args, 2) self.popstack(3) def do_unnumberedsubsec(self, args): self.heading('H2', args, -1) self.popstack(3) def do_appendixsubsec(self, args): self.heading('H2', args, -1) self.popstack(3) def do_subheading(self, args): self.heading('H2', args, -1) def do_subsubsection(self, args): self.heading('H3', args, 3) self.popstack(4) def do_unnumberedsubsubsec(self, args): self.heading('H3', args, -1) self.popstack(4) def do_appendixsubsubsec(self, args): self.heading('H3', args, -1) self.popstack(4) def do_subsubheading(self, args): self.heading('H3', args, -1) def heading(self, type, args, level): if level >= 0: while len(self.numbering) <= level: self.numbering.append(0) del self.numbering[level+1:] self.numbering[level] = self.numbering[level] + 1 x = '' for i in self.numbering: x = x + repr(i) + '.' args = x + ' ' + args self.contents.append((level, args, self.nodename)) self.write('<', type, '>') self.expand(args) self.write('\n') if self.debugging or self.print_headers: print '---', args def do_contents(self, args): # pass self.listcontents('Table of Contents', 999) def do_shortcontents(self, args): pass # self.listcontents('Short Contents', 0) do_summarycontents = do_shortcontents def listcontents(self, title, maxlevel): self.write('

    ', title, '

    \n
      \n') prevlevels = [0] for level, title, node in self.contents: if level > maxlevel: continue if level > prevlevels[-1]: # can only advance one level at a time self.write(' '*prevlevels[-1], '
        \n') prevlevels.append(level) elif level < prevlevels[-1]: # might drop back multiple levels while level < prevlevels[-1]: del prevlevels[-1] self.write(' '*prevlevels[-1], '
      \n') self.write(' '*level, '
    • ') self.expand(title) self.write('\n') self.write('
    \n' * len(prevlevels)) # --- Page lay-out --- # These commands are only meaningful in printed text def do_page(self, args): pass def do_need(self, args): pass def bgn_group(self, args): pass def end_group(self): pass # --- Line lay-out --- def do_sp(self, args): if self.nofill: self.write('\n') else: self.write('

    \n') def do_hline(self, args): self.write('


    ') # --- Function and variable definitions --- def bgn_deffn(self, args): self.write('
    ') self.do_deffnx(args) def end_deffn(self): self.write('
    \n') def do_deffnx(self, args): self.write('
    ') words = splitwords(args, 2) [category, name], rest = words[:2], words[2:] self.expand('@b{%s}' % name) for word in rest: self.expand(' ' + makevar(word)) #self.expand(' -- ' + category) self.write('\n
    ') self.index('fn', name) def bgn_defun(self, args): self.bgn_deffn('Function ' + args) end_defun = end_deffn def do_defunx(self, args): self.do_deffnx('Function ' + args) def bgn_defmac(self, args): self.bgn_deffn('Macro ' + args) end_defmac = end_deffn def do_defmacx(self, args): self.do_deffnx('Macro ' + args) def bgn_defspec(self, args): self.bgn_deffn('{Special Form} ' + args) end_defspec = end_deffn def do_defspecx(self, args): self.do_deffnx('{Special Form} ' + args) def bgn_defvr(self, args): self.write('
    ') self.do_defvrx(args) end_defvr = end_deffn def do_defvrx(self, args): self.write('
    ') words = splitwords(args, 2) [category, name], rest = words[:2], words[2:] self.expand('@code{%s}' % name) # If there are too many arguments, show them for word in rest: self.expand(' ' + word) #self.expand(' -- ' + category) self.write('\n
    ') self.index('vr', name) def bgn_defvar(self, args): self.bgn_defvr('Variable ' + args) end_defvar = end_defvr def do_defvarx(self, args): self.do_defvrx('Variable ' + args) def bgn_defopt(self, args): self.bgn_defvr('{User Option} ' + args) end_defopt = end_defvr def do_defoptx(self, args): self.do_defvrx('{User Option} ' + args) # --- Ditto for typed languages --- def bgn_deftypefn(self, args): self.write('
    ') self.do_deftypefnx(args) end_deftypefn = end_deffn def do_deftypefnx(self, args): self.write('
    ') words = splitwords(args, 3) [category, datatype, name], rest = words[:3], words[3:] self.expand('@code{%s} @b{%s}' % (datatype, name)) for word in rest: self.expand(' ' + makevar(word)) #self.expand(' -- ' + category) self.write('\n
    ') self.index('fn', name) def bgn_deftypefun(self, args): self.bgn_deftypefn('Function ' + args) end_deftypefun = end_deftypefn def do_deftypefunx(self, args): self.do_deftypefnx('Function ' + args) def bgn_deftypevr(self, args): self.write('
    ') self.do_deftypevrx(args) end_deftypevr = end_deftypefn def do_deftypevrx(self, args): self.write('
    ') words = splitwords(args, 3) [category, datatype, name], rest = words[:3], words[3:] self.expand('@code{%s} @b{%s}' % (datatype, name)) # If there are too many arguments, show them for word in rest: self.expand(' ' + word) #self.expand(' -- ' + category) self.write('\n
    ') self.index('fn', name) def bgn_deftypevar(self, args): self.bgn_deftypevr('Variable ' + args) end_deftypevar = end_deftypevr def do_deftypevarx(self, args): self.do_deftypevrx('Variable ' + args) # --- Ditto for object-oriented languages --- def bgn_defcv(self, args): self.write('
    ') self.do_defcvx(args) end_defcv = end_deftypevr def do_defcvx(self, args): self.write('
    ') words = splitwords(args, 3) [category, classname, name], rest = words[:3], words[3:] self.expand('@b{%s}' % name) # If there are too many arguments, show them for word in rest: self.expand(' ' + word) #self.expand(' -- %s of @code{%s}' % (category, classname)) self.write('\n
    ') self.index('vr', '%s @r{on %s}' % (name, classname)) def bgn_defivar(self, args): self.bgn_defcv('{Instance Variable} ' + args) end_defivar = end_defcv def do_defivarx(self, args): self.do_defcvx('{Instance Variable} ' + args) def bgn_defop(self, args): self.write('
    ') self.do_defopx(args) end_defop = end_defcv def do_defopx(self, args): self.write('
    ') words = splitwords(args, 3) [category, classname, name], rest = words[:3], words[3:] self.expand('@b{%s}' % name) for word in rest: self.expand(' ' + makevar(word)) #self.expand(' -- %s of @code{%s}' % (category, classname)) self.write('\n
    ') self.index('fn', '%s @r{on %s}' % (name, classname)) def bgn_defmethod(self, args): self.bgn_defop('Method ' + args) end_defmethod = end_defop def do_defmethodx(self, args): self.do_defopx('Method ' + args) # --- Ditto for data types --- def bgn_deftp(self, args): self.write('
    ') self.do_deftpx(args) end_deftp = end_defcv def do_deftpx(self, args): self.write('
    ') words = splitwords(args, 2) [category, name], rest = words[:2], words[2:] self.expand('@b{%s}' % name) for word in rest: self.expand(' ' + word) #self.expand(' -- ' + category) self.write('\n
    ') self.index('tp', name) # --- Making Lists and Tables def bgn_enumerate(self, args): if not args: self.write('
      \n') self.stackinfo[len(self.stack)] = '
    \n' else: self.itemnumber = args self.write('
      \n') self.stackinfo[len(self.stack)] = '
    \n' def end_enumerate(self): self.itemnumber = None self.write(self.stackinfo[len(self.stack) + 1]) del self.stackinfo[len(self.stack) + 1] def bgn_itemize(self, args): self.itemarg = args self.write('
      \n') def end_itemize(self): self.itemarg = None self.write('
    \n') def bgn_table(self, args): self.itemarg = args self.write('
    \n') def end_table(self): self.itemarg = None self.write('
    \n') def bgn_ftable(self, args): self.itemindex = 'fn' self.bgn_table(args) def end_ftable(self): self.itemindex = None self.end_table() def bgn_vtable(self, args): self.itemindex = 'vr' self.bgn_table(args) def end_vtable(self): self.itemindex = None self.end_table() def do_item(self, args): if self.itemindex: self.index(self.itemindex, args) if self.itemarg: if self.itemarg[0] == '@' and self.itemarg[1] and \ self.itemarg[1] in string.ascii_letters: args = self.itemarg + '{' + args + '}' else: # some other character, e.g. '-' args = self.itemarg + ' ' + args if self.itemnumber <> None: args = self.itemnumber + '. ' + args self.itemnumber = increment(self.itemnumber) if self.stack and self.stack[-1] == 'table': self.write('
    ') self.expand(args) self.write('\n
    ') elif self.stack and self.stack[-1] == 'multitable': self.write('') self.expand(args) self.write('\n\n') else: self.write('
  • ') self.expand(args) self.write(' ') do_itemx = do_item # XXX Should suppress leading blank line # rpyron 2002-05-07 multitable support def bgn_multitable(self, args): self.itemarg = None # should be handled by columnfractions self.write('\n') def end_multitable(self): self.itemarg = None self.write('
    \n
    \n') def handle_columnfractions(self): # It would be better to handle this, but for now it's in the way... self.itemarg = None def handle_tab(self): self.write('\n ') # --- Enumerations, displays, quotations --- # XXX Most of these should increase the indentation somehow def bgn_quotation(self, args): self.write('
    ') def end_quotation(self): self.write('
    \n') def bgn_example(self, args): self.nofill = self.nofill + 1 self.write('
    ')
        def end_example(self):
            self.write('
    \n') self.nofill = self.nofill - 1 bgn_lisp = bgn_example # Synonym when contents are executable lisp code end_lisp = end_example bgn_smallexample = bgn_example # XXX Should use smaller font end_smallexample = end_example bgn_smalllisp = bgn_lisp # Ditto end_smalllisp = end_lisp bgn_display = bgn_example end_display = end_example bgn_format = bgn_display end_format = end_display def do_exdent(self, args): self.expand(args + '\n') # XXX Should really mess with indentation def bgn_flushleft(self, args): self.nofill = self.nofill + 1 self.write('
    \n')
        def end_flushleft(self):
            self.write('
    \n') self.nofill = self.nofill - 1 def bgn_flushright(self, args): self.nofill = self.nofill + 1 self.write('
    \n') def end_flushright(self): self.write('
    \n') self.nofill = self.nofill - 1 def bgn_menu(self, args): self.write('\n') self.write(' Menu

    \n') self.htmlhelp.beginmenu() def end_menu(self): self.write('

    \n') self.htmlhelp.endmenu() def bgn_cartouche(self, args): pass def end_cartouche(self): pass # --- Indices --- def resetindex(self): self.noncodeindices = ['cp'] self.indextitle = {} self.indextitle['cp'] = 'Concept' self.indextitle['fn'] = 'Function' self.indextitle['ky'] = 'Keyword' self.indextitle['pg'] = 'Program' self.indextitle['tp'] = 'Type' self.indextitle['vr'] = 'Variable' # self.whichindex = {} for name in self.indextitle.keys(): self.whichindex[name] = [] def user_index(self, name, args): if self.whichindex.has_key(name): self.index(name, args) else: print '*** No index named', repr(name) def do_cindex(self, args): self.index('cp', args) def do_findex(self, args): self.index('fn', args) def do_kindex(self, args): self.index('ky', args) def do_pindex(self, args): self.index('pg', args) def do_tindex(self, args): self.index('tp', args) def do_vindex(self, args): self.index('vr', args) def index(self, name, args): self.whichindex[name].append((args, self.nodename)) self.htmlhelp.index(args, self.nodename) def do_synindex(self, args): words = args.split() if len(words) <> 2: print '*** bad @synindex', args return [old, new] = words if not self.whichindex.has_key(old) or \ not self.whichindex.has_key(new): print '*** bad key(s) in @synindex', args return if old <> new and \ self.whichindex[old] is not self.whichindex[new]: inew = self.whichindex[new] inew[len(inew):] = self.whichindex[old] self.whichindex[old] = inew do_syncodeindex = do_synindex # XXX Should use code font def do_printindex(self, args): words = args.split() for name in words: if self.whichindex.has_key(name): self.prindex(name) else: print '*** No index named', repr(name) def prindex(self, name): iscodeindex = (name not in self.noncodeindices) index = self.whichindex[name] if not index: return if self.debugging: print '!'*self.debugging, '--- Generating', \ self.indextitle[name], 'index' # The node already provides a title index1 = [] junkprog = re.compile('^(@[a-z]+)?{') for key, node in index: sortkey = key.lower() # Remove leading `@cmd{' from sort key # -- don't bother about the matching `}' oldsortkey = sortkey while 1: mo = junkprog.match(sortkey) if not mo: break i = mo.end() sortkey = sortkey[i:] index1.append((sortkey, key, node)) del index[:] index1.sort() self.write('
    \n') prevkey = prevnode = None for sortkey, key, node in index1: if (key, node) == (prevkey, prevnode): continue if self.debugging > 1: print '!'*self.debugging, key, ':', node self.write('
    ') if iscodeindex: key = '@code{' + key + '}' if key != prevkey: self.expand(key) self.write('\n
    %s\n' % (makefile(node), node)) prevkey, prevnode = key, node self.write('
    \n') # --- Final error reports --- def report(self): if self.unknown: print '--- Unrecognized commands ---' cmds = self.unknown.keys() cmds.sort() for cmd in cmds: print cmd.ljust(20), self.unknown[cmd] class TexinfoParserHTML3(TexinfoParser): COPYRIGHT_SYMBOL = "©" FN_ID_PATTERN = "[%(id)s]" FN_SOURCE_PATTERN = '' + FN_ID_PATTERN + '' FN_TARGET_PATTERN = '\n' \ '

    ' + FN_ID_PATTERN \ + '\n%(text)s

    \n' FN_HEADER = '
    \n
    \n' \ ' Footnotes\n

    \n' Node = HTML3Node def bgn_quotation(self, args): self.write('') def end_quotation(self): self.write('\n') def bgn_example(self, args): # this use of would not be legal in HTML 2.0, # but is in more recent DTDs. self.nofill = self.nofill + 1 self.write('

    ')
        def end_example(self):
            self.write("
    \n") self.nofill = self.nofill - 1 def bgn_flushleft(self, args): self.nofill = self.nofill + 1 self.write('
    \n')
    
        def bgn_flushright(self, args):
            self.nofill = self.nofill + 1
            self.write('
    \n') def end_flushright(self): self.write('
    \n') self.nofill = self.nofill - 1 def bgn_menu(self, args): self.write('\n') # rpyron 2002-05-07 class HTMLHelp: """ This class encapsulates support for HTML Help. Node names, file names, menu items, index items, and image file names are accumulated until a call to finalize(). At that time, three output files are created in the current directory: `helpbase`.hhp is a HTML Help Workshop project file. It contains various information, some of which I do not understand; I just copied the default project info from a fresh installation. `helpbase`.hhc is the Contents file for the project. `helpbase`.hhk is the Index file for the project. When these files are used as input to HTML Help Workshop, the resulting file will be named: `helpbase`.chm If none of the defaults in `helpbase`.hhp are changed, the .CHM file will have Contents, Index, Search, and Favorites tabs. """ codeprog = re.compile('@code{(.*?)}') def __init__(self,helpbase,dirname): self.helpbase = helpbase self.dirname = dirname self.projectfile = None self.contentfile = None self.indexfile = None self.nodelist = [] self.nodenames = {} # nodename : index self.nodeindex = {} self.filenames = {} # filename : filename self.indexlist = [] # (args,nodename) == (key,location) self.current = '' self.menudict = {} self.dumped = {} def addnode(self,name,next,prev,up,filename): node = (name,next,prev,up,filename) # add this file to dict # retrieve list with self.filenames.values() self.filenames[filename] = filename # add this node to nodelist self.nodeindex[name] = len(self.nodelist) self.nodelist.append(node) # set 'current' for menu items self.current = name self.menudict[self.current] = [] def menuitem(self,nodename): menu = self.menudict[self.current] menu.append(nodename) def addimage(self,imagename): self.filenames[imagename] = imagename def index(self, args, nodename): self.indexlist.append((args,nodename)) def beginmenu(self): pass def endmenu(self): pass def finalize(self): if not self.helpbase: return # generate interesting filenames resultfile = self.helpbase + '.chm' projectfile = self.helpbase + '.hhp' contentfile = self.helpbase + '.hhc' indexfile = self.helpbase + '.hhk' # generate a reasonable title title = self.helpbase # get the default topic file (topname,topnext,topprev,topup,topfile) = self.nodelist[0] defaulttopic = topfile # PROJECT FILE try: fp = open(projectfile,'w') print>>fp, '[OPTIONS]' print>>fp, 'Auto Index=Yes' print>>fp, 'Binary TOC=No' print>>fp, 'Binary Index=Yes' print>>fp, 'Compatibility=1.1' print>>fp, 'Compiled file=' + resultfile + '' print>>fp, 'Contents file=' + contentfile + '' print>>fp, 'Default topic=' + defaulttopic + '' print>>fp, 'Error log file=ErrorLog.log' print>>fp, 'Index file=' + indexfile + '' print>>fp, 'Title=' + title + '' print>>fp, 'Display compile progress=Yes' print>>fp, 'Full-text search=Yes' print>>fp, 'Default window=main' print>>fp, '' print>>fp, '[WINDOWS]' print>>fp, ('main=,"' + contentfile + '","' + indexfile + '","","",,,,,0x23520,222,0x1046,[10,10,780,560],' '0xB0000,,,,,,0') print>>fp, '' print>>fp, '[FILES]' print>>fp, '' self.dumpfiles(fp) fp.close() except IOError, msg: print projectfile, ':', msg sys.exit(1) # CONTENT FILE try: fp = open(contentfile,'w') print>>fp, '' print>>fp, '' print>>fp, '' print>>fp, '' print>>fp, ('') print>>fp, '' print>>fp, '' print>>fp, '' print>>fp, ' ' print>>fp, ' ' print>>fp, ' ' print>>fp, ' ' print>>fp, ' ' self.dumpnodes(fp) print>>fp, '' print>>fp, '' fp.close() except IOError, msg: print contentfile, ':', msg sys.exit(1) # INDEX FILE try: fp = open(indexfile ,'w') print>>fp, '' print>>fp, '' print>>fp, '' print>>fp, '' print>>fp, ('') print>>fp, '' print>>fp, '' print>>fp, '' print>>fp, '' print>>fp, '' self.dumpindex(fp) print>>fp, '' print>>fp, '' fp.close() except IOError, msg: print indexfile , ':', msg sys.exit(1) def dumpfiles(self, outfile=sys.stdout): filelist = self.filenames.values() filelist.sort() for filename in filelist: print>>outfile, filename def dumpnodes(self, outfile=sys.stdout): self.dumped = {} if self.nodelist: nodename, dummy, dummy, dummy, dummy = self.nodelist[0] self.topnode = nodename print>>outfile, '
      ' for node in self.nodelist: self.dumpnode(node,0,outfile) print>>outfile, '
    ' def dumpnode(self, node, indent=0, outfile=sys.stdout): if node: # Retrieve info for this node (nodename,next,prev,up,filename) = node self.current = nodename # Have we been dumped already? if self.dumped.has_key(nodename): return self.dumped[nodename] = 1 # Print info for this node print>>outfile, ' '*indent, print>>outfile, '
  • ', print>>outfile, '', print>>outfile, '', print>>outfile, '' # Does this node have menu items? try: menu = self.menudict[nodename] self.dumpmenu(menu,indent+2,outfile) except KeyError: pass def dumpmenu(self, menu, indent=0, outfile=sys.stdout): if menu: currentnode = self.current if currentnode != self.topnode: # XXX this is a hack print>>outfile, ' '*indent + '
      ' indent += 2 for item in menu: menunode = self.getnode(item) self.dumpnode(menunode,indent,outfile) if currentnode != self.topnode: # XXX this is a hack print>>outfile, ' '*indent + '
    ' indent -= 2 def getnode(self, nodename): try: index = self.nodeindex[nodename] return self.nodelist[index] except KeyError: return None except IndexError: return None # (args,nodename) == (key,location) def dumpindex(self, outfile=sys.stdout): print>>outfile, '
      ' for (key,location) in self.indexlist: key = self.codeexpand(key) location = makefile(location) location = self.dirname + '/' + location print>>outfile, '
    • ', print>>outfile, '', print>>outfile, '', print>>outfile, '' print>>outfile, '
    ' def codeexpand(self, line): co = self.codeprog.match(line) if not co: return line bgn, end = co.span(0) a, b = co.span(1) line = line[:bgn] + line[a:b] + line[end:] return line # Put @var{} around alphabetic substrings def makevar(str): return '@var{'+str+'}' # Split a string in "words" according to findwordend def splitwords(str, minlength): words = [] i = 0 n = len(str) while i < n: while i < n and str[i] in ' \t\n': i = i+1 if i >= n: break start = i i = findwordend(str, i, n) words.append(str[start:i]) while len(words) < minlength: words.append('') return words # Find the end of a "word", matching braces and interpreting @@ @{ @} fwprog = re.compile('[@{} ]') def findwordend(str, i, n): level = 0 while i < n: mo = fwprog.search(str, i) if not mo: break i = mo.start() c = str[i]; i = i+1 if c == '@': i = i+1 # Next character is not special elif c == '{': level = level+1 elif c == '}': level = level-1 elif c == ' ' and level <= 0: return i-1 return n # Convert a node name into a file name def makefile(nodename): nodename = nodename.strip() return fixfunnychars(nodename) + '.html' # Characters that are perfectly safe in filenames and hyperlinks goodchars = string.ascii_letters + string.digits + '!@-=+.' # Replace characters that aren't perfectly safe by dashes # Underscores are bad since Cern HTTPD treats them as delimiters for # encoding times, so you get mismatches if you compress your files: # a.html.gz will map to a_b.html.gz def fixfunnychars(addr): i = 0 while i < len(addr): c = addr[i] if c not in goodchars: c = '-' addr = addr[:i] + c + addr[i+1:] i = i + len(c) return addr # Increment a string used as an enumeration def increment(s): if not s: return '1' for sequence in string.digits, string.lowercase, string.uppercase: lastc = s[-1] if lastc in sequence: i = sequence.index(lastc) + 1 if i >= len(sequence): if len(s) == 1: s = sequence[0]*2 if s == '00': s = '10' else: s = increment(s[:-1]) + sequence[0] else: s = s[:-1] + sequence[i] return s return s # Don't increment def test(): import sys debugging = 0 print_headers = 0 cont = 0 html3 = 0 htmlhelp = '' while sys.argv[1] == ['-d']: debugging = debugging + 1 del sys.argv[1] if sys.argv[1] == '-p': print_headers = 1 del sys.argv[1] if sys.argv[1] == '-c': cont = 1 del sys.argv[1] if sys.argv[1] == '-3': html3 = 1 del sys.argv[1] if sys.argv[1] == '-H': helpbase = sys.argv[2] del sys.argv[1:3] if len(sys.argv) <> 3: print 'usage: texi2hh [-d [-d]] [-p] [-c] [-3] [-H htmlhelp]', \ 'inputfile outputdirectory' sys.exit(2) if html3: parser = TexinfoParserHTML3() else: parser = TexinfoParser() parser.cont = cont parser.debugging = debugging parser.print_headers = print_headers file = sys.argv[1] dirname = sys.argv[2] parser.setdirname(dirname) parser.setincludedir(os.path.dirname(file)) htmlhelp = HTMLHelp(helpbase, dirname) parser.sethtmlhelp(htmlhelp) try: fp = open(file, 'r') except IOError, msg: print file, ':', msg sys.exit(1) parser.parse(fp) fp.close() parser.report() htmlhelp.finalize() if __name__ == "__main__": test()