kopia lustrzana https://github.com/micropython/micropython-lib
cmd: Customize to work with MicroPython.
rodzic
d71c6a3a0b
commit
eac000342e
100
cmd/cmd.py
100
cmd/cmd.py
|
@ -40,14 +40,25 @@ The data members `self.doc_header', `self.misc_header', and
|
||||||
`self.undoc_header' set the headers used for the help function's
|
`self.undoc_header' set the headers used for the help function's
|
||||||
listings of documented functions, miscellaneous topics, and undocumented
|
listings of documented functions, miscellaneous topics, and undocumented
|
||||||
functions respectively.
|
functions respectively.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
This is a copy of python's Cmd, but leaves out features that aren't relevant
|
||||||
|
or can't currently be implemented for MicroPython.
|
||||||
|
|
||||||
|
One of the notable deviations is that since MicroPython strips doc strings,
|
||||||
|
this means that that help by doc string feature doesn't work.
|
||||||
|
|
||||||
|
completions have also been stripped out.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import string, sys
|
#import string, sys
|
||||||
|
import sys # MiroPython doesn't yet have a string module
|
||||||
|
|
||||||
__all__ = ["Cmd"]
|
__all__ = ["Cmd"]
|
||||||
|
|
||||||
PROMPT = '(Cmd) '
|
PROMPT = '(Cmd) '
|
||||||
IDENTCHARS = string.ascii_letters + string.digits + '_'
|
#IDENTCHARS = string.ascii_letters + string.digits + '_'
|
||||||
|
IDENTCHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_'
|
||||||
|
|
||||||
class Cmd:
|
class Cmd:
|
||||||
"""A simple framework for writing line-oriented command interpreters.
|
"""A simple framework for writing line-oriented command interpreters.
|
||||||
|
@ -73,13 +84,10 @@ class Cmd:
|
||||||
nohelp = "*** No help on %s"
|
nohelp = "*** No help on %s"
|
||||||
use_rawinput = 1
|
use_rawinput = 1
|
||||||
|
|
||||||
def __init__(self, completekey='tab', stdin=None, stdout=None):
|
def __init__(self, stdin=None, stdout=None):
|
||||||
"""Instantiate a line-oriented interpreter framework.
|
"""Instantiate a line-oriented interpreter framework.
|
||||||
|
|
||||||
The optional argument 'completekey' is the readline name of a
|
The optional arguments stdin and stdout
|
||||||
completion key; it defaults to the Tab key. If completekey is
|
|
||||||
not None and the readline module is available, command completion
|
|
||||||
is done automatically. The optional arguments stdin and stdout
|
|
||||||
specify alternate input and output file objects; if not specified,
|
specify alternate input and output file objects; if not specified,
|
||||||
sys.stdin and sys.stdout are used.
|
sys.stdin and sys.stdout are used.
|
||||||
|
|
||||||
|
@ -93,7 +101,6 @@ class Cmd:
|
||||||
else:
|
else:
|
||||||
self.stdout = sys.stdout
|
self.stdout = sys.stdout
|
||||||
self.cmdqueue = []
|
self.cmdqueue = []
|
||||||
self.completekey = completekey
|
|
||||||
|
|
||||||
def cmdloop(self, intro=None):
|
def cmdloop(self, intro=None):
|
||||||
"""Repeatedly issue a prompt, accept input, parse an initial prefix
|
"""Repeatedly issue a prompt, accept input, parse an initial prefix
|
||||||
|
@ -103,14 +110,6 @@ class Cmd:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.preloop()
|
self.preloop()
|
||||||
if self.use_rawinput and self.completekey:
|
|
||||||
try:
|
|
||||||
import readline
|
|
||||||
self.old_completer = readline.get_completer()
|
|
||||||
readline.set_completer(self.complete)
|
|
||||||
readline.parse_and_bind(self.completekey+": complete")
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
try:
|
try:
|
||||||
if intro is not None:
|
if intro is not None:
|
||||||
self.intro = intro
|
self.intro = intro
|
||||||
|
@ -139,13 +138,7 @@ class Cmd:
|
||||||
stop = self.postcmd(stop, line)
|
stop = self.postcmd(stop, line)
|
||||||
self.postloop()
|
self.postloop()
|
||||||
finally:
|
finally:
|
||||||
if self.use_rawinput and self.completekey:
|
pass
|
||||||
try:
|
|
||||||
import readline
|
|
||||||
readline.set_completer(self.old_completer)
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def precmd(self, line):
|
def precmd(self, line):
|
||||||
"""Hook method executed just before the command line is
|
"""Hook method executed just before the command line is
|
||||||
|
@ -235,60 +228,11 @@ class Cmd:
|
||||||
"""
|
"""
|
||||||
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
|
|
||||||
complete_*() method is available.
|
|
||||||
|
|
||||||
By default, it returns an empty list.
|
|
||||||
|
|
||||||
"""
|
|
||||||
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):
|
def get_names(self):
|
||||||
# This method used to pull in base class attributes
|
# This method used to pull in base class attributes
|
||||||
# at a time dir() didn't do it yet.
|
# at a time dir() didn't do it yet.
|
||||||
return dir(self.__class__)
|
return dir(self.__class__)
|
||||||
|
|
||||||
def complete_help(self, *args):
|
|
||||||
commands = set(self.completenames(*args))
|
|
||||||
topics = set(a[5:] for a in self.get_names()
|
|
||||||
if a.startswith('help_' + args[0]))
|
|
||||||
return list(commands | topics)
|
|
||||||
|
|
||||||
def do_help(self, arg):
|
def do_help(self, arg):
|
||||||
'List available commands with "help" or detailed help with "help cmd".'
|
'List available commands with "help" or detailed help with "help cmd".'
|
||||||
if arg:
|
if arg:
|
||||||
|
@ -296,13 +240,6 @@ class Cmd:
|
||||||
try:
|
try:
|
||||||
func = getattr(self, 'help_' + arg)
|
func = getattr(self, 'help_' + arg)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
try:
|
|
||||||
doc=getattr(self, 'do_' + arg).__doc__
|
|
||||||
if 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
|
return
|
||||||
func()
|
func()
|
||||||
|
@ -326,8 +263,6 @@ class Cmd:
|
||||||
if cmd in help:
|
if cmd in help:
|
||||||
cmds_doc.append(cmd)
|
cmds_doc.append(cmd)
|
||||||
del help[cmd]
|
del help[cmd]
|
||||||
elif getattr(self, name).__doc__:
|
|
||||||
cmds_doc.append(cmd)
|
|
||||||
else:
|
else:
|
||||||
cmds_undoc.append(cmd)
|
cmds_undoc.append(cmd)
|
||||||
self.stdout.write("%s\n"%str(self.doc_leader))
|
self.stdout.write("%s\n"%str(self.doc_leader))
|
||||||
|
@ -397,5 +332,6 @@ class Cmd:
|
||||||
while texts and not texts[-1]:
|
while texts and not texts[-1]:
|
||||||
del texts[-1]
|
del texts[-1]
|
||||||
for col in range(len(texts)):
|
for col in range(len(texts)):
|
||||||
texts[col] = texts[col].ljust(colwidths[col])
|
#texts[col] = texts[col].ljust(colwidths[col])
|
||||||
|
texts[col] = '%-*s' % (colwidths[col], texts[col])
|
||||||
self.stdout.write("%s\n"%str(" ".join(texts)))
|
self.stdout.write("%s\n"%str(" ".join(texts)))
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
srctype = cpython
|
||||||
|
type = module
|
||||||
|
version = 0.0.1
|
|
@ -0,0 +1,18 @@
|
||||||
|
import sys
|
||||||
|
# Remove current dir from sys.path, otherwise setuptools will peek up our
|
||||||
|
# module instead of system.
|
||||||
|
sys.path.pop(0)
|
||||||
|
from setuptools import setup
|
||||||
|
|
||||||
|
|
||||||
|
setup(name='micropython-cmd',
|
||||||
|
version='0.0.1',
|
||||||
|
description='CPython cmd module ported to MicroPython',
|
||||||
|
long_description='This is a module ported from CPython standard library to be compatible with\nMicroPython interpreter. Usually, this means applying small patches for\nfeatures not supported (yet, or at all) in MicroPython. Sometimes, heavier\nchanges are required. Note that CPython modules are written with availability\nof vast resources in mind, and may not work for MicroPython ports with\nlimited heap. If you are affected by such a case, please help reimplement\nthe module from scratch.',
|
||||||
|
url='https://github.com/micropython/micropython/issues/405',
|
||||||
|
author='CPython Developers',
|
||||||
|
author_email='python-dev@python.org',
|
||||||
|
maintainer='MicroPython Developers',
|
||||||
|
maintainer_email='micro-python@googlegroups.com',
|
||||||
|
license='Python',
|
||||||
|
py_modules=['cmd'])
|
Ładowanie…
Reference in New Issue