diff options
author | Himadri Bhattacharjee <107522312+lavafroth@users.noreply.github.com> | 2024-08-04 16:36:10 +0530 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-04 06:06:10 -0500 |
commit | 802bfed173bd3adbcd8838cf0d1aa1ccb5c170da (patch) | |
tree | 732bb19097485386315e4d1fce914f656002360e | |
parent | 07e7c8c81f32481b44c0a55b9b0fc37c56f5fa16 (diff) |
feat: prefer exact match when completion mode is prefix (#13302)
<!--
if this PR closes one or more issues, you can automatically link the PR
with
them by using one of the [*linking
keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword),
e.g.
- this PR should close #xxxx
- fixes #xxxx
you can also mention related issues, PRs or discussions!
-->
Fixes #13204
# Description
<!--
Thank you for improving Nushell. Please, check our [contributing
guide](../CONTRIBUTING.md) and talk to the core team before making major
changes.
Description of your pull request goes here. **Provide examples and/or
screenshots** if your changes affect the user experience.
-->
When the completion mode is set to `prefix`, path completions explicitly
check for and prefer an exact match for a basename instead of longer or
similar names.
# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
Exact match is inactive since there's no trailing slash
```
~/Public/nushell| ls crates/nu-plugin<tab>
crates/nu-plugin/ crates/nu-plugin-core/ crates/nu-plugin-engine/ crates/nu-plugin-protocol/
crates/nu-plugin-test-support/
```
Exact match is active
```
~/Public/nushell| ls crates/nu-plugin/<tab>
crates/nu-plugin/Cargo.toml crates/nu-plugin/LICENSE crates/nu-plugin/README.md crates/nu-plugin/src/
```
Fuzzy matching persists its behavior
```
~/Public/nushell> $env.config.completions.algorithm = "fuzzy";
~/Public/nushell| ls crates/nu-plugin/car
crates/nu-cmd-plugin/Cargo.toml crates/nu-plugin/Cargo.toml crates/nu-plugin-core/Cargo.toml crates/nu-plugin-engine/Cargo.toml
crates/nu-plugin-protocol/Cargo.toml crates/nu-plugin-test-support/Cargo.toml
```
# Tests + Formatting
<!--
Don't forget to add tests that cover your changes.
Make sure you've run and fixed any issues with these commands:
- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use toolkit.nu; toolkit test stdlib"` to run the
tests for the standard library
> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->
# After Submitting
<!-- If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
-->
-rw-r--r-- | crates/nu-cli/src/completions/completion_common.rs | 38 |
1 files changed, 32 insertions, 6 deletions
diff --git a/crates/nu-cli/src/completions/completion_common.rs b/crates/nu-cli/src/completions/completion_common.rs index 5469ba132..2b85f6091 100644 --- a/crates/nu-cli/src/completions/completion_common.rs +++ b/crates/nu-cli/src/completions/completion_common.rs @@ -12,7 +12,7 @@ use nu_protocol::{ use nu_utils::get_ls_colors; use std::path::{is_separator, Component, Path, PathBuf, MAIN_SEPARATOR as SEP}; -use super::SortBy; +use super::{MatchAlgorithm, SortBy}; #[derive(Clone, Default)] pub struct PathBuiltFromString { @@ -20,12 +20,21 @@ pub struct PathBuiltFromString { isdir: bool, } -fn complete_rec( +/// Recursively goes through paths that match a given `partial`. +/// built: State struct for a valid matching path built so far. +/// +/// `isdir`: whether the current partial path has a trailing slash. +/// Parsing a path string into a pathbuf loses that bit of information. +/// +/// want_directory: Whether we want only directories as completion matches. +/// Some commands like `cd` can only be run on directories whereas others +/// like `ls` can be run on regular files as well. +pub fn complete_rec( partial: &[&str], built: &PathBuiltFromString, cwd: &Path, options: &CompletionOptions, - dir: bool, + want_directory: bool, isdir: bool, ) -> Vec<PathBuiltFromString> { let mut completions = vec![]; @@ -35,7 +44,7 @@ fn complete_rec( let mut built = built.clone(); built.parts.push(base.to_string()); built.isdir = true; - return complete_rec(rest, &built, cwd, options, dir, isdir); + return complete_rec(rest, &built, cwd, options, want_directory, isdir); } } @@ -56,7 +65,7 @@ fn complete_rec( built.parts.push(entry_name.clone()); built.isdir = entry_isdir; - if !dir || entry_isdir { + if !want_directory || entry_isdir { entries.push((entry_name, built)); } } @@ -68,12 +77,29 @@ fn complete_rec( match partial.split_first() { Some((base, rest)) => { if matches(base, &entry_name, options) { + // We use `isdir` to confirm that the current component has + // at least one next component or a slash. + // Serves as confirmation to ignore longer completions for + // components in between. if !rest.is_empty() || isdir { - completions.extend(complete_rec(rest, &built, cwd, options, dir, isdir)); + completions.extend(complete_rec( + rest, + &built, + cwd, + options, + want_directory, + isdir, + )); } else { completions.push(built); } } + if entry_name.eq(base) + && matches!(options.match_algorithm, MatchAlgorithm::Prefix) + && isdir + { + break; + } } None => { completions.push(built); |