Skip to content

Commit 82e599e

Browse files
authored
Merge pull request #5602 from shannmu/delimiter_values
Support delimited values in native completions
2 parents a3a4764 + 59bf26d commit 82e599e

File tree

2 files changed

+180
-0
lines changed

2 files changed

+180
-0
lines changed

clap_complete/src/dynamic/complete.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,9 @@ fn complete_arg_value(
262262
let mut values = Vec::new();
263263
debug!("complete_arg_value: arg={arg:?}, value={value:?}");
264264

265+
let (prefix, value) =
266+
rsplit_delimiter(value, arg.get_value_delimiter()).unwrap_or((None, value));
267+
265268
let value_os = match value {
266269
Ok(value) => OsStr::new(value),
267270
Err(value_os) => value_os,
@@ -316,9 +319,28 @@ fn complete_arg_value(
316319
values.sort();
317320
}
318321

322+
if let Some(prefix) = prefix {
323+
values = values
324+
.into_iter()
325+
.map(|comp| comp.add_prefix(prefix))
326+
.collect();
327+
}
319328
values
320329
}
321330

331+
fn rsplit_delimiter<'s, 'o>(
332+
value: Result<&'s str, &'o OsStr>,
333+
delimiter: Option<char>,
334+
) -> Option<(Option<&'s str>, Result<&'s str, &'o OsStr>)> {
335+
let delimiter = delimiter?;
336+
let value = value.ok()?;
337+
let pos = value.rfind(delimiter)?;
338+
let (prefix, value) = value
339+
.split_at_checked(pos + delimiter.len_utf8())
340+
.expect("since delimiter was found, it is within bounds");
341+
Some((Some(prefix), Ok(value)))
342+
}
343+
322344
fn complete_path(
323345
value_os: &OsStr,
324346
current_dir: Option<&std::path::Path>,

clap_complete/tests/testsuite/dynamic.rs

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,164 @@ pos_c
615615
);
616616
}
617617

618+
#[test]
619+
fn suggest_delimiter_values() {
620+
let mut cmd = Command::new("delimiter")
621+
.arg(
622+
clap::Arg::new("delimiter")
623+
.long("delimiter")
624+
.short('D')
625+
.value_parser([
626+
PossibleValue::new("comma"),
627+
PossibleValue::new("space"),
628+
PossibleValue::new("tab"),
629+
])
630+
.value_delimiter(','),
631+
)
632+
.arg(
633+
clap::Arg::new("pos")
634+
.index(1)
635+
.value_parser(["a_pos", "b_pos", "c_pos"])
636+
.value_delimiter(','),
637+
);
638+
639+
assert_data_eq!(
640+
complete!(cmd, "--delimiter [TAB]"),
641+
snapbox::str![
642+
"comma
643+
space
644+
tab"
645+
]
646+
);
647+
648+
assert_data_eq!(
649+
complete!(cmd, "--delimiter=[TAB]"),
650+
snapbox::str![
651+
"--delimiter=comma
652+
--delimiter=space
653+
--delimiter=tab"
654+
]
655+
);
656+
657+
assert_data_eq!(complete!(cmd, "--delimiter c[TAB]"), snapbox::str!["comma"]);
658+
659+
assert_data_eq!(
660+
complete!(cmd, "--delimiter=c[TAB]"),
661+
snapbox::str!["--delimiter=comma"]
662+
);
663+
664+
assert_data_eq!(
665+
complete!(cmd, "--delimiter comma,[TAB]"),
666+
snapbox::str![
667+
"comma,comma
668+
comma,space
669+
comma,tab"
670+
]
671+
);
672+
673+
assert_data_eq!(
674+
complete!(cmd, "--delimiter=comma,[TAB]"),
675+
snapbox::str![
676+
"--delimiter=comma,comma
677+
--delimiter=comma,space
678+
--delimiter=comma,tab
679+
--delimiter=comma,a_pos
680+
--delimiter=comma,b_pos
681+
--delimiter=comma,c_pos"
682+
]
683+
);
684+
685+
assert_data_eq!(
686+
complete!(cmd, "--delimiter comma,s[TAB]"),
687+
snapbox::str!["comma,space"]
688+
);
689+
690+
assert_data_eq!(
691+
complete!(cmd, "--delimiter=comma,s[TAB]"),
692+
snapbox::str!["--delimiter=comma,space"]
693+
);
694+
695+
assert_data_eq!(
696+
complete!(cmd, "-D [TAB]"),
697+
snapbox::str![
698+
"comma
699+
space
700+
tab"
701+
]
702+
);
703+
704+
assert_data_eq!(
705+
complete!(cmd, "-D=[TAB]"),
706+
snapbox::str![
707+
"-D=comma
708+
-D=space
709+
-D=tab"
710+
]
711+
);
712+
713+
assert_data_eq!(complete!(cmd, "-D c[TAB]"), snapbox::str!["comma"]);
714+
715+
assert_data_eq!(complete!(cmd, "-D=c[TAB]"), snapbox::str!["-D=comma"]);
716+
717+
assert_data_eq!(
718+
complete!(cmd, "-D comma,[TAB]"),
719+
snapbox::str![
720+
"comma,comma
721+
comma,space
722+
comma,tab"
723+
]
724+
);
725+
726+
assert_data_eq!(
727+
complete!(cmd, "-D=comma,[TAB]"),
728+
snapbox::str![
729+
"-D=comma,comma
730+
-D=comma,space
731+
-D=comma,tab
732+
-D=comma,a_pos
733+
-D=comma,b_pos
734+
-D=comma,c_pos"
735+
]
736+
);
737+
738+
assert_data_eq!(
739+
complete!(cmd, "-D comma,s[TAB]"),
740+
snapbox::str!["comma,space"]
741+
);
742+
743+
assert_data_eq!(
744+
complete!(cmd, "-D=comma,s[TAB]"),
745+
snapbox::str!["-D=comma,space"]
746+
);
747+
748+
assert_data_eq!(
749+
complete!(cmd, "-- [TAB]"),
750+
snapbox::str![
751+
"--delimiter
752+
--help\tPrint help
753+
-D
754+
-h\tPrint help
755+
a_pos
756+
b_pos
757+
c_pos"
758+
]
759+
);
760+
761+
assert_data_eq!(
762+
complete!(cmd, " -- a_pos,[TAB]"),
763+
snapbox::str![
764+
"a_pos,a_pos
765+
a_pos,b_pos
766+
a_pos,c_pos"
767+
]
768+
);
769+
770+
assert_data_eq!(
771+
complete!(cmd, "-- a_pos,b[TAB]"),
772+
snapbox::str!["a_pos,b_pos"]
773+
);
774+
}
775+
618776
fn complete(cmd: &mut Command, args: impl AsRef<str>, current_dir: Option<&Path>) -> String {
619777
let input = args.as_ref();
620778
let mut args = vec![std::ffi::OsString::from(cmd.get_name())];

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy