2222 cast ,
2323)
2424
25- from rich .text import Text
26-
27- from .constants import INFINITY
28- from .rich_utils import Cmd2SimpleTable
29-
30- if TYPE_CHECKING : # pragma: no cover
31- from .cmd2 import Cmd
32-
3325from rich .table import Column
26+ from rich .text import Text
3427
3528from .argparse_custom import (
36- ChoicesCallable ,
3729 Cmd2ArgumentParser ,
3830 generate_range_error ,
3931)
4335 Completions ,
4436 all_display_numeric ,
4537)
38+ from .constants import INFINITY
4639from .exceptions import CompletionError
40+ from .rich_utils import Cmd2SimpleTable
41+ from .types import (
42+ ChoicesProviderUnbound ,
43+ CmdOrSet ,
44+ CompleterUnbound ,
45+ )
46+
47+ if TYPE_CHECKING : # pragma: no cover
48+ from .cmd2 import Cmd
49+
4750
4851# Name of the choice/completer function argument that, if present, will be passed a dictionary of
4952# command line tokens up through the token being completed mapped to their argparse destination name.
@@ -708,33 +711,32 @@ def print_help(self, tokens: Sequence[str], file: IO[str] | None = None) -> None
708711 return
709712 self ._parser .print_help (file = file )
710713
711- def _get_raw_choices (self , arg_state : _ArgumentState ) -> list [CompletionItem ] | ChoicesCallable | None :
712- """Extract choices from action or return the choices_callable."""
713- if arg_state .action .choices is not None :
714- # If choices are subcommands, then get their help text to populate display_meta.
715- if isinstance (arg_state .action , argparse ._SubParsersAction ):
716- parser_help = {}
717- for action in arg_state .action ._choices_actions :
718- if action .dest in arg_state .action .choices :
719- subparser = arg_state .action .choices [action .dest ]
720- parser_help [subparser ] = action .help or ''
721-
722- return [
723- CompletionItem (name , display_meta = parser_help .get (subparser , '' ))
724- for name , subparser in arg_state .action .choices .items ()
725- ]
726-
727- # Standard choices
714+ def _choices_to_items (self , arg_state : _ArgumentState ) -> list [CompletionItem ]:
715+ """Convert choices from action to list of CompletionItems."""
716+ if arg_state .action .choices is None :
717+ return []
718+
719+ # If choices are subcommands, then get their help text to populate display_meta.
720+ if isinstance (arg_state .action , argparse ._SubParsersAction ):
721+ parser_help = {}
722+ for action in arg_state .action ._choices_actions :
723+ if action .dest in arg_state .action .choices :
724+ subparser = arg_state .action .choices [action .dest ]
725+ parser_help [subparser ] = action .help or ''
726+
728727 return [
729- choice if isinstance (choice , CompletionItem ) else CompletionItem (choice ) for choice in arg_state .action .choices
728+ CompletionItem (name , display_meta = parser_help .get (subparser , '' ))
729+ for name , subparser in arg_state .action .choices .items ()
730730 ]
731731
732- choices_callable : ChoicesCallable | None = arg_state .action .get_choices_callable () # type: ignore[attr-defined]
733- return choices_callable
732+ # Standard choices
733+ return [
734+ choice if isinstance (choice , CompletionItem ) else CompletionItem (choice ) for choice in arg_state .action .choices
735+ ]
734736
735737 def _prepare_callable_params (
736738 self ,
737- choices_callable : ChoicesCallable ,
739+ to_call : ChoicesProviderUnbound [ CmdOrSet ] | CompleterUnbound [ CmdOrSet ] ,
738740 arg_state : _ArgumentState ,
739741 text : str ,
740742 consumed_arg_values : dict [str , list [str ]],
@@ -745,14 +747,14 @@ def _prepare_callable_params(
745747 kwargs : dict [str , Any ] = {}
746748
747749 # Resolve the 'self' instance for the method
748- self_arg = self ._cmd2_app ._resolve_func_self (choices_callable . to_call , cmd_set )
750+ self_arg = self ._cmd2_app ._resolve_func_self (to_call , cmd_set )
749751 if self_arg is None :
750- raise CompletionError ("Could not find CommandSet instance matching defining type for completer " )
752+ raise CompletionError ("Could not find CommandSet instance matching defining type" )
751753
752754 args .append (self_arg )
753755
754756 # Check if the function expects 'arg_tokens'
755- to_call_params = inspect .signature (choices_callable . to_call ).parameters
757+ to_call_params = inspect .signature (to_call ).parameters
756758 if ARG_TOKENS in to_call_params :
757759 arg_tokens = {** self ._parent_tokens , ** consumed_arg_values }
758760 arg_tokens .setdefault (arg_state .action .dest , []).append (text )
@@ -776,26 +778,33 @@ def _complete_arg(
776778 :return: a Completions object
777779 :raises CompletionError: if the completer or choices function this calls raises one
778780 """
779- raw_choices = self ._get_raw_choices (arg_state )
780- if not raw_choices :
781- return Completions ()
782-
783- # Check if the argument uses a completer function
784- if isinstance (raw_choices , ChoicesCallable ) and raw_choices .is_completer :
785- args , kwargs = self ._prepare_callable_params (raw_choices , arg_state , text , consumed_arg_values , cmd_set )
781+ # Check if the argument uses a completer
782+ completer = arg_state .action .get_completer () # type: ignore[attr-defined]
783+ if completer is not None :
784+ args , kwargs = self ._prepare_callable_params (
785+ completer ,
786+ arg_state ,
787+ text ,
788+ consumed_arg_values ,
789+ cmd_set ,
790+ )
786791 args .extend ([text , line , begidx , endidx ])
787- completions = raw_choices . completer (* args , ** kwargs )
792+ completions : Completions = completer (* args , ** kwargs )
788793
789- # Otherwise it uses a choices list or choices provider function
794+ # Otherwise it uses a choices provider or choices list
790795 else :
791- all_choices : list [CompletionItem ] = []
792-
793- if isinstance (raw_choices , ChoicesCallable ):
794- args , kwargs = self ._prepare_callable_params (raw_choices , arg_state , text , consumed_arg_values , cmd_set )
795- choices_func = raw_choices .choices_provider
796- all_choices = list (choices_func (* args , ** kwargs ))
796+ choices_provider = arg_state .action .get_choices_provider () # type: ignore[attr-defined]
797+ if choices_provider is not None :
798+ args , kwargs = self ._prepare_callable_params (
799+ choices_provider ,
800+ arg_state ,
801+ text ,
802+ consumed_arg_values ,
803+ cmd_set ,
804+ )
805+ all_choices = list (choices_provider (* args , ** kwargs ))
797806 else :
798- all_choices = raw_choices
807+ all_choices = self . _choices_to_items ( arg_state )
799808
800809 # Filter used values and run basic completion
801810 used_values = consumed_arg_values .get (arg_state .action .dest , [])
0 commit comments