1
- from __future__ import unicode_literals
1
+ from __future__ import annotations
2
2
3
3
import os
4
+ import typing as t
4
5
from glob import iglob
6
+ from typing import Generator
5
7
6
8
import 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
8
11
9
12
from .utils import _resolve_context , split_arg_string
10
13
26
29
AUTO_COMPLETION_PARAM = "autocompletion"
27
30
28
31
29
- def text_type (text ):
30
- return "{}" .format (text )
31
-
32
-
33
32
class ClickCompleter (Completer ):
34
33
__slots__ = ("cli" , "ctx" , "parsed_args" , "parsed_ctx" , "ctx_command" )
35
34
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 :
37
42
self .cli = cli
38
43
self .ctx = ctx
39
- self .parsed_args = []
44
+ self .parsed_args : list [ str ] = []
40
45
self .parsed_ctx = ctx
41
46
self .ctx_command = ctx .command
42
47
self .show_only_unused = show_only_unused
43
48
self .shortest_only = shortest_only
44
49
45
50
def _get_completion_from_autocompletion_functions (
46
51
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 ] = []
53
58
54
59
if HAS_CLICK_V8 :
55
60
autocompletions = param .shell_complete (autocomplete_ctx , incomplete )
@@ -62,7 +67,7 @@ def _get_completion_from_autocompletion_functions(
62
67
if isinstance (autocomplete , tuple ):
63
68
param_choices .append (
64
69
Completion (
65
- text_type (autocomplete [0 ]),
70
+ str (autocomplete [0 ]),
66
71
- len (incomplete ),
67
72
display_meta = autocomplete [1 ],
68
73
)
@@ -71,46 +76,48 @@ def _get_completion_from_autocompletion_functions(
71
76
elif HAS_CLICK_V8 and isinstance (
72
77
autocomplete , click .shell_completion .CompletionItem
73
78
):
74
- param_choices .append (
75
- Completion (text_type (autocomplete .value ), - len (incomplete ))
76
- )
79
+ param_choices .append (Completion (autocomplete .value , - len (incomplete )))
77
80
78
81
else :
79
- param_choices .append (
80
- Completion (text_type (autocomplete ), - len (incomplete ))
81
- )
82
+ param_choices .append (Completion (str (autocomplete ), - len (incomplete )))
82
83
83
84
return param_choices
84
85
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
+
86
91
if not getattr (param .type , "case_sensitive" , True ):
87
92
incomplete = incomplete .lower ()
88
93
return [
89
94
Completion (
90
- text_type ( choice ) ,
95
+ choice ,
91
96
- len (incomplete ),
92
- display = text_type ( repr (choice ) if " " in choice else choice ) ,
97
+ display = repr (choice ) if " " in choice else choice ,
93
98
)
94
- for choice in param . type .choices # type: ignore[attr-defined]
99
+ for choice in param_type .choices # type: ignore[attr-defined]
95
100
if choice .lower ().startswith (incomplete )
96
101
]
97
102
98
103
else :
99
104
return [
100
105
Completion (
101
- text_type ( choice ) ,
106
+ choice ,
102
107
- len (incomplete ),
103
- display = text_type ( repr (choice ) if " " in choice else choice ) ,
108
+ display = repr (choice ) if " " in choice else choice ,
104
109
)
105
- for choice in param . type .choices # type: ignore[attr-defined]
110
+ for choice in param_type .choices # type: ignore[attr-defined]
106
111
if choice .startswith (incomplete )
107
112
]
108
113
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 ]:
110
117
if "*" in incomplete :
111
118
return []
112
119
113
- choices = []
120
+ choices : list [ Completion ] = []
114
121
_incomplete = os .path .expandvars (incomplete )
115
122
search_pattern = _incomplete .strip ("'\" \t \n \r \v " ).replace ("\\ \\ " , "\\ " ) + "*"
116
123
quote = ""
@@ -134,29 +141,36 @@ def _get_completion_for_Path_types(self, param, args, incomplete):
134
141
135
142
choices .append (
136
143
Completion (
137
- text_type ( path ) ,
144
+ path ,
138
145
- len (incomplete ),
139
- display = text_type ( os .path .basename (path .strip ("'\" " ) )),
146
+ display = os .path .basename (path .strip ("'\" " )),
140
147
)
141
148
)
142
149
143
150
return choices
144
151
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
+
146
160
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 ()
154
163
if any (i .startswith (incomplete ) for i in v )
155
164
]
156
165
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 ] = []
160
174
param_type = param .type
161
175
162
176
# 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)
185
199
186
200
def _get_completion_for_cmd_args (
187
201
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 ] = []
194
208
param_called = False
195
209
196
210
for param in ctx_command .params :
@@ -229,9 +243,9 @@ def _get_completion_for_cmd_args(
229
243
elif option .startswith (incomplete ) and not hide :
230
244
choices .append (
231
245
Completion (
232
- text_type ( option ) ,
246
+ option ,
233
247
- len (incomplete ),
234
- display_meta = text_type ( param .help or "" ) ,
248
+ display_meta = param .help or "" ,
235
249
)
236
250
)
237
251
@@ -250,12 +264,14 @@ def _get_completion_for_cmd_args(
250
264
251
265
return choices
252
266
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 ]:
254
270
# Code analogous to click._bashcomplete.do_complete
255
271
256
272
args = split_arg_string (document .text_before_cursor , posix = False )
257
273
258
- choices = []
274
+ choices : list [ Completion ] = []
259
275
cursor_within_command = (
260
276
document .text_before_cursor .rstrip () == document .text_before_cursor
261
277
)
@@ -277,7 +293,7 @@ def get_completions(self, document, complete_event=None):
277
293
try :
278
294
self .parsed_ctx = _resolve_context (args , self .ctx )
279
295
except Exception :
280
- return [] # autocompletion for nonexistent cmd can throw here
296
+ return # autocompletion for nonexistent cmd can throw here
281
297
self .ctx_command = self .parsed_ctx .command
282
298
283
299
if getattr (self .ctx_command , "hidden" , False ):
@@ -301,7 +317,7 @@ def get_completions(self, document, complete_event=None):
301
317
elif name .lower ().startswith (incomplete_lower ):
302
318
choices .append (
303
319
Completion (
304
- text_type ( name ) ,
320
+ name ,
305
321
- len (incomplete ),
306
322
display_meta = getattr (command , "short_help" , "" ),
307
323
)
@@ -310,10 +326,5 @@ def get_completions(self, document, complete_event=None):
310
326
except Exception as e :
311
327
click .echo ("{}: {}" .format (type (e ).__name__ , str (e )))
312
328
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
-
318
329
for item in choices :
319
330
yield item
0 commit comments