From e6da8596c433f46bc337c7e8a14c7de1b0310e4c Mon Sep 17 00:00:00 2001 From: Kevin Van Brunt Date: Thu, 13 Aug 2020 14:19:05 -0400 Subject: Replaced choices_function / choices_method with choices_provider. Replaced completer_function / completer_method with completer. ArgparseCompleter now always passes cmd2.Cmd or CommandSet instance as the self argument to choices_provider and completer functions. Moved basic_complete from utils into cmd2.Cmd class. Moved CompletionError to exceptions.py --- cmd2/utils.py | 62 +++++++---------------------------------------------------- 1 file changed, 7 insertions(+), 55 deletions(-) (limited to 'cmd2/utils.py') diff --git a/cmd2/utils.py b/cmd2/utils.py index a2b1c854..d8d6b7cc 100644 --- a/cmd2/utils.py +++ b/cmd2/utils.py @@ -74,40 +74,13 @@ def str_to_bool(val: str) -> bool: raise ValueError("must be True or False (case-insensitive)") -class CompletionError(Exception): - """ - Raised during tab completion operations to report any sort of error you want printed. This can also be used - just to display a message, even if it's not an error. For instance, ArgparseCompleter raises CompletionErrors - to display tab completion hints and sets apply_style to False so hints aren't colored like error text. - - Example use cases - - - Reading a database to retrieve a tab completion data set failed - - A previous command line argument that determines the data set being completed is invalid - - Tab completion hints - """ - def __init__(self, *args, apply_style: bool = True, **kwargs): - """ - Initializer for CompletionError - :param apply_style: If True, then ansi.style_error will be applied to the message text when printed. - Set to False in cases where the message text already has the desired style. - Defaults to True. - """ - self.apply_style = apply_style - - # noinspection PyArgumentList - super().__init__(*args, **kwargs) - - class Settable: """Used to configure a cmd2 instance member to be settable via the set command in the CLI""" def __init__(self, name: str, val_type: Callable, description: str, *, onchange_cb: Callable[[str, Any, Any], Any] = None, choices: Iterable = None, - choices_function: Optional[Callable] = None, - choices_method: Optional[Callable] = None, - completer_function: Optional[Callable] = None, - completer_method: Optional[Callable] = None): + choices_provider: Optional[Callable] = None, + completer: Optional[Callable] = None): """ Settable Initializer @@ -129,14 +102,11 @@ class Settable: same settings in argparse-based tab completion. A maximum of one of these should be provided. :param choices: iterable of accepted values - :param choices_function: function that provides choices for this argument - :param choices_method: cmd2-app method that provides choices for this argument (See note below) - :param completer_function: tab completion function that provides choices for this argument - :param completer_method: cmd2-app tab completion method that provides choices - for this argument (See note below) + :param choices_provider: function that provides choices for this argument + :param completer: tab completion function that provides choices for this argument Note: - For choices_method and completer_method, do not set them to a bound method. This is because + For choices_provider and completer, do not set them to a bound method. This is because ArgparseCompleter passes the self argument explicitly to these functions. Therefore instead of passing something like self.path_complete, pass cmd2.Cmd.path_complete. @@ -150,10 +120,8 @@ class Settable: self.description = description self.onchange_cb = onchange_cb self.choices = choices - self.choices_function = choices_function - self.choices_method = choices_method - self.completer_function = completer_function - self.completer_method = completer_method + self.choices_provider = choices_provider + self.completer = completer def namedtuple_with_defaults(typename: str, field_names: Union[str, List[str]], @@ -689,22 +657,6 @@ class RedirectionSavedState: self.saved_redirecting = saved_redirecting -# noinspection PyUnusedLocal -def basic_complete(text: str, line: str, begidx: int, endidx: int, match_against: Iterable) -> List[str]: - """ - Basic tab completion function that matches against a list of strings without considering line contents - or cursor position. The args required by this function are defined in the header of Python's cmd.py. - - :param text: the string prefix we are attempting to match (all matches must begin with it) - :param line: the current input line with leading whitespace removed - :param begidx: the beginning index of the prefix text - :param endidx: the ending index of the prefix text - :param match_against: the strings being matched against - :return: a list of possible tab completions - """ - return [cur_match for cur_match in match_against if cur_match.startswith(text)] - - class TextAlignment(Enum): """Horizontal text alignment""" LEFT = 1 -- cgit v1.2.1 From b5e08b06b4032d8656fa768814069b17ea613b62 Mon Sep 17 00:00:00 2001 From: Kevin Van Brunt Date: Tue, 18 Aug 2020 12:06:47 -0400 Subject: Documented support for standalone functions being used as completers and choices_providers. Added unit tests for this case. --- cmd2/utils.py | 6 ------ 1 file changed, 6 deletions(-) (limited to 'cmd2/utils.py') diff --git a/cmd2/utils.py b/cmd2/utils.py index d8d6b7cc..c5874d6e 100644 --- a/cmd2/utils.py +++ b/cmd2/utils.py @@ -104,12 +104,6 @@ class Settable: :param choices: iterable of accepted values :param choices_provider: function that provides choices for this argument :param completer: tab completion function that provides choices for this argument - - Note: - For choices_provider and completer, do not set them to a bound method. This is because - ArgparseCompleter passes the self argument explicitly to these functions. - - Therefore instead of passing something like self.path_complete, pass cmd2.Cmd.path_complete. """ if val_type == bool: val_type = str_to_bool -- cgit v1.2.1 From d582466335d3182a15dc40bf2d8b6737fb158d46 Mon Sep 17 00:00:00 2001 From: Kevin Van Brunt Date: Wed, 9 Sep 2020 01:03:21 -0400 Subject: Moved two classes from cmd2.py to utils.py. --- cmd2/utils.py | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) (limited to 'cmd2/utils.py') diff --git a/cmd2/utils.py b/cmd2/utils.py index c5874d6e..b89d57bb 100644 --- a/cmd2/utils.py +++ b/cmd2/utils.py @@ -1,8 +1,10 @@ # coding=utf-8 """Shared utility functions""" +import argparse import collections import collections.abc as collections_abc +import enum import functools import glob import inspect @@ -12,7 +14,6 @@ import subprocess import sys import threading import unicodedata -from enum import Enum from typing import Any, Callable, Dict, Iterable, List, Optional, TextIO, Union from . import constants @@ -651,7 +652,7 @@ class RedirectionSavedState: self.saved_redirecting = saved_redirecting -class TextAlignment(Enum): +class TextAlignment(enum.Enum): """Horizontal text alignment""" LEFT = 1 CENTER = 2 @@ -1017,3 +1018,37 @@ def get_defining_class(meth): if isinstance(cls, type): return cls return getattr(meth, '__objclass__', None) # handle special descriptor objects + + +class CompletionMode(enum.Enum): + """Enum for what type of tab completion to perform in cmd2.Cmd.read_input()""" + # Tab completion will be disabled during read_input() call + # Use of custom up-arrow history supported + NONE = 1 + + # read_input() will tab complete cmd2 commands and their arguments + # cmd2's command line history will be used for up arrow if history is not provided. + # Otherwise use of custom up-arrow history supported. + COMMANDS = 2 + + # read_input() will tab complete based on one of its following parameters: + # choices, choices_provider, completer, parser + # Use of custom up-arrow history supported + CUSTOM = 3 + + +class CustomCompletionSettings: + """Used by cmd2.Cmd.complete() to tab complete strings other than command arguments""" + def __init__(self, parser: argparse.ArgumentParser, *, preserve_quotes: bool = False): + """ + Initializer + + :param parser: arg parser defining format of string being tab completed + :param preserve_quotes: if True, then quoted tokens will keep their quotes when processed by + ArgparseCompleter. This is helpful in cases when you're tab completing + flag-like tokens (e.g. -o, --option) and you don't want them to be + treated as argparse flags when quoted. Set this to True if you plan + on passing the string to argparse with the tokens still quoted. + """ + self.parser = parser + self.preserve_quotes = preserve_quotes -- cgit v1.2.1