complete/fish: improve shell completions for fish

- 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
This commit is contained in:
Jan Verbeek
2023-12-11 07:03:49 +01:00
committed by Andrew Gallant
parent 23af5fb043
commit e0a85678e1
8 changed files with 131 additions and 52 deletions

View File

@@ -34,6 +34,8 @@ use crate::flags::{
#[cfg(test)]
use crate::flags::parse::parse_low_raw;
use super::CompletionType;
/// A list of all flags in ripgrep via implementations of `Flag`.
///
/// The order of these flags matter. It determines the order of the flags in
@@ -1582,6 +1584,9 @@ The encoding detection that ripgrep uses can be reverted to its automatic mode
via the \flag-negate{encoding} flag.
"
}
fn completion_type(&self) -> CompletionType {
CompletionType::Encoding
}
fn update(&self, v: FlagValue, args: &mut LowArgs) -> anyhow::Result<()> {
let value = match v {
@@ -1977,6 +1982,9 @@ When \flag{file} or \flag{regexp} is used, then ripgrep treats all positional
arguments as files or directories to search.
"
}
fn completion_type(&self) -> CompletionType {
CompletionType::Filename
}
fn update(&self, v: FlagValue, args: &mut LowArgs) -> anyhow::Result<()> {
let path = PathBuf::from(v.unwrap_value());
@@ -2808,6 +2816,9 @@ to calling \fBgethostname\fP. On Windows, this corresponds to calling
ripgrep uses your system's hostname for producing hyperlinks.
"#
}
fn completion_type(&self) -> CompletionType {
CompletionType::Executable
}
fn update(&self, v: FlagValue, args: &mut LowArgs) -> anyhow::Result<()> {
let path = PathBuf::from(v.unwrap_value());
@@ -3141,6 +3152,9 @@ If you are looking for a way to include or exclude files and directories
directly on the command line, then use \flag{glob} instead.
"
}
fn completion_type(&self) -> CompletionType {
CompletionType::Filename
}
fn update(&self, v: FlagValue, args: &mut LowArgs) -> anyhow::Result<()> {
let path = PathBuf::from(v.unwrap_value());
@@ -5410,6 +5424,9 @@ format, then \fBpzstd\fP is used to decompress the contents to stdout.
This overrides the \flag{search-zip} flag.
"#
}
fn completion_type(&self) -> CompletionType {
CompletionType::Executable
}
fn update(&self, v: FlagValue, args: &mut LowArgs) -> anyhow::Result<()> {
let path = match v {
@@ -6781,6 +6798,9 @@ any rules found in ignore files.
To see the list of available file types, use the \flag{type-list} flag.
"#
}
fn completion_type(&self) -> CompletionType {
CompletionType::Filetype
}
fn update(&self, v: FlagValue, args: &mut LowArgs) -> anyhow::Result<()> {
args.type_changes.push(TypeChange::Select {
@@ -7000,6 +7020,9 @@ will only search files that are unrecognized by its type definitions.
To see the list of available file types, use the \flag{type-list} flag.
"#
}
fn completion_type(&self) -> CompletionType {
CompletionType::Filetype
}
fn update(&self, v: FlagValue, args: &mut LowArgs) -> anyhow::Result<()> {
args.type_changes.push(TypeChange::Negate {