1- from __future__ import unicode_literals
1+ from __future__ import annotations
22
33import os
4+ import typing as t
45from glob import iglob
6+ from typing import Generator
57
68import click
7- from prompt_toolkit .completion import Completion , Completer
9+ from prompt_toolkit .completion import CompleteEvent , Completer , Completion
10+ from prompt_toolkit .document import Document
811
912from .utils import _resolve_context , split_arg_string
1013
2629 AUTO_COMPLETION_PARAM = "autocompletion"
2730
2831
29- def text_type (text ):
30- return "{}" .format (text )
31-
32-
3332class ClickCompleter (Completer ):
3433 __slots__ = ("cli" , "ctx" , "parsed_args" , "parsed_ctx" , "ctx_command" )
3534
36- def __init__ (self , cli , ctx , show_only_unused = False , shortest_only = False ):
35+ def __init__ (
36+ self ,
37+ cli : click .MultiCommand ,
38+ ctx : click .Context ,
39+ show_only_unused : bool = False ,
40+ shortest_only : bool = False ,
41+ ) -> None :
3742 self .cli = cli
3843 self .ctx = ctx
39- self .parsed_args = []
44+ self .parsed_args : list [ str ] = []
4045 self .parsed_ctx = ctx
4146 self .ctx_command = ctx .command
4247 self .show_only_unused = show_only_unused
4348 self .shortest_only = shortest_only
4449
4550 def _get_completion_from_autocompletion_functions (
4651 self ,
47- param ,
48- autocomplete_ctx ,
49- args ,
50- incomplete ,
51- ):
52- param_choices = []
52+ param : click . Parameter ,
53+ autocomplete_ctx : click . Context ,
54+ args : list [ str ] ,
55+ incomplete : str ,
56+ ) -> list [ Completion ] :
57+ param_choices : list [ Completion ] = []
5358
5459 if HAS_CLICK_V8 :
5560 autocompletions = param .shell_complete (autocomplete_ctx , incomplete )
@@ -62,7 +67,7 @@ def _get_completion_from_autocompletion_functions(
6267 if isinstance (autocomplete , tuple ):
6368 param_choices .append (
6469 Completion (
65- text_type (autocomplete [0 ]),
70+ str (autocomplete [0 ]),
6671 - len (incomplete ),
6772 display_meta = autocomplete [1 ],
6873 )
@@ -71,46 +76,48 @@ def _get_completion_from_autocompletion_functions(
7176 elif HAS_CLICK_V8 and isinstance (
7277 autocomplete , click .shell_completion .CompletionItem
7378 ):
74- param_choices .append (
75- Completion (text_type (autocomplete .value ), - len (incomplete ))
76- )
79+ param_choices .append (Completion (autocomplete .value , - len (incomplete )))
7780
7881 else :
79- param_choices .append (
80- Completion (text_type (autocomplete ), - len (incomplete ))
81- )
82+ param_choices .append (Completion (str (autocomplete ), - len (incomplete )))
8283
8384 return param_choices
8485
85- def _get_completion_from_choices_click_le_7 (self , param , incomplete ):
86+ def _get_completion_from_choices_click_le_7 (
87+ self , param : click .Parameter , incomplete : str
88+ ) -> list [Completion ]:
89+ param_type = t .cast (click .Choice , param .type )
90+
8691 if not getattr (param .type , "case_sensitive" , True ):
8792 incomplete = incomplete .lower ()
8893 return [
8994 Completion (
90- text_type ( choice ) ,
95+ choice ,
9196 - len (incomplete ),
92- display = text_type ( repr (choice ) if " " in choice else choice ) ,
97+ display = repr (choice ) if " " in choice else choice ,
9398 )
94- for choice in param . type .choices # type: ignore[attr-defined]
99+ for choice in param_type .choices # type: ignore[attr-defined]
95100 if choice .lower ().startswith (incomplete )
96101 ]
97102
98103 else :
99104 return [
100105 Completion (
101- text_type ( choice ) ,
106+ choice ,
102107 - len (incomplete ),
103- display = text_type ( repr (choice ) if " " in choice else choice ) ,
108+ display = repr (choice ) if " " in choice else choice ,
104109 )
105- for choice in param . type .choices # type: ignore[attr-defined]
110+ for choice in param_type .choices # type: ignore[attr-defined]
106111 if choice .startswith (incomplete )
107112 ]
108113
109- def _get_completion_for_Path_types (self , param , args , incomplete ):
114+ def _get_completion_for_Path_types (
115+ self , param : click .Parameter , args : list [str ], incomplete : str
116+ ) -> list [Completion ]:
110117 if "*" in incomplete :
111118 return []
112119
113- choices = []
120+ choices : list [ Completion ] = []
114121 _incomplete = os .path .expandvars (incomplete )
115122 search_pattern = _incomplete .strip ("'\" \t \n \r \v " ).replace ("\\ \\ " , "\\ " ) + "*"
116123 quote = ""
@@ -134,29 +141,36 @@ def _get_completion_for_Path_types(self, param, args, incomplete):
134141
135142 choices .append (
136143 Completion (
137- text_type ( path ) ,
144+ path ,
138145 - len (incomplete ),
139- display = text_type ( os .path .basename (path .strip ("'\" " ) )),
146+ display = os .path .basename (path .strip ("'\" " )),
140147 )
141148 )
142149
143150 return choices
144151
145- def _get_completion_for_Boolean_type (self , param , incomplete ):
152+ def _get_completion_for_Boolean_type (
153+ self , param : click .Parameter , incomplete : str
154+ ) -> list [Completion ]:
155+ boolean_mapping : dict [str , tuple [str , ...]] = {
156+ "true" : ("1" , "true" , "t" , "yes" , "y" , "on" ),
157+ "false" : ("0" , "false" , "f" , "no" , "n" , "off" ),
158+ }
159+
146160 return [
147- Completion (
148- text_type (k ), - len (incomplete ), display_meta = text_type ("/" .join (v ))
149- )
150- for k , v in {
151- "true" : ("1" , "true" , "t" , "yes" , "y" , "on" ),
152- "false" : ("0" , "false" , "f" , "no" , "n" , "off" ),
153- }.items ()
161+ Completion (k , - len (incomplete ), display_meta = "/" .join (v ))
162+ for k , v in boolean_mapping .items ()
154163 if any (i .startswith (incomplete ) for i in v )
155164 ]
156165
157- def _get_completion_from_params (self , autocomplete_ctx , args , param , incomplete ):
158-
159- choices = []
166+ def _get_completion_from_params (
167+ self ,
168+ autocomplete_ctx : click .Context ,
169+ args : list [str ],
170+ param : click .Parameter ,
171+ incomplete : str ,
172+ ) -> list [Completion ]:
173+ choices : list [Completion ] = []
160174 param_type = param .type
161175
162176 # shell_complete method for click.Choice is intorduced in click-v8
@@ -185,12 +199,12 @@ def _get_completion_from_params(self, autocomplete_ctx, args, param, incomplete)
185199
186200 def _get_completion_for_cmd_args (
187201 self ,
188- ctx_command ,
189- incomplete ,
190- autocomplete_ctx ,
191- args ,
192- ):
193- choices = []
202+ ctx_command : click . Command ,
203+ incomplete : str ,
204+ autocomplete_ctx : click . Context ,
205+ args : list [ str ] ,
206+ ) -> list [ Completion ] :
207+ choices : list [ Completion ] = []
194208 param_called = False
195209
196210 for param in ctx_command .params :
@@ -229,9 +243,9 @@ def _get_completion_for_cmd_args(
229243 elif option .startswith (incomplete ) and not hide :
230244 choices .append (
231245 Completion (
232- text_type ( option ) ,
246+ option ,
233247 - len (incomplete ),
234- display_meta = text_type ( param .help or "" ) ,
248+ display_meta = param .help or "" ,
235249 )
236250 )
237251
@@ -250,12 +264,14 @@ def _get_completion_for_cmd_args(
250264
251265 return choices
252266
253- def get_completions (self , document , complete_event = None ):
267+ def get_completions (
268+ self , document : Document , complete_event : CompleteEvent | None = None
269+ ) -> Generator [Completion , None , None ]:
254270 # Code analogous to click._bashcomplete.do_complete
255271
256272 args = split_arg_string (document .text_before_cursor , posix = False )
257273
258- choices = []
274+ choices : list [ Completion ] = []
259275 cursor_within_command = (
260276 document .text_before_cursor .rstrip () == document .text_before_cursor
261277 )
@@ -277,7 +293,7 @@ def get_completions(self, document, complete_event=None):
277293 try :
278294 self .parsed_ctx = _resolve_context (args , self .ctx )
279295 except Exception :
280- return [] # autocompletion for nonexistent cmd can throw here
296+ return # autocompletion for nonexistent cmd can throw here
281297 self .ctx_command = self .parsed_ctx .command
282298
283299 if getattr (self .ctx_command , "hidden" , False ):
@@ -301,7 +317,7 @@ def get_completions(self, document, complete_event=None):
301317 elif name .lower ().startswith (incomplete_lower ):
302318 choices .append (
303319 Completion (
304- text_type ( name ) ,
320+ name ,
305321 - len (incomplete ),
306322 display_meta = getattr (command , "short_help" , "" ),
307323 )
@@ -310,10 +326,5 @@ def get_completions(self, document, complete_event=None):
310326 except Exception as e :
311327 click .echo ("{}: {}" .format (type (e ).__name__ , str (e )))
312328
313- # If we are inside a parameter that was called, we want to show only
314- # relevant choices
315- # if param_called:
316- # choices = param_choices
317-
318329 for item in choices :
319330 yield item
0 commit comments