summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Van Brunt <kmvanbrunt@gmail.com>2019-02-27 00:04:24 -0500
committerKevin Van Brunt <kmvanbrunt@gmail.com>2019-02-27 00:04:24 -0500
commit5ea65255d90be65655bb09a775c01cc2c6f81965 (patch)
tree31a5377938ca52b053d3ed1b80c1b6221bb4f20d
parent559983db44bb6e294d668eb8b7341ae5c5d5c18c (diff)
downloadcmd2-git-5ea65255d90be65655bb09a775c01cc2c6f81965.tar.gz
Added matches_sort_key member to cmd2
-rw-r--r--CHANGELOG.md3
-rw-r--r--cmd2/argparse_completer.py23
-rw-r--r--cmd2/cmd2.py22
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: