summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Van Brunt <kmvanbrunt@gmail.com>2018-03-16 16:35:05 -0400
committerKevin Van Brunt <kmvanbrunt@gmail.com>2018-03-16 16:35:05 -0400
commit624f3ac76be348a291264a53bb9ae808ba3034c8 (patch)
treedea6a251343d7e397e5fe81cad1ff5b131672656
parent47d551ba9b879277f46dcba0bc9085382f98ae61 (diff)
downloadcmd2-git-624f3ac76be348a291264a53bb9ae808ba3034c8.tar.gz
alias and unalias commands are implemented
-rwxr-xr-xcmd2.py103
1 files changed, 93 insertions, 10 deletions
diff --git a/cmd2.py b/cmd2.py
index fd450585..2a5993b6 100755
--- a/cmd2.py
+++ b/cmd2.py
@@ -164,6 +164,27 @@ def set_use_arg_list(val):
USE_ARG_LIST = val
+# noinspection PyUnusedLocal
+def basic_complete(text, line, begidx, endidx, match_against):
+ """
+ Performs tab completion against a list
+ :param text: str - the string prefix we are attempting to match (all returned matches must begin with it)
+ :param line: str - the current input line with leading whitespace removed
+ :param begidx: int - the beginning index of the prefix text
+ :param endidx: int - the ending index of the prefix text
+ :param match_against: iterable - the list being matched against
+ :return: List[str] - a list of possible tab completions
+ """
+ completions = [cur_str for cur_str in match_against if cur_str.startswith(text)]
+
+ # If there is only 1 match and it's at the end of the line, then add a space
+ if len(completions) == 1 and endidx == len(line):
+ completions[0] += ' '
+
+ completions.sort()
+ return completions
+
+
def flag_based_complete(text, line, begidx, endidx, flag_dict, all_else=None):
"""
Tab completes based on a particular flag preceding the token being completed
@@ -500,7 +521,7 @@ def with_argparser_and_unknown_args(argparser):
argparser.prog = func.__name__[3:]
# If the description has not been set, then use the method docstring if one exists
- if not argparser.description and func.__doc__:
+ if argparser.description is None and func.__doc__:
argparser.description = func.__doc__
cmd_wrapper.__doc__ = argparser.format_help()
@@ -539,7 +560,7 @@ def with_argparser(argparser):
argparser.prog = func.__name__[3:]
# If the description has not been set, then use the method docstring if one exists
- if not argparser.description and func.__doc__:
+ if argparser.description is None and func.__doc__:
argparser.description = func.__doc__
cmd_wrapper.__doc__ = argparser.format_help()
@@ -1396,9 +1417,8 @@ class Cmd(cmd.Cmd):
# Complete the command against aliases and command names
strs_to_match = list(self.aliases.keys())
- # Get command names
- do_text = 'do_' + text
- strs_to_match.extend([cur_name[3:] for cur_name in self.get_names() if cur_name.startswith(do_text)])
+ # Add command names
+ strs_to_match.extend(self.get_command_names())
# Perform matching
completions = [cur_str for cur_str in strs_to_match if cur_str.startswith(text)]
@@ -1414,6 +1434,10 @@ class Cmd(cmd.Cmd):
except IndexError:
return None
+ def get_command_names(self):
+ """ Returns a list of commands """
+ return [cur_name[3:] for cur_name in self.get_names() if cur_name.startswith('do_')]
+
def complete_help(self, text, line, begidx, endidx):
"""
Override of parent class method to handle tab completing subcommands
@@ -1924,31 +1948,90 @@ class Cmd(cmd.Cmd):
@with_argument_list
def do_alias(self, arglist):
- """ Views and creates aliases """
+ """Define or display aliases
+
+Usage: Usage: alias [<name> <value>]
+ Where:
+ name - name of the alias being added or edited
+ value - what the alias will be resolved to
+ this can contain spaces and does not need to be quoted
+
+ Without arguments, `alias' prints a list of all aliases in a resuable form
+ Example: alias ls !ls -lF
+"""
# If no args were given, then print a list of current aliases
if len(arglist) == 0:
for cur_alias in self.aliases:
- self.poutput("{}: {}".format(cur_alias, self.aliases[cur_alias]))
+ self.poutput("alias {} {}".format(cur_alias, self.aliases[cur_alias]))
# The user is creating an alias
- elif len(arglist) == 2:
+ elif len(arglist) >= 2:
name = arglist[0]
- value = arglist[1]
+ value = ' '.join(arglist[1:])
+
+ # Make sure the alias does not match an existing command
+ cmd_func = self._func_named(name)
+ if cmd_func is not None:
+ self.perror("Alias names cannot match an existing command: {!r}".format(name), traceback_war=False)
+ return
# Check for a valid name
for cur_char in name:
if cur_char not in self.identchars:
self.perror("Alias names can only contain the following characters: {}".format(self.identchars),
traceback_war=False)
+ return
# Set the alias
self.aliases[name] = value
- self.poutput("Alias created: {}: {}".format(name, value))
+ self.poutput("Alias created")
else:
self.do_help('alias')
+ def complete_alias(self, text, line, begidx, endidx):
+ """ Tab completion for alias """
+ index_dict = \
+ {
+ 1: self.aliases,
+ 2: self.get_command_names()
+ }
+ return index_based_complete(text, line, begidx, endidx, index_dict, path_complete)
+
+ @with_argument_list
+ def do_unalias(self, arglist):
+ """Unsets aliases
+
+Usage: Usage: unalias [-a] name [name ...]
+ Where:
+ name - name of the alias being unset
+
+ Options:
+ -a remove all alias definitions
+"""
+ if len(arglist) == 0:
+ self.do_help('unalias')
+
+ if '-a' in arglist:
+ self.aliases.clear()
+ self.poutput("All aliases cleared")
+
+ else:
+ # Get rid of duplicates
+ arglist = list(set(arglist))
+
+ for cur_arg in arglist:
+ if cur_arg in self.aliases:
+ del self.aliases[cur_arg]
+ self.poutput("Alias {!r} cleared".format(cur_arg))
+ else:
+ self.perror("Alias {!r} does not exist".format(cur_arg), traceback_war=False)
+
+ def complete_unalias(self, text, line, begidx, endidx):
+ """ Tab completion for unalias """
+ return basic_complete(text, line, begidx, endidx, self.aliases)
+
@with_argument_list
def do_help(self, arglist):
"""List available commands with "help" or detailed help with "help cmd"."""