1 """A generic class to build line-oriented command interpreters.
3 Interpreters constructed with this class obey the following conventions:
5 1. End of file on input is processed as the command 'EOF'.
6 2. A command is parsed out of each line by collecting the prefix composed
7 of characters in the identchars member.
8 3. A command `foo' is dispatched to a method 'do_foo()'; the do_ method
9 is passed a single argument consisting of the remainder of the line.
10 4. Typing an empty line repeats the last command. (Actually, it calls the
11 method `emptyline', which may be overridden in a subclass.)
12 5. There is a predefined `help' method. Given an argument `topic', it
13 calls the command `help_topic'. With no arguments, it lists all topics
14 with defined help_ functions, broken into up to three topics; documented
15 commands, miscellaneous help topics, and undocumented commands.
16 6. The command '?' is a synonym for `help'. The command '!' is a synonym
17 for `shell', if a do_shell method exists.
19 The `default' method may be overridden to intercept commands for which there
22 The data member `self.ruler' sets the character used to draw separator lines
23 in the help messages. If empty, no ruler line is drawn. It defaults to "=".
25 If the value of `self.intro' is nonempty when the cmdloop method is called,
26 it is printed out on interpreter startup. This value may be overridden
27 via an optional argument to the cmdloop() method.
29 The data members `self.doc_header', `self.misc_header', and
30 `self.undoc_header' set the headers used for the help function's
31 listings of documented functions, miscellaneous topics, and undocumented
32 functions respectively.
34 These interpreters use raw_input; thus, if the readline module is loaded,
35 they automatically support Emacs-like command history and editing features.
41 IDENTCHARS
= string
.letters
+ string
.digits
+ '_'
45 identchars
= IDENTCHARS
51 doc_header
= "Documented commands (type help <topic>):"
52 misc_header
= "Miscellaneous help topics:"
53 undoc_header
= "Undocumented commands:"
54 nohelp
= "*** No help on %s"
56 def __init__(self
): pass
58 def cmdloop(self
, intro
=None):
67 line
= self
.cmdqueue
[0]
71 line
= raw_input(self
.prompt
)
74 line
= self
.precmd(line
)
75 stop
= self
.onecmd(line
)
76 stop
= self
.postcmd(stop
, line
)
79 def precmd(self
, line
):
82 def postcmd(self
, stop
, line
):
91 def onecmd(self
, line
):
92 line
= string
.strip(line
)
96 if hasattr(self
, 'do_shell'):
99 return self
.default(line
)
101 return self
.emptyline()
104 while i
< n
and line
[i
] in self
.identchars
: i
= i
+1
105 cmd
, arg
= line
[:i
], string
.strip(line
[i
:])
107 return self
.default(line
)
110 func
= getattr(self
, 'do_' + cmd
)
111 except AttributeError:
112 return self
.default(line
)
117 return self
.onecmd(self
.lastcmd
)
119 def default(self
, line
):
120 print '*** Unknown syntax:', line
122 def do_help(self
, arg
):
124 # XXX check arg syntax
126 func
= getattr(self
, 'help_' + arg
)
129 doc
=getattr(self
, 'do_' + arg
).__doc
__
135 print self
.nohelp
% (arg
,)
139 # Inheritance says we have to look in class and
140 # base classes; order is not important.
142 classes
= [self
.__class
__]
146 classes
= classes
+ list(aclass
.__bases
__)
147 names
= names
+ dir(aclass
)
153 if name
[:5] == 'help_':
156 # There can be duplicates if routines overridden
159 if name
[:3] == 'do_':
164 if help.has_key(cmd
):
167 elif getattr(self
, name
).__doc
__:
170 cmds_undoc
.append(cmd
)
171 print self
.doc_leader
172 self
.print_topics(self
.doc_header
, cmds_doc
, 15,80)
173 self
.print_topics(self
.misc_header
, help.keys(),15,80)
174 self
.print_topics(self
.undoc_header
, cmds_undoc
, 15,80)
176 def print_topics(self
, header
, cmds
, cmdlen
, maxcol
):
180 print self
.ruler
* len(header
)
181 (cmds_per_line
,junk
)=divmod(maxcol
,cmdlen
)
185 print (("%-"+`cmdlen`
+"s") % cmd
),
186 col
= (col
+1) % cmds_per_line