summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZearin <zearin@gonk.net>2011-10-08 09:05:10 -0400
committerZearin <zearin@gonk.net>2011-10-08 09:05:10 -0400
commite641f29289cd22aeea7fa277c9c3beaa93028a84 (patch)
tree511dfd3a5cce027491285fe5aa48e331e82a033a
parent55084970e49c839cee9b2c7337f2905bc7950391 (diff)
downloadcmd2-e641f29289cd22aeea7fa277c9c3beaa93028a84.tar.gz
Moved all `do_*` methods to commands.py.
The contents of commands.py gets imported at the top of the Cmd class. Also did a couple other small tweaks to the Cmd class. Mostly moving stuff around (private defs first, sorted the class variables near the top of Cmd, etc.)
-rwxr-xr-xcmd2.py667
-rw-r--r--commands.py354
2 files changed, 520 insertions, 501 deletions
diff --git a/cmd2.py b/cmd2.py
index b2b9cd6..88a3ac0 100755
--- a/cmd2.py
+++ b/cmd2.py
@@ -48,8 +48,8 @@ import pyparsing
# Local imports
-from . import commands, \
- errors, \
+# (commands.py is imported in the Cmd class)
+from . import errors, \
parsers, \
support, \
tests
@@ -73,48 +73,88 @@ if sys.version_info[0] == 2:
class Cmd(cmd.Cmd):
- echo = False
+ from . import commands # I *think* this lets commands get their own file
+ # while still limiting their scope to this class...
+
+
+ _STOP_AND_EXIT = True # distinguish script file's end from actual exit
+ _STOP_SCRIPT_NO_EXIT = -999
+
+
+ # @TODO
+ # Refactor all shell settings into a module or single
+ # data structure (list/dict/whatever).
+ # Perhaps call it "shopt"?
+ #
+ # Currently the "settable" StubbornDict groups user-settable
+ # options, but I'd prefer they *existed* as a group,
+ # rather than merely a bunch of variables that get *referenced*
+ # as a group.
+
+
+
+
+ abbrev = True # Abbreviated commands recognized
case_insensitive = True # Commands recognized regardless of case
continuation_prompt = '> '
- timing = False # Prints elapsed time for each command
+ current_script_dir = None
+ debug = False
+ default_file_name = 'command.txt' # For ``save``, ``load``, etc.
+ default_to_shell = False
+ defaultExtension = 'txt' # For ``save``, ``load``, etc.
+ echo = False
+ excludeFromHistory = '''run r list l history hi ed edit li eof'''.split()
+ feedback_to_output = False # Include nonessentials in >, | output
+ kept_state = None
# make sure your terminators are not in legalChars!
legalChars = u'!#$%.:?@_' + pyparsing.alphanums + pyparsing.alphas8bit
+ locals_in_py = True
+ noSpecialParse = 'set ed edit exit'.split()
+ quiet = False # Do not suppress nonessential output
+ redirector = '>' # For redirecting output to a file
+ reserved_words = []
shortcuts = { '?': 'help',
'!': 'shell',
'@': 'load',
'@@': '_relative_load' }
-
- excludeFromHistory = '''run r list l history hi ed edit li eof'''.split()
- default_to_shell = False
- noSpecialParse = 'set ed edit exit'.split()
- defaultExtension = 'txt' # For ``save``, ``load``, etc.
- default_file_name = 'command.txt' # For ``save``, ``load``, etc.
- abbrev = True # Abbreviated commands recognized
- current_script_dir = None
- reserved_words = []
- feedback_to_output = False # Include nonessentials in >, | output
- quiet = False # Do not suppress nonessential output
- debug = False
- locals_in_py = True
- kept_state = None
- redirector = '>' # For redirecting output to a file
+ timing = False # Prints elapsed time for each command
settable = stubbornDict('''
- prompt
+ abbrev Accept abbreviated commands
+ case_insensitive upper- and lower-case both OK
colors Colorized output (*nix only)
continuation_prompt On 2nd+ line of input
debug Show full error stack on error
default_file_name for ``save``, ``load``, etc.
+ echo Echo command issued into output
editor Program used by ``edit``
- case_insensitive upper- and lower-case both OK
feedback_to_output include nonessentials in `|`, `>` results
+ prompt
quiet Don't print nonessential feedback
- echo Echo command issued into output
timing Report execution times
- abbrev Accept abbreviated commands
''')
+ editor = os.environ.get('EDITOR')
+
+ if not editor:
+ if sys.platform[:3] == 'win':
+ editor = 'notepad'
+ else:
+ for editor in ['gedit', 'kate', 'vim', 'emacs', 'nano', 'pico']:
+ if subprocess.Popen(['which', editor], stdout=subprocess.PIPE).communicate()[0]:
+ break
+
+
+ prefixParser = pyparsing.Empty()
+ commentGrammars = pyparsing.Or([pyparsing.pythonStyleComment, pyparsing.cStyleComment])
+ commentGrammars.addParseAction(lambda x: '')
+ commentInProgress = pyparsing.Literal('/*') + pyparsing.SkipTo(pyparsing.stringEnd ^ '*/')
+ terminators = [';']
+ blankLinesAllowed = False
+ multilineCommands = []
+
+
def __init__(self, *args, **kwargs):
# @FIXME
#
@@ -132,83 +172,60 @@ class Cmd(cmd.Cmd):
self._init_parser()
- def poutput(self, msg):
- '''
- Convenience shortcut for self.stdout.write(). Adds newline if necessary.
- '''
- if msg:
- self.stdout.write(msg)
- if msg[-1] != '\n':
- self.stdout.write('\n')
-
-
- def perror(self, errmsg, statement=None):
- if self.debug:
- traceback.print_exc()
- print (str(errmsg))
-
-
- def pfeedback(self, msg):
+ def _cmdloop(self, intro=None):
'''
- Prints nonessential feedback. Can be silenced with `quiet`.
-
- Inclusion in redirected output is controlled by `feedback_to_output`.
+ 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.
'''
- if not self.quiet:
- if self.feedback_to_output:
- self.poutput(msg)
- else:
- print (msg)
-
- _STOP_AND_EXIT = True # distinguish script file's end from actual exit
- _STOP_SCRIPT_NO_EXIT = -999
-
- editor = os.environ.get('EDITOR')
-
- if not editor:
- if sys.platform[:3] == 'win':
- editor = 'notepad'
- else:
- for editor in ['gedit', 'kate', 'vim', 'emacs', 'nano', 'pico']:
- if subprocess.Popen(['which', editor], stdout=subprocess.PIPE).communicate()[0]:
- break
-
- colorcodes = { 'bold' :{True:'\x1b[1m' ,False:'\x1b[22m'},
- 'cyan' :{True:'\x1b[36m',False:'\x1b[39m'},
- 'blue' :{True:'\x1b[34m',False:'\x1b[39m'},
- 'red' :{True:'\x1b[31m',False:'\x1b[39m'},
- 'magenta' :{True:'\x1b[35m',False:'\x1b[39m'},
- 'green' :{True:'\x1b[32m',False:'\x1b[39m'},
- 'underline' :{True:'\x1b[4m' ,False:'\x1b[24m'}
- }
-
- colors = (platform.system() != 'Windows')
-
-
- def colorize(self, val, color):
- '''
- Wraps the provided string in UNIX-style special characters that
- turn on (and then off) text color and style.
+ # An almost-perfect copy from Cmd.
+ #
+ # However, the `pseudo_raw_input` portion has been
+ # split out so that it can be called separately.
- The string is returned unchanged if the ``colors`` environment variable
- is ``False`` or the application is running on Windows.
+ self.preloop()
- ``color`` should be one of the supported strings (or styles):
- red/blue/green/cyan/magenta, bold, underline
- '''
- if self.colors and (self.stdout == self.initial_stdout):
- return self.colorcodes[color][True] + val + self.colorcodes[color][False]
- return val
+ 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:
+ if intro is not None:
+ self.intro = intro
+ if self.intro:
+ self.stdout.write(str(self.intro)+"\n")
+ stop = None
+ while not stop:
+ if self.cmdqueue:
+ line = self.cmdqueue.pop(0)
+ else:
+ line = self.pseudo_raw_input(self.prompt)
+ if (self.echo) and (isinstance(self.stdin, file)):
+ self.stdout.write(line + '\n')
+ stop = self.onecmd_plus_hooks(line)
+ self.postloop()
+ finally:
+ if self.use_rawinput and self.completekey:
+ try:
+ import readline
+ readline.set_completer(self.old_completer)
+ except ImportError:
+ pass
+ return stop
- prefixParser = pyparsing.Empty()
- commentGrammars = pyparsing.Or([pyparsing.pythonStyleComment, pyparsing.cStyleComment])
- commentGrammars.addParseAction(lambda x: '')
- commentInProgress = pyparsing.Literal('/*') + pyparsing.SkipTo(pyparsing.stringEnd ^ '*/')
- terminators = [';']
- blankLinesAllowed = False
- multilineCommands = []
+ def _default(self, statement):
+ arg = statement.full_parsed_statement()
+ if self.default_to_shell:
+ result = os.system(arg)
+ if not result:
+ return self.postparsing_postcmd(None)
+ return self.postparsing_postcmd(self.default(arg))
# @TODO
@@ -502,6 +519,64 @@ class Cmd(cmd.Cmd):
return stop
+ def poutput(self, msg):
+ '''
+ Convenience shortcut for self.stdout.write(). Adds newline if necessary.
+ '''
+ if msg:
+ self.stdout.write(msg)
+ if msg[-1] != '\n':
+ self.stdout.write('\n')
+
+
+ def perror(self, errmsg, statement=None):
+ if self.debug:
+ traceback.print_exc()
+ print (str(errmsg))
+
+
+ def pfeedback(self, msg):
+ '''
+ Prints nonessential feedback. Can be silenced with `quiet`.
+
+ Inclusion in redirected output is controlled by `feedback_to_output`.
+ '''
+ if not self.quiet:
+ if self.feedback_to_output:
+ self.poutput(msg)
+ else:
+ print (msg)
+
+
+ colorcodes = { 'bold' :{True:'\x1b[1m' ,False:'\x1b[22m'},
+ 'cyan' :{True:'\x1b[36m',False:'\x1b[39m'},
+ 'blue' :{True:'\x1b[34m',False:'\x1b[39m'},
+ 'red' :{True:'\x1b[31m',False:'\x1b[39m'},
+ 'magenta' :{True:'\x1b[35m',False:'\x1b[39m'},
+ 'green' :{True:'\x1b[32m',False:'\x1b[39m'},
+ 'underline' :{True:'\x1b[4m' ,False:'\x1b[24m'}
+ }
+
+
+ colors = (platform.system() != 'Windows')
+
+
+ def colorize(self, val, color):
+ '''
+ Wraps the provided string in UNIX-style special characters that
+ turn on (and then off) text color and style.
+
+ The string is returned unchanged if the ``colors`` environment variable
+ is ``False`` or the application is running on Windows.
+
+ ``color`` should be one of the supported strings (or styles):
+ red/blue/green/cyan/magenta, bold, underline
+ '''
+ if self.colors and (self.stdout == self.initial_stdout):
+ return self.colorcodes[color][True] + val + self.colorcodes[color][False]
+ return val
+
+
def func_named(self, arg):
result = None
target = 'do_' + arg
@@ -633,15 +708,6 @@ class Cmd(cmd.Cmd):
return stop
- def _default(self, statement):
- arg = statement.full_parsed_statement()
- if self.default_to_shell:
- result = os.system(arg)
- if not result:
- return self.postparsing_postcmd(None)
- return self.postparsing_postcmd(self.default(arg))
-
-
def pseudo_raw_input(self, prompt):
'''
Copied from cmd's cmdloop. Similar to raw_input, but accounts for changed stdin/stdout.
@@ -663,53 +729,6 @@ class Cmd(cmd.Cmd):
return line
- def _cmdloop(self, 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.
- '''
-
- # An almost-perfect copy from Cmd.
- #
- # However, the `pseudo_raw_input` portion has been
- # split out so that it can be called separately.
-
- 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:
- if intro is not None:
- self.intro = intro
- if self.intro:
- self.stdout.write(str(self.intro)+"\n")
- stop = None
- while not stop:
- if self.cmdqueue:
- line = self.cmdqueue.pop(0)
- else:
- line = self.pseudo_raw_input(self.prompt)
- if (self.echo) and (isinstance(self.stdin, file)):
- self.stdout.write(line + '\n')
- stop = self.onecmd_plus_hooks(line)
- self.postloop()
- finally:
- if self.use_rawinput and self.completekey:
- try:
- import readline
- readline.set_completer(self.old_completer)
- except ImportError:
- pass
- return stop
-
-
def select(self, options, prompt='Your choice? '):
'''
Presents a numbered menu to the user. Modeled after
@@ -814,356 +833,6 @@ class Cmd(cmd.Cmd):
return self._STOP_AND_EXIT
- def do__relative_load(self, arg=None):
- '''
- Runs commands in script at file or URL; if this is called from within an
- already-running script, the filename will be interpreted relative to the
- already-running script's directory.
- '''
- if arg:
- arg = arg.split(None, 1)
- targetname, args = arg[0], (arg[1:] or [''])[0]
- targetname = os.path.join(self.current_script_dir or '', targetname)
- self.do__load('%s %s' % (targetname, args))
-
- urlre = re.compile('(https?://[-\\w\\./]+)')
-
- def do_cmdenvironment(self, args):
- '''
- Summary report of interactive parameters.
- '''
-
- self.stdout.write("""
- Commands are %(casesensitive)scase-sensitive.
- Commands may be terminated with: %(terminators)s
-
- Settable parameters: %(settable)s\n""" % \
- { 'casesensitive' : (self.case_insensitive and 'not ') or '',
- 'terminators' : str(self.terminators),
- 'settable' : ' '.join(self.settable)
- })
-
-
- def do_help(self, arg):
- if arg:
- funcname = self.func_named(arg)
- if funcname:
- fn = getattr(self, funcname)
- try:
- fn.optionParser.print_help(file=self.stdout)
- except AttributeError:
- cmd.Cmd.do_help(self, funcname[3:])
- else:
- cmd.Cmd.do_help(self, arg)
-
-
- def do_shortcuts(self, args):
- '''
- Lists single-key shortcuts available.
- '''
- result = "\n".join('%s: %s' % (sc[0], sc[1]) for sc in sorted(self.shortcuts))
- self.stdout.write("Single-key shortcuts for other commands:\n%s\n" % (result))
-
-
- def do_EOF(self, arg):
- return self._STOP_SCRIPT_NO_EXIT # End of script; should not exit app
-
- do_eof = do_EOF
-
-
- def do_quit(self, arg):
- return self._STOP_AND_EXIT
-
- do_exit = do_quit
- do_q = do_quit
-
-
- @options(
- [make_option(
- '-l', '--long',
- action ="store_true",
- help ="describe function of parameter")])
- def do_show(self, arg, opts):
- '''
- Show the value of a parameter.
- '''
- param = arg.strip().lower()
- result = {}
- maxlen = 0
- for p in self.settable:
- if (not param) or p.startswith(param):
- result[p] = '%s: %s' % (p, str(getattr(self, p)))
- maxlen = max(maxlen, len(result[p]))
- if result:
- for p in sorted(result):
- if opts.long:
- self.poutput('%s # %s' % (result[p].ljust(maxlen), self.settable[p]))
- else:
- self.poutput(result[p])
- else:
- raise NotImplementedError("Parameter '%s' not supported (type 'show' for list of parameters)." % param)
-
-
- def do_set(self, arg):
- '''
- Set a cmd2 parameter. Accepts abbreviated parameter names
- if there is no ambiguity. Lists settable parameters and values if
- called with no arguments.
- '''
- try:
- statement, paramName, val = arg.parsed.raw.split(None, 2)
- val = val.strip()
- paramName = paramName.strip().lower()
-
- if paramName not in self.settable:
- hits = [p for p in self.settable if p.startswith(paramName)]
- if len(hits) == 1:
- paramName = hits[0]
- else:
- return self.do_show(paramName)
- currentVal = getattr(self, paramName)
-
- if (val[0] == val[-1]) and val[0] in ("'", '"'):
- val = val[1:-1]
- else:
- val = cast(currentVal, val)
-
- setattr(self, paramName, val)
- self.stdout.write('%s - was: %s\nnow: %s\n' % (paramName, currentVal, val))
-
- if currentVal != val:
- try:
- onchange_hook = getattr(self, '_onchange_%s' % paramName)
- onchange_hook(old=currentVal, new=val)
- except AttributeError:
- pass
- except (ValueError, AttributeError, NotSettableError), e:
- self.do_show(arg)
-
-
- def do_pause(self, arg):
- '''Display the provided text, then wait for the user to press RETURN.'''
- raw_input(arg + '\n')
-
-
- def do_shell(self, arg):
- '''
- Executes a command as if at the OS prompt.
- '''
- os.system(arg)
-
-
- def do_py(self, arg):
- '''
- py <command>: Executes a Python command.
- py: Enters interactive Python mode.
-
- End with ``Ctrl-D`` (Unix) / ``Ctrl-Z`` (Windows), ``quit()``, '`exit()``.
-
- Non-python commands can be issued with ``cmd("your command")``.
- Run python code from external files with ``run("filename.py")``
- '''
- self.pystate['self'] = self
- arg = arg.parsed.raw[2:].strip()
- localvars = (self.locals_in_py and self.pystate) or {}
- interp = InteractiveConsole(locals=localvars)
- interp.runcode('import sys, os;sys.path.insert(0, os.getcwd())')
-
- if arg.strip():
- interp.runcode(arg)
- else:
- def quit():
- raise EmbeddedConsoleExit
- def onecmd_plus_hooks(arg):
- return self.onecmd_plus_hooks(arg + '\n')
- def run(arg):
- try:
- file = open(arg)
- interp.runcode(file.read())
- file.close()
- except IOError, e:
- self.perror(e)
- self.pystate['quit'] = quit
- self.pystate['exit'] = quit
- self.pystate['cmd'] = onecmd_plus_hooks
- self.pystate['run'] = run
-
- try:
- cprt = 'Type "help", "copyright", "credits" or "license" for more information.'
- keepstate = Statekeeper(sys, ('stdin','stdout'))
- sys.stdout = self.stdout
- sys.stdin = self.stdin
- interp.interact(banner= "Python %s on %s\n%s\n(%s)\n%s" %
- (sys.version, sys.platform, cprt, self.__class__.__name__, self.do_py.__doc__))
- except EmbeddedConsoleExit:
- pass
- keepstate.restore()
-
-
- @options(
- [make_option(
- '-s', '--script',
- action = 'store_true',
- help = 'Script format; no separation lines'),],
- arg_desc = '(limit on which commands to include)')
- def do_history(self, arg, opts):
- '''
- history [arg]: lists past commands issued
-
- | no arg: list all
- | arg is integer: list one history item, by index
- | arg is string: string search
- | /arg enclosed slashes/: regular expression search
- '''
- if arg:
- history = self.history.get(arg)
- else:
- history = self.history
- for hi in history:
- if opts.script:
- self.poutput(hi)
- else:
- self.stdout.write(hi.pr())
-
-
- def do_list(self, arg):
- '''list [arg]: lists last command issued
-
- no arg -> list most recent command
- arg is integer -> list one history item, by index
- a..b, a:b, a:, ..b -> list spans from a (or start) to b (or end)
- arg is string -> list all commands matching string search
- /arg enclosed in slashes/ -> regular expression search
- '''
- try:
- history = self.history.span(arg or '-1')
- except IndexError:
- history = self.history.search(arg)
- for hi in history:
- self.poutput(hi.pr())
-
- do_hi = do_history
- do_l = do_list
- do_li = do_list
-
-
- def do_ed(self, arg):
- '''
- ed: edit most recent command in text editor
- ed [N]: edit numbered command from history
- ed [filename]: edit specified file name
-
- Commands are run after editor is closed.
-
- The editor defaults to the EDITOR environment variable. You
- can also use `set edit <program-name>` to choose an editor.
- '''
- if not self.editor:
- raise EnvironmentError("Please use 'set editor' to specify your text editing program of choice.")
- filename = self.default_file_name
- if arg:
- try:
- buffer = self.last_matching(int(arg))
- except ValueError:
- filename = arg
- buffer = ''
- else:
- buffer = self.history[-1]
-
- if buffer:
- f = open(os.path.expanduser(filename), 'w')
- f.write(buffer or '')
- f.close()
- os.system('%s %s' % (self.editor, filename))
- self.do__load(filename)
-
- do_edit = do_ed
-
- saveparser = (pyparsing.Optional(pyparsing.Word(pyparsing.nums)^'*')("idx") +
- pyparsing.Optional(pyparsing.Word(legalChars + '/\\'))("fname") +
- pyparsing.stringEnd)
-
-
- def do_save(self, arg):
- '''
- `save [N] [filename.ext]`
-
- Saves command from history to file.
-
- | N => Number of command (from history), or `*`;
- | most recent command if omitted
- '''
- try:
- args = self.saveparser.parseString(arg)
- except pyparsing.ParseException:
- self.perror('Could not understand save target %s' % arg)
- raise SyntaxError(self.do_save.__doc__)
-
- fname = args.fname or self.default_file_name
-
- if args.idx == '*':
- saveme = '\n\n'.join(self.history[:])
- elif args.idx:
- saveme = self.history[int(args.idx)-1]
- else:
- saveme = self.history[-1]
-
- try:
- f = open(os.path.expanduser(fname), 'w')
- f.write(saveme)
- f.close()
- self.pfeedback('Saved to %s' % (fname))
- except Exception, e:
- self.perror('Error saving %s' % (fname))
- raise
-
-
- def do_load(self, arg=None):
- '''
- Runs script of command(s) from a file or URL.
- '''
- if arg is None:
- targetname = self.default_file_name
- else:
- arg = arg.split(None, 1)
- targetname, args = arg[0], (arg[1:] or [''])[0].strip()
- try:
- target = self.read_file_or_url(targetname)
- except IOError, e:
- self.perror('Problem accessing script from %s: \n%s' % (targetname, e))
- return
- keepstate = Statekeeper(self, ('stdin','use_rawinput','prompt',
- 'continuation_prompt','current_script_dir'))
- self.stdin = target
- self.use_rawinput = False
- self.prompt = self.continuation_prompt = ''
- self.current_script_dir = os.path.split(targetname)[0]
- stop = self._cmdloop()
- self.stdin.close()
- keepstate.restore()
- self.lastcmd = ''
- return stop and (stop != self._STOP_SCRIPT_NO_EXIT)
-
- do__load = do_load # avoid an unfortunate legacy use of do_load from sqlpython
-
- def do_run(self, arg):
- '''
- run [arg]: re-runs an earlier command
-
- no arg -> run most recent command
- arg is integer -> run one history item, by index
- arg is string -> run most recent command by string search
- /arg enclosed in slashes/ -> run most recent by regex
- '''
- 'run [N]: runs the SQL that was run N commands ago'
- runme = self.last_matching(arg)
- self.pfeedback(runme)
- if runme:
- stop = self.onecmd_plus_hooks(runme)
-
- do_r = do_run
-
-
def cmdloop(self):
parser = optparse.OptionParser()
parser.add_option('-t', '--test',
diff --git a/commands.py b/commands.py
index 608bc63..61f5170 100644
--- a/commands.py
+++ b/commands.py
@@ -1,3 +1,353 @@
'''
-This file should contain all the `do_*` commands built-in to Cmd2.
-''' \ No newline at end of file
+This file should contain all the built-in `do_*` commands of Cmd2.
+'''
+
+
+def do__relative_load(self, arg=None):
+ '''
+ Runs commands in script at file or URL; if this is called from within an
+ already-running script, the filename will be interpreted relative to the
+ already-running script's directory.
+ '''
+ if arg:
+ arg = arg.split(None, 1)
+ targetname, args = arg[0], (arg[1:] or [''])[0]
+ targetname = os.path.join(self.current_script_dir or '', targetname)
+ self.do__load('%s %s' % (targetname, args))
+
+urlre = re.compile('(https?://[-\\w\\./]+)')
+
+def do_cmdenvironment(self, args):
+ '''
+ Summary report of interactive parameters.
+ '''
+
+ self.stdout.write("""
+ Commands are %(casesensitive)scase-sensitive.
+ Commands may be terminated with: %(terminators)s
+
+ Settable parameters: %(settable)s\n""" % \
+ { 'casesensitive' : (self.case_insensitive and 'not ') or '',
+ 'terminators' : str(self.terminators),
+ 'settable' : ' '.join(self.settable)
+ })
+
+
+def do_help(self, arg):
+ if arg:
+ funcname = self.func_named(arg)
+ if funcname:
+ fn = getattr(self, funcname)
+ try:
+ fn.optionParser.print_help(file=self.stdout)
+ except AttributeError:
+ cmd.Cmd.do_help(self, funcname[3:])
+ else:
+ cmd.Cmd.do_help(self, arg)
+
+
+def do_shortcuts(self, args):
+ '''
+ Lists single-key shortcuts available.
+ '''
+ result = "\n".join('%s: %s' % (sc[0], sc[1]) for sc in sorted(self.shortcuts))
+ self.stdout.write("Single-key shortcuts for other commands:\n%s\n" % (result))
+
+
+def do_EOF(self, arg):
+ return self._STOP_SCRIPT_NO_EXIT # End of script; should not exit app
+
+do_eof = do_EOF
+
+
+def do_quit(self, arg):
+ return self._STOP_AND_EXIT
+
+do_exit = do_quit
+do_q = do_quit
+
+
+@options(
+ [make_option(
+ '-l', '--long',
+ action ="store_true",
+ help ="describe function of parameter")])
+def do_show(self, arg, opts):
+ '''
+ Show the value of a parameter.
+ '''
+ param = arg.strip().lower()
+ result = {}
+ maxlen = 0
+ for p in self.settable:
+ if (not param) or p.startswith(param):
+ result[p] = '%s: %s' % (p, str(getattr(self, p)))
+ maxlen = max(maxlen, len(result[p]))
+ if result:
+ for p in sorted(result):
+ if opts.long:
+ self.poutput('%s # %s' % (result[p].ljust(maxlen), self.settable[p]))
+ else:
+ self.poutput(result[p])
+ else:
+ raise NotImplementedError("Parameter '%s' not supported (type 'show' for list of parameters)." % param)
+
+
+def do_set(self, arg):
+ '''
+ Set a cmd2 parameter. Accepts abbreviated parameter names
+ if there is no ambiguity. Lists settable parameters and values if
+ called with no arguments.
+ '''
+ try:
+ statement, paramName, val = arg.parsed.raw.split(None, 2)
+ val = val.strip()
+ paramName = paramName.strip().lower()
+
+ if paramName not in self.settable:
+ hits = [p for p in self.settable if p.startswith(paramName)]
+ if len(hits) == 1:
+ paramName = hits[0]
+ else:
+ return self.do_show(paramName)
+ currentVal = getattr(self, paramName)
+
+ if (val[0] == val[-1]) and val[0] in ("'", '"'):
+ val = val[1:-1]
+ else:
+ val = cast(currentVal, val)
+
+ setattr(self, paramName, val)
+ self.stdout.write('%s - was: %s\nnow: %s\n' % (paramName, currentVal, val))
+
+ if currentVal != val:
+ try:
+ onchange_hook = getattr(self, '_onchange_%s' % paramName)
+ onchange_hook(old=currentVal, new=val)
+ except AttributeError:
+ pass
+ except (ValueError, AttributeError, NotSettableError), e:
+ self.do_show(arg)
+
+
+def do_pause(self, arg):
+ '''Display the provided text, then wait for the user to press RETURN.'''
+ raw_input(arg + '\n')
+
+
+def do_shell(self, arg):
+ '''
+ Executes a command as if at the OS prompt.
+ '''
+ os.system(arg)
+
+
+def do_py(self, arg):
+ '''
+ py <command>: Executes a Python command.
+ py: Enters interactive Python mode.
+
+ End with ``Ctrl-D`` (Unix) / ``Ctrl-Z`` (Windows), ``quit()``, '`exit()``.
+
+ Non-python commands can be issued with ``cmd("your command")``.
+ Run python code from external files with ``run("filename.py")``
+ '''
+ self.pystate['self'] = self
+ arg = arg.parsed.raw[2:].strip()
+ localvars = (self.locals_in_py and self.pystate) or {}
+ interp = InteractiveConsole(locals=localvars)
+ interp.runcode('import sys, os;sys.path.insert(0, os.getcwd())')
+
+ if arg.strip():
+ interp.runcode(arg)
+ else:
+ def quit():
+ raise EmbeddedConsoleExit
+ def onecmd_plus_hooks(arg):
+ return self.onecmd_plus_hooks(arg + '\n')
+ def run(arg):
+ try:
+ file = open(arg)
+ interp.runcode(file.read())
+ file.close()
+ except IOError, e:
+ self.perror(e)
+ self.pystate['quit'] = quit
+ self.pystate['exit'] = quit
+ self.pystate['cmd'] = onecmd_plus_hooks
+ self.pystate['run'] = run
+
+ try:
+ cprt = 'Type "help", "copyright", "credits" or "license" for more information.'
+ keepstate = Statekeeper(sys, ('stdin','stdout'))
+ sys.stdout = self.stdout
+ sys.stdin = self.stdin
+ interp.interact(banner= "Python %s on %s\n%s\n(%s)\n%s" %
+ (sys.version, sys.platform, cprt, self.__class__.__name__, self.do_py.__doc__))
+ except EmbeddedConsoleExit:
+ pass
+ keepstate.restore()
+
+
+@options(
+ [make_option(
+ '-s', '--script',
+ action = 'store_true',
+ help = 'Script format; no separation lines'),],
+ arg_desc = '(limit on which commands to include)')
+def do_history(self, arg, opts):
+ '''
+ history [arg]: lists past commands issued
+
+ | no arg: list all
+ | arg is integer: list one history item, by index
+ | arg is string: string search
+ | /arg enclosed slashes/: regular expression search
+ '''
+ if arg:
+ history = self.history.get(arg)
+ else:
+ history = self.history
+ for hi in history:
+ if opts.script:
+ self.poutput(hi)
+ else:
+ self.stdout.write(hi.pr())
+
+
+def do_list(self, arg):
+ '''list [arg]: lists last command issued
+
+ no arg -> list most recent command
+ arg is integer -> list one history item, by index
+ a..b, a:b, a:, ..b -> list spans from a (or start) to b (or end)
+ arg is string -> list all commands matching string search
+ /arg enclosed in slashes/ -> regular expression search
+ '''
+ try:
+ history = self.history.span(arg or '-1')
+ except IndexError:
+ history = self.history.search(arg)
+ for hi in history:
+ self.poutput(hi.pr())
+
+do_hi = do_history
+do_l = do_list
+do_li = do_list
+
+
+def do_ed(self, arg):
+ '''
+ ed: edit most recent command in text editor
+ ed [N]: edit numbered command from history
+ ed [filename]: edit specified file name
+
+ Commands are run after editor is closed.
+
+ The editor defaults to the EDITOR environment variable. You
+ can also use `set edit <program-name>` to choose an editor.
+ '''
+ if not self.editor:
+ raise EnvironmentError("Please use 'set editor' to specify your text editing program of choice.")
+ filename = self.default_file_name
+ if arg:
+ try:
+ buffer = self.last_matching(int(arg))
+ except ValueError:
+ filename = arg
+ buffer = ''
+ else:
+ buffer = self.history[-1]
+
+ if buffer:
+ f = open(os.path.expanduser(filename), 'w')
+ f.write(buffer or '')
+ f.close()
+ os.system('%s %s' % (self.editor, filename))
+ self.do__load(filename)
+
+do_edit = do_ed
+
+saveparser = (pyparsing.Optional(pyparsing.Word(pyparsing.nums)^'*')("idx") +
+ pyparsing.Optional(pyparsing.Word(legalChars + '/\\'))("fname") +
+ pyparsing.stringEnd)
+
+
+def do_save(self, arg):
+ '''
+ `save [N] [filename.ext]`
+
+ Saves command from history to file.
+
+ | N => Number of command (from history), or `*`;
+ | most recent command if omitted
+ '''
+ try:
+ args = self.saveparser.parseString(arg)
+ except pyparsing.ParseException:
+ self.perror('Could not understand save target %s' % arg)
+ raise SyntaxError(self.do_save.__doc__)
+
+ fname = args.fname or self.default_file_name
+
+ if args.idx == '*':
+ saveme = '\n\n'.join(self.history[:])
+ elif args.idx:
+ saveme = self.history[int(args.idx)-1]
+ else:
+ saveme = self.history[-1]
+
+ try:
+ f = open(os.path.expanduser(fname), 'w')
+ f.write(saveme)
+ f.close()
+ self.pfeedback('Saved to %s' % (fname))
+ except Exception, e:
+ self.perror('Error saving %s' % (fname))
+ raise
+
+
+def do_load(self, arg=None):
+ '''
+ Runs script of command(s) from a file or URL.
+ '''
+ if arg is None:
+ targetname = self.default_file_name
+ else:
+ arg = arg.split(None, 1)
+ targetname, args = arg[0], (arg[1:] or [''])[0].strip()
+ try:
+ target = self.read_file_or_url(targetname)
+ except IOError, e:
+ self.perror('Problem accessing script from %s: \n%s' % (targetname, e))
+ return
+ keepstate = Statekeeper(self, ('stdin','use_rawinput','prompt',
+ 'continuation_prompt','current_script_dir'))
+ self.stdin = target
+ self.use_rawinput = False
+ self.prompt = self.continuation_prompt = ''
+ self.current_script_dir = os.path.split(targetname)[0]
+ stop = self._cmdloop()
+ self.stdin.close()
+ keepstate.restore()
+ self.lastcmd = ''
+ return stop and (stop != self._STOP_SCRIPT_NO_EXIT)
+
+do__load = do_load # avoid an unfortunate legacy use of do_load from sqlpython
+
+def do_run(self, arg):
+ '''
+ run [arg]: re-runs an earlier command
+
+ no arg -> run most recent command
+ arg is integer -> run one history item, by index
+ arg is string -> run most recent command by string search
+ /arg enclosed in slashes/ -> run most recent by regex
+ '''
+ 'run [N]: runs the SQL that was run N commands ago'
+ runme = self.last_matching(arg)
+ self.pfeedback(runme)
+ if runme:
+ stop = self.onecmd_plus_hooks(runme)
+
+do_r = do_run \ No newline at end of file