diff options
author | Kevin Van Brunt <kmvanbrunt@gmail.com> | 2019-07-16 10:48:17 -0400 |
---|---|---|
committer | Kevin Van Brunt <kmvanbrunt@gmail.com> | 2019-07-16 10:48:17 -0400 |
commit | 90cfcdfc795d0c4eb6768eae9623a049e9e79e8d (patch) | |
tree | 0112e281f5c6c62afe041b53b13b4dfa0824e8c0 | |
parent | 1820ebe60a4d059b6f016041fe9b401758ae321e (diff) | |
download | cmd2-git-90cfcdfc795d0c4eb6768eae9623a049e9e79e8d.tar.gz |
Moved the sorting of shortcuts into StatementParser which allows users to pass in a dictionary instead of a tuple for shortcuts.
-rw-r--r-- | cmd2/argparse_custom.py | 2 | ||||
-rw-r--r-- | cmd2/cmd2.py | 9 | ||||
-rw-r--r-- | cmd2/parsing.py | 13 | ||||
-rw-r--r-- | tests/test_history.py | 2 | ||||
-rw-r--r-- | tests/test_parsing.py | 2 |
5 files changed, 15 insertions, 13 deletions
diff --git a/cmd2/argparse_custom.py b/cmd2/argparse_custom.py index 1cdb7840..5d8e76ef 100644 --- a/cmd2/argparse_custom.py +++ b/cmd2/argparse_custom.py @@ -74,7 +74,7 @@ Tab Completion: completer_method This is exactly like completer_function, but the function needs to be an instance method of a cmd2-based class. When AutoCompleter calls the method, it will pass the app instance as the self argument. cmd2 provides - a few completer methods for convenience (e.g. path_complete, delimiter_complete) + a few completer methods for convenience (e.g., path_complete, delimiter_complete) Example: This adds file-path completion to an argument diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py index b8e5d9d2..2c37635d 100644 --- a/cmd2/cmd2.py +++ b/cmd2/cmd2.py @@ -397,9 +397,6 @@ class Cmd(cmd.Cmd): self._py_history = [] self.pyscript_name = 'app' - if shortcuts is None: - shortcuts = constants.DEFAULT_SHORTCUTS - shortcuts = sorted(shortcuts.items(), reverse=True) self.statement_parser = StatementParser(allow_redirection=allow_redirection, terminators=terminators, multiline_commands=multiline_commands, @@ -472,7 +469,7 @@ class Cmd(cmd.Cmd): # If natural sorting is preferred, then set this to NATURAL_SORT_KEY. # cmd2 uses this key for sorting: # command and category names - # alias, macro, and settable names + # alias, macro, settable, and shortcut names # tab completion results when self.matches_sorted is False self.default_sort_key = ALPHABETICAL_SORT_KEY @@ -2816,7 +2813,9 @@ class Cmd(cmd.Cmd): @with_argparser(ArgParser()) def do_shortcuts(self, _: argparse.Namespace) -> None: """List available shortcuts""" - result = "\n".join('%s: %s' % (sc[0], sc[1]) for sc in sorted(self.statement_parser.shortcuts)) + # Sort the shortcut tuples by name + sorted_shortcuts = sorted(self.statement_parser.shortcuts, key=lambda x: self.default_sort_key(x[0])) + result = "\n".join('{}: {}'.format(sc[0], sc[1]) for sc in sorted_shortcuts) self.poutput("Shortcuts for other commands:\n{}".format(result)) @with_argparser(ArgParser(epilog=INTERNAL_COMMAND_EPILOG)) diff --git a/cmd2/parsing.py b/cmd2/parsing.py index 2e94516a..dbfabc80 100644 --- a/cmd2/parsing.py +++ b/cmd2/parsing.py @@ -249,7 +249,7 @@ class StatementParser: terminators: Optional[Iterable[str]] = None, multiline_commands: Optional[Iterable[str]] = None, aliases: Optional[Dict[str, str]] = None, - shortcuts: Optional[Iterable[Tuple[str, str]]] = None) -> None: + shortcuts: Optional[Dict[str, str]] = None) -> None: """Initialize an instance of StatementParser. The following will get converted to an immutable tuple before storing internally: @@ -261,7 +261,7 @@ class StatementParser: :param terminators: iterable containing strings which should terminate multiline commands :param multiline_commands: iterable containing the names of commands that accept multiline input :param aliases: dictionary containing aliases - :param shortcuts: an iterable of tuples with each tuple containing the shortcut and the expansion + :param shortcuts: dictionary containing shortcuts """ self.allow_redirection = allow_redirection if terminators is None: @@ -276,10 +276,13 @@ class StatementParser: self.aliases = dict() else: self.aliases = aliases + if shortcuts is None: - self.shortcuts = tuple() - else: - self.shortcuts = tuple(shortcuts) + shortcuts = constants.DEFAULT_SHORTCUTS + + # Sort the shortcuts in descending order by name length because the longest match + # should take precedence. (e.g., @@file should match '@@' and not '@'. + self.shortcuts = tuple(sorted(shortcuts.items(), key=lambda x: len(x[0]), reverse=True)) # commands have to be a word, so make a regular expression # that matches the first word in the line. This regex has three diff --git a/tests/test_history.py b/tests/test_history.py index add93ea6..88f38172 100644 --- a/tests/test_history.py +++ b/tests/test_history.py @@ -276,7 +276,7 @@ def parser(): 'l': '!ls -al', 'anothermultiline': 'multiline', 'fake': 'run_pyscript'}, - shortcuts=[('?', 'help'), ('!', 'shell')] + shortcuts={'?': 'help', '!': 'shell'} ) return parser diff --git a/tests/test_parsing.py b/tests/test_parsing.py index 13a535c0..a629d9fa 100644 --- a/tests/test_parsing.py +++ b/tests/test_parsing.py @@ -21,7 +21,7 @@ def parser(): 'l': '!ls -al', 'anothermultiline': 'multiline', 'fake': 'run_pyscript'}, - shortcuts=[('?', 'help'), ('!', 'shell')] + shortcuts={'?': 'help', '!': 'shell'} ) return parser |