test harnesses, administrative tools, and prototypes that will
later be wrapped in a more sophisticated interface.
-\begin{classdesc}{Cmd}{}
+\begin{classdesc}{Cmd}{\optional{completekey}}
A \class{Cmd} instance or subclass instance is a line-oriented
interpreter framework. There is no good reason to instantiate
\class{Cmd} itself; rather, it's useful as a superclass of an
interpreter class you define yourself in order to inherit
\class{Cmd}'s methods and encapsulate action methods.
+
+The optional argument is the \refmodule{readline} name of a completion
+key; it defaults to \code{``tab''}. If \var{completekey} is not
+\code{None} and \module{readline} is available, command completion is
+done automatically.
+
\end{classdesc}
\subsection{Cmd Objects}
beginning with the character \character{!} is dispatched to the
method \method{do_shell} (if such a method is defined).
+If completion is enabled, completing commands will be done
+automatically, and completing of commands args is done by calling
+\method{complete_foo()} with arguments \samp{text}, \samp{line},
+\samp{begidx}, \samp{endidx}. \samp{text} is string we are matching
+against, all returned matches must begin with it. \samp{line} is the
+current input line (lstripped), \samp{begidx} and \samp{endidx} are
+the beginning and end indexes of the text being matched, which could
+be used to provide different completion depending upon which position
+the argument is in.
+
All subclasses of \class{Cmd} inherit a predefined \method{do_help}.
This method, called with an argument \code{bar}, invokes the
corresponding method \method{help_bar()}. With no argument,
error message and returns.
\end{methoddesc}
+\begin{methoddesc}{completedefault}{text, line, begidx, endidx}
+Method called to complete an input line when no command-specific
+\code{complete_} method is available. By default, it returns an
+empty list.
+\end{methoddesc}
+
\begin{methoddesc}{precmd}{}
Hook method executed just before the command line is interpreted, but
after the input prompt is generated and issued. This
commands, miscellaneous help topics, and undocumented commands.
6. The command '?' is a synonym for `help'. The command '!' is a synonym
for `shell', if a do_shell method exists.
+7. If completion is enabled, completing commands will be done automatically,
+ and completing of commands args is done by calling complete_foo() with
+ arguments text, line, begidx, endidx. text is string we are matching
+ against, all returned matches must begin with it. line is the current
+ input line (lstripped), begidx and endidx are the beginning and end
+ indexes of the text being matched, which could be used to provide
+ different completion depending upon which position the argument is in.
The `default' method may be overridden to intercept commands for which there
is no do_ method.
+The `completedefault' method may be overridden to intercept completions for
+commands that have no complete_ method.
+
The data member `self.ruler' sets the character used to draw separator lines
in the help messages. If empty, no ruler line is drawn. It defaults to "=".
nohelp = "*** No help on %s"
use_rawinput = 1
- def __init__(self): pass
+ def __init__(self, completekey='tab'):
+ if completekey:
+ try:
+ import readline
+ readline.set_completer(self.complete)
+ readline.parse_and_bind(completekey+": complete")
+ except ImportError:
+ pass
def cmdloop(self, intro=None):
self.preloop()
def postloop(self):
pass
- def onecmd(self, line):
+ def parseline(self, line):
line = line.strip()
if not line:
- return self.emptyline()
+ return None, None, line
elif line[0] == '?':
line = 'help ' + line[1:]
elif line[0] == '!':
if hasattr(self, 'do_shell'):
line = 'shell ' + line[1:]
else:
- return self.default(line)
- self.lastcmd = line
+ return None, None, line
i, n = 0, len(line)
while i < n and line[i] in self.identchars: i = i+1
cmd, arg = line[:i], line[i:].strip()
+ return cmd, arg, line
+
+ def onecmd(self, line):
+ cmd, arg, line = self.parseline(line)
+ if not line:
+ return self.emptyline()
+ if cmd is None:
+ return self.default(line)
+ self.lastcmd = line
if cmd == '':
return self.default(line)
else:
def default(self, line):
print '*** Unknown syntax:', line
+ def completedefault(self, *ignored):
+ return []
+
+ def completenames(self, text, *ignored):
+ dotext = 'do_'+text
+ return [a[3:] for a in self.get_names() if a.startswith(dotext)]
+
+ def complete(self, text, state):
+ """Return the next possible completion for 'text'.
+
+ If a command has not been entered, then complete against command list.
+ Otherwise try to call complete_<command> to get list of completions.
+ """
+ if state == 0:
+ import readline
+ origline = readline.get_line_buffer()
+ line = origline.lstrip()
+ stripped = len(origline) - len(line)
+ begidx = readline.get_begidx() - stripped
+ endidx = readline.get_endidx() - stripped
+ if begidx>0:
+ cmd, args, foo = self.parseline(line)
+ if cmd == '':
+ compfunc = self.completedefault
+ else:
+ try:
+ compfunc = getattr(self, 'complete_' + cmd)
+ except AttributeError:
+ compfunc = self.completedefault
+ else:
+ compfunc = self.completenames
+ self.completion_matches = compfunc(text, line, begidx, endidx)
+ try:
+ return self.completion_matches[state]
+ except IndexError:
+ return None
+
+ def get_names(self):
+ # Inheritance says we have to look in class and
+ # base classes; order is not important.
+ names = []
+ classes = [self.__class__]
+ while classes:
+ aclass = classes[0]
+ if aclass.__bases__:
+ classes = classes + list(aclass.__bases__)
+ names = names + dir(aclass)
+ del classes[0]
+ return names
+
+ def complete_help(self, *args):
+ return self.completenames(*args)
+
def do_help(self, arg):
if arg:
# XXX check arg syntax
return
func()
else:
- # Inheritance says we have to look in class and
- # base classes; order is not important.
- names = []
- classes = [self.__class__]
- while classes:
- aclass = classes[0]
- if aclass.__bases__:
- classes = classes + list(aclass.__bases__)
- names = names + dir(aclass)
- del classes[0]
+ names = self.get_names()
cmds_doc = []
cmds_undoc = []
help = {}