Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 30 additions & 26 deletions Lib/cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,16 @@
functions respectively.
"""

import string, sys
import inspect
import string
import sys

__all__ = ["Cmd"]

PROMPT = '(Cmd) '
IDENTCHARS = string.ascii_letters + string.digits + '_'


class Cmd:
"""A simple framework for writing line-oriented command interpreters.

Expand Down Expand Up @@ -108,14 +111,14 @@ def cmdloop(self, intro=None):
import readline
self.old_completer = readline.get_completer()
readline.set_completer(self.complete)
readline.parse_and_bind(self.completekey+": complete")
readline.parse_and_bind(self.completekey + ": complete")
except ImportError:
pass
try:
if intro is not None:
self.intro = intro
if self.intro:
self.stdout.write(str(self.intro)+"\n")
self.stdout.write(str(self.intro) + "\n")
stop = None
while not stop:
if self.cmdqueue:
Expand Down Expand Up @@ -146,7 +149,6 @@ def cmdloop(self, intro=None):
except ImportError:
pass


def precmd(self, line):
"""Hook method executed just before the command line is
interpreted, but after the input prompt is generated and issued.
Expand Down Expand Up @@ -185,7 +187,8 @@ def parseline(self, line):
else:
return None, None, line
i, n = 0, len(line)
while i < n and line[i] in self.identchars: i = i+1
while i < n and line[i] in self.identchars:
i = i + 1
cmd, arg = line[:i], line[i:].strip()
return cmd, arg, line

Expand All @@ -205,7 +208,7 @@ def onecmd(self, line):
if cmd is None:
return self.default(line)
self.lastcmd = line
if line == 'EOF' :
if line == 'EOF':
self.lastcmd = ''
if cmd == '':
return self.default(line)
Expand Down Expand Up @@ -233,7 +236,7 @@ def default(self, line):
returns.

"""
self.stdout.write('*** Unknown syntax: %s\n'%line)
self.stdout.write('*** Unknown syntax: %s\n' % line)

def completedefault(self, *ignored):
"""Method called to complete an input line when no command-specific
Expand All @@ -245,7 +248,7 @@ def completedefault(self, *ignored):
return []

def completenames(self, text, *ignored):
dotext = 'do_'+text
dotext = 'do_' + text
return [a[3:] for a in self.get_names() if a.startswith(dotext)]

def complete(self, text, state):
Expand All @@ -261,7 +264,7 @@ def complete(self, text, state):
stripped = len(origline) - len(line)
begidx = readline.get_begidx() - stripped
endidx = readline.get_endidx() - stripped
if begidx>0:
if begidx > 0:
cmd, args, foo = self.parseline(line)
if cmd == '':
compfunc = self.completedefault
Expand Down Expand Up @@ -297,13 +300,14 @@ def do_help(self, arg):
func = getattr(self, 'help_' + arg)
except AttributeError:
try:
doc=getattr(self, 'do_' + arg).__doc__
doc = getattr(self, 'do_' + arg).__doc__
doc = inspect.cleandoc(doc)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUIC, this line is the actual patch

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this and, obviously, the additional import

if doc:
self.stdout.write("%s\n"%str(doc))
self.stdout.write("%s\n" % str(doc))
return
except AttributeError:
pass
self.stdout.write("%s\n"%str(self.nohelp % (arg,)))
self.stdout.write("%s\n" % str(self.nohelp % (arg,)))
return
func()
else:
Expand All @@ -322,25 +326,25 @@ def do_help(self, arg):
if name == prevname:
continue
prevname = name
cmd=name[3:]
cmd = name[3:]
if cmd in topics:
cmds_doc.append(cmd)
topics.remove(cmd)
elif getattr(self, name).__doc__:
cmds_doc.append(cmd)
else:
cmds_undoc.append(cmd)
self.stdout.write("%s\n"%str(self.doc_leader))
self.print_topics(self.doc_header, cmds_doc, 15,80)
self.print_topics(self.misc_header, sorted(topics),15,80)
self.print_topics(self.undoc_header, cmds_undoc, 15,80)
self.stdout.write("%s\n" % str(self.doc_leader))
self.print_topics(self.doc_header, cmds_doc, 15, 80)
self.print_topics(self.misc_header, sorted(topics), 15, 80)
self.print_topics(self.undoc_header, cmds_undoc, 15, 80)

def print_topics(self, header, cmds, cmdlen, maxcol):
if cmds:
self.stdout.write("%s\n"%str(header))
self.stdout.write("%s\n" % str(header))
if self.ruler:
self.stdout.write("%s\n"%str(self.ruler * len(header)))
self.columnize(cmds, maxcol-1)
self.stdout.write("%s\n" % str(self.ruler * len(header)))
self.columnize(cmds, maxcol - 1)
self.stdout.write("\n")

def columnize(self, list, displaywidth=80):
Expand All @@ -354,23 +358,23 @@ def columnize(self, list, displaywidth=80):
return

nonstrings = [i for i in range(len(list))
if not isinstance(list[i], str)]
if not isinstance(list[i], str)]
if nonstrings:
raise TypeError("list[i] not a string for i in %s"
% ", ".join(map(str, nonstrings)))
size = len(list)
if size == 1:
self.stdout.write('%s\n'%str(list[0]))
self.stdout.write('%s\n' % str(list[0]))
return
# Try every row count from 1 upwards
for nrows in range(1, len(list)):
ncols = (size+nrows-1) // nrows
ncols = (size + nrows - 1) // nrows
colwidths = []
totwidth = -2
for col in range(ncols):
colwidth = 0
for row in range(nrows):
i = row + nrows*col
i = row + nrows * col
if i >= size:
break
x = list[i]
Expand All @@ -388,7 +392,7 @@ def columnize(self, list, displaywidth=80):
for row in range(nrows):
texts = []
for col in range(ncols):
i = row + nrows*col
i = row + nrows * col
if i >= size:
x = ""
else:
Expand All @@ -398,4 +402,4 @@ def columnize(self, list, displaywidth=80):
del texts[-1]
for col in range(len(texts)):
texts[col] = texts[col].ljust(colwidths[col])
self.stdout.write("%s\n"%str(" ".join(texts)))
self.stdout.write("%s\n" % str(" ".join(texts)))
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
:meth:`cmd.Cmd.do_help` now cleans docstrings with :func:`inspect.cleandoc`
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if ":meth:cmd.Cmd.do_help" is correct, there definitely is no cmd.Cmd.do_help anchor in the documentation. Maybe I'd need to update the documentation to give do_help a separate section. I'm open to feedback here and in general.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems to work. Let's not worry about it.

before writing them. Patch by Filip Łapkiewicz.