| """ |
| Online help module. |
| |
| This module is experimental and could be removed or radically changed |
| at any time. |
| |
| It is intended specifically for the standard interpreter command |
| line but is intended to be compatible with and useful for other |
| (e.g. GUI, handheld) environments. Help with those other environments is |
| appreciated. |
| |
| Please remember to set PYTHONDOCS to the location of your HTML files: |
| |
| e.g. |
| set PYTHONDOCS=c:\python\docs |
| PYTHONDOCS=/python/docs |
| |
| The docs directory should have a lib subdirectory with "index.html" in it. |
| If it has *.tex then you have the documentation *source* distribution, not |
| the runtime distribution. |
| |
| The module exposes one object: "help". "help" has a repr that does something |
| useful if you just type: |
| |
| >>> from onlinehelp import help |
| >>> help |
| |
| Of course one day the first line will be done automatically by site.py or |
| something like that. help can be used as a function. |
| |
| The function takes the following forms of input: |
| |
| help( "string" ) -- built-in topic or global |
| help( <ob> ) -- docstring from object or type |
| help( "doc:filename" ) -- filename from Python documentation |
| |
| Type help to get the rest of the instructions. |
| """ |
| import htmllib # todo: add really basic tr/td support |
| import formatter |
| import os, sys |
| import re |
| |
| prompt="--more-- (enter for more, q to quit) " |
| |
| topics={} # all built-in (non-HTML, non-docstring) topics go in here |
| commands="" # only used at the top level |
| |
| def topLevelCommand( name, description, text ): |
| """ this function is just for use at the top-level to make sure that |
| every advertised top-level topic has a description and every |
| description has text. Maybe we can generalize it later.""" |
| |
| global commands |
| topics[name]=text |
| |
| if description[0]=="[": |
| placeholder="(dummy)" |
| elif description[0]=="<": |
| placeholder="link" |
| else: |
| placeholder="" |
| commands=commands+'help( "%s" ) %s - %s\n' % \ |
| (name, placeholder, description ) |
| |
| topLevelCommand( |
| "intro", |
| "What is Python? Read this first!", |
| """Welcome to Python, the easy to learn, portable, object oriented |
| programming language. |
| |
| [info on how to use help] |
| |
| [info on intepreter]""" |
| ) |
| |
| topLevelCommand( |
| "keywords", |
| "What are the keywords?", |
| "") |
| |
| topLevelCommand( |
| "syntax", |
| "What is the overall syntax?", |
| "[placeholder]") |
| |
| topLevelCommand( |
| "operators", |
| "What operators are available?", |
| "<doc:ref/operators.html>" ) |
| |
| topLevelCommand( |
| "builtins", |
| "What functions, types, etc. are built-in?", |
| "<doc:lib/built-in-funcs.html>") |
| |
| topLevelCommand( "modules", |
| "What modules are in the standard library?", |
| "<doc:lib/lib.html>") |
| |
| topLevelCommand( |
| "copyright", |
| "Who owns Python?", |
| "[who knows]") |
| |
| topLevelCommand( |
| "moreinfo", |
| "Where is there more information?", |
| "[placeholder]") |
| |
| topLevelCommand( |
| "changes", |
| "What changed in Python 2.0?", |
| "[placeholder]" |
| ) |
| |
| topLevelCommand( |
| "extensions", |
| "What extensions are installed?", |
| "[placeholder]") |
| |
| topLevelCommand( |
| "faq", |
| "What questions are frequently asked?", |
| "[placeholder]") |
| |
| topLevelCommand( |
| "ack", |
| "Who has done work on Python lately?", |
| "[placeholder for list of people who contributed patches]") |
| |
| |
| topics[ "prompt" ]="""<doc:tut/node4.html>""" |
| topics[ "types" ]="""<doc:ref/types.html>""" |
| topics["everything"]= \ |
| """<pre>The help function allows you to read help on Python's various |
| functions, objects, instructions and modules. You have two options: |
| |
| 1. Use help( obj ) to browse the help attached to some function, module |
| class or other object. e.g. help( dir ) |
| |
| 2. Use help( "somestring" ) to browse help on one of the predefined |
| help topics, unassociated with any particular object: |
| |
| %s</pre>""" % commands |
| |
| topics[ "keywords" ]=\ |
| """<pre>"if" - Conditional execution |
| "while" - Loop while a condition is true |
| "for" - Loop over a sequence of values (often numbers) |
| "try" - Set up an exception handler |
| "def" - Define a named function |
| "class" - Define a class |
| "assert" - Check that some code is working as you expect it to. |
| "pass" - Do nothing |
| "del" - Delete a data value |
| "print" - Print a value |
| "return" - Return information from a function |
| "raise" - Raise an exception |
| "break" - Terminate a loop |
| "continue" - Skip to the next loop statement |
| "import" - Import a module |
| "global" - Declare a variable global |
| "exec" - Execute some dynamically generated code |
| "lambda" - Define an unnamed function |
| |
| For more information, type e.g. help("assert")</pre>""" |
| |
| topics[ "if" ]="""<doc:ref/if.html>""" |
| topics[ "while" ]="""<doc:ref/while.html>""" |
| topics[ "for" ]="""<doc:ref/for.html>""" |
| topics[ "try" ]="""<doc:ref/try.html>""" |
| topics[ "def" ]="""<doc:ref/def.html>""" |
| topics[ "class" ]="""<doc:ref/class.html>""" |
| topics[ "assert" ]="""<doc:ref/assert.html>""" |
| topics[ "pass" ]="""<doc:ref/pass.html>""" |
| topics[ "del" ]="""<doc:ref/del.html>""" |
| topics[ "print" ]="""<doc:ref/print.html>""" |
| topics[ "return" ]="""<doc:ref/return.html>""" |
| topics[ "raise" ]="""<doc:ref/raise.html>""" |
| topics[ "break" ]="""<doc:ref/break.html>""" |
| topics[ "continue" ]="""<doc:ref/continue.html>""" |
| topics[ "import" ]="""<doc:ref/import.html>""" |
| topics[ "global" ]="""<doc:ref/global.html>""" |
| topics[ "exec" ]="""<doc:ref/exec.html>""" |
| topics[ "lambda" ]="""<doc:ref/lambda.html>""" |
| |
| envir_var="PYTHONDOCS" |
| |
| class Help: |
| def __init__( self, out, line_length, docdir=None ): |
| self.out=out |
| self.line_length=line_length |
| self.Parser=htmllib.HTMLParser |
| self.Formatter=formatter.AbstractFormatter |
| self.Pager=Pager |
| self.Writer=formatter.DumbWriter |
| if os.environ.has_key(envir_var): |
| self.docdir=os.environ[envir_var] |
| else: |
| if os.environ.has_key("PYTHONHOME"): |
| pyhome=os.environ["PYTHONHOME"] |
| else: |
| pyhome=os.path.split( sys.executable )[0] |
| self.docdir=os.path.join( pyhome, "doc" ) |
| |
| testfile=os.path.join( |
| os.path.join( self.docdir, "lib" ), "index.html") |
| |
| if not os.path.exists( testfile ): |
| error = \ |
| """Cannot find documentation directory %s. |
| Set the %s environment variable to point to a "doc" directory. |
| It should have a subdirectory "Lib" with a file named "index.html". |
| """ % (self.docdir, envir_var ) |
| raise EnvironmentError, error |
| |
| def __repr__( self ): |
| self( "everything" ) |
| return "" |
| |
| def __call__( self, ob, out=None ): |
| try: |
| self.call( ob, out ) |
| return 1 |
| except (KeyboardInterrupt, EOFError): |
| return 0 |
| |
| def call( self, ob, out ): |
| self.pager=out or self.Pager( self.out, self.line_length ) |
| |
| if type( ob ) in (type(""),type(u"")): |
| if ob.startswith( "<" ): |
| ob=ob[1:] |
| if ob.endswith( ">" ): |
| ob=ob[:-1] |
| |
| self.write( 'Topic: help( "%s" )\n' % ob ) |
| |
| if ob.startswith("doc:"): |
| path=ob[4:] |
| fullpath=os.path.join( self.docdir, path ) |
| data=open( fullpath ).read() |
| index=ob.rfind( "/" ) |
| self.writeHTML( ob[:index], data ) |
| else: |
| try: |
| info=topics[ob] |
| docrlmatch=re.search( "(<doc:[^>]+>)", info.split("\n")[0] ) |
| if docrlmatch: # a first-line redirect |
| self( docrlmatch.group(1) ) |
| else: |
| self.writeHTML( "", info ) |
| except KeyError: |
| glo=__builtins__.__dict__.get( ob, 0 ) |
| if glo: |
| self( glo ) |
| else: |
| sys.stderr.write( "No such topic "+`ob` ) |
| return None |
| else: |
| self.write( 'Topic: help( %s )\n' % ob ) |
| if hasattr( ob, "__doc__" ): |
| self.writeText(ob.__doc__) |
| else: |
| self.writeText( type( ob ).__doc__ ) |
| |
| |
| def writeHTML( self, base, str ): |
| parser=self.Parser(self.Formatter( self.Writer( self ))) |
| parser.feed( str ) # calls self.write automatically |
| for i in range( len( parser.anchorlist) ): |
| self.pager.write( "[%s] %s/%s\n" %(i+1, base,parser.anchorlist[i] )) |
| self.pager.flush() |
| self.out.write( "\n" ) |
| |
| def writeText( self, str ): |
| self.pager.write( str ) |
| self.pager.flush() |
| self.out.write( "\n" ) |
| |
| def write( self, str ): |
| self.pager.write( str ) |
| |
| from cStringIO import StringIO |
| |
| class Pager: |
| numlines=1 |
| |
| def __init__(self, out, pagesize=24, linestart="" ): |
| self.out=out |
| self.pagesize=pagesize |
| self.buf=StringIO() |
| self.linestart=linestart |
| |
| def close(self ): |
| self.flush() |
| |
| def flush(self ): |
| data=self.buf.getvalue().rstrip() # dump trailing ws |
| while data.endswith( "\n|" ): # dump trailing lines |
| data=data[:-2] |
| self.out.write( data ) |
| self.buf=StringIO() |
| |
| def write(self, str ): |
| lines=str.split( "\n" ) |
| self.buf.write( lines[0] ) |
| for line in lines[1:]: |
| self.buf.write( "\n| " ) |
| self.buf.write( line ) |
| if self.numlines and not self.numlines%(self.pagesize): |
| dat=self.buf.getvalue().strip() |
| self.out.write( "| " ) |
| self.out.write( dat ) |
| self.out.write( "\n" ) |
| j=raw_input(prompt) |
| if j and j[0]=="q": |
| raise EOFError |
| self.buf=StringIO() |
| self.numlines=self.numlines+1 |
| |
| help=Help(sys.stdout,24) |
| |
| def test(): |
| rc = 1 |
| rc = rc and help( "everything" ) |
| rc = rc and help( "exec" ) |
| rc = rc and help( "doc:lib/unix.html" ) |
| rc = rc and help( "doc:lib/module-tty.html" ) |
| rc = rc and help( "doc:ref/print.html" ) |
| rc = rc and help( "faq" ) |
| rc = rc and help( dir ) |
| repr( help ) |
| |
| if __name__=="__main__": |
| if len( sys.argv )!=2: |
| print "Usage: %s <topic> or %s test" % ( sys.argv[0], sys.argv[0] ) |
| sys.exit(0) |
| elif sys.argv[1]=="test": |
| test() |
| else: |
| help( sys.argv[1] ) |
| |