Skip to content

Commit

Permalink
fix(completion): dotnu_completion dir with space, expand tilde
Browse files Browse the repository at this point in the history
  • Loading branch information
blindFS committed Feb 2, 2025
1 parent 63fa6a6 commit b5c0c45
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 19 deletions.
48 changes: 31 additions & 17 deletions crates/nu-cli/src/completions/dotnu_completions.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::completions::{file_path_completion, Completer, CompletionOptions};
use nu_path::expand_tilde;
use nu_protocol::{
engine::{Stack, StateWorkingSet},
Span,
Expand Down Expand Up @@ -28,7 +29,10 @@ impl Completer for DotNuCompletion {
_pos: usize,
options: &CompletionOptions,
) -> Vec<SemanticSuggestion> {
let prefix_str = String::from_utf8_lossy(prefix).replace('`', "");
let prefix_str = String::from_utf8_lossy(prefix);
let start_with_backquote = prefix_str.starts_with('`');
let end_with_backquote = prefix_str.ends_with('`');
let prefix_str = prefix_str.replace('`', "");
let mut search_dirs: Vec<PathBuf> = vec![];

// If prefix_str is only a word we want to search in the current dir
Expand All @@ -46,12 +50,8 @@ impl Completer for DotNuCompletion {
lib_dirs
.as_list()
.into_iter()
.flat_map(|it| {
it.iter().map(|x| {
x.to_path()
.expect("internal error: failed to convert lib path")
})
})
.flat_map(|it| it.iter().filter_map(|x| x.to_path().ok()))
.map(expand_tilde)
.collect()
})
.unwrap_or_default();
Expand All @@ -78,13 +78,12 @@ impl Completer for DotNuCompletion {

// Fetch the files filtering the ones that ends with .nu
// and transform them into suggestions

let completions = file_path_completion(
span,
partial,
&search_dirs
.iter()
.map(|d| d.to_str().unwrap_or_default())
.filter_map(|d| d.to_str())
.collect::<Vec<_>>(),
options,
working_set.permanent_state,
Expand All @@ -93,20 +92,35 @@ impl Completer for DotNuCompletion {
completions
.into_iter()
// Different base dir, so we list the .nu files or folders
.filter(|it| it.path.ends_with(".nu") || it.path.ends_with(SEP))
.filter(|it| {
// for paths with spaces in them
let path = it.path.trim_end_matches('`');
path.ends_with(".nu") || path.ends_with(SEP)
})
.map(|x| {
let append_whitespace = x.path.ends_with(".nu");
let append_whitespace =
x.path.ends_with(".nu") && (!start_with_backquote || end_with_backquote);
// Re-calculate the span to replace
let span_offset = if base_dir == "." {
0
} else {
base_dir.len() + 1
} + prefix.iter().take_while(|c| **c == b'`').count();
let mut span_offset = 0;
let mut value = x.path.to_string();
// Complete only the last path component
if base_dir != "." {
span_offset = base_dir.len() + 1
}
// Retain only one '`'
if start_with_backquote {
value = value.trim_start_matches('`').to_string();
span_offset += 1;
}
// Add the backquote back
if end_with_backquote && !value.ends_with('`') {
value.push('`');
}
let end = x.span.end - offset;
let start = std::cmp::min(end, x.span.start - offset + span_offset);
SemanticSuggestion {
suggestion: Suggestion {
value: x.path,
value,
style: x.style,
span: reedline::Span { start, end },
append_whitespace,
Expand Down
13 changes: 11 additions & 2 deletions crates/nu-cli/tests/completions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,13 +275,22 @@ fn dotnu_completions() {

// Test nested nu script
#[cfg(windows)]
let completion_str = "use .\\dir_module\\sub_module\\".to_string();
let completion_str = "use `.\\dir_module\\sub module\\".to_string();
#[cfg(not(windows))]
let completion_str = "use ./dir_module/sub_module/".to_string();
let completion_str = "use `./dir_module/sub module/".to_string();
let suggestions = completer.complete(&completion_str, completion_str.len());

match_suggestions(&vec!["sub.nu".into()], &suggestions);

// Test nested nu script, with ending '`'
#[cfg(windows)]
let completion_str = "use `.\\dir_module\\sub module\\`".to_string();
#[cfg(not(windows))]
let completion_str = "use `./dir_module/sub module/`".to_string();
let suggestions = completer.complete(&completion_str, completion_str.len());

match_suggestions(&vec!["sub.nu`".into()], &suggestions);

let expected = vec![
"asdf.nu".into(),
"bar.nu".into(),
Expand Down

0 comments on commit b5c0c45

Please sign in to comment.