mirror of
https://github.com/clap-rs/clap
synced 2024-11-10 06:44:16 +00:00
Merge pull request #5705 from epage/command
fix(complete)!: Remove CompleteCommand
This commit is contained in:
commit
50f7646cf7
22 changed files with 34 additions and 1191 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -485,7 +485,6 @@ dependencies = [
|
|||
"shlex",
|
||||
"snapbox",
|
||||
"trycmd",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -38,7 +38,6 @@ clap = { path = "../", version = "4.5.15", default-features = false, features =
|
|||
clap_lex = { path = "../clap_lex", version = "0.7.0", optional = true }
|
||||
is_executable = { version = "1.0.1", optional = true }
|
||||
shlex = { version = "1.3.0", optional = true }
|
||||
unicode-xid = { version = "0.2.2", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
snapbox = { version = "0.6.0", features = ["diff", "dir", "examples"] }
|
||||
|
@ -51,13 +50,12 @@ automod = "1.0.14"
|
|||
|
||||
[[example]]
|
||||
name = "dynamic"
|
||||
required-features = ["unstable-dynamic", "unstable-command"]
|
||||
required-features = ["unstable-dynamic"]
|
||||
|
||||
[features]
|
||||
default = []
|
||||
unstable-doc = ["unstable-dynamic", "unstable-command"] # for docs.rs
|
||||
unstable-doc = ["unstable-dynamic"] # for docs.rs
|
||||
unstable-dynamic = ["dep:clap_lex", "dep:shlex", "dep:is_executable", "clap/unstable-ext"]
|
||||
unstable-command = ["unstable-dynamic", "dep:unicode-xid", "clap/derive", "dep:is_executable", "clap/unstable-ext"]
|
||||
debug = ["clap/debug"]
|
||||
|
||||
[lints]
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
use clap::FromArgMatches;
|
||||
use clap::Subcommand;
|
||||
|
||||
fn command() -> clap::Command {
|
||||
let cmd = clap::Command::new("dynamic")
|
||||
clap::Command::new("dynamic")
|
||||
.arg(
|
||||
clap::Arg::new("input")
|
||||
.long("input")
|
||||
|
@ -15,8 +12,7 @@ fn command() -> clap::Command {
|
|||
.short('F')
|
||||
.value_parser(["json", "yaml", "toml"]),
|
||||
)
|
||||
.args_conflicts_with_subcommands(true);
|
||||
clap_complete::CompleteCommand::augment_subcommands(cmd)
|
||||
.args_conflicts_with_subcommands(true)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -24,11 +20,7 @@ fn main() {
|
|||
|
||||
let cmd = command();
|
||||
let matches = cmd.get_matches();
|
||||
if let Ok(completions) = clap_complete::CompleteCommand::from_arg_matches(&matches) {
|
||||
completions.complete(&mut command());
|
||||
} else {
|
||||
println!("{matches:#?}");
|
||||
}
|
||||
println!("{matches:#?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
use clap::builder::PossibleValue;
|
||||
#[cfg(feature = "unstable-command")]
|
||||
use clap::{FromArgMatches, Subcommand};
|
||||
use clap_complete::{generate, Generator, Shell};
|
||||
|
||||
fn main() {
|
||||
|
@ -15,12 +13,6 @@ fn main() {
|
|||
return;
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable-command")]
|
||||
if let Ok(completions) = clap_complete::CompleteCommand::from_arg_matches(&matches) {
|
||||
completions.complete(&mut cli());
|
||||
return;
|
||||
};
|
||||
|
||||
println!("{:?}", matches);
|
||||
}
|
||||
|
||||
|
@ -30,7 +22,7 @@ fn print_completions<G: Generator>(gen: G, cmd: &mut clap::Command) {
|
|||
|
||||
#[allow(clippy::let_and_return)]
|
||||
fn cli() -> clap::Command {
|
||||
let cli = clap::Command::new("exhaustive")
|
||||
clap::Command::new("exhaustive")
|
||||
.version("3.0")
|
||||
.propagate_version(true)
|
||||
.args([
|
||||
|
@ -197,8 +189,5 @@ fn cli() -> clap::Command {
|
|||
.long("email")
|
||||
.value_hint(clap::ValueHint::EmailAddress),
|
||||
]),
|
||||
]);
|
||||
#[cfg(feature = "unstable-command")]
|
||||
let cli = clap_complete::CompleteCommand::augment_subcommands(cli);
|
||||
cli
|
||||
])
|
||||
}
|
||||
|
|
|
@ -1,253 +0,0 @@
|
|||
//! [`<bin> complete`][CompleteCommand] completion integration
|
||||
//!
|
||||
//! - If you aren't using a subcommand, see [`CompleteCommand`]
|
||||
//! - If you are using subcommands, see [`CompleteArgs`]
|
||||
//!
|
||||
//! To source your completions:
|
||||
//!
|
||||
//! **WARNING:** We recommend re-sourcing your completions on upgrade.
|
||||
//! These completions work by generating shell code that calls into `your_program` while completing.
|
||||
//! That interface is unstable and a mismatch between the shell code and `your_program` may result
|
||||
//! in either invalid completions or no completions being generated.
|
||||
//! For this reason, we recommend generating the shell code anew on shell startup so that it is
|
||||
//! "self-correcting" on shell launch, rather than writing the generated completions to a file.
|
||||
//!
|
||||
//! Bash
|
||||
//! ```bash
|
||||
//! echo "source <(your_program complete bash)" >> ~/.bashrc
|
||||
//! ```
|
||||
//!
|
||||
//! Elvish
|
||||
//! ```elvish
|
||||
//! echo "eval (your_program complete elvish)" >> ~/.elvish/rc.elv
|
||||
//! ```
|
||||
//!
|
||||
//! Fish
|
||||
//! ```fish
|
||||
//! echo "source (your_program complete fish | psub)" >> ~/.config/fish/config.fish
|
||||
//! ```
|
||||
//!
|
||||
//! Powershell
|
||||
//! ```powershell
|
||||
//! echo "your_program complete powershell | Invoke-Expression" >> $PROFILE
|
||||
//! ```
|
||||
//!
|
||||
//! Zsh
|
||||
//! ```zsh
|
||||
//! echo "source <(your_program complete zsh)" >> ~/.zshrc
|
||||
//! ```
|
||||
|
||||
mod shells;
|
||||
|
||||
use std::ffi::OsString;
|
||||
use std::io::Write as _;
|
||||
|
||||
pub use shells::*;
|
||||
|
||||
/// A completion subcommand to add to your CLI
|
||||
///
|
||||
/// To customize completions, see
|
||||
/// - [`ValueHint`][crate::ValueHint]
|
||||
/// - [`ValueEnum`][clap::ValueEnum]
|
||||
/// - [`ArgValueCandidates`][crate::ArgValueCandidates]
|
||||
/// - [`ArgValueCompleter`][crate::ArgValueCompleter]
|
||||
///
|
||||
/// **Warning:** `stdout` should not be written to before [`CompleteCommand::complete`] has had a
|
||||
/// chance to run.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// To integrate completions into an application without subcommands:
|
||||
/// ```no_run
|
||||
/// // src/main.rs
|
||||
/// use clap::{CommandFactory, FromArgMatches, Parser, Subcommand};
|
||||
/// use clap_complete::CompleteCommand;
|
||||
///
|
||||
/// #[derive(Parser, Debug)]
|
||||
/// #[clap(name = "dynamic", about = "A dynamic command line tool")]
|
||||
/// struct Cli {
|
||||
/// /// The subcommand to run complete
|
||||
/// #[command(subcommand)]
|
||||
/// complete: Option<CompleteCommand>,
|
||||
///
|
||||
/// /// Input file path
|
||||
/// #[clap(short, long, value_hint = clap::ValueHint::FilePath)]
|
||||
/// input: Option<String>,
|
||||
/// /// Output format
|
||||
/// #[clap(short = 'F', long, value_parser = ["json", "yaml", "toml"])]
|
||||
/// format: Option<String>,
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// let cli = Cli::parse();
|
||||
/// if let Some(completions) = cli.complete {
|
||||
/// completions.complete(&mut Cli::command());
|
||||
/// }
|
||||
///
|
||||
/// // normal logic continues...
|
||||
/// }
|
||||
///```
|
||||
#[derive(clap::Subcommand)]
|
||||
#[allow(missing_docs)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[command(about = None, long_about = None)]
|
||||
pub enum CompleteCommand {
|
||||
/// Register shell completions for this program
|
||||
#[command(hide = true)]
|
||||
Complete(CompleteArgs),
|
||||
}
|
||||
|
||||
impl CompleteCommand {
|
||||
/// Process the completion request and exit
|
||||
///
|
||||
/// **Warning:** `stdout` should not be written to before this has had a
|
||||
/// chance to run.
|
||||
pub fn complete(&self, cmd: &mut clap::Command) -> std::convert::Infallible {
|
||||
self.try_complete(cmd).unwrap_or_else(|e| e.exit());
|
||||
std::process::exit(0)
|
||||
}
|
||||
|
||||
/// Process the completion request
|
||||
///
|
||||
/// **Warning:** `stdout` should not be written to before or after this has run.
|
||||
pub fn try_complete(&self, cmd: &mut clap::Command) -> clap::error::Result<()> {
|
||||
debug!("CompleteCommand::try_complete: {self:?}");
|
||||
let CompleteCommand::Complete(args) = self;
|
||||
args.try_complete(cmd)
|
||||
}
|
||||
}
|
||||
|
||||
/// A completion subcommand to add to your CLI
|
||||
///
|
||||
/// To customize completions, see
|
||||
/// - [`ValueHint`][crate::ValueHint]
|
||||
/// - [`ValueEnum`][clap::ValueEnum]
|
||||
/// - [`ArgValueCandidates`][crate::ArgValueCandidates]
|
||||
/// - [`ArgValueCompleter`][crate::ArgValueCompleter]
|
||||
///
|
||||
/// **Warning:** `stdout` should not be written to before [`CompleteArgs::complete`] has had a
|
||||
/// chance to run.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// To integrate completions into an application without subcommands:
|
||||
/// ```no_run
|
||||
/// // src/main.rs
|
||||
/// use clap::{CommandFactory, FromArgMatches, Parser, Subcommand};
|
||||
/// use clap_complete::CompleteArgs;
|
||||
///
|
||||
/// #[derive(Parser, Debug)]
|
||||
/// #[clap(name = "dynamic", about = "A dynamic command line tool")]
|
||||
/// struct Cli {
|
||||
/// #[command(subcommand)]
|
||||
/// complete: Command,
|
||||
/// }
|
||||
///
|
||||
/// #[derive(Subcommand, Debug)]
|
||||
/// enum Command {
|
||||
/// Complete(CompleteArgs),
|
||||
/// Print,
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// let cli = Cli::parse();
|
||||
/// match cli.complete {
|
||||
/// Command::Complete(completions) => {
|
||||
/// completions.complete(&mut Cli::command());
|
||||
/// },
|
||||
/// Command::Print => {
|
||||
/// println!("Hello world!");
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///```
|
||||
#[derive(clap::Args, Clone, Debug)]
|
||||
#[command(about = None, long_about = None)]
|
||||
pub struct CompleteArgs {
|
||||
/// Specify shell to complete for
|
||||
#[arg(value_name = "NAME")]
|
||||
shell: Option<Shell>,
|
||||
|
||||
#[arg(raw = true, value_name = "ARG", hide = true)]
|
||||
comp_words: Option<Vec<OsString>>,
|
||||
}
|
||||
|
||||
impl CompleteArgs {
|
||||
/// Process the completion request and exit
|
||||
///
|
||||
/// **Warning:** `stdout` should not be written to before this has had a
|
||||
/// chance to run.
|
||||
pub fn complete(&self, cmd: &mut clap::Command) -> std::convert::Infallible {
|
||||
self.try_complete(cmd).unwrap_or_else(|e| e.exit());
|
||||
std::process::exit(0)
|
||||
}
|
||||
|
||||
/// Process the completion request
|
||||
///
|
||||
/// **Warning:** `stdout` should not be written to before or after this has run.
|
||||
pub fn try_complete(&self, cmd: &mut clap::Command) -> clap::error::Result<()> {
|
||||
debug!("CompleteCommand::try_complete: {self:?}");
|
||||
|
||||
let shell = self.shell.or_else(Shell::from_env).ok_or_else(|| {
|
||||
std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"unknown shell, please specify the name of your shell",
|
||||
)
|
||||
})?;
|
||||
|
||||
if let Some(comp_words) = self.comp_words.as_ref() {
|
||||
let current_dir = std::env::current_dir().ok();
|
||||
|
||||
let mut buf = Vec::new();
|
||||
shell.write_complete(cmd, comp_words.clone(), current_dir.as_deref(), &mut buf)?;
|
||||
std::io::stdout().write_all(&buf)?;
|
||||
} else {
|
||||
let name = cmd.get_name();
|
||||
let bin = cmd.get_bin_name().unwrap_or_else(|| cmd.get_name());
|
||||
|
||||
let mut buf = Vec::new();
|
||||
shell.write_registration(name, bin, bin, &mut buf)?;
|
||||
std::io::stdout().write_all(&buf)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Shell-integration for completions
|
||||
///
|
||||
/// This will generally be called by [`CompleteCommand`] or [`CompleteArgs`].
|
||||
///
|
||||
/// This handles adapting between the shell and [`completer`][crate::engine::complete()].
|
||||
/// A `CommandCompleter` can choose how much of that lives within the registration script and or
|
||||
/// lives in [`CommandCompleter::write_complete`].
|
||||
pub trait CommandCompleter {
|
||||
/// Register for completions
|
||||
///
|
||||
/// Write the `buf` the logic needed for calling into `<cmd> complete`, passing needed
|
||||
/// arguments to [`CommandCompleter::write_complete`] through the environment.
|
||||
///
|
||||
/// **WARNING:** There are no stability guarantees between the call to
|
||||
/// [`CommandCompleter::write_complete`] that this generates and actually calling [`CommandCompleter::write_complete`].
|
||||
/// Caching the results of this call may result in invalid or no completions to be generated.
|
||||
fn write_registration(
|
||||
&self,
|
||||
name: &str,
|
||||
bin: &str,
|
||||
completer: &str,
|
||||
buf: &mut dyn std::io::Write,
|
||||
) -> Result<(), std::io::Error>;
|
||||
/// Complete the given command
|
||||
///
|
||||
/// Adapt information from arguments and [`CommandCompleter::write_registration`]-defined env
|
||||
/// variables to what is needed for [`completer`][crate::engine::complete()].
|
||||
///
|
||||
/// Write out the [`CompletionCandidate`][crate::engine::CompletionCandidate]s in a way the shell will understand.
|
||||
fn write_complete(
|
||||
&self,
|
||||
cmd: &mut clap::Command,
|
||||
args: Vec<OsString>,
|
||||
current_dir: Option<&std::path::Path>,
|
||||
buf: &mut dyn std::io::Write,
|
||||
) -> Result<(), std::io::Error>;
|
||||
}
|
|
@ -1,529 +0,0 @@
|
|||
use std::ffi::OsString;
|
||||
use std::fmt::Display;
|
||||
use std::str::FromStr;
|
||||
|
||||
use clap::builder::PossibleValue;
|
||||
use clap::ValueEnum;
|
||||
use unicode_xid::UnicodeXID as _;
|
||||
|
||||
use super::CommandCompleter;
|
||||
|
||||
/// Completion support for built-in shells
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
#[non_exhaustive]
|
||||
pub enum Shell {
|
||||
/// Bourne Again `SHell` (bash)
|
||||
Bash,
|
||||
/// Elvish shell
|
||||
Elvish,
|
||||
/// Friendly Interactive `SHell` (fish)
|
||||
Fish,
|
||||
/// `PowerShell`
|
||||
Powershell,
|
||||
/// Z `SHell` (zsh)
|
||||
Zsh,
|
||||
}
|
||||
|
||||
impl Shell {
|
||||
/// Parse a shell from a path to the executable for the shell
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use clap_complete::shells::Shell;
|
||||
///
|
||||
/// assert_eq!(Shell::from_shell_path("/bin/bash"), Some(Shell::Bash));
|
||||
/// assert_eq!(Shell::from_shell_path("/usr/bin/zsh"), Some(Shell::Zsh));
|
||||
/// assert_eq!(Shell::from_shell_path("/opt/my_custom_shell"), None);
|
||||
/// ```
|
||||
pub fn from_shell_path(path: impl AsRef<std::path::Path>) -> Option<Shell> {
|
||||
parse_shell_from_path(path.as_ref())
|
||||
}
|
||||
|
||||
/// Determine the user's current shell from the environment
|
||||
///
|
||||
/// This will read the SHELL environment variable and try to determine which shell is in use
|
||||
/// from that.
|
||||
///
|
||||
/// If SHELL is not set, then on windows, it will default to powershell, and on
|
||||
/// other operating systems it will return `None`.
|
||||
///
|
||||
/// If SHELL is set, but contains a value that doesn't correspond to one of the supported shell
|
||||
/// types, then return `None`.
|
||||
///
|
||||
/// # Example:
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use clap::Command;
|
||||
/// use clap_complete::{generate, shells::Shell};
|
||||
/// # fn build_cli() -> Command {
|
||||
/// # Command::new("compl")
|
||||
/// # }
|
||||
/// let shell = Shell::from_env();
|
||||
/// println!("{shell:?}");
|
||||
/// ```
|
||||
pub fn from_env() -> Option<Shell> {
|
||||
if let Some(env_shell) = std::env::var_os("SHELL") {
|
||||
Shell::from_shell_path(env_shell)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn completer(&self) -> &dyn CommandCompleter {
|
||||
match self {
|
||||
Self::Bash => &Bash,
|
||||
Self::Elvish => &Elvish,
|
||||
Self::Fish => &Fish,
|
||||
Self::Powershell => &Powershell,
|
||||
Self::Zsh => &Zsh,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CommandCompleter for Shell {
|
||||
fn write_registration(
|
||||
&self,
|
||||
name: &str,
|
||||
bin: &str,
|
||||
completer: &str,
|
||||
buf: &mut dyn std::io::Write,
|
||||
) -> Result<(), std::io::Error> {
|
||||
self.completer()
|
||||
.write_registration(name, bin, completer, buf)
|
||||
}
|
||||
fn write_complete(
|
||||
&self,
|
||||
cmd: &mut clap::Command,
|
||||
args: Vec<OsString>,
|
||||
current_dir: Option<&std::path::Path>,
|
||||
buf: &mut dyn std::io::Write,
|
||||
) -> Result<(), std::io::Error> {
|
||||
self.completer().write_complete(cmd, args, current_dir, buf)
|
||||
}
|
||||
}
|
||||
|
||||
// use a separate function to avoid having to monomorphize the entire function due
|
||||
// to from_shell_path being generic
|
||||
fn parse_shell_from_path(path: &std::path::Path) -> Option<Shell> {
|
||||
let name = path.file_stem()?.to_str()?;
|
||||
match name {
|
||||
"bash" => Some(Shell::Bash),
|
||||
"elvish" => Some(Shell::Elvish),
|
||||
"fish" => Some(Shell::Fish),
|
||||
"powershell" | "powershell_ise" => Some(Shell::Powershell),
|
||||
"zsh" => Some(Shell::Zsh),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Shell {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.to_possible_value()
|
||||
.expect("no values are skipped")
|
||||
.get_name()
|
||||
.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Shell {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
for variant in Self::value_variants() {
|
||||
if variant.to_possible_value().unwrap().matches(s, false) {
|
||||
return Ok(*variant);
|
||||
}
|
||||
}
|
||||
Err(format!("invalid variant: {s}"))
|
||||
}
|
||||
}
|
||||
|
||||
// Hand-rolled so it can work even when `derive` feature is disabled
|
||||
impl ValueEnum for Shell {
|
||||
fn value_variants<'a>() -> &'a [Self] {
|
||||
&[
|
||||
Shell::Bash,
|
||||
Shell::Elvish,
|
||||
Shell::Fish,
|
||||
Shell::Powershell,
|
||||
Shell::Zsh,
|
||||
]
|
||||
}
|
||||
|
||||
fn to_possible_value(&self) -> Option<PossibleValue> {
|
||||
Some(match self {
|
||||
Shell::Bash => PossibleValue::new("bash"),
|
||||
Shell::Elvish => PossibleValue::new("elvish"),
|
||||
Shell::Fish => PossibleValue::new("fish"),
|
||||
Shell::Powershell => PossibleValue::new("powershell"),
|
||||
Shell::Zsh => PossibleValue::new("zsh"),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Bash completion adapter
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub struct Bash;
|
||||
|
||||
impl CommandCompleter for Bash {
|
||||
fn write_registration(
|
||||
&self,
|
||||
name: &str,
|
||||
bin: &str,
|
||||
completer: &str,
|
||||
buf: &mut dyn std::io::Write,
|
||||
) -> Result<(), std::io::Error> {
|
||||
let escaped_name = name.replace('-', "_");
|
||||
debug_assert!(
|
||||
escaped_name.chars().all(|c| c.is_xid_continue()),
|
||||
"`name` must be an identifier, got `{escaped_name}`"
|
||||
);
|
||||
let mut upper_name = escaped_name.clone();
|
||||
upper_name.make_ascii_uppercase();
|
||||
|
||||
let completer =
|
||||
shlex::try_quote(completer).unwrap_or(std::borrow::Cow::Borrowed(completer));
|
||||
|
||||
let script = r#"
|
||||
_clap_complete_NAME() {
|
||||
local IFS=$'\013'
|
||||
local _CLAP_COMPLETE_INDEX=${COMP_CWORD}
|
||||
local _CLAP_COMPLETE_COMP_TYPE=${COMP_TYPE}
|
||||
if compopt +o nospace 2> /dev/null; then
|
||||
local _CLAP_COMPLETE_SPACE=false
|
||||
else
|
||||
local _CLAP_COMPLETE_SPACE=true
|
||||
fi
|
||||
COMPREPLY=( $( \
|
||||
IFS="$IFS" \
|
||||
_CLAP_COMPLETE_INDEX="$_CLAP_COMPLETE_INDEX" \
|
||||
_CLAP_COMPLETE_COMP_TYPE="$_CLAP_COMPLETE_COMP_TYPE" \
|
||||
_CLAP_COMPLETE_SPACE="$_CLAP_COMPLETE_SPACE" \
|
||||
"COMPLETER" complete bash -- "${COMP_WORDS[@]}" \
|
||||
) )
|
||||
if [[ $? != 0 ]]; then
|
||||
unset COMPREPLY
|
||||
elif [[ $SUPPRESS_SPACE == 1 ]] && [[ "${COMPREPLY-}" =~ [=/:]$ ]]; then
|
||||
compopt -o nospace
|
||||
fi
|
||||
}
|
||||
if [[ "${BASH_VERSINFO[0]}" -eq 4 && "${BASH_VERSINFO[1]}" -ge 4 || "${BASH_VERSINFO[0]}" -gt 4 ]]; then
|
||||
complete -o nospace -o bashdefault -o nosort -F _clap_complete_NAME BIN
|
||||
else
|
||||
complete -o nospace -o bashdefault -F _clap_complete_NAME BIN
|
||||
fi
|
||||
"#
|
||||
.replace("NAME", &escaped_name)
|
||||
.replace("BIN", bin)
|
||||
.replace("COMPLETER", &completer)
|
||||
.replace("UPPER", &upper_name);
|
||||
|
||||
writeln!(buf, "{script}")?;
|
||||
Ok(())
|
||||
}
|
||||
fn write_complete(
|
||||
&self,
|
||||
cmd: &mut clap::Command,
|
||||
args: Vec<OsString>,
|
||||
current_dir: Option<&std::path::Path>,
|
||||
buf: &mut dyn std::io::Write,
|
||||
) -> Result<(), std::io::Error> {
|
||||
let index: usize = std::env::var("_CLAP_COMPLETE_INDEX")
|
||||
.ok()
|
||||
.and_then(|i| i.parse().ok())
|
||||
.unwrap_or_default();
|
||||
let _comp_type: CompType = std::env::var("_CLAP_COMPLETE_COMP_TYPE")
|
||||
.ok()
|
||||
.and_then(|i| i.parse().ok())
|
||||
.unwrap_or_default();
|
||||
let _space: Option<bool> = std::env::var("_CLAP_COMPLETE_SPACE")
|
||||
.ok()
|
||||
.and_then(|i| i.parse().ok());
|
||||
let ifs: Option<String> = std::env::var("IFS").ok().and_then(|i| i.parse().ok());
|
||||
let completions = crate::engine::complete(cmd, args, index, current_dir)?;
|
||||
|
||||
for (i, candidate) in completions.iter().enumerate() {
|
||||
if i != 0 {
|
||||
write!(buf, "{}", ifs.as_deref().unwrap_or("\n"))?;
|
||||
}
|
||||
write!(buf, "{}", candidate.get_value().to_string_lossy())?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Type of completion attempted that caused a completion function to be called
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[non_exhaustive]
|
||||
enum CompType {
|
||||
/// Normal completion
|
||||
Normal,
|
||||
/// List completions after successive tabs
|
||||
Successive,
|
||||
/// List alternatives on partial word completion
|
||||
Alternatives,
|
||||
/// List completions if the word is not unmodified
|
||||
Unmodified,
|
||||
/// Menu completion
|
||||
Menu,
|
||||
}
|
||||
|
||||
impl FromStr for CompType {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"9" => Ok(Self::Normal),
|
||||
"63" => Ok(Self::Successive),
|
||||
"33" => Ok(Self::Alternatives),
|
||||
"64" => Ok(Self::Unmodified),
|
||||
"37" => Ok(Self::Menu),
|
||||
_ => Err(format!("unsupported COMP_TYPE `{}`", s)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for CompType {
|
||||
fn default() -> Self {
|
||||
Self::Normal
|
||||
}
|
||||
}
|
||||
|
||||
/// Elvish completion adapter
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub struct Elvish;
|
||||
|
||||
impl CommandCompleter for Elvish {
|
||||
fn write_registration(
|
||||
&self,
|
||||
_name: &str,
|
||||
bin: &str,
|
||||
completer: &str,
|
||||
buf: &mut dyn std::io::Write,
|
||||
) -> Result<(), std::io::Error> {
|
||||
let bin = shlex::try_quote(bin).unwrap_or(std::borrow::Cow::Borrowed(bin));
|
||||
let completer =
|
||||
shlex::try_quote(completer).unwrap_or(std::borrow::Cow::Borrowed(completer));
|
||||
|
||||
let script = r#"
|
||||
set edit:completion:arg-completer[BIN] = { |@words|
|
||||
set E:_CLAP_IFS = "\n"
|
||||
|
||||
var index = (count $words)
|
||||
set index = (- $index 1)
|
||||
set E:_CLAP_COMPLETE_INDEX = (to-string $index)
|
||||
|
||||
put (COMPLETER complete elvish -- $@words) | to-lines
|
||||
}
|
||||
"#
|
||||
.replace("COMPLETER", &completer)
|
||||
.replace("BIN", &bin);
|
||||
|
||||
writeln!(buf, "{script}")?;
|
||||
Ok(())
|
||||
}
|
||||
fn write_complete(
|
||||
&self,
|
||||
cmd: &mut clap::Command,
|
||||
args: Vec<OsString>,
|
||||
current_dir: Option<&std::path::Path>,
|
||||
buf: &mut dyn std::io::Write,
|
||||
) -> Result<(), std::io::Error> {
|
||||
let index: usize = std::env::var("_CLAP_COMPLETE_INDEX")
|
||||
.ok()
|
||||
.and_then(|i| i.parse().ok())
|
||||
.unwrap_or_default();
|
||||
let ifs: Option<String> = std::env::var("_CLAP_IFS").ok().and_then(|i| i.parse().ok());
|
||||
let completions = crate::engine::complete(cmd, args, index, current_dir)?;
|
||||
|
||||
for (i, candidate) in completions.iter().enumerate() {
|
||||
if i != 0 {
|
||||
write!(buf, "{}", ifs.as_deref().unwrap_or("\n"))?;
|
||||
}
|
||||
write!(buf, "{}", candidate.get_value().to_string_lossy())?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Fish completion adapter
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub struct Fish;
|
||||
|
||||
impl CommandCompleter for Fish {
|
||||
fn write_registration(
|
||||
&self,
|
||||
_name: &str,
|
||||
bin: &str,
|
||||
completer: &str,
|
||||
buf: &mut dyn std::io::Write,
|
||||
) -> Result<(), std::io::Error> {
|
||||
let bin = shlex::try_quote(bin).unwrap_or(std::borrow::Cow::Borrowed(bin));
|
||||
let completer =
|
||||
shlex::try_quote(completer).unwrap_or(std::borrow::Cow::Borrowed(completer));
|
||||
|
||||
writeln!(
|
||||
buf,
|
||||
r#"complete -x -c {bin} -a "("'{completer}'" complete fish -- (commandline --current-process --tokenize --cut-at-cursor) (commandline --current-token))""#
|
||||
)
|
||||
}
|
||||
fn write_complete(
|
||||
&self,
|
||||
cmd: &mut clap::Command,
|
||||
args: Vec<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::engine::complete(cmd, args, index, current_dir)?;
|
||||
|
||||
for candidate in completions {
|
||||
write!(buf, "{}", candidate.get_value().to_string_lossy())?;
|
||||
if let Some(help) = candidate.get_help() {
|
||||
write!(
|
||||
buf,
|
||||
"\t{}",
|
||||
help.to_string().lines().next().unwrap_or_default()
|
||||
)?;
|
||||
}
|
||||
writeln!(buf)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Powershell completion adapter
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub struct Powershell;
|
||||
|
||||
impl CommandCompleter for Powershell {
|
||||
fn write_registration(
|
||||
&self,
|
||||
_name: &str,
|
||||
bin: &str,
|
||||
completer: &str,
|
||||
buf: &mut dyn std::io::Write,
|
||||
) -> Result<(), std::io::Error> {
|
||||
let bin = shlex::try_quote(bin).unwrap_or(std::borrow::Cow::Borrowed(bin));
|
||||
let completer =
|
||||
shlex::try_quote(completer).unwrap_or(std::borrow::Cow::Borrowed(completer));
|
||||
|
||||
writeln!(
|
||||
buf,
|
||||
r#"
|
||||
Register-ArgumentCompleter -Native -CommandName {bin} -ScriptBlock {{
|
||||
param($wordToComplete, $commandAst, $cursorPosition)
|
||||
|
||||
$results = Invoke-Expression "&{completer} complete powershell -- $($commandAst.ToString())";
|
||||
$results | ForEach-Object {{
|
||||
$split = $_.Split("`t");
|
||||
$cmd = $split[0];
|
||||
|
||||
if ($split.Length -eq 2) {{
|
||||
$help = $split[1];
|
||||
}}
|
||||
else {{
|
||||
$help = $split[0];
|
||||
}}
|
||||
|
||||
[System.Management.Automation.CompletionResult]::new($cmd, $cmd, 'ParameterValue', $help)
|
||||
}}
|
||||
}};
|
||||
"#
|
||||
)
|
||||
}
|
||||
|
||||
fn write_complete(
|
||||
&self,
|
||||
cmd: &mut clap::Command,
|
||||
args: Vec<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::engine::complete(cmd, args, index, current_dir)?;
|
||||
|
||||
for candidate in completions {
|
||||
write!(buf, "{}", candidate.get_value().to_string_lossy())?;
|
||||
if let Some(help) = candidate.get_help() {
|
||||
write!(
|
||||
buf,
|
||||
"\t{}",
|
||||
help.to_string().lines().next().unwrap_or_default()
|
||||
)?;
|
||||
}
|
||||
writeln!(buf)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Zsh completion adapter
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub struct Zsh;
|
||||
|
||||
impl CommandCompleter for Zsh {
|
||||
fn write_registration(
|
||||
&self,
|
||||
_name: &str,
|
||||
bin: &str,
|
||||
completer: &str,
|
||||
buf: &mut dyn std::io::Write,
|
||||
) -> Result<(), std::io::Error> {
|
||||
let bin = shlex::try_quote(bin).unwrap_or(std::borrow::Cow::Borrowed(bin));
|
||||
let completer =
|
||||
shlex::try_quote(completer).unwrap_or(std::borrow::Cow::Borrowed(completer));
|
||||
|
||||
let script = r#"#compdef BIN
|
||||
function _clap_dynamic_completer() {
|
||||
local _CLAP_COMPLETE_INDEX=$(expr $CURRENT - 1)
|
||||
local _CLAP_IFS=$'\n'
|
||||
|
||||
local completions=("${(@f)$( \
|
||||
_CLAP_IFS="$_CLAP_IFS" \
|
||||
_CLAP_COMPLETE_INDEX="$_CLAP_COMPLETE_INDEX" \
|
||||
COMPLETER complete zsh -- ${words} 2>/dev/null \
|
||||
)}")
|
||||
|
||||
if [[ -n $completions ]]; then
|
||||
compadd -a completions
|
||||
fi
|
||||
}
|
||||
|
||||
compdef _clap_dynamic_completer BIN"#
|
||||
.replace("COMPLETER", &completer)
|
||||
.replace("BIN", &bin);
|
||||
|
||||
writeln!(buf, "{script}")?;
|
||||
Ok(())
|
||||
}
|
||||
fn write_complete(
|
||||
&self,
|
||||
cmd: &mut clap::Command,
|
||||
args: Vec<OsString>,
|
||||
current_dir: Option<&std::path::Path>,
|
||||
buf: &mut dyn std::io::Write,
|
||||
) -> Result<(), std::io::Error> {
|
||||
let index: usize = std::env::var("_CLAP_COMPLETE_INDEX")
|
||||
.ok()
|
||||
.and_then(|i| i.parse().ok())
|
||||
.unwrap_or_default();
|
||||
let ifs: Option<String> = std::env::var("_CLAP_IFS").ok().and_then(|i| i.parse().ok());
|
||||
|
||||
// If the current word is empty, add an empty string to the args
|
||||
let mut args = args.clone();
|
||||
if args.len() == index {
|
||||
args.push("".into());
|
||||
}
|
||||
let completions = crate::engine::complete(cmd, args, index, current_dir)?;
|
||||
|
||||
for (i, candidate) in completions.iter().enumerate() {
|
||||
if i != 0 {
|
||||
write!(buf, "{}", ifs.as_deref().unwrap_or("\n"))?;
|
||||
}
|
||||
write!(buf, "{}", candidate.get_value().to_string_lossy())?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -66,18 +66,12 @@ const INTERNAL_ERROR_MSG: &str = "Fatal internal error. Please consider filing a
|
|||
mod macros;
|
||||
|
||||
pub mod aot;
|
||||
#[cfg(feature = "unstable-command")]
|
||||
pub mod command;
|
||||
#[cfg(feature = "unstable-dynamic")]
|
||||
pub mod engine;
|
||||
#[cfg(feature = "unstable-dynamic")]
|
||||
pub mod env;
|
||||
|
||||
pub use clap::ValueHint;
|
||||
#[cfg(feature = "unstable-command")]
|
||||
pub use command::CompleteArgs;
|
||||
#[cfg(feature = "unstable-command")]
|
||||
pub use command::CompleteCommand;
|
||||
#[doc(inline)]
|
||||
#[cfg(feature = "unstable-dynamic")]
|
||||
pub use engine::ArgValueCandidates;
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
PS1='% '
|
||||
. /etc/bash_completion
|
||||
|
||||
_clap_complete_exhaustive() {
|
||||
local IFS=$'\013'
|
||||
local _CLAP_COMPLETE_INDEX=${COMP_CWORD}
|
||||
local _CLAP_COMPLETE_COMP_TYPE=${COMP_TYPE}
|
||||
if compopt +o nospace 2> /dev/null; then
|
||||
local _CLAP_COMPLETE_SPACE=false
|
||||
else
|
||||
local _CLAP_COMPLETE_SPACE=true
|
||||
fi
|
||||
COMPREPLY=( $( \
|
||||
IFS="$IFS" \
|
||||
_CLAP_COMPLETE_INDEX="$_CLAP_COMPLETE_INDEX" \
|
||||
_CLAP_COMPLETE_COMP_TYPE="$_CLAP_COMPLETE_COMP_TYPE" \
|
||||
_CLAP_COMPLETE_SPACE="$_CLAP_COMPLETE_SPACE" \
|
||||
"exhaustive" complete bash -- "${COMP_WORDS[@]}" \
|
||||
) )
|
||||
if [[ $? != 0 ]]; then
|
||||
unset COMPREPLY
|
||||
elif [[ $SUPPRESS_SPACE == 1 ]] && [[ "${COMPREPLY-}" =~ [=/:]$ ]]; then
|
||||
compopt -o nospace
|
||||
fi
|
||||
}
|
||||
if [[ "${BASH_VERSINFO[0]}" -eq 4 && "${BASH_VERSINFO[1]}" -ge 4 || "${BASH_VERSINFO[0]}" -gt 4 ]]; then
|
||||
complete -o nospace -o bashdefault -o nosort -F _clap_complete_exhaustive exhaustive
|
||||
else
|
||||
complete -o nospace -o bashdefault -F _clap_complete_exhaustive exhaustive
|
||||
fi
|
||||
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
set edit:rprompt = (constantly "")
|
||||
set edit:prompt = (constantly "% ")
|
||||
|
||||
set edit:completion:arg-completer[exhaustive] = { |@words|
|
||||
set E:_CLAP_IFS = "\n"
|
||||
|
||||
var index = (count $words)
|
||||
set index = (- $index 1)
|
||||
set E:_CLAP_COMPLETE_INDEX = (to-string $index)
|
||||
|
||||
put (exhaustive complete elvish -- $@words) | to-lines
|
||||
}
|
||||
|
||||
|
|
@ -1 +0,0 @@
|
|||
complete -x -c exhaustive -a "("'exhaustive'" complete fish -- (commandline --current-process --tokenize --cut-at-cursor) (commandline --current-token))"
|
|
@ -1,7 +0,0 @@
|
|||
set -U fish_greeting ""
|
||||
set -U fish_autosuggestion_enabled 0
|
||||
function fish_title
|
||||
end
|
||||
function fish_prompt
|
||||
printf '%% '
|
||||
end;
|
|
@ -1,5 +0,0 @@
|
|||
fpath=($fpath $ZDOTDIR/zsh)
|
||||
autoload -U +X compinit && compinit -u # bypass compaudit security checking
|
||||
precmd_functions="" # avoid the prompt being overwritten
|
||||
PS1='%% '
|
||||
PROMPT='%% '
|
|
@ -1,17 +0,0 @@
|
|||
#compdef exhaustive
|
||||
function _clap_dynamic_completer() {
|
||||
local _CLAP_COMPLETE_INDEX=$(expr $CURRENT - 1)
|
||||
local _CLAP_IFS=$'\n'
|
||||
|
||||
local completions=("${(@f)$( \
|
||||
_CLAP_IFS="$_CLAP_IFS" \
|
||||
_CLAP_COMPLETE_INDEX="$_CLAP_COMPLETE_INDEX" \
|
||||
exhaustive complete zsh -- ${words} 2>/dev/null \
|
||||
)}")
|
||||
|
||||
if [[ -n $completions ]]; then
|
||||
compadd -a completions
|
||||
fi
|
||||
}
|
||||
|
||||
compdef _clap_dynamic_completer exhaustive
|
|
@ -20,9 +20,6 @@ _exhaustive() {
|
|||
exhaustive,alias)
|
||||
cmd="exhaustive__alias"
|
||||
;;
|
||||
exhaustive,complete)
|
||||
cmd="exhaustive__complete"
|
||||
;;
|
||||
exhaustive,help)
|
||||
cmd="exhaustive__help"
|
||||
;;
|
||||
|
@ -47,9 +44,6 @@ _exhaustive() {
|
|||
exhaustive__help,alias)
|
||||
cmd="exhaustive__help__alias"
|
||||
;;
|
||||
exhaustive__help,complete)
|
||||
cmd="exhaustive__help__complete"
|
||||
;;
|
||||
exhaustive__help,help)
|
||||
cmd="exhaustive__help__help"
|
||||
;;
|
||||
|
@ -168,7 +162,7 @@ _exhaustive() {
|
|||
|
||||
case "${cmd}" in
|
||||
exhaustive)
|
||||
opts="-h -V --global --generate --help --version action quote value pacman last alias hint complete help"
|
||||
opts="-h -V --global --generate --help --version action quote value pacman last alias hint help"
|
||||
if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||
return 0
|
||||
|
@ -237,22 +231,8 @@ _exhaustive() {
|
|||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||
return 0
|
||||
;;
|
||||
exhaustive__complete)
|
||||
opts="-h -V --global --help --version bash elvish fish powershell zsh [ARG]..."
|
||||
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||
return 0
|
||||
fi
|
||||
case "${prev}" in
|
||||
*)
|
||||
COMPREPLY=()
|
||||
;;
|
||||
esac
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||
return 0
|
||||
;;
|
||||
exhaustive__help)
|
||||
opts="action quote value pacman last alias hint complete help"
|
||||
opts="action quote value pacman last alias hint help"
|
||||
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||
return 0
|
||||
|
@ -293,20 +273,6 @@ _exhaustive() {
|
|||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||
return 0
|
||||
;;
|
||||
exhaustive__help__complete)
|
||||
opts=""
|
||||
if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||
return 0
|
||||
fi
|
||||
case "${prev}" in
|
||||
*)
|
||||
COMPREPLY=()
|
||||
;;
|
||||
esac
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||
return 0
|
||||
;;
|
||||
exhaustive__help__help)
|
||||
opts=""
|
||||
if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
|
||||
|
|
|
@ -33,7 +33,6 @@ set edit:completion:arg-completer[exhaustive] = {|@words|
|
|||
cand last 'last'
|
||||
cand alias 'alias'
|
||||
cand hint 'hint'
|
||||
cand complete 'Register shell completions for this program'
|
||||
cand help 'Print this message or the help of the given subcommand(s)'
|
||||
}
|
||||
&'exhaustive;action'= {
|
||||
|
@ -238,13 +237,6 @@ set edit:completion:arg-completer[exhaustive] = {|@words|
|
|||
cand -V 'Print version'
|
||||
cand --version 'Print version'
|
||||
}
|
||||
&'exhaustive;complete'= {
|
||||
cand --global 'everywhere'
|
||||
cand -h 'Print help'
|
||||
cand --help 'Print help'
|
||||
cand -V 'Print version'
|
||||
cand --version 'Print version'
|
||||
}
|
||||
&'exhaustive;help'= {
|
||||
cand action 'action'
|
||||
cand quote 'quote'
|
||||
|
@ -253,7 +245,6 @@ set edit:completion:arg-completer[exhaustive] = {|@words|
|
|||
cand last 'last'
|
||||
cand alias 'alias'
|
||||
cand hint 'hint'
|
||||
cand complete 'Register shell completions for this program'
|
||||
cand help 'Print this message or the help of the given subcommand(s)'
|
||||
}
|
||||
&'exhaustive;help;action'= {
|
||||
|
@ -297,8 +288,6 @@ set edit:completion:arg-completer[exhaustive] = {|@words|
|
|||
}
|
||||
&'exhaustive;help;hint'= {
|
||||
}
|
||||
&'exhaustive;help;complete'= {
|
||||
}
|
||||
&'exhaustive;help;help'= {
|
||||
}
|
||||
]
|
||||
|
|
|
@ -35,7 +35,6 @@ complete -c exhaustive -n "__fish_exhaustive_needs_command" -f -a "pacman"
|
|||
complete -c exhaustive -n "__fish_exhaustive_needs_command" -f -a "last"
|
||||
complete -c exhaustive -n "__fish_exhaustive_needs_command" -f -a "alias"
|
||||
complete -c exhaustive -n "__fish_exhaustive_needs_command" -f -a "hint"
|
||||
complete -c exhaustive -n "__fish_exhaustive_needs_command" -f -a "complete" -d 'Register shell completions for this program'
|
||||
complete -c exhaustive -n "__fish_exhaustive_needs_command" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
|
||||
complete -c exhaustive -n "__fish_exhaustive_using_subcommand action" -l set -d 'value' -r
|
||||
complete -c exhaustive -n "__fish_exhaustive_using_subcommand action" -l choice -d 'enum' -r -f -a "{first\t'',second\t''}"
|
||||
|
@ -136,18 +135,14 @@ complete -c exhaustive -n "__fish_exhaustive_using_subcommand hint" -l email -r
|
|||
complete -c exhaustive -n "__fish_exhaustive_using_subcommand hint" -l global -d 'everywhere'
|
||||
complete -c exhaustive -n "__fish_exhaustive_using_subcommand hint" -s h -l help -d 'Print help'
|
||||
complete -c exhaustive -n "__fish_exhaustive_using_subcommand hint" -s V -l version -d 'Print version'
|
||||
complete -c exhaustive -n "__fish_exhaustive_using_subcommand complete" -l global -d 'everywhere'
|
||||
complete -c exhaustive -n "__fish_exhaustive_using_subcommand complete" -s h -l help -d 'Print help'
|
||||
complete -c exhaustive -n "__fish_exhaustive_using_subcommand complete" -s V -l version -d 'Print version'
|
||||
complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from action quote value pacman last alias hint complete help" -f -a "action"
|
||||
complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from action quote value pacman last alias hint complete help" -f -a "quote"
|
||||
complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from action quote value pacman last alias hint complete help" -f -a "value"
|
||||
complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from action quote value pacman last alias hint complete help" -f -a "pacman"
|
||||
complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from action quote value pacman last alias hint complete help" -f -a "last"
|
||||
complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from action quote value pacman last alias hint complete help" -f -a "alias"
|
||||
complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from action quote value pacman last alias hint complete help" -f -a "hint"
|
||||
complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from action quote value pacman last alias hint complete help" -f -a "complete" -d 'Register shell completions for this program'
|
||||
complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from action quote value pacman last alias hint complete help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
|
||||
complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from action quote value pacman last alias hint help" -f -a "action"
|
||||
complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from action quote value pacman last alias hint help" -f -a "quote"
|
||||
complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from action quote value pacman last alias hint help" -f -a "value"
|
||||
complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from action quote value pacman last alias hint help" -f -a "pacman"
|
||||
complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from action quote value pacman last alias hint help" -f -a "last"
|
||||
complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from action quote value pacman last alias hint help" -f -a "alias"
|
||||
complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from action quote value pacman last alias hint help" -f -a "hint"
|
||||
complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from action quote value pacman last alias hint help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
|
||||
complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and __fish_seen_subcommand_from quote" -f -a "cmd-single-quotes" -d 'Can be \'always\', \'auto\', or \'never\''
|
||||
complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and __fish_seen_subcommand_from quote" -f -a "cmd-double-quotes" -d 'Can be "always", "auto", or "never"'
|
||||
complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and __fish_seen_subcommand_from quote" -f -a "cmd-backticks" -d 'For more information see `echo test`'
|
||||
|
|
|
@ -323,17 +323,6 @@ _arguments "${_arguments_options[@]}" : \
|
|||
'*::command_with_args:_cmdambivalent' \
|
||||
&& ret=0
|
||||
;;
|
||||
(complete)
|
||||
_arguments "${_arguments_options[@]}" : \
|
||||
'--global[everywhere]' \
|
||||
'-h[Print help]' \
|
||||
'--help[Print help]' \
|
||||
'-V[Print version]' \
|
||||
'--version[Print version]' \
|
||||
'::shell -- Specify shell to complete for:(bash elvish fish powershell zsh)' \
|
||||
'*::comp_words:' \
|
||||
&& ret=0
|
||||
;;
|
||||
(help)
|
||||
_arguments "${_arguments_options[@]}" : \
|
||||
":: :_exhaustive__help_commands" \
|
||||
|
@ -434,10 +423,6 @@ _arguments "${_arguments_options[@]}" : \
|
|||
_arguments "${_arguments_options[@]}" : \
|
||||
&& ret=0
|
||||
;;
|
||||
(complete)
|
||||
_arguments "${_arguments_options[@]}" : \
|
||||
&& ret=0
|
||||
;;
|
||||
(help)
|
||||
_arguments "${_arguments_options[@]}" : \
|
||||
&& ret=0
|
||||
|
@ -461,7 +446,6 @@ _exhaustive_commands() {
|
|||
'last:' \
|
||||
'alias:' \
|
||||
'hint:' \
|
||||
'complete:Register shell completions for this program' \
|
||||
'help:Print this message or the help of the given subcommand(s)' \
|
||||
)
|
||||
_describe -t commands 'exhaustive commands' commands "$@"
|
||||
|
@ -476,11 +460,6 @@ _exhaustive__alias_commands() {
|
|||
local commands; commands=()
|
||||
_describe -t commands 'exhaustive alias commands' commands "$@"
|
||||
}
|
||||
(( $+functions[_exhaustive__complete_commands] )) ||
|
||||
_exhaustive__complete_commands() {
|
||||
local commands; commands=()
|
||||
_describe -t commands 'exhaustive complete commands' commands "$@"
|
||||
}
|
||||
(( $+functions[_exhaustive__help_commands] )) ||
|
||||
_exhaustive__help_commands() {
|
||||
local commands; commands=(
|
||||
|
@ -491,7 +470,6 @@ _exhaustive__help_commands() {
|
|||
'last:' \
|
||||
'alias:' \
|
||||
'hint:' \
|
||||
'complete:Register shell completions for this program' \
|
||||
'help:Print this message or the help of the given subcommand(s)' \
|
||||
)
|
||||
_describe -t commands 'exhaustive help commands' commands "$@"
|
||||
|
@ -506,11 +484,6 @@ _exhaustive__help__alias_commands() {
|
|||
local commands; commands=()
|
||||
_describe -t commands 'exhaustive help alias commands' commands "$@"
|
||||
}
|
||||
(( $+functions[_exhaustive__help__complete_commands] )) ||
|
||||
_exhaustive__help__complete_commands() {
|
||||
local commands; commands=()
|
||||
_describe -t commands 'exhaustive help complete commands' commands "$@"
|
||||
}
|
||||
(( $+functions[_exhaustive__help__help_commands] )) ||
|
||||
_exhaustive__help__help_commands() {
|
||||
local commands; commands=()
|
||||
|
|
|
@ -111,24 +111,6 @@ fn value_terminator() {
|
|||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable-command")]
|
||||
#[test]
|
||||
fn register_minimal() {
|
||||
use clap_complete::command::CommandCompleter as _;
|
||||
|
||||
let name = "my-app";
|
||||
let bin = name;
|
||||
let completer = name;
|
||||
|
||||
let mut buf = Vec::new();
|
||||
clap_complete::command::Bash
|
||||
.write_registration(name, bin, completer, &mut buf)
|
||||
.unwrap();
|
||||
snapbox::Assert::new()
|
||||
.action_env("SNAPSHOTS")
|
||||
.eq(buf, snapbox::file!["../snapshots/register_minimal.bash"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn two_multi_valued_arguments() {
|
||||
let name = "my-app";
|
||||
|
@ -171,15 +153,17 @@ fn complete() {
|
|||
common::load_runtime::<completest_pty::BashRuntimeBuilder>("static", "exhaustive");
|
||||
|
||||
let input = "exhaustive \t\t";
|
||||
let expected = r#"%
|
||||
-h --global --help action value last hint help
|
||||
-V --generate --version quote pacman alias complete "#;
|
||||
let expected = snapbox::str![[r#"
|
||||
%
|
||||
-h --global --help action value last hint
|
||||
-V --generate --version quote pacman alias help
|
||||
"#]];
|
||||
let actual = runtime.complete(input, &term).unwrap();
|
||||
assert_data_eq!(actual, expected);
|
||||
|
||||
// Issue 5239 (https://github.com/clap-rs/clap/issues/5239)
|
||||
let input = "exhaustive hint --file test\t";
|
||||
let expected = "exhaustive hint --file test % exhaustive hint --file tests/";
|
||||
let expected = snapbox::str!["exhaustive hint --file test % exhaustive hint --file tests/"];
|
||||
let actual = runtime.complete(input, &term).unwrap();
|
||||
assert_data_eq!(actual, expected);
|
||||
|
||||
|
@ -285,41 +269,3 @@ fn complete_dynamic_env() {
|
|||
let actual = runtime.complete(input, &term).unwrap();
|
||||
assert_data_eq!(actual, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(unix, feature = "unstable-command"))]
|
||||
fn register_dynamic_command() {
|
||||
common::register_example::<completest_pty::BashRuntimeBuilder>("dynamic-command", "exhaustive");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(unix, feature = "unstable-command"))]
|
||||
fn complete_dynamic_command() {
|
||||
if !common::has_command("bash") {
|
||||
return;
|
||||
}
|
||||
|
||||
let term = completest::Term::new();
|
||||
let mut runtime =
|
||||
common::load_runtime::<completest_pty::BashRuntimeBuilder>("dynamic-command", "exhaustive");
|
||||
|
||||
let input = "exhaustive \t\t";
|
||||
let expected = snapbox::str![[r#"
|
||||
%
|
||||
--global --help -h action help last quote
|
||||
--generate --version -V alias hint pacman value
|
||||
"#]];
|
||||
let actual = runtime.complete(input, &term).unwrap();
|
||||
assert_data_eq!(actual, expected);
|
||||
|
||||
let input = "exhaustive quote \t\t";
|
||||
let expected = snapbox::str![[r#"
|
||||
%
|
||||
--single-quotes --brackets --help cmd-backslash cmd-expansions
|
||||
--double-quotes --expansions --version cmd-backticks cmd-single-quotes
|
||||
--backticks --choice -h cmd-brackets escape-help
|
||||
--backslash --global -V cmd-double-quotes help
|
||||
"#]];
|
||||
let actual = runtime.complete(input, &term).unwrap();
|
||||
assert_data_eq!(actual, expected);
|
||||
}
|
||||
|
|
|
@ -321,7 +321,6 @@ pub(crate) fn register_example<R: completest::RuntimeBuilder>(context: &str, nam
|
|||
// Unconditionally include to avoid completion file tests failing based on the how
|
||||
// `cargo test` is invoked
|
||||
"--features=unstable-dynamic",
|
||||
"--features=unstable-command",
|
||||
],
|
||||
)
|
||||
.unwrap();
|
||||
|
@ -381,7 +380,6 @@ where
|
|||
// Unconditionally include to avoid completion file tests failing based on the how
|
||||
// `cargo test` is invoked
|
||||
"--features=unstable-dynamic",
|
||||
"--features=unstable-command",
|
||||
],
|
||||
)
|
||||
.unwrap();
|
||||
|
|
|
@ -163,7 +163,6 @@ fn complete() {
|
|||
-h Print help
|
||||
action action
|
||||
alias alias
|
||||
complete Register shell completions for this program
|
||||
help Print this message or the help of the given subcommand(s)
|
||||
hint hint
|
||||
last last
|
||||
|
@ -214,48 +213,3 @@ fn complete_dynamic_env() {
|
|||
let actual = runtime.complete(input, &term).unwrap();
|
||||
assert_data_eq!(actual, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(unix, feature = "unstable-command"))]
|
||||
fn register_dynamic_command() {
|
||||
common::register_example::<completest_pty::ElvishRuntimeBuilder>(
|
||||
"dynamic-command",
|
||||
"exhaustive",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(unix, feature = "unstable-command"))]
|
||||
fn complete_dynamic_command() {
|
||||
if !common::has_command("elvish") {
|
||||
return;
|
||||
}
|
||||
|
||||
let term = completest::Term::new();
|
||||
let mut runtime = common::load_runtime::<completest_pty::ElvishRuntimeBuilder>(
|
||||
"dynamic-command",
|
||||
"exhaustive",
|
||||
);
|
||||
|
||||
let input = "exhaustive \t";
|
||||
let expected = snapbox::str![[r#"
|
||||
% exhaustive --generate
|
||||
COMPLETING argument
|
||||
--generate --help -V action help last quote
|
||||
--global --version -h alias hint pacman value
|
||||
"#]];
|
||||
let actual = runtime.complete(input, &term).unwrap();
|
||||
assert_data_eq!(actual, expected);
|
||||
|
||||
let input = "exhaustive quote \t";
|
||||
let expected = snapbox::str![[r#"
|
||||
% exhaustive quote --backslash
|
||||
COMPLETING argument
|
||||
--backslash --double-quotes --single-quotes cmd-backslash cmd-expansions
|
||||
--backticks --expansions --version cmd-backticks cmd-single-quotes
|
||||
--brackets --global -V cmd-brackets escape-help
|
||||
--choice --help -h cmd-double-quotes help
|
||||
"#]];
|
||||
let actual = runtime.complete(input, &term).unwrap();
|
||||
assert_data_eq!(actual, expected);
|
||||
}
|
||||
|
|
|
@ -152,16 +152,20 @@ fn complete() {
|
|||
common::load_runtime::<completest_pty::FishRuntimeBuilder>("static", "exhaustive");
|
||||
|
||||
let input = "exhaustive \t";
|
||||
let expected = r#"% exhaustive
|
||||
action complete (Register shell completions for this program) hint pacman value
|
||||
alias help (Print this message or the help of the given subcommand(s)) last quote "#;
|
||||
let expected = snapbox::str![[r#"
|
||||
% exhaustive
|
||||
action help (Print this message or the help of the given subcommand(s)) last quote
|
||||
alias hint pacman value
|
||||
"#]];
|
||||
let actual = runtime.complete(input, &term).unwrap();
|
||||
assert_data_eq!(actual, expected);
|
||||
|
||||
let input = "exhaustive quote --choice \t";
|
||||
let actual = runtime.complete(input, &term).unwrap();
|
||||
let expected = r#"% exhaustive quote --choice
|
||||
bash (bash (shell)) fish (fish shell) zsh (zsh shell)"#;
|
||||
let expected = snapbox::str![[r#"
|
||||
% exhaustive quote --choice
|
||||
bash (bash (shell)) fish (fish shell) zsh (zsh shell)
|
||||
"#]];
|
||||
assert_data_eq!(actual, expected);
|
||||
}
|
||||
|
||||
|
@ -221,60 +225,3 @@ help (Print this message or the help of the given subcommand(s))
|
|||
let actual = runtime.complete(input, &term).unwrap();
|
||||
assert_data_eq!(actual, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(unix, feature = "unstable-command"))]
|
||||
fn register_dynamic_command() {
|
||||
common::register_example::<completest_pty::FishRuntimeBuilder>("dynamic-command", "exhaustive");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(unix, feature = "unstable-command"))]
|
||||
fn complete_dynamic_command() {
|
||||
if !common::has_command("fish") {
|
||||
return;
|
||||
}
|
||||
|
||||
let term = completest::Term::new();
|
||||
let mut runtime =
|
||||
common::load_runtime::<completest_pty::FishRuntimeBuilder>("dynamic-command", "exhaustive");
|
||||
|
||||
let input = "exhaustive \t\t";
|
||||
let expected = snapbox::str![[r#"
|
||||
% exhaustive action
|
||||
action pacman --generate (generate)
|
||||
alias quote --global (everywhere)
|
||||
help (Print this message or the help of the given subcommand(s)) value --help (Print help)
|
||||
hint -h (Print help) --version (Print version)
|
||||
last -V (Print version)
|
||||
"#]];
|
||||
let actual = runtime.complete(input, &term).unwrap();
|
||||
assert_data_eq!(actual, expected);
|
||||
|
||||
let input = "exhaustive quote \t\t";
|
||||
let expected = snapbox::str![[r#"
|
||||
% exhaustive quote
|
||||
cmd-backslash (Avoid '/n')
|
||||
cmd-backticks (For more information see `echo test`)
|
||||
cmd-brackets (List packages [filter])
|
||||
cmd-double-quotes (Can be "always", "auto", or "never")
|
||||
cmd-expansions (Execute the shell command with $SHELL)
|
||||
cmd-single-quotes (Can be 'always', 'auto', or 'never')
|
||||
escape-help (/tab "')
|
||||
help (Print this message or the help of the given subcommand(s))
|
||||
-h (Print help (see more with '--help'))
|
||||
-V (Print version)
|
||||
--backslash (Avoid '/n')
|
||||
--backticks (For more information see `echo test`)
|
||||
--brackets (List packages [filter])
|
||||
--choice
|
||||
--double-quotes (Can be "always", "auto", or "never")
|
||||
--expansions (Execute the shell command with $SHELL)
|
||||
--global (everywhere)
|
||||
--help (Print help (see more with '--help'))
|
||||
--single-quotes (Can be 'always', 'auto', or 'never')
|
||||
--version (Print version)
|
||||
"#]];
|
||||
let actual = runtime.complete(input, &term).unwrap();
|
||||
assert_data_eq!(actual, expected);
|
||||
}
|
||||
|
|
|
@ -155,9 +155,8 @@ fn complete() {
|
|||
let input = "exhaustive \t";
|
||||
let expected = snapbox::str![[r#"
|
||||
% exhaustive
|
||||
complete -- Register shell completions for this program
|
||||
help -- Print this message or the help of the given subcommand(s)
|
||||
pacman action alias value quote hint last --
|
||||
help -- Print this message or the help of the given subcommand(s)
|
||||
pacman action alias value quote hint last --
|
||||
"#]];
|
||||
let actual = runtime.complete(input, &term).unwrap();
|
||||
assert_data_eq!(actual, expected);
|
||||
|
@ -200,41 +199,3 @@ fn complete_dynamic_env() {
|
|||
let actual = runtime.complete(input, &term).unwrap();
|
||||
assert_data_eq!(actual, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(unix, feature = "unstable-command"))]
|
||||
fn register_dynamic_command() {
|
||||
common::register_example::<completest_pty::ZshRuntimeBuilder>("dynamic-command", "exhaustive");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(unix, feature = "unstable-command"))]
|
||||
fn complete_dynamic_command() {
|
||||
if !common::has_command("zsh") {
|
||||
return;
|
||||
}
|
||||
|
||||
let term = completest::Term::new();
|
||||
let mut runtime =
|
||||
common::load_runtime::<completest_pty::ZshRuntimeBuilder>("dynamic-command", "exhaustive");
|
||||
|
||||
let input = "exhaustive \t\t";
|
||||
let expected = snapbox::str![[r#"
|
||||
% exhaustive
|
||||
--generate --help -V action help last quote
|
||||
--global --version -h alias hint pacman value
|
||||
"#]];
|
||||
let actual = runtime.complete(input, &term).unwrap();
|
||||
assert_data_eq!(actual, expected);
|
||||
|
||||
let input = "exhaustive quote \t\t";
|
||||
let expected = snapbox::str![[r#"
|
||||
% exhaustive quote
|
||||
--backslash --double-quotes --single-quotes cmd-backslash cmd-expansions
|
||||
--backticks --expansions --version cmd-backticks cmd-single-quotes
|
||||
--brackets --global -V cmd-brackets escape-help
|
||||
--choice --help -h cmd-double-quotes help
|
||||
"#]];
|
||||
let actual = runtime.complete(input, &term).unwrap();
|
||||
assert_data_eq!(actual, expected);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue