@@ -157,100 +157,20 @@ fn complete_arg(
157
157
{
158
158
completions. extend ( complete_arg_value ( arg. to_value ( ) , positional, current_dir) ) ;
159
159
}
160
-
161
- if arg. is_empty ( ) {
162
- completions. extend ( longs_and_visible_aliases ( cmd) ) ;
163
- completions. extend ( hidden_longs_aliases ( cmd) ) ;
164
-
165
- let dash_or_arg = if arg. is_empty ( ) {
166
- "-" . into ( )
167
- } else {
168
- arg. to_value_os ( ) . to_string_lossy ( )
169
- } ;
170
- completions. extend (
171
- shorts_and_visible_aliases ( cmd)
172
- . into_iter ( )
173
- . map ( |comp| comp. add_prefix ( dash_or_arg. to_string ( ) ) ) ,
174
- ) ;
175
- } else if arg. is_stdio ( ) {
176
- // HACK: Assuming knowledge of is_stdio
177
- let dash_or_arg = if arg. is_empty ( ) {
178
- "-" . into ( )
179
- } else {
180
- arg. to_value_os ( ) . to_string_lossy ( )
181
- } ;
182
- completions. extend (
183
- shorts_and_visible_aliases ( cmd)
184
- . into_iter ( )
185
- . map ( |comp| comp. add_prefix ( dash_or_arg. to_string ( ) ) ) ,
186
- ) ;
187
-
188
- completions. extend ( longs_and_visible_aliases ( cmd) ) ;
189
- completions. extend ( hidden_longs_aliases ( cmd) ) ;
190
- } else if arg. is_escape ( ) {
191
- // HACK: Assuming knowledge of is_escape
192
- completions. extend ( longs_and_visible_aliases ( cmd) ) ;
193
- completions. extend ( hidden_longs_aliases ( cmd) ) ;
194
- } else if let Some ( ( flag, value) ) = arg. to_long ( ) {
195
- if let Ok ( flag) = flag {
196
- if let Some ( value) = value {
197
- if let Some ( arg) = cmd. get_arguments ( ) . find ( |a| a. get_long ( ) == Some ( flag) )
198
- {
199
- completions. extend (
200
- complete_arg_value ( value. to_str ( ) . ok_or ( value) , arg, current_dir)
201
- . into_iter ( )
202
- . map ( |comp| comp. add_prefix ( format ! ( "--{flag}=" ) ) ) ,
203
- ) ;
204
- }
205
- } else {
206
- completions. extend ( longs_and_visible_aliases ( cmd) . into_iter ( ) . filter (
207
- |comp| comp. get_value ( ) . starts_with ( format ! ( "--{flag}" ) . as_str ( ) ) ,
208
- ) ) ;
209
- completions. extend ( hidden_longs_aliases ( cmd) . into_iter ( ) . filter ( |comp| {
210
- comp. get_value ( ) . starts_with ( format ! ( "--{flag}" ) . as_str ( ) )
211
- } ) ) ;
212
- }
213
- }
214
- } else if let Some ( short) = arg. to_short ( ) {
215
- if !short. is_negative_number ( ) {
216
- // Find the first takes_values option.
217
- let ( leading_flags, takes_value_opt, mut short) = parse_shortflags ( cmd, short) ;
218
-
219
- // Clone `short` to `peek_short` to peek whether the next flag is a `=`.
220
- if let Some ( opt) = takes_value_opt {
221
- let mut peek_short = short. clone ( ) ;
222
- let has_equal = if let Some ( Ok ( '=' ) ) = peek_short. next_flag ( ) {
223
- short. next_flag ( ) ;
224
- true
225
- } else {
226
- false
227
- } ;
228
-
229
- let value = short. next_value_os ( ) . unwrap_or ( OsStr :: new ( "" ) ) ;
230
- completions. extend (
231
- complete_arg_value ( value. to_str ( ) . ok_or ( value) , opt, current_dir)
232
- . into_iter ( )
233
- . map ( |comp| {
234
- let sep = if has_equal { "=" } else { "" } ;
235
- comp. add_prefix ( format ! ( "-{leading_flags}{sep}" ) )
236
- } ) ,
237
- ) ;
238
- } else {
239
- completions. extend (
240
- shorts_and_visible_aliases ( cmd)
241
- . into_iter ( )
242
- . map ( |comp| comp. add_prefix ( format ! ( "-{leading_flags}" ) ) ) ,
243
- ) ;
244
- }
245
- }
246
- }
160
+ completions. extend ( complete_option ( arg, cmd, current_dir) ) ;
247
161
}
248
- ParseState :: Pos ( .. ) => {
162
+ ParseState :: Pos ( ( _ , num_arg ) ) => {
249
163
if let Some ( positional) = cmd
250
164
. get_positionals ( )
251
165
. find ( |p| p. get_index ( ) == Some ( pos_index) )
252
166
{
253
167
completions. extend ( complete_arg_value ( arg. to_value ( ) , positional, current_dir) ) ;
168
+ if positional
169
+ . get_num_args ( )
170
+ . is_some_and ( |num_args| num_arg >= num_args. min_values ( ) )
171
+ {
172
+ completions. extend ( complete_option ( arg, cmd, current_dir) ) ;
173
+ }
254
174
}
255
175
}
256
176
ParseState :: Opt ( ( opt, count) ) => {
@@ -297,6 +217,104 @@ fn complete_arg(
297
217
Ok ( completions)
298
218
}
299
219
220
+ fn complete_option (
221
+ arg : & clap_lex:: ParsedArg < ' _ > ,
222
+ cmd : & clap:: Command ,
223
+ current_dir : Option < & std:: path:: Path > ,
224
+ ) -> Vec < CompletionCandidate > {
225
+ let mut completions = Vec :: < CompletionCandidate > :: new ( ) ;
226
+ if arg. is_empty ( ) {
227
+ completions. extend ( longs_and_visible_aliases ( cmd) ) ;
228
+ completions. extend ( hidden_longs_aliases ( cmd) ) ;
229
+
230
+ let dash_or_arg = if arg. is_empty ( ) {
231
+ "-" . into ( )
232
+ } else {
233
+ arg. to_value_os ( ) . to_string_lossy ( )
234
+ } ;
235
+ completions. extend (
236
+ shorts_and_visible_aliases ( cmd)
237
+ . into_iter ( )
238
+ . map ( |comp| comp. add_prefix ( dash_or_arg. to_string ( ) ) ) ,
239
+ ) ;
240
+ } else if arg. is_stdio ( ) {
241
+ // HACK: Assuming knowledge of is_stdio
242
+ let dash_or_arg = if arg. is_empty ( ) {
243
+ "-" . into ( )
244
+ } else {
245
+ arg. to_value_os ( ) . to_string_lossy ( )
246
+ } ;
247
+ completions. extend (
248
+ shorts_and_visible_aliases ( cmd)
249
+ . into_iter ( )
250
+ . map ( |comp| comp. add_prefix ( dash_or_arg. to_string ( ) ) ) ,
251
+ ) ;
252
+
253
+ completions. extend ( longs_and_visible_aliases ( cmd) ) ;
254
+ completions. extend ( hidden_longs_aliases ( cmd) ) ;
255
+ } else if arg. is_escape ( ) {
256
+ // HACK: Assuming knowledge of is_escape
257
+ completions. extend ( longs_and_visible_aliases ( cmd) ) ;
258
+ completions. extend ( hidden_longs_aliases ( cmd) ) ;
259
+ } else if let Some ( ( flag, value) ) = arg. to_long ( ) {
260
+ if let Ok ( flag) = flag {
261
+ if let Some ( value) = value {
262
+ if let Some ( arg) = cmd. get_arguments ( ) . find ( |a| a. get_long ( ) == Some ( flag) ) {
263
+ completions. extend (
264
+ complete_arg_value ( value. to_str ( ) . ok_or ( value) , arg, current_dir)
265
+ . into_iter ( )
266
+ . map ( |comp| comp. add_prefix ( format ! ( "--{flag}=" ) ) ) ,
267
+ ) ;
268
+ }
269
+ } else {
270
+ completions. extend (
271
+ longs_and_visible_aliases ( cmd)
272
+ . into_iter ( )
273
+ . filter ( |comp| comp. get_value ( ) . starts_with ( format ! ( "--{flag}" ) . as_str ( ) ) ) ,
274
+ ) ;
275
+ completions. extend (
276
+ hidden_longs_aliases ( cmd)
277
+ . into_iter ( )
278
+ . filter ( |comp| comp. get_value ( ) . starts_with ( format ! ( "--{flag}" ) . as_str ( ) ) ) ,
279
+ ) ;
280
+ }
281
+ }
282
+ } else if let Some ( short) = arg. to_short ( ) {
283
+ if !short. is_negative_number ( ) {
284
+ // Find the first takes_values option.
285
+ let ( leading_flags, takes_value_opt, mut short) = parse_shortflags ( cmd, short) ;
286
+
287
+ // Clone `short` to `peek_short` to peek whether the next flag is a `=`.
288
+ if let Some ( opt) = takes_value_opt {
289
+ let mut peek_short = short. clone ( ) ;
290
+ let has_equal = if let Some ( Ok ( '=' ) ) = peek_short. next_flag ( ) {
291
+ short. next_flag ( ) ;
292
+ true
293
+ } else {
294
+ false
295
+ } ;
296
+
297
+ let value = short. next_value_os ( ) . unwrap_or ( OsStr :: new ( "" ) ) ;
298
+ completions. extend (
299
+ complete_arg_value ( value. to_str ( ) . ok_or ( value) , opt, current_dir)
300
+ . into_iter ( )
301
+ . map ( |comp| {
302
+ let sep = if has_equal { "=" } else { "" } ;
303
+ comp. add_prefix ( format ! ( "-{leading_flags}{sep}" ) )
304
+ } ) ,
305
+ ) ;
306
+ } else {
307
+ completions. extend (
308
+ shorts_and_visible_aliases ( cmd)
309
+ . into_iter ( )
310
+ . map ( |comp| comp. add_prefix ( format ! ( "-{leading_flags}" ) ) ) ,
311
+ ) ;
312
+ }
313
+ }
314
+ }
315
+ completions
316
+ }
317
+
300
318
fn complete_arg_value (
301
319
value : Result < & str , & OsStr > ,
302
320
arg : & clap:: Arg ,
0 commit comments