15
15
from . import cmd2
16
16
from . import utils
17
17
from .ansi import ansi_safe_wcswidth , style_error
18
+ from .argparse_custom import ATTR_CHOICES_CALLABLE , INFINITY , generate_range_error
18
19
from .argparse_custom import ATTR_SUPPRESS_TAB_HINT , ATTR_DESCRIPTIVE_COMPLETION_HEADER , ATTR_NARGS_RANGE
19
- from .argparse_custom import ChoicesCallable , CompletionItem , ATTR_CHOICES_CALLABLE , INFINITY , generate_range_error
20
+ from .argparse_custom import ChoicesCallable , CompletionError , CompletionItem
20
21
from .rl_utils import rl_force_redisplay
21
22
22
23
# If no descriptive header is supplied, then this will be used instead
@@ -319,8 +320,12 @@ def consume_argument(arg_state: AutoCompleter._ArgumentState) -> None:
319
320
320
321
# Check if we are completing a flag's argument
321
322
if flag_arg_state is not None :
322
- completion_results = self ._complete_for_arg (flag_arg_state .action , text , line ,
323
- begidx , endidx , consumed_arg_values )
323
+ try :
324
+ completion_results = self ._complete_for_arg (flag_arg_state .action , text , line ,
325
+ begidx , endidx , consumed_arg_values )
326
+ except CompletionError as ex :
327
+ self ._print_completion_error (flag_arg_state .action , ex )
328
+ return []
324
329
325
330
# If we have results, then return them
326
331
if completion_results :
@@ -341,8 +346,12 @@ def consume_argument(arg_state: AutoCompleter._ArgumentState) -> None:
341
346
action = self ._positional_actions [pos_index ]
342
347
pos_arg_state = AutoCompleter ._ArgumentState (action )
343
348
344
- completion_results = self ._complete_for_arg (pos_arg_state .action , text , line ,
345
- begidx , endidx , consumed_arg_values )
349
+ try :
350
+ completion_results = self ._complete_for_arg (pos_arg_state .action , text , line ,
351
+ begidx , endidx , consumed_arg_values )
352
+ except CompletionError as ex :
353
+ self ._print_completion_error (pos_arg_state .action , ex )
354
+ return []
346
355
347
356
# If we have results, then return them
348
357
if completion_results :
@@ -456,7 +465,11 @@ def format_help(self, tokens: List[str]) -> str:
456
465
def _complete_for_arg (self , arg_action : argparse .Action ,
457
466
text : str , line : str , begidx : int , endidx : int ,
458
467
consumed_arg_values : Dict [str , List [str ]]) -> List [str ]:
459
- """Tab completion routine for an argparse argument"""
468
+ """
469
+ Tab completion routine for an argparse argument
470
+ :return: list of completions
471
+ :raises CompletionError if the completer or choices function this calls raises one
472
+ """
460
473
# Check if the arg provides choices to the user
461
474
if arg_action .choices is not None :
462
475
arg_choices = arg_action .choices
@@ -520,53 +533,72 @@ def _complete_for_arg(self, arg_action: argparse.Action,
520
533
return self ._format_completions (arg_action , results )
521
534
522
535
@staticmethod
523
- def _print_arg_hint (arg_action : argparse .Action ) -> None :
524
- """Print argument hint to the terminal when tab completion results in no results"""
525
-
526
- # Check if hinting is disabled
527
- suppress_hint = getattr (arg_action , ATTR_SUPPRESS_TAB_HINT , False )
528
- if suppress_hint or arg_action .help == argparse .SUPPRESS or arg_action .dest == argparse .SUPPRESS :
529
- return
530
-
536
+ def _format_message_prefix (arg_action : argparse .Action ) -> str :
537
+ """Format the arg prefix text that appears before messages printed to the user"""
531
538
# Check if this is a flag
532
539
if arg_action .option_strings :
533
540
flags = ', ' .join (arg_action .option_strings )
534
541
param = ' ' + str (arg_action .dest ).upper ()
535
- prefix = '{}{}' .format (flags , param )
542
+ return '{}{}' .format (flags , param )
536
543
537
544
# Otherwise this is a positional
538
545
else :
539
- prefix = '{}' .format (str (arg_action .dest ).upper ())
546
+ return '{}' .format (str (arg_action .dest ).upper ())
547
+
548
+ @staticmethod
549
+ def _print_message (msg : str ) -> None :
550
+ """Print a message instead of tab completions and redraw the prompt and input line"""
551
+ print (msg )
552
+ rl_force_redisplay ()
553
+
554
+ def _print_arg_hint (self , arg_action : argparse .Action ) -> None :
555
+ """
556
+ Print argument hint to the terminal when tab completion results in no results
557
+ :param arg_action: action being tab completed
558
+ """
559
+ # Check if hinting is disabled
560
+ suppress_hint = getattr (arg_action , ATTR_SUPPRESS_TAB_HINT , False )
561
+ if suppress_hint or arg_action .help == argparse .SUPPRESS or arg_action .dest == argparse .SUPPRESS :
562
+ return
540
563
564
+ prefix = self ._format_message_prefix (arg_action )
541
565
prefix = ' {0: <{width}} ' .format (prefix , width = 20 )
542
566
pref_len = len (prefix )
543
567
544
568
help_text = '' if arg_action .help is None else arg_action .help
545
569
help_lines = help_text .splitlines ()
546
570
547
571
if len (help_lines ) == 1 :
548
- print ('\n Hint:\n {}{}\n ' .format (prefix , help_lines [0 ]))
572
+ self . _print_message ('\n Hint:\n {}{}\n ' .format (prefix , help_lines [0 ]))
549
573
else :
550
574
out_str = '\n {}' .format (prefix )
551
575
out_str += '\n {0: <{width}}' .format ('' , width = pref_len ).join (help_lines )
552
- print ('\n Hint:' + out_str + '\n ' )
576
+ self . _print_message ('\n Hint:' + out_str + '\n ' )
553
577
554
- # Redraw prompt and input line
555
- rl_force_redisplay ()
556
-
557
- @staticmethod
558
- def _print_unfinished_flag_error (flag_arg_state : _ArgumentState ) -> None :
559
- """Print an error during tab completion when the user has not finished the current flag"""
560
- flags = ', ' .join (flag_arg_state .action .option_strings )
561
- param = ' ' + str (flag_arg_state .action .dest ).upper ()
562
- prefix = '{}{}' .format (flags , param )
578
+ def _print_unfinished_flag_error (self , flag_arg_state : _ArgumentState ) -> None :
579
+ """
580
+ Print an error during tab completion when the user has not finished the current flag
581
+ :param flag_arg_state: information about the unfinished flag action
582
+ """
583
+ prefix = self ._format_message_prefix (flag_arg_state .action )
563
584
564
585
out_str = "\n Error:\n "
565
586
out_str += ' {0: <{width}} ' .format (prefix , width = 20 )
566
587
out_str += generate_range_error (flag_arg_state .min , flag_arg_state .max )
567
588
568
589
out_str += ' ({} entered)' .format (flag_arg_state .count )
569
- print (style_error ('{}\n ' .format (out_str )))
590
+ self . _print_message (style_error ('{}\n ' .format (out_str )))
570
591
571
- # Redraw prompt and input line
572
- rl_force_redisplay ()
592
+ def _print_completion_error (self , arg_action : argparse .Action , completion_error : CompletionError ) -> None :
593
+ """
594
+ Print a CompletionError to the user
595
+ :param arg_action: action being tab completed
596
+ :param completion_error: error that occurred
597
+ """
598
+ prefix = self ._format_message_prefix (arg_action )
599
+
600
+ out_str = "\n Error:\n "
601
+ out_str += ' {0: <{width}} ' .format (prefix , width = 20 )
602
+ out_str += str (completion_error )
603
+
604
+ self ._print_message (style_error ('{}\n ' .format (out_str )))
0 commit comments