]> granicus.if.org Git - python/commitdiff
Online help facility for the Python interprter and other interactive
authorPaul Prescod <prescod@prescod.net>
Sun, 16 Jul 2000 19:53:00 +0000 (19:53 +0000)
committerPaul Prescod <prescod@prescod.net>
Sun, 16 Jul 2000 19:53:00 +0000 (19:53 +0000)
environments.

Lib/onlinehelp.py [new file with mode: 0644]

diff --git a/Lib/onlinehelp.py b/Lib/onlinehelp.py
new file mode 100644 (file)
index 0000000..41b25c1
--- /dev/null
@@ -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] )
+