@@ -3,7 +3,9 @@ use std::ffi::OsString;
3
3
4
4
use clap_lex:: OsStrExt as _;
5
5
6
+ use super :: custom:: complete_path;
6
7
use super :: ArgValueCandidates ;
8
+ use super :: ArgValueCompleter ;
7
9
use super :: CompletionCandidate ;
8
10
9
11
/// Complete the given command, shell-agnostic
@@ -270,7 +272,9 @@ fn complete_arg_value(
270
272
Err ( value_os) => value_os,
271
273
} ;
272
274
273
- if let Some ( completer) = arg. get :: < ArgValueCandidates > ( ) {
275
+ if let Some ( completer) = arg. get :: < ArgValueCompleter > ( ) {
276
+ values. extend ( completer. complete ( value_os) ) ;
277
+ } else if let Some ( completer) = arg. get :: < ArgValueCandidates > ( ) {
274
278
values. extend ( complete_custom_arg_value ( value_os, completer) ) ;
275
279
} else if let Some ( possible_values) = possible_values ( arg) {
276
280
if let Ok ( value) = value {
@@ -289,17 +293,17 @@ fn complete_arg_value(
289
293
// Should not complete
290
294
}
291
295
clap:: ValueHint :: Unknown | clap:: ValueHint :: AnyPath => {
292
- values. extend ( complete_path ( value_os, current_dir, |_| true ) ) ;
296
+ values. extend ( complete_path ( value_os, current_dir, & |_| true ) ) ;
293
297
}
294
298
clap:: ValueHint :: FilePath => {
295
- values. extend ( complete_path ( value_os, current_dir, |p| p. is_file ( ) ) ) ;
299
+ values. extend ( complete_path ( value_os, current_dir, & |p| p. is_file ( ) ) ) ;
296
300
}
297
301
clap:: ValueHint :: DirPath => {
298
- values. extend ( complete_path ( value_os, current_dir, |p| p. is_dir ( ) ) ) ;
302
+ values. extend ( complete_path ( value_os, current_dir, & |p| p. is_dir ( ) ) ) ;
299
303
}
300
304
clap:: ValueHint :: ExecutablePath => {
301
305
use is_executable:: IsExecutable ;
302
- values. extend ( complete_path ( value_os, current_dir, |p| p. is_executable ( ) ) ) ;
306
+ values. extend ( complete_path ( value_os, current_dir, & |p| p. is_executable ( ) ) ) ;
303
307
}
304
308
clap:: ValueHint :: CommandName
305
309
| clap:: ValueHint :: CommandString
@@ -312,7 +316,7 @@ fn complete_arg_value(
312
316
}
313
317
_ => {
314
318
// Safe-ish fallback
315
- values. extend ( complete_path ( value_os, current_dir, |_| true ) ) ;
319
+ values. extend ( complete_path ( value_os, current_dir, & |_| true ) ) ;
316
320
}
317
321
}
318
322
@@ -341,69 +345,14 @@ fn rsplit_delimiter<'s, 'o>(
341
345
Some ( ( Some ( prefix) , Ok ( value) ) )
342
346
}
343
347
344
- fn complete_path (
345
- value_os : & OsStr ,
346
- current_dir : Option < & std:: path:: Path > ,
347
- is_wanted : impl Fn ( & std:: path:: Path ) -> bool ,
348
- ) -> Vec < CompletionCandidate > {
349
- let mut completions = Vec :: new ( ) ;
350
-
351
- let current_dir = match current_dir {
352
- Some ( current_dir) => current_dir,
353
- None => {
354
- // Can't complete without a `current_dir`
355
- return Vec :: new ( ) ;
356
- }
357
- } ;
358
- let ( existing, prefix) = value_os
359
- . split_once ( "\\ " )
360
- . unwrap_or ( ( OsStr :: new ( "" ) , value_os) ) ;
361
- let root = current_dir. join ( existing) ;
362
- debug ! ( "complete_path: root={root:?}, prefix={prefix:?}" ) ;
363
- let prefix = prefix. to_string_lossy ( ) ;
364
-
365
- for entry in std:: fs:: read_dir ( & root)
366
- . ok ( )
367
- . into_iter ( )
368
- . flatten ( )
369
- . filter_map ( Result :: ok)
370
- {
371
- let raw_file_name = entry. file_name ( ) ;
372
- if !raw_file_name. starts_with ( & prefix) {
373
- continue ;
374
- }
375
-
376
- if entry. metadata ( ) . map ( |m| m. is_dir ( ) ) . unwrap_or ( false ) {
377
- let path = entry. path ( ) ;
378
- let mut suggestion = pathdiff:: diff_paths ( & path, current_dir) . unwrap_or ( path) ;
379
- suggestion. push ( "" ) ; // Ensure trailing `/`
380
- completions
381
- . push ( CompletionCandidate :: new ( suggestion. as_os_str ( ) . to_owned ( ) ) . help ( None ) ) ;
382
- } else {
383
- let path = entry. path ( ) ;
384
- if is_wanted ( & path) {
385
- let suggestion = pathdiff:: diff_paths ( & path, current_dir) . unwrap_or ( path) ;
386
- completions
387
- . push ( CompletionCandidate :: new ( suggestion. as_os_str ( ) . to_owned ( ) ) . help ( None ) ) ;
388
- }
389
- }
390
- }
391
-
392
- completions
393
- }
394
-
395
348
fn complete_custom_arg_value (
396
349
value : & OsStr ,
397
350
completer : & ArgValueCandidates ,
398
351
) -> Vec < CompletionCandidate > {
399
352
debug ! ( "complete_custom_arg_value: completer={completer:?}, value={value:?}" ) ;
400
353
401
- let mut values = Vec :: new ( ) ;
402
- let custom_arg_values = completer. candidates ( ) ;
403
- values. extend ( custom_arg_values) ;
404
-
354
+ let mut values = completer. candidates ( ) ;
405
355
values. retain ( |comp| comp. get_content ( ) . starts_with ( & value. to_string_lossy ( ) ) ) ;
406
-
407
356
values
408
357
}
409
358
0 commit comments