diff options
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/onlinehelp.py | 344 |
1 files changed, 344 insertions, 0 deletions
diff --git a/Lib/onlinehelp.py b/Lib/onlinehelp.py new file mode 100644 index 0000000000..41b25c13d0 --- /dev/null +++ b/Lib/onlinehelp.py @@ -0,0 +1,344 @@ +""" +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] ) + |