kmd 2.5.dev0 – Interpreter Framework¶
A framework for building command interpreters and shells.
Overview¶
A framework for building command interpreters and shells.
Interpreters¶
The kmd.Kmd
class provides a simple framework for writing
line-oriented command interpreters, also known as shells. These are often
useful for test harnesses, prototypes, and administrative tools.
A kmd.Kmd
instance is a line-oriented command interpreter.
There is no good reason to instantiate kmd.Kmd
itself; rather, it is used as
base class for interpreter classes you define.
Completions¶
The kmd.completions
package defines the custom completion
protocol and implements a set of ready-to-use
completions for kmd.Kmd
.
Applications may use the provided completions and/or add their own,
domain-specific completions based on code in this package.
Quoting¶
The kmd.quoting
module defines constants and functions for writing
custom completions.
Upstream Documentation¶
The standard library documentation for cmd.Cmd.
The rl GNU Readline Bindings.
Interpreters¶
A base class for custom command interpreters.
Kmd Class¶
- class kmd.Kmd(completekey='TAB', stdin=None, stdout=None, stderr=None)¶
Interpreter base class.
This is a subclass of the standard library’s
cmd.Cmd
class, using the newrl
bindings for GNU Readline. The standard library documentation applies unless noted otherwise. Changes include:The
Kmd
constructor accepts an additionalstderr
argument.preloop()
andpostloop()
are not stubs but contain important code bits. Subclasses must make sure to call their parents’ implementations.New methods:
input()
,word_break_hook()
,comment()
,help()
, andrun()
.Incomplete command names are automatically expanded if they are unique.
Command aliases can be defined by extending the
aliases
dictionary.help_*()
methods optionally receive the help topic as argument.complete_*()
methods may return any kind of iterable, not just lists.
Example:
import kmd class MyShell(kmd.Kmd): prompt = 'myshell> ' def do_quit(self, args): return True MyShell().run()
- Kmd.alias_header = 'Command aliases (type help <topic>):'¶
Header for the aliases section of the default help screen. If set to the empty string, the aliases section is omitted.
- Kmd.shell_escape_chars = '!'¶
Special, single-character aliases for
do_shell()
.
- Kmd.history_file = ''¶
If a history filename is set, Kmd loads and saves the history in
preloop()
andpostloop()
.
- Kmd.history_max_entries = -1¶
A non-negative value limits the history size.
- Kmd.cmdloop(intro=None)¶
Repeatedly issue a prompt, accept input, parse an initial prefix off the received input, and dispatch to action methods, passing them the remainder of the line as argument.
- Kmd.preloop()¶
Called when the
cmdloop()
method is entered. Configures the readline completer and loads the history file.
- Kmd.postloop()¶
Called when the
cmdloop()
method is exited. Resets the readline completer and saves the history file. Note thatpostloop()
is called even ifcmdloop()
exits with an exception!
- Kmd.input(prompt)¶
Read a line from the keyboard using
input()
(orraw_input()
in Python 2). When the user presses the TAB key, invoke the readline completer.
- Kmd.word_break_hook(begidx, endidx)¶
When completing
?<topic>
make sure?
is a word break character.Ditto for
!<command>
and!
. Installed asrl.completer.word_break_hook
.
- Kmd.complete(text, state)¶
Return the next possible completion for
text
.If a command has not been entered, complete against the command list. Otherwise try to call
complete_<command>()
to get a list of completions. Installed asrl.completer.completer
.
- Kmd.onecmd(line)¶
Interpret a command line.
This may be overridden, but should not normally need to be; see the
precmd()
andpostcmd()
methods for useful execution hooks. The return value is a flag indicating whether interpretation of commands by the interpreter should stop.If there is a
do_<command>()
method for the command prefix, that method is called, with the remainder of the line as argument, and its return value is returned. Otherwise the return value of thedefault()
method is returned.
- Kmd.parseline(line)¶
Parse the line into a command name and a string containing the arguments. Returns a tuple containing (command, args, line); command and args may be None if the line could not be parsed.
- Kmd.default(line)¶
Called when the command prefix is not recognized. By default prints an error message.
- Kmd.do_help(topic='')¶
Print the help screen for
topic
.If there is a
help_<topic>()
method, that method is called, with the unexpanded topic as argument. Otherwise, and iftopic
is a command, the docstring of thedo_<command>()
method is printed to stdout. Iftopic
is empty thehelp()
method is invoked.
- Kmd.help()¶
Print the default help screen. Empty sections and sections with empty headers are omitted.
Completions¶
A set of completions for use with kmd.Kmd.
Completion Protocol¶
A custom completion is a class that implements at least two methods:
- Completion.__init__()¶
Initializes the completion and configures the readline completer for the type of completion instantiated. May accept additional arguments.
- Completion.__call__(text)¶
Returns an iterable of matches for
text
.
Filename Completion¶
- class kmd.completions.FilenameCompletion(quote_char='\\')¶
Complete file and directory names. The
quote_char
argument specifies the preferred quoting style. Available styles are single-quote, double-quote, and backslash (the default).To ensure proper configuration of readline,
FilenameCompletion
should always be instantiated before other completions.
- FilenameCompletion.__call__(text)¶
Return filenames matching
text
. Starts at the current working directory.
- FilenameCompletion.char_is_quoted(text, index)¶
Return True if the character at
index
is quoted. Installed asrl.completer.char_is_quoted_function
.
- FilenameCompletion.quote_filename(text, single_match, quote_char)¶
Return a quoted version of
text
. Installed asrl.completer.filename_quoting_function
.
- FilenameCompletion.dequote_filename(text, quote_char)¶
Return a dequoted version of
text
. Installed asrl.completer.filename_dequoting_function
.
- FilenameCompletion.rewrite_dirname(text)¶
Convert a directory name the user typed to a format suitable for passing to
opendir()
. Installed asrl.completer.directory_rewrite_hook
.
- FilenameCompletion.rewrite_filename(text)¶
Convert a filename read from the filesystem to a format suitable for comparing against the completion word. Installed as
rl.completer.filename_rewrite_hook
.
- FilenameCompletion.stat_filename(text)¶
Convert a filename the user typed to a format suitable for passing to
stat()
. Installed asrl.completer.filename_stat_hook
.
Username Completion¶
- class kmd.completions.UsernameCompletion¶
Complete user names.
- UsernameCompletion.__call__(text)¶
Return user names matching
text
.User names are returned without decoration. The search string may start with a
~
character, in which case the users’ home directories are returned instead. Home directories start with a~
and end with a/
character.
Hostname Completion¶
- class kmd.completions.HostnameCompletion(hostsfile='/etc/hosts')¶
Complete host names found in the system’s hosts file.
- HostnameCompletion.__call__(text)¶
Return host names matching
text
.Host names are returned with a leading
@
character. The search string may start with an@
character which is stripped before matching.
Environment Completion¶
- class kmd.completions.EnvironmentCompletion¶
Complete names of variables in the process environment.
- EnvironmentCompletion.__call__(text)¶
Return environment variables matching
text
.Variable names are returned with a leading
$
character. The search string may start with a$
character which is stripped before matching.
Command Completion¶
- class kmd.completions.CommandCompletion¶
Complete names of commands on the system PATH.
- CommandCompletion.__call__(text)¶
Return executables matching
text
. Does not include shell built-ins or aliases.
Quoting¶
String and filename quoting support.
Constants¶
- kmd.quoting.QUOTE_CHARACTERS = '"\''¶
These characters may be used in pairs to quote substrings of the line.
- kmd.quoting.WORD_BREAK_CHARACTERS = ' \t\n"\'><;|&=(:'¶
These characters define word boundaries.
- kmd.quoting.FILENAME_QUOTE_CHARACTERS = '\\ \t\n"\'@><;|&=()#$`?*[!:{'¶
These characters are quoted when they occur in filenames.
- kmd.quoting.SLASHIFY_IN_QUOTES = '\\"$`\n'¶
These characters are backslash-quoted even between double quotes.
Extracted from Bash¶
- kmd.quoting.BASH_QUOTE_CHARACTERS = '\'"'¶
Quote characters used by Bash.
- kmd.quoting.BASH_COMPLETER_WORD_BREAK_CHARACTERS = ' \t\n"\'@><;|&=(:'¶
Word break characters used by Bash.
- kmd.quoting.BASH_NOHOSTNAME_WORD_BREAK_CHARACTERS = ' \t\n"\'><;|&=(:'¶
Word break characters used by Bash when hostname completion is off.
- kmd.quoting.BASH_FILENAME_QUOTE_CHARACTERS = '\\ \t\n"\'@><;|&=()#$`?*[!:{~'¶
Filename quote characters used by Bash.
- kmd.quoting.BASH_COMMAND_SEPARATORS = ';|&{(`'¶
Command separators used by Bash.
- kmd.quoting.BASH_WHITESPACE_CHARACTERS = ' \t\n'¶
Whitespace characters used by Bash.
- kmd.quoting.BASH_SLASHIFY_IN_QUOTES = '\\"$`\n'¶
Slashify characters used by Bash.
Functions¶
- kmd.quoting.backslash_quote(text, chars='')¶
Backslash-quote all
rl.completer.filename_quote_characters
intext
. Ifchars
is given, only characters inchars
are quoted.
- kmd.quoting.backslash_dequote(text, chars='')¶
Backslash-dequote all
rl.completer.filename_quote_characters
intext
. Ifchars
is given, only characters inchars
are dequoted.
- kmd.quoting.is_fully_quoted(text, chars='')¶
Return True if all
rl.completer.filename_quote_characters
intext
are backslash-quoted. Ifchars
is given, only characters inchars
are checked.
- kmd.quoting.char_is_quoted(text, index)¶
Return True if the character at
index
is quoted.
- kmd.quoting.quote_string(text, single_match=True, quote_char='')¶
Return a
quote_char
-quoted version oftext
. Ifsingle_match
is False, the quotes are not closed. The defaultquote_char
is the first character inrl.completer.quote_characters
.
- kmd.quoting.backslash_quote_string(text, single_match=True, quote_char='')¶
Return a backslash-quoted version of
text
. If aquote_char
is given, behave likequote_string()
.
- kmd.quoting.backslash_dequote_string(text, quote_char='')¶
Return a backslash-dequoted version of
text
. Ifquote_char
is the single-quote, backslash-dequoting is limited to single-quotes.
- kmd.quoting.quote_filename(text, single_match=True, quote_char='')¶
Return a
quote_char
-quoted version oftext
. Ifsingle_match
is False ortext
is a directory, the quotes are not closed. The defaultquote_char
is the first character inrl.completer.quote_characters
.
- kmd.quoting.backslash_quote_filename(text, single_match=True, quote_char='')¶
Return a backslash-quoted version of
text
. If aquote_char
is given, behave likequote_filename()
.
- kmd.quoting.backslash_dequote_filename(text, quote_char='')¶
Return a backslash-dequoted version of
text
. Ifquote_char
is the single-quote, backslash-dequoting is limited to single-quotes.
Examples¶
Example code.
Simple App¶
A bare-bones application demonstrating filename and environment variable
completion. You can run this example with python -m kmd.examples.myshell
.
# TAB-complete command names, help topics, filenames, and environment variables
import os
import kmd
from kmd.completions import FilenameCompletion
from kmd.completions import EnvironmentCompletion
class MyShell(kmd.Kmd):
intro = 'myshell 1.0 (type help for help)\n'
prompt = 'myshell> '
def preloop(self):
super().preloop()
self.completefilename = FilenameCompletion()
self.completeenviron = EnvironmentCompletion()
def do_cat(self, args):
"""Usage: cat <filename>"""
os.system('cat ' + args)
def do_echo(self, args):
"""Usage: echo $<varname>"""
os.system('echo ' + args)
def do_quit(self, args):
"""Usage: quit"""
return True
def do_EOF(self, args):
return True
def complete_cat(self, text, *ignored):
return self.completefilename(text)
def complete_echo(self, text, *ignored):
return self.completeenviron(text)
def help_help(self):
self.stdout.write('Usage: help [<topic>]\n')
def emptyline(self):
pass
def main():
return MyShell().run()
if __name__ == '__main__':
main()
Custom Completion¶
An implementation of environment variable completion.
# Environment variable completion
import os
from rl import completer
class EnvironmentCompletion(object):
def __init__(self):
"""Configure the readline completer
"""
if '$' not in completer.word_break_characters:
completer.word_break_characters += '$'
if '$' not in completer.special_prefixes:
completer.special_prefixes += '$'
def __call__(self, text):
"""Return environment variables matching 'text'
Variable names are returned with a leading '$' character.
The search string may start with a '$' character which is
stripped before matching.
"""
if text.startswith('$'):
text = text[1:]
return ['$'+x for x in os.environ if x.startswith(text)]