mirror of
https://github.com/BurntSushi/ripgrep.git
synced 2025-03-23 04:34:39 +02:00
- Stop using `-n __fish_use_subcommand`. This had the effect of ignoring options if a positional argument has already been given, but that's not how ripgrep works. - Only suggest negation options if the option they're negating is passed (e.g., only complete `--no-pcre2` if `--pcre2` is present). The zsh completions already do this. - Take into account whether an option takes an argument. If an option is not a switch then it won't suggest further options until the argument is given, e.g. `-C<tab>` won't suggest options but `-i<tab>` will. - Suggest correct arguments for options. We already completed a fixed set of choices where available, but now we go further: - Filenames are only suggested for options that take filenames. - `--pre` and `--hostname-bin` suggest binaries from `$PATH`. - `-t`/`--type`/&c use `--type-list` for suggestions, like in zsh, with a preview of the glob patterns. - `--encoding` uses a hardcoded list extracted from the zsh completions. This has been refactored into a separate file, and the range globs (`{1..5}`) replaced by comma globs (`{1,2,3,4,5}`) since those work in both shells. I verified that this produces the same list as before in zsh, and the same list in fish (albeit in a different order). PR #2684
69 lines
2.3 KiB
Rust
69 lines
2.3 KiB
Rust
/*!
|
|
Provides completions for ripgrep's CLI for the fish shell.
|
|
*/
|
|
|
|
use crate::flags::{defs::FLAGS, CompletionType};
|
|
|
|
const TEMPLATE: &'static str = "complete -c rg !SHORT! -l !LONG! -d '!DOC!'";
|
|
const TEMPLATE_NEGATED: &'static str =
|
|
"complete -c rg -l !NEGATED! -n '__fish_contains_opt !SHORT! !LONG!' -d '!DOC!'\n";
|
|
|
|
/// Generate completions for Fish.
|
|
pub(crate) fn generate() -> String {
|
|
let mut out = String::new();
|
|
for flag in FLAGS.iter() {
|
|
let short = match flag.name_short() {
|
|
None => "".to_string(),
|
|
Some(byte) => format!("-s {}", char::from(byte)),
|
|
};
|
|
let long = flag.name_long();
|
|
let doc = flag.doc_short().replace("'", "\\'");
|
|
let mut completion = TEMPLATE
|
|
.replace("!SHORT!", &short)
|
|
.replace("!LONG!", &long)
|
|
.replace("!DOC!", &doc);
|
|
|
|
match flag.completion_type() {
|
|
CompletionType::Filename => {
|
|
completion.push_str(" -r -F");
|
|
}
|
|
CompletionType::Executable => {
|
|
completion.push_str(" -r -f -a '(__fish_complete_command)'");
|
|
}
|
|
CompletionType::Filetype => {
|
|
completion.push_str(
|
|
" -r -f -a '(rg --type-list | string replace : \\t)'",
|
|
);
|
|
}
|
|
CompletionType::Encoding => {
|
|
completion.push_str(" -r -f -a '");
|
|
completion.push_str(super::ENCODINGS);
|
|
completion.push_str("'");
|
|
}
|
|
CompletionType::Other if !flag.doc_choices().is_empty() => {
|
|
completion.push_str(" -r -f -a '");
|
|
completion.push_str(&flag.doc_choices().join(" "));
|
|
completion.push_str("'");
|
|
}
|
|
CompletionType::Other if !flag.is_switch() => {
|
|
completion.push_str(" -r -f");
|
|
}
|
|
CompletionType::Other => (),
|
|
}
|
|
|
|
completion.push('\n');
|
|
out.push_str(&completion);
|
|
|
|
if let Some(negated) = flag.name_negated() {
|
|
out.push_str(
|
|
&TEMPLATE_NEGATED
|
|
.replace("!NEGATED!", &negated)
|
|
.replace("!SHORT!", &short)
|
|
.replace("!LONG!", &long)
|
|
.replace("!DOC!", &doc),
|
|
);
|
|
}
|
|
}
|
|
out
|
|
}
|