mirror of
https://github.com/clap-rs/clap
synced 2024-12-13 22:32:33 +00:00
feat(clap_complete): Support hiding long flags and their long aliases
This commit is contained in:
parent
903b73bd1c
commit
d1e0f6073c
3 changed files with 88 additions and 20 deletions
|
@ -3952,6 +3952,21 @@ impl Arg {
|
||||||
Some(longs)
|
Some(longs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get hidden aliases for this argument, if any
|
||||||
|
#[inline]
|
||||||
|
pub fn get_aliases(&self) -> Option<Vec<&str>> {
|
||||||
|
if self.aliases.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(
|
||||||
|
self.aliases
|
||||||
|
.iter()
|
||||||
|
.filter_map(|(s, v)| if !*v { Some(s.as_str()) } else { None })
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the names of possible values for this argument. Only useful for user
|
/// Get the names of possible values for this argument. Only useful for user
|
||||||
/// facing applications, such as building help messages or man files
|
/// facing applications, such as building help messages or man files
|
||||||
pub fn get_possible_values(&self) -> Vec<PossibleValue> {
|
pub fn get_possible_values(&self) -> Vec<PossibleValue> {
|
||||||
|
|
|
@ -118,6 +118,7 @@ fn complete_arg(
|
||||||
os.to_string_lossy()
|
os.to_string_lossy()
|
||||||
))
|
))
|
||||||
.help(help)
|
.help(help)
|
||||||
|
.visible(true)
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -126,11 +127,18 @@ fn complete_arg(
|
||||||
comp.get_content()
|
comp.get_content()
|
||||||
.starts_with(format!("--{}", flag).as_str())
|
.starts_with(format!("--{}", flag).as_str())
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
completions.extend(hidden_longs_aliases(cmd).into_iter().filter(|comp| {
|
||||||
|
comp.get_content()
|
||||||
|
.starts_with(format!("--{}", flag).as_str())
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if arg.is_escape() || arg.is_stdio() || arg.is_empty() {
|
} else if arg.is_escape() || arg.is_stdio() || arg.is_empty() {
|
||||||
// HACK: Assuming knowledge of is_escape / is_stdio
|
// HACK: Assuming knowledge of is_escape / is_stdio
|
||||||
completions.extend(longs_and_visible_aliases(cmd));
|
completions.extend(longs_and_visible_aliases(cmd));
|
||||||
|
|
||||||
|
completions.extend(hidden_longs_aliases(cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
if arg.is_empty() || arg.is_stdio() || arg.is_short() {
|
if arg.is_empty() || arg.is_stdio() || arg.is_short() {
|
||||||
|
@ -151,6 +159,7 @@ fn complete_arg(
|
||||||
comp.get_content().to_string_lossy()
|
comp.get_content().to_string_lossy()
|
||||||
))
|
))
|
||||||
.help(comp.get_help().cloned())
|
.help(comp.get_help().cloned())
|
||||||
|
.visible(true)
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -163,7 +172,7 @@ fn complete_arg(
|
||||||
completions.extend(
|
completions.extend(
|
||||||
complete_arg_value(arg.to_value(), positional, current_dir)
|
complete_arg_value(arg.to_value(), positional, current_dir)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(os, help)| CompletionCandidate::new(os).help(help)),
|
.map(|(os, help)| CompletionCandidate::new(os).help(help).visible(true)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,6 +180,10 @@ fn complete_arg(
|
||||||
completions.extend(complete_subcommand(value, cmd));
|
completions.extend(complete_subcommand(value, cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if completions.iter().any(|a| a.is_visible()) {
|
||||||
|
completions.retain(|a| a.is_visible())
|
||||||
|
}
|
||||||
|
|
||||||
Ok(completions)
|
Ok(completions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,7 +310,7 @@ fn complete_subcommand(value: &str, cmd: &clap::Command) -> Vec<CompletionCandid
|
||||||
scs
|
scs
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets all the long options, their visible aliases and flags of a [`clap::Command`].
|
/// Gets all the long options, their visible aliases and flags of a [`clap::Command`] with formatted `--` prefix.
|
||||||
/// Includes `help` and `version` depending on the [`clap::Command`] settings.
|
/// Includes `help` and `version` depending on the [`clap::Command`] settings.
|
||||||
fn longs_and_visible_aliases(p: &clap::Command) -> Vec<CompletionCandidate> {
|
fn longs_and_visible_aliases(p: &clap::Command) -> Vec<CompletionCandidate> {
|
||||||
debug!("longs: name={}", p.get_name());
|
debug!("longs: name={}", p.get_name());
|
||||||
|
@ -306,7 +319,27 @@ fn longs_and_visible_aliases(p: &clap::Command) -> Vec<CompletionCandidate> {
|
||||||
.filter_map(|a| {
|
.filter_map(|a| {
|
||||||
a.get_long_and_visible_aliases().map(|longs| {
|
a.get_long_and_visible_aliases().map(|longs| {
|
||||||
longs.into_iter().map(|s| {
|
longs.into_iter().map(|s| {
|
||||||
CompletionCandidate::new(format!("--{}", s)).help(a.get_help().cloned())
|
CompletionCandidate::new(format!("--{}", s.to_string()))
|
||||||
|
.help(a.get_help().cloned())
|
||||||
|
.visible(!a.is_hide_set())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.flatten()
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets all the long hidden aliases and flags of a [`clap::Command`].
|
||||||
|
fn hidden_longs_aliases(p: &clap::Command) -> Vec<CompletionCandidate> {
|
||||||
|
debug!("longs: name={}", p.get_name());
|
||||||
|
|
||||||
|
p.get_arguments()
|
||||||
|
.filter_map(|a| {
|
||||||
|
a.get_aliases().map(|longs| {
|
||||||
|
longs.into_iter().map(|s| {
|
||||||
|
CompletionCandidate::new(format!("--{}", s.to_string()))
|
||||||
|
.help(a.get_help().cloned())
|
||||||
|
.visible(false)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -322,9 +355,11 @@ fn shorts_and_visible_aliases(p: &clap::Command) -> Vec<CompletionCandidate> {
|
||||||
p.get_arguments()
|
p.get_arguments()
|
||||||
.filter_map(|a| {
|
.filter_map(|a| {
|
||||||
a.get_short_and_visible_aliases().map(|shorts| {
|
a.get_short_and_visible_aliases().map(|shorts| {
|
||||||
shorts
|
shorts.into_iter().map(|s| {
|
||||||
.into_iter()
|
CompletionCandidate::new(s.to_string())
|
||||||
.map(|s| CompletionCandidate::new(s.to_string()).help(a.get_help().cloned()))
|
.help(a.get_help().cloned())
|
||||||
|
.visible(!a.is_hide_set())
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.flatten()
|
.flatten()
|
||||||
|
@ -351,14 +386,16 @@ fn subcommands(p: &clap::Command) -> Vec<CompletionCandidate> {
|
||||||
debug!("subcommands: Has subcommands...{:?}", p.has_subcommands());
|
debug!("subcommands: Has subcommands...{:?}", p.has_subcommands());
|
||||||
p.get_subcommands()
|
p.get_subcommands()
|
||||||
.flat_map(|sc| {
|
.flat_map(|sc| {
|
||||||
sc.get_name_and_visible_aliases()
|
sc.get_name_and_visible_aliases().into_iter().map(|s| {
|
||||||
.into_iter()
|
CompletionCandidate::new(s.to_string())
|
||||||
.map(|s| CompletionCandidate::new(s.to_string()).help(sc.get_about().cloned()))
|
.help(sc.get_about().cloned())
|
||||||
|
.visible(true)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A completion candidate defination
|
/// A completion candidate definition
|
||||||
///
|
///
|
||||||
/// This makes it easier to add more fields to completion candidate,
|
/// This makes it easier to add more fields to completion candidate,
|
||||||
/// rather than using `(OsString, Option<StyledStr>)` or `(String, Option<StyledStr>)` to represent a completion candidate
|
/// rather than using `(OsString, Option<StyledStr>)` or `(String, Option<StyledStr>)` to represent a completion candidate
|
||||||
|
@ -369,6 +406,9 @@ pub struct CompletionCandidate {
|
||||||
|
|
||||||
/// Help message with a completion candidate
|
/// Help message with a completion candidate
|
||||||
help: Option<StyledStr>,
|
help: Option<StyledStr>,
|
||||||
|
|
||||||
|
/// Whether the completion candidate is visible
|
||||||
|
visible: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CompletionCandidate {
|
impl CompletionCandidate {
|
||||||
|
@ -387,6 +427,12 @@ impl CompletionCandidate {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the visibility of the completion candidate
|
||||||
|
pub fn visible(mut self, visible: bool) -> Self {
|
||||||
|
self.visible = visible;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the content of the completion candidate
|
/// Get the content of the completion candidate
|
||||||
pub fn get_content(&self) -> &OsStr {
|
pub fn get_content(&self) -> &OsStr {
|
||||||
&self.content
|
&self.content
|
||||||
|
@ -396,4 +442,9 @@ impl CompletionCandidate {
|
||||||
pub fn get_help(&self) -> Option<&StyledStr> {
|
pub fn get_help(&self) -> Option<&StyledStr> {
|
||||||
self.help.as_ref()
|
self.help.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the visibility of the completion candidate
|
||||||
|
pub fn is_visible(&self) -> bool {
|
||||||
|
self.visible
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,10 +45,7 @@ fn suggest_hidden_long_flags() {
|
||||||
|
|
||||||
assert_data_eq!(
|
assert_data_eq!(
|
||||||
complete!(cmd, "--hello-world"),
|
complete!(cmd, "--hello-world"),
|
||||||
snapbox::str![
|
snapbox::str!["--hello-world-visible"]
|
||||||
"--hello-world-visible
|
|
||||||
--hello-world-hidden"
|
|
||||||
]
|
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_data_eq!(
|
assert_data_eq!(
|
||||||
|
@ -108,9 +105,7 @@ fn suggest_hidden_long_flag_aliases() {
|
||||||
complete!(cmd, "--test"),
|
complete!(cmd, "--test"),
|
||||||
snapbox::str![
|
snapbox::str![
|
||||||
"--test_visible
|
"--test_visible
|
||||||
--test_visible-alias_visible
|
--test_visible-alias_visible"
|
||||||
--test_hidden
|
|
||||||
--test_hidden-alias_visible"
|
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -118,13 +113,20 @@ fn suggest_hidden_long_flag_aliases() {
|
||||||
complete!(cmd, "--test_h"),
|
complete!(cmd, "--test_h"),
|
||||||
snapbox::str![
|
snapbox::str![
|
||||||
"--test_hidden
|
"--test_hidden
|
||||||
--test_hidden-alias_visible"
|
--test_hidden-alias_visible
|
||||||
|
--test_hidden-alias_hidden"
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_data_eq!(complete!(cmd, "--test_visible-alias_h"), snapbox::str![""]);
|
assert_data_eq!(
|
||||||
|
complete!(cmd, "--test_visible-alias_h"),
|
||||||
|
snapbox::str!["--test_visible-alias_hidden"]
|
||||||
|
);
|
||||||
|
|
||||||
assert_data_eq!(complete!(cmd, "--test_hidden-alias_h"), snapbox::str![""]);
|
assert_data_eq!(
|
||||||
|
complete!(cmd, "--test_hidden-alias_h"),
|
||||||
|
snapbox::str!["--test_hidden-alias_hidden"]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Reference in a new issue