summaryrefslogtreecommitdiff
path: root/cmd2
diff options
context:
space:
mode:
authorKevin Van Brunt <kmvanbrunt@gmail.com>2020-02-18 12:59:46 -0500
committerKevin Van Brunt <kmvanbrunt@gmail.com>2020-02-18 12:59:46 -0500
commitd3deca3c99c299149a30aa3ec760dc17f8abc456 (patch)
tree58ac6df4330780cec94e854782a7bfae23c16589 /cmd2
parent065536a484bb705e1e6b7971fc4c8efdb637185e (diff)
downloadcmd2-git-d3deca3c99c299149a30aa3ec760dc17f8abc456.tar.gz
Added apply_style to CompletionError
Simplified error class structure in argparse_completer.py
Diffstat (limited to 'cmd2')
-rw-r--r--cmd2/argparse_completer.py56
-rw-r--r--cmd2/cmd2.py8
-rw-r--r--cmd2/utils.py16
3 files changed, 32 insertions, 48 deletions
diff --git a/cmd2/argparse_completer.py b/cmd2/argparse_completer.py
index add8868c..d75c04d0 100644
--- a/cmd2/argparse_completer.py
+++ b/cmd2/argparse_completer.py
@@ -10,7 +10,6 @@ import argparse
import inspect
import numbers
import shutil
-import textwrap
from collections import deque
from typing import Dict, List, Optional, Union
@@ -95,30 +94,8 @@ class _ArgumentState:
self.max = self.action.nargs
-class _ArgparseCompletionError(CompletionError):
- """CompletionError specific to argparse-based tab completion"""
- pass
-
-
-# noinspection PyProtectedMember
-class _ActionCompletionError(_ArgparseCompletionError):
- def __init__(self, arg_action: argparse.Action, completion_error: CompletionError) -> None:
- """
- Adds action-specific information to a CompletionError. These are raised when
- non-argparse related errors occur during tab completion.
- :param arg_action: action being tab completed
- :param completion_error: error that occurred
- """
- # Indent all lines of completion_error
- indented_error = textwrap.indent(str(completion_error), ' ')
-
- error = ("Error tab completing {}:\n"
- "{}".format(argparse._get_action_name(arg_action), indented_error))
- super().__init__(ansi.style_error(error))
-
-
# noinspection PyProtectedMember
-class _UnfinishedFlagError(_ArgparseCompletionError):
+class _UnfinishedFlagError(CompletionError):
def __init__(self, flag_arg_state: _ArgumentState) -> None:
"""
CompletionError which occurs when the user has not finished the current flag
@@ -128,11 +105,11 @@ class _UnfinishedFlagError(_ArgparseCompletionError):
format(argparse._get_action_name(flag_arg_state.action),
generate_range_error(flag_arg_state.min, flag_arg_state.max),
flag_arg_state.count)
- super().__init__(ansi.style_error(error))
+ super().__init__(error)
# noinspection PyProtectedMember
-class _NoResultsError(_ArgparseCompletionError):
+class _NoResultsError(CompletionError):
def __init__(self, parser: argparse.ArgumentParser, arg_action: argparse.Action) -> None:
"""
CompletionError which occurs when there are no results. If hinting is allowed, then its message will
@@ -151,7 +128,8 @@ class _NoResultsError(_ArgparseCompletionError):
formatter.add_argument(arg_action)
formatter.end_section()
hint_str = formatter.format_help()
- super().__init__(hint_str)
+ # Set apply_style to False because we don't want hints to look like errors
+ super().__init__(hint_str, apply_style=False)
# noinspection PyProtectedMember
@@ -253,9 +231,9 @@ class ArgparseCompleter:
if arg_action == completer_action:
return
- error = ansi.style_error("\nError: argument {}: not allowed with argument {}\n".
- format(argparse._get_action_name(arg_action),
- argparse._get_action_name(completer_action)))
+ error = ("Error: argument {}: not allowed with argument {}\n".
+ format(argparse._get_action_name(arg_action),
+ argparse._get_action_name(completer_action)))
raise CompletionError(error)
# Mark that this action completed the group
@@ -418,13 +396,8 @@ class ArgparseCompleter:
# Check if we are completing a flag's argument
if flag_arg_state is not None:
- try:
- completion_results = self._complete_for_arg(flag_arg_state.action, text, line,
- begidx, endidx, consumed_arg_values)
- except _ArgparseCompletionError as ex:
- raise ex
- except CompletionError as ex:
- raise _ActionCompletionError(flag_arg_state.action, ex)
+ completion_results = self._complete_for_arg(flag_arg_state.action, text, line,
+ begidx, endidx, consumed_arg_values)
# If we have results, then return them
if completion_results:
@@ -443,13 +416,8 @@ class ArgparseCompleter:
action = remaining_positionals.popleft()
pos_arg_state = _ArgumentState(action)
- try:
- completion_results = self._complete_for_arg(pos_arg_state.action, text, line,
- begidx, endidx, consumed_arg_values)
- except _ArgparseCompletionError as ex:
- raise ex
- except CompletionError as ex:
- raise _ActionCompletionError(pos_arg_state.action, ex)
+ completion_results = self._complete_for_arg(pos_arg_state.action, text, line,
+ begidx, endidx, consumed_arg_values)
# If we have results, then return them
if completion_results:
diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py
index 60d5463a..67304636 100644
--- a/cmd2/cmd2.py
+++ b/cmd2/cmd2.py
@@ -1416,10 +1416,12 @@ class Cmd(cmd.Cmd):
except IndexError:
return None
- except CompletionError as e:
- err_str = str(e)
+ except CompletionError as ex:
+ err_str = str(ex)
+ # Don't print error and redraw the prompt unless the error has length
if err_str:
- # Don't print error and redraw the prompt unless the error has length
+ if ex.apply_style:
+ err_str = ansi.style_error(err_str)
ansi.style_aware_write(sys.stdout, '\n' + err_str + '\n')
rl_force_redisplay()
return None
diff --git a/cmd2/utils.py b/cmd2/utils.py
index b6b45891..6a67c43f 100644
--- a/cmd2/utils.py
+++ b/cmd2/utils.py
@@ -75,12 +75,26 @@ def str_to_bool(val: str) -> bool:
class CompletionError(Exception):
"""
Raised during tab completion operations to report any sort of error you want printed by the ArgparseCompleter
+ This can also be used just to display a message, even if it's not an error. 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
"""
- pass
+ 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: