Skip to content

Commit 006e39d

Browse files
committed
fix(completion): dotnu_completion for nested folders/scripts
1 parent 4540f38 commit 006e39d

File tree

4 files changed

+58
-49
lines changed

4 files changed

+58
-49
lines changed

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

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,6 @@ pub struct FileSuggestion {
157157
pub span: nu_protocol::Span,
158158
pub path: String,
159159
pub style: Option<Style>,
160-
pub cwd: PathBuf,
161160
}
162161

163162
/// # Parameters
@@ -261,7 +260,6 @@ pub fn complete_item(
261260
if should_collapse_dots {
262261
p = collapse_ndots(p);
263262
}
264-
let cwd = p.cwd.clone();
265263
let path = original_cwd.apply(p, path_separator);
266264
let style = ls_colors.as_ref().map(|lsc| {
267265
lsc.style_for_path_with_metadata(
@@ -277,7 +275,6 @@ pub fn complete_item(
277275
span,
278276
path: escape_path(path, want_directory),
279277
style,
280-
cwd,
281278
}
282279
})
283280
.collect()

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

Lines changed: 37 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use nu_protocol::{
44
Span,
55
};
66
use reedline::Suggestion;
7-
use std::path::{is_separator, Path, MAIN_SEPARATOR as SEP, MAIN_SEPARATOR_STR};
7+
use std::path::{is_separator, MAIN_SEPARATOR as SEP, MAIN_SEPARATOR_STR};
88

99
use super::SemanticSuggestion;
1010

@@ -36,9 +36,6 @@ impl Completer for DotNuCompletion {
3636
.rsplit_once(is_separator)
3737
.unwrap_or((".", &prefix_str));
3838
let base_dir = base.replace(is_separator, MAIN_SEPARATOR_STR);
39-
let mut partial = partial.to_string();
40-
// On windows, this standardizes paths to use \
41-
let mut is_current_folder = false;
4239

4340
// Fetch the lib dirs
4441
let lib_dirs: Vec<String> = working_set
@@ -66,25 +63,22 @@ impl Completer for DotNuCompletion {
6663

6764
// Check if the base_dir is a folder
6865
// rsplit_once removes the separator
66+
let cwd = working_set
67+
.permanent_state
68+
.cwd(None)
69+
.ok()
70+
.map(|pb| pb.to_string_lossy().into_owned())
71+
.unwrap_or_default();
6972
if base_dir != "." {
70-
// Add the base dir into the directories to be searched
71-
search_dirs.push(base_dir.clone());
72-
73-
// Reset the partial adding the basic dir back
74-
// in order to make the span replace work properly
75-
let mut base_dir_partial = base_dir;
76-
base_dir_partial.push_str(&partial);
77-
78-
partial = base_dir_partial;
73+
// Search in base_dir as well as lib_dirs
74+
search_dirs.push(format!("{cwd}{SEP}{base_dir}"));
75+
search_dirs.extend(
76+
lib_dirs
77+
.into_iter()
78+
.map(|dir| format!("{dir}{SEP}{base_dir}")),
79+
);
7980
} else {
80-
// Fetch the current folder
81-
#[allow(deprecated)]
82-
let current_folder = working_set.permanent_state.current_work_dir();
83-
is_current_folder = true;
84-
85-
// Add the current folder and the lib dirs into the
86-
// directories to be searched
87-
search_dirs.push(current_folder);
81+
search_dirs.push(cwd);
8882
search_dirs.extend(lib_dirs);
8983
}
9084

@@ -93,40 +87,37 @@ impl Completer for DotNuCompletion {
9387

9488
let completions = file_path_completion(
9589
span,
96-
&partial,
90+
partial,
9791
&search_dirs.iter().map(|d| d.as_str()).collect::<Vec<_>>(),
9892
options,
9993
working_set.permanent_state,
10094
stack,
10195
);
10296
completions
10397
.into_iter()
104-
.filter(move |it| {
105-
// Different base dir, so we list the .nu files or folders
106-
if !is_current_folder {
107-
it.path.ends_with(".nu") || it.path.ends_with(SEP)
98+
// Different base dir, so we list the .nu files or folders
99+
.filter(|it| it.path.ends_with(".nu") || it.path.ends_with(SEP))
100+
.map(|x| {
101+
let append_whitespace = x.path.ends_with(".nu");
102+
// Re-calculate the span to replace
103+
let span_offset = if base_dir == "." {
104+
0
108105
} else {
109-
// Lib dirs, so we filter only the .nu files or directory modules
110-
if it.path.ends_with(SEP) {
111-
Path::new(&it.cwd).join(&it.path).join("mod.nu").exists()
112-
} else {
113-
it.path.ends_with(".nu")
114-
}
115-
}
116-
})
117-
.map(move |x| SemanticSuggestion {
118-
suggestion: Suggestion {
119-
value: x.path,
120-
style: x.style,
121-
span: reedline::Span {
122-
start: x.span.start - offset,
123-
end: x.span.end - offset,
106+
base_dir.len() + 1
107+
} + prefix.iter().take_while(|c| **c == b'`').count();
108+
let end = x.span.end - offset;
109+
let start = std::cmp::min(end, x.span.start - offset + span_offset);
110+
SemanticSuggestion {
111+
suggestion: Suggestion {
112+
value: x.path,
113+
style: x.style,
114+
span: reedline::Span { start, end },
115+
append_whitespace,
116+
..Suggestion::default()
124117
},
125-
append_whitespace: true,
126-
..Suggestion::default()
127-
},
128-
// TODO????
129-
kind: None,
118+
// TODO????
119+
kind: None,
120+
}
130121
})
131122
.collect::<Vec<_>>()
132123
}

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,15 @@ fn dotnu_completions() {
273273
// Instantiate a new completer
274274
let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
275275

276+
// Test nested nu script
277+
#[cfg(windows)]
278+
let completion_str = "use .\\dir_module\\sub_module\\".to_string();
279+
#[cfg(not(windows))]
280+
let completion_str = "use ./dir_module/sub_module/".to_string();
281+
let suggestions = completer.complete(&completion_str, completion_str.len());
282+
283+
match_suggestions(&vec!["sub.nu".into()], &suggestions);
284+
276285
let expected = vec![
277286
"asdf.nu".into(),
278287
"bar.nu".into(),
@@ -283,6 +292,18 @@ fn dotnu_completions() {
283292
#[cfg(not(windows))]
284293
"dir_module/".into(),
285294
"foo.nu".into(),
295+
#[cfg(windows)]
296+
"lib-dir1\\".into(),
297+
#[cfg(not(windows))]
298+
"lib-dir1/".into(),
299+
#[cfg(windows)]
300+
"lib-dir2\\".into(),
301+
#[cfg(not(windows))]
302+
"lib-dir2/".into(),
303+
#[cfg(windows)]
304+
"lib-dir3\\".into(),
305+
#[cfg(not(windows))]
306+
"lib-dir3/".into(),
286307
"spam.nu".into(),
287308
"xyzzy.nu".into(),
288309
];

tests/fixtures/dotnu_completions/dir_module/sub_module/sub.nu

Whitespace-only changes.

0 commit comments

Comments
 (0)