mirror of
https://github.com/nushell/nushell.git
synced 2024-11-08 01:24:38 +01:00
fix: preserve path when completing intermediate directory (#10831)
<!-- 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 #10766 # 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. --> If the partial supplied to the completion function is shorter than the span, the cursor is in between the path, we are trying to complete an intermediate directory. In such a case we: - only suggest directory names - don't append the slash since it is already present - only complete the path till the component the cursor is on # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> Intermediate directories can be completed without erasing the rest of the path. # 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 std testing; testing run-tests --path crates/nu-std"` 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. -->
This commit is contained in:
parent
cf7040a215
commit
275dba82d5
@ -1,5 +1,6 @@
|
|||||||
use crate::completions::{matches, CompletionOptions};
|
use crate::completions::{matches, CompletionOptions};
|
||||||
use nu_path::home_dir;
|
use nu_path::home_dir;
|
||||||
|
use nu_protocol::{engine::StateWorkingSet, Span};
|
||||||
use std::path::{is_separator, Component, Path, PathBuf, MAIN_SEPARATOR as SEP};
|
use std::path::{is_separator, Component, Path, PathBuf, MAIN_SEPARATOR as SEP};
|
||||||
|
|
||||||
fn complete_rec(
|
fn complete_rec(
|
||||||
@ -160,3 +161,36 @@ pub fn escape_path(path: String, dir: bool) -> String {
|
|||||||
path
|
path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct AdjustView {
|
||||||
|
pub prefix: String,
|
||||||
|
pub span: Span,
|
||||||
|
pub readjusted: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn adjust_if_intermediate(
|
||||||
|
prefix: &[u8],
|
||||||
|
working_set: &StateWorkingSet,
|
||||||
|
mut span: nu_protocol::Span,
|
||||||
|
) -> AdjustView {
|
||||||
|
let span_contents = String::from_utf8_lossy(working_set.get_span_contents(span)).to_string();
|
||||||
|
let mut prefix = String::from_utf8_lossy(prefix).to_string();
|
||||||
|
|
||||||
|
// A difference of 1 because of the cursor's unicode code point in between.
|
||||||
|
// Using .chars().count() because unicode and Windows.
|
||||||
|
let readjusted = span_contents.chars().count() - prefix.chars().count() > 1;
|
||||||
|
if readjusted {
|
||||||
|
let remnant: String = span_contents
|
||||||
|
.chars()
|
||||||
|
.skip(prefix.chars().count() + 1)
|
||||||
|
.take_while(|&c| !is_separator(c))
|
||||||
|
.collect();
|
||||||
|
prefix.push_str(&remnant);
|
||||||
|
span = Span::new(span.start, span.start + prefix.chars().count() + 1);
|
||||||
|
}
|
||||||
|
AdjustView {
|
||||||
|
prefix,
|
||||||
|
span,
|
||||||
|
readjusted,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
use crate::completions::{completion_common::complete_item, Completer, CompletionOptions, SortBy};
|
use crate::completions::{
|
||||||
|
completion_common::{adjust_if_intermediate, complete_item, AdjustView},
|
||||||
|
Completer, CompletionOptions, SortBy,
|
||||||
|
};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
engine::{EngineState, StateWorkingSet},
|
engine::{EngineState, StateWorkingSet},
|
||||||
levenshtein_distance, Span,
|
levenshtein_distance, Span,
|
||||||
@ -21,19 +24,19 @@ impl DirectoryCompletion {
|
|||||||
impl Completer for DirectoryCompletion {
|
impl Completer for DirectoryCompletion {
|
||||||
fn fetch(
|
fn fetch(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: &StateWorkingSet,
|
working_set: &StateWorkingSet,
|
||||||
prefix: Vec<u8>,
|
prefix: Vec<u8>,
|
||||||
span: Span,
|
span: Span,
|
||||||
offset: usize,
|
offset: usize,
|
||||||
_: usize,
|
_: usize,
|
||||||
options: &CompletionOptions,
|
options: &CompletionOptions,
|
||||||
) -> Vec<Suggestion> {
|
) -> Vec<Suggestion> {
|
||||||
let partial = String::from_utf8_lossy(&prefix).to_string();
|
let AdjustView { prefix, span, .. } = adjust_if_intermediate(&prefix, working_set, span);
|
||||||
|
|
||||||
// Filter only the folders
|
// Filter only the folders
|
||||||
let output: Vec<_> = directory_completion(
|
let output: Vec<_> = directory_completion(
|
||||||
span,
|
span,
|
||||||
&partial,
|
&prefix,
|
||||||
&self.engine_state.current_work_dir(),
|
&self.engine_state.current_work_dir(),
|
||||||
options,
|
options,
|
||||||
)
|
)
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
use crate::completions::{completion_common::complete_item, Completer, CompletionOptions, SortBy};
|
use crate::completions::{
|
||||||
|
completion_common::{adjust_if_intermediate, complete_item, AdjustView},
|
||||||
|
Completer, CompletionOptions, SortBy,
|
||||||
|
};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
engine::{EngineState, StateWorkingSet},
|
engine::{EngineState, StateWorkingSet},
|
||||||
levenshtein_distance, Span,
|
levenshtein_distance, Span,
|
||||||
@ -21,15 +24,21 @@ impl FileCompletion {
|
|||||||
impl Completer for FileCompletion {
|
impl Completer for FileCompletion {
|
||||||
fn fetch(
|
fn fetch(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: &StateWorkingSet,
|
working_set: &StateWorkingSet,
|
||||||
prefix: Vec<u8>,
|
prefix: Vec<u8>,
|
||||||
span: Span,
|
span: Span,
|
||||||
offset: usize,
|
offset: usize,
|
||||||
_: usize,
|
_: usize,
|
||||||
options: &CompletionOptions,
|
options: &CompletionOptions,
|
||||||
) -> Vec<Suggestion> {
|
) -> Vec<Suggestion> {
|
||||||
let prefix = String::from_utf8_lossy(&prefix).to_string();
|
let AdjustView {
|
||||||
let output: Vec<_> = file_path_completion(
|
prefix,
|
||||||
|
span,
|
||||||
|
readjusted,
|
||||||
|
} = adjust_if_intermediate(&prefix, working_set, span);
|
||||||
|
|
||||||
|
let output: Vec<_> = complete_item(
|
||||||
|
readjusted,
|
||||||
span,
|
span,
|
||||||
&prefix,
|
&prefix,
|
||||||
&self.engine_state.current_work_dir(),
|
&self.engine_state.current_work_dir(),
|
||||||
|
Loading…
Reference in New Issue
Block a user