diff options
author | Kevin Van Brunt <kmvanbrunt@gmail.com> | 2019-02-27 00:04:24 -0500 |
---|---|---|
committer | Kevin Van Brunt <kmvanbrunt@gmail.com> | 2019-02-27 00:04:24 -0500 |
commit | 5ea65255d90be65655bb09a775c01cc2c6f81965 (patch) | |
tree | 31a5377938ca52b053d3ed1b80c1b6221bb4f20d | |
parent | 559983db44bb6e294d668eb8b7341ae5c5d5c18c (diff) | |
download | cmd2-git-5ea65255d90be65655bb09a775c01cc2c6f81965.tar.gz |
Added matches_sort_key member to cmd2
-rw-r--r-- | CHANGELOG.md | 3 | ||||
-rw-r--r-- | cmd2/argparse_completer.py | 23 | ||||
-rw-r--r-- | cmd2/cmd2.py | 22 |
3 files changed, 32 insertions, 16 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c9f9322..a36d9d21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## 0.9.11 (TBD, 2019) * Enhancements * Simplified examples that illustrate ``argparse`` tab completion via ``AutoCompleter`` + * Added ``matches_sort_key`` to override the default way tab completion matches are sorted * Deprecations * Deprecated support for bash completion since this feature had slow performance. Also it relied on ``AutoCompleter`` which has since developed a dependency on ``cmd2`` methods. @@ -9,7 +10,7 @@ requires that it can't be ``None``. * ``AutoCompleter`` no longer assumes ``CompletionItem`` results are sorted. Therefore you should follow the ``cmd2`` convention of setting ``self.matches_sorted`` to True before returning the results if you have already - sorted the ``CompletionItem`` list. Otherwise ``cmd2`` will just sort them alphabetically. + sorted the ``CompletionItem`` list. Otherwise it will be sorted using ``self.matches_sort_key``. ## 0.9.10 (February 22, 2019) * Bug Fixes diff --git a/cmd2/argparse_completer.py b/cmd2/argparse_completer.py index c9293b4e..7732c5c5 100644 --- a/cmd2/argparse_completer.py +++ b/cmd2/argparse_completer.py @@ -61,21 +61,19 @@ Released under MIT license, see LICENSE file """ import argparse -from colorama import Fore import os +import re as _re import sys -from typing import List, Dict, Tuple, Callable, Union - # imports copied from argparse to support our customized argparse functions from argparse import ZERO_OR_MORE, ONE_OR_MORE, ArgumentError, _, _get_action_name, SUPPRESS +from typing import List, Dict, Tuple, Callable, Union -import re as _re - +from colorama import Fore +from wcwidth import wcswidth from .rl_utils import rl_force_redisplay - # attribute that can optionally added to an argparse argument (called an Action) to # define the completion choices for the argument. You may provide a Collection or a Function. ACTION_ARG_CHOICES = 'arg_choices' @@ -588,12 +586,19 @@ class AutoCompleter(object): def _format_completions(self, action, completions: List[Union[str, CompletionItem]]) -> List[str]: if completions and len(completions) > 1 and isinstance(completions[0], CompletionItem): - token_width = len(action.dest) + + # If the user has not already sorted the CompletionItems, then do that now + if not self._cmd2_app.matches_sorted: + completions.sort(key=self._cmd2_app.matches_sort_key) + self._cmd2_app.matches_sorted = True + + token_width = wcswidth(action.dest) completions_with_desc = [] for item in completions: - if len(item) > token_width: - token_width = len(item) + item_width = wcswidth(item) + if item_width > token_width: + token_width = item_width term_size = os.get_terminal_size() fill_width = int(term_size.columns * .6) - (token_width + 2) diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py index 1f981417..78da5d44 100644 --- a/cmd2/cmd2.py +++ b/cmd2/cmd2.py @@ -129,6 +129,10 @@ COMMAND_FUNC_PREFIX = 'do_' # All help functions start with this HELP_FUNC_PREFIX = 'help_' +# Sorting keys for strings +ALPHABETICAL_SORT_KEY = utils.norm_fold +NATURAL_SORT_KEY = utils.natural_keys + def categorize(func: Union[Callable, Iterable], category: str) -> None: """Categorize a function. @@ -492,6 +496,12 @@ class Cmd(cmd.Cmd): if os.path.exists(startup_script) and os.path.getsize(startup_script) > 0: self.cmdqueue.append("load '{}'".format(startup_script)) + # The default key for sorting tab completion matches. This only applies when the matches are not + # already marked as sorted by setting self.matches_sorted to True. Its default value performs a + # case-insensitive alphabetical sort. If natural sorting preferred, then set this to NATURAL_SORT_KEY. + # Otherwise it can be set to any custom key to meet your needs. + self.matches_sort_key = ALPHABETICAL_SORT_KEY + ############################################################################################################ # The following variables are used by tab-completion functions. They are reset each time complete() is run # in reset_completion_defaults() and it is up to completer functions to set them before returning results. @@ -520,7 +530,7 @@ class Cmd(cmd.Cmd): self.matches_delimited = False # Set to True before returning matches to complete() in cases where matches are sorted with custom ordering. - # If False, then complete() will sort the matches alphabetically before they are displayed. + # If False, then complete() will sort the matches using self.matches_sort_key before they are displayed. self.matches_sorted = False # Set the pager(s) for use with the ppaged() method for displaying output using a pager @@ -1119,8 +1129,8 @@ class Cmd(cmd.Cmd): self.allow_appended_space = False self.allow_closing_quote = False - # Sort the matches alphabetically before any trailing slashes are added - matches.sort(key=utils.norm_fold) + # Sort the matches before any trailing slashes are added + matches.sort(key=self.matches_sort_key) self.matches_sorted = True # Build display_matches and add a slash to directories @@ -1560,10 +1570,10 @@ class Cmd(cmd.Cmd): self.completion_matches[0] += str_to_append - # Sort matches alphabetically if they haven't already been sorted + # Sort matches if they haven't already been sorted if not self.matches_sorted: - self.completion_matches.sort(key=utils.norm_fold) - self.display_matches.sort(key=utils.norm_fold) + self.completion_matches.sort(key=self.matches_sort_key) + self.display_matches.sort(key=self.matches_sort_key) self.matches_sorted = True try: |