mirror of
https://github.com/clap-rs/clap
synced 2025-03-04 15:27:16 +00:00
Merge pull request #5048 from ModProg/fish-dynamic-completions-v3
feat(completions): Dynamic fish completions
This commit is contained in:
commit
40650fa707
10 changed files with 82 additions and 4 deletions
38
clap_complete/src/dynamic/shells/fish.rs
Normal file
38
clap_complete/src/dynamic/shells/fish.rs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/// Fish completions
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
|
pub struct Fish;
|
||||||
|
|
||||||
|
impl crate::dynamic::Completer for Fish {
|
||||||
|
fn file_name(&self, name: &str) -> String {
|
||||||
|
format!("{name}.fish")
|
||||||
|
}
|
||||||
|
fn write_registration(
|
||||||
|
&self,
|
||||||
|
_name: &str,
|
||||||
|
bin: &str,
|
||||||
|
completer: &str,
|
||||||
|
buf: &mut dyn std::io::Write,
|
||||||
|
) -> Result<(), std::io::Error> {
|
||||||
|
let bin = shlex::quote(bin);
|
||||||
|
let completer = shlex::quote(completer);
|
||||||
|
writeln!(
|
||||||
|
buf,
|
||||||
|
r#"complete -x -c {bin} -a "("'{completer}'" complete --shell fish -- (commandline --current-process --tokenize --cut-at-cursor) (commandline --current-token))""#
|
||||||
|
)
|
||||||
|
}
|
||||||
|
fn write_complete(
|
||||||
|
&self,
|
||||||
|
cmd: &mut clap::Command,
|
||||||
|
args: Vec<std::ffi::OsString>,
|
||||||
|
current_dir: Option<&std::path::Path>,
|
||||||
|
buf: &mut dyn std::io::Write,
|
||||||
|
) -> Result<(), std::io::Error> {
|
||||||
|
let index = args.len() - 1;
|
||||||
|
let completions = crate::dynamic::complete(cmd, args, index, current_dir)?;
|
||||||
|
|
||||||
|
for completion in completions {
|
||||||
|
writeln!(buf, "{}", completion.to_string_lossy())?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,11 @@
|
||||||
//! Shell support
|
//! Shell support
|
||||||
|
|
||||||
mod bash;
|
mod bash;
|
||||||
|
mod fish;
|
||||||
mod shell;
|
mod shell;
|
||||||
|
|
||||||
pub use bash::*;
|
pub use bash::*;
|
||||||
|
pub use fish::*;
|
||||||
pub use shell::*;
|
pub use shell::*;
|
||||||
|
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
|
|
|
@ -10,6 +10,8 @@ use clap::ValueEnum;
|
||||||
pub enum Shell {
|
pub enum Shell {
|
||||||
/// Bourne Again SHell (bash)
|
/// Bourne Again SHell (bash)
|
||||||
Bash,
|
Bash,
|
||||||
|
/// Friendly Interactive SHell (fish)
|
||||||
|
Fish,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Shell {
|
impl Display for Shell {
|
||||||
|
@ -37,12 +39,13 @@ impl FromStr for Shell {
|
||||||
// Hand-rolled so it can work even when `derive` feature is disabled
|
// Hand-rolled so it can work even when `derive` feature is disabled
|
||||||
impl ValueEnum for Shell {
|
impl ValueEnum for Shell {
|
||||||
fn value_variants<'a>() -> &'a [Self] {
|
fn value_variants<'a>() -> &'a [Self] {
|
||||||
&[Shell::Bash]
|
&[Shell::Bash, Shell::Fish]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_possible_value<'a>(&self) -> Option<PossibleValue> {
|
fn to_possible_value<'a>(&self) -> Option<PossibleValue> {
|
||||||
Some(match self {
|
Some(match self {
|
||||||
Shell::Bash => PossibleValue::new("bash"),
|
Shell::Bash => PossibleValue::new("bash"),
|
||||||
|
Shell::Fish => PossibleValue::new("fish"),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,6 +54,7 @@ impl Shell {
|
||||||
fn completer(&self) -> &dyn crate::dynamic::Completer {
|
fn completer(&self) -> &dyn crate::dynamic::Completer {
|
||||||
match self {
|
match self {
|
||||||
Self::Bash => &super::Bash,
|
Self::Bash => &super::Bash,
|
||||||
|
Self::Fish => &super::Fish,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
complete -x -c exhaustive -a "("'exhaustive'" complete --shell fish -- (commandline --current-process --tokenize --cut-at-cursor) (commandline --current-token))"
|
|
@ -0,0 +1,7 @@
|
||||||
|
set -U fish_greeting ""
|
||||||
|
set -U fish_autosuggestion_enabled 0
|
||||||
|
function fish_title
|
||||||
|
end
|
||||||
|
function fish_prompt
|
||||||
|
printf '%% '
|
||||||
|
end;
|
|
@ -236,7 +236,7 @@ _exhaustive() {
|
||||||
fi
|
fi
|
||||||
case "${prev}" in
|
case "${prev}" in
|
||||||
--shell)
|
--shell)
|
||||||
COMPREPLY=($(compgen -W "bash" -- "${cur}"))
|
COMPREPLY=($(compgen -W "bash fish" -- "${cur}"))
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
--register)
|
--register)
|
||||||
|
|
|
@ -104,7 +104,7 @@ complete -c exhaustive -n "__fish_seen_subcommand_from hint" -l email -r -f
|
||||||
complete -c exhaustive -n "__fish_seen_subcommand_from hint" -l global -d 'everywhere'
|
complete -c exhaustive -n "__fish_seen_subcommand_from hint" -l global -d 'everywhere'
|
||||||
complete -c exhaustive -n "__fish_seen_subcommand_from hint" -s h -l help -d 'Print help'
|
complete -c exhaustive -n "__fish_seen_subcommand_from hint" -s h -l help -d 'Print help'
|
||||||
complete -c exhaustive -n "__fish_seen_subcommand_from hint" -s V -l version -d 'Print version'
|
complete -c exhaustive -n "__fish_seen_subcommand_from hint" -s V -l version -d 'Print version'
|
||||||
complete -c exhaustive -n "__fish_seen_subcommand_from complete" -l shell -d 'Specify shell to complete for' -r -f -a "{bash }"
|
complete -c exhaustive -n "__fish_seen_subcommand_from complete" -l shell -d 'Specify shell to complete for' -r -f -a "{bash ,fish }"
|
||||||
complete -c exhaustive -n "__fish_seen_subcommand_from complete" -l register -d 'Path to write completion-registration to' -r -F
|
complete -c exhaustive -n "__fish_seen_subcommand_from complete" -l register -d 'Path to write completion-registration to' -r -F
|
||||||
complete -c exhaustive -n "__fish_seen_subcommand_from complete" -l global -d 'everywhere'
|
complete -c exhaustive -n "__fish_seen_subcommand_from complete" -l global -d 'everywhere'
|
||||||
complete -c exhaustive -n "__fish_seen_subcommand_from complete" -s h -l help -d 'Print help (see more with \'--help\')'
|
complete -c exhaustive -n "__fish_seen_subcommand_from complete" -s h -l help -d 'Print help (see more with \'--help\')'
|
||||||
|
|
|
@ -309,7 +309,7 @@ _arguments "${_arguments_options[@]}" \
|
||||||
;;
|
;;
|
||||||
(complete)
|
(complete)
|
||||||
_arguments "${_arguments_options[@]}" \
|
_arguments "${_arguments_options[@]}" \
|
||||||
'--shell=[Specify shell to complete for]:SHELL:(bash)' \
|
'--shell=[Specify shell to complete for]:SHELL:(bash fish)' \
|
||||||
'--register=[Path to write completion-registration to]:REGISTER:_files' \
|
'--register=[Path to write completion-registration to]:REGISTER:_files' \
|
||||||
'--global[everywhere]' \
|
'--global[everywhere]' \
|
||||||
'-h[Print help (see more with '\''--help'\'')]' \
|
'-h[Print help (see more with '\''--help'\'')]' \
|
||||||
|
|
1
clap_complete/tests/snapshots/register_dynamic.fish
Normal file
1
clap_complete/tests/snapshots/register_dynamic.fish
Normal file
|
@ -0,0 +1 @@
|
||||||
|
complete -x -c my-app -a 'my-app'" complete --shell fish -- (commandline --current-process --tokenize --cut-at-cursor) (commandline --current-token)"
|
|
@ -143,3 +143,28 @@ alias help (Print this message or the help of the given subcommand(s)) last
|
||||||
let actual = runtime.complete(input, &term).unwrap();
|
let actual = runtime.complete(input, &term).unwrap();
|
||||||
snapbox::assert_eq(expected, actual);
|
snapbox::assert_eq(expected, actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(all(unix, feature = "unstable-dynamic"))]
|
||||||
|
#[test]
|
||||||
|
fn register_dynamic() {
|
||||||
|
common::register_example("dynamic", "exhaustive", completest::Shell::Fish);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(all(unix, feature = "unstable-dynamic"))]
|
||||||
|
fn complete_dynamic() {
|
||||||
|
if !common::has_command("fish") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let term = completest::Term::new();
|
||||||
|
let mut runtime = common::load_runtime("dynamic", "exhaustive", completest::Shell::Fish);
|
||||||
|
|
||||||
|
let input = "exhaustive \t";
|
||||||
|
let expected = r#"% exhaustive
|
||||||
|
action help pacman -h --global
|
||||||
|
alias hint quote -V --help
|
||||||
|
complete last value --generate --version"#;
|
||||||
|
let actual = runtime.complete(input, &term).unwrap();
|
||||||
|
snapbox::assert_eq(expected, actual);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue