Skip to content

Commit b5c0c45

Browse files
committed
fix(completion): dotnu_completion dir with space, expand tilde
1 parent 63fa6a6 commit b5c0c45

File tree

3 files changed

+42
-19
lines changed

3 files changed

+42
-19
lines changed

crates/nu-cli/src/completions/dotnu_completions.rs

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::completions::{file_path_completion, Completer, CompletionOptions};
2+
use nu_path::expand_tilde;
23
use nu_protocol::{
34
engine::{Stack, StateWorkingSet},
45
Span,
@@ -28,7 +29,10 @@ impl Completer for DotNuCompletion {
2829
_pos: usize,
2930
options: &CompletionOptions,
3031
) -> Vec<SemanticSuggestion> {
31-
let prefix_str = String::from_utf8_lossy(prefix).replace('`', "");
32+
let prefix_str = String::from_utf8_lossy(prefix);
33+
let start_with_backquote = prefix_str.starts_with('`');
34+
let end_with_backquote = prefix_str.ends_with('`');
35+
let prefix_str = prefix_str.replace('`', "");
3236
let mut search_dirs: Vec<PathBuf> = vec![];
3337

3438
// If prefix_str is only a word we want to search in the current dir
@@ -46,12 +50,8 @@ impl Completer for DotNuCompletion {
4650
lib_dirs
4751
.as_list()
4852
.into_iter()
49-
.flat_map(|it| {
50-
it.iter().map(|x| {
51-
x.to_path()
52-
.expect("internal error: failed to convert lib path")
53-
})
54-
})
53+
.flat_map(|it| it.iter().filter_map(|x| x.to_path().ok()))
54+
.map(expand_tilde)
5555
.collect()
5656
})
5757
.unwrap_or_default();
@@ -78,13 +78,12 @@ impl Completer for DotNuCompletion {
7878

7979
// Fetch the files filtering the ones that ends with .nu
8080
// and transform them into suggestions
81-
8281
let completions = file_path_completion(
8382
span,
8483
partial,
8584
&search_dirs
8685
.iter()
87-
.map(|d| d.to_str().unwrap_or_default())
86+
.filter_map(|d| d.to_str())
8887
.collect::<Vec<_>>(),
8988
options,
9089
working_set.permanent_state,
@@ -93,20 +92,35 @@ impl Completer for DotNuCompletion {
9392
completions
9493
.into_iter()
9594
// Different base dir, so we list the .nu files or folders
96-
.filter(|it| it.path.ends_with(".nu") || it.path.ends_with(SEP))
95+
.filter(|it| {
96+
// for paths with spaces in them
97+
let path = it.path.trim_end_matches('`');
98+
path.ends_with(".nu") || path.ends_with(SEP)
99+
})
97100
.map(|x| {
98-
let append_whitespace = x.path.ends_with(".nu");
101+
let append_whitespace =
102+
x.path.ends_with(".nu") && (!start_with_backquote || end_with_backquote);
99103
// Re-calculate the span to replace
100-
let span_offset = if base_dir == "." {
101-
0
102-
} else {
103-
base_dir.len() + 1
104-
} + prefix.iter().take_while(|c| **c == b'`').count();
104+
let mut span_offset = 0;
105+
let mut value = x.path.to_string();
106+
// Complete only the last path component
107+
if base_dir != "." {
108+
span_offset = base_dir.len() + 1
109+
}
110+
// Retain only one '`'
111+
if start_with_backquote {
112+
value = value.trim_start_matches('`').to_string();
113+
span_offset += 1;
114+
}
115+
// Add the backquote back
116+
if end_with_backquote && !value.ends_with('`') {
117+
value.push('`');
118+
}
105119
let end = x.span.end - offset;
106120
let start = std::cmp::min(end, x.span.start - offset + span_offset);
107121
SemanticSuggestion {
108122
suggestion: Suggestion {
109-
value: x.path,
123+
value,
110124
style: x.style,
111125
span: reedline::Span { start, end },
112126
append_whitespace,

crates/nu-cli/tests/completions/mod.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -275,13 +275,22 @@ fn dotnu_completions() {
275275

276276
// Test nested nu script
277277
#[cfg(windows)]
278-
let completion_str = "use .\\dir_module\\sub_module\\".to_string();
278+
let completion_str = "use `.\\dir_module\\sub module\\".to_string();
279279
#[cfg(not(windows))]
280-
let completion_str = "use ./dir_module/sub_module/".to_string();
280+
let completion_str = "use `./dir_module/sub module/".to_string();
281281
let suggestions = completer.complete(&completion_str, completion_str.len());
282282

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

285+
// Test nested nu script, with ending '`'
286+
#[cfg(windows)]
287+
let completion_str = "use `.\\dir_module\\sub module\\`".to_string();
288+
#[cfg(not(windows))]
289+
let completion_str = "use `./dir_module/sub module/`".to_string();
290+
let suggestions = completer.complete(&completion_str, completion_str.len());
291+
292+
match_suggestions(&vec!["sub.nu`".into()], &suggestions);
293+
285294
let expected = vec![
286295
"asdf.nu".into(),
287296
"bar.nu".into(),

tests/fixtures/dotnu_completions/dir_module/sub_module/sub.nu renamed to tests/fixtures/dotnu_completions/dir_module/sub module/sub.nu

File renamed without changes.

0 commit comments

Comments
 (0)