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.
43 IDENTCHARS
= string
.letters
+ string
.digits
+ '_'
47 identchars
= IDENTCHARS
51 doc_header
= "Documented commands (type help <topic>):"
52 misc_header
= "Miscellaneous help topics:"
53 undoc_header
= "Undocumented commands:"
55 def __init__(self
): pass
57 def cmdloop(self
, intro
=None):
66 line
= raw_input(self
.prompt
)
70 stop
= self
.onecmd(line
)
86 def onecmd(self
, line
):
87 line
= string
.strip(line
)
91 if hasattr(self
, 'do_shell'):
94 return self
.default(line
)
96 return self
.emptyline()
99 while i
< n
and line
[i
] in self
.identchars
: i
= i
+1
100 cmd
, arg
= line
[:i
], string
.strip(line
[i
:])
102 return self
.default(line
)
105 func
= getattr(self
, 'do_' + cmd
)
106 except AttributeError:
107 return self
.default(line
)
111 return self
.onecmd(self
.lastcmd
)
113 def default(self
, line
):
114 print '*** Unknown syntax:', line
116 def do_help(self
, arg
):
118 # XXX check arg syntax
120 func
= getattr(self
, 'help_' + arg
)
122 print '*** No help on', `arg`
126 names
= dir(self
.__class
__)
131 if name
[:5] == 'help_':
134 if name
[:3] == 'do_':
136 if help.has_key(cmd
):
140 cmds_undoc
.append(cmd
)
142 self
.print_topics(self
.doc_header
, cmds_doc
, 15,80)
143 self
.print_topics(self
.misc_header
, help.keys(),15,80)
144 self
.print_topics(self
.undoc_header
, cmds_undoc
, 15,80)
146 def print_topics(self
, header
, cmds
, cmdlen
, maxcol
):
150 print self
.ruler
* len(header
)
151 (cmds_per_line
,junk
)=divmod(maxcol
,cmdlen
)
155 print (("%-"+`cmdlen`
+"s") % cmd
),
156 col
= (col
+1) % cmds_per_line