Skip to content

Commit 85243eb

Browse files
committed
fix file item completion
1 parent be77126 commit 85243eb

File tree

2 files changed

+46
-107
lines changed

2 files changed

+46
-107
lines changed

src/file.rs

Lines changed: 20 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,8 @@
1-
use regex::Regex;
21
use std::ffi::OsStr;
32
use std::fs;
43
use std::path::Path;
54
use std::path::PathBuf;
65

7-
pub fn find_file_paths(input: &str) -> Vec<String> {
8-
let pattern = r#"(\./[^\s<>:\",|?*]+(?:/[^\s<>:\",|?*]+)*|\.\./[^\s<>:\"|?*]+(?:/[^\s<>:\"|?*]+)*|[a-zA-Z]:\\[^\s<>:\",|?*]+(?:\\[^\s<>:\",|?*]+)*|/[^<>\s:\",|?*\r\n]+(?:/[^<>:\"|?*\r\n]+)*)"#;
9-
let re = Regex::new(pattern).unwrap();
10-
re.find_iter(input)
11-
.map(|m| m.as_str().to_string())
12-
.collect()
13-
}
14-
156
pub fn list_all_file_items(path: &Path) -> Vec<String> {
167
let read_result = fs::read_dir(path);
178
let mut result = Vec::new();
@@ -29,20 +20,29 @@ pub fn list_all_file_items(path: &Path) -> Vec<String> {
2920
result
3021
}
3122

32-
pub fn get_file_items(text: &str, root_folder: &str) -> Vec<String> {
23+
const MAX_LINE_LENGTH: usize = 600;
24+
25+
pub fn get_file_items(current_line: &str, root_folder: &str) -> Vec<(String, usize)> {
26+
if current_line.len() >= MAX_LINE_LENGTH {
27+
return Vec::new();
28+
}
29+
3330
let mut file_items = Vec::new();
34-
let file_paths = find_file_paths(&text);
35-
// info!("file path size: {}", file_paths.len());
36-
for file_path in file_paths.iter() {
37-
let mut root = PathBuf::from(root_folder);
38-
root = root.join(file_path);
39-
if !root.is_dir() {
40-
root = root.parent().map(|p| p.to_path_buf()).unwrap();
31+
for (j, _) in current_line.char_indices().filter(|&(_, ch)| ch == '/' || ch == '\\') {
32+
for i in 0..j {
33+
let p = &current_line[i..j];
34+
35+
for base in [root_folder, ""].iter().map(PathBuf::from) {
36+
let path = base.join(p);
37+
file_items.extend(
38+
list_all_file_items(&path)
39+
.into_iter()
40+
.map(|file_path| (file_path, j))
41+
);
42+
}
4143
}
42-
let possible = list_all_file_items(&root);
43-
file_items.extend(possible);
44-
// info!("file path: {}", file_path);
4544
}
45+
4646
file_items.sort();
4747
file_items.dedup();
4848
file_items
@@ -74,82 +74,4 @@ mod tests {
7474
let items = list_all_file_items(Path::new("doesnt_exist"));
7575
assert_eq!(0, items.len());
7676
}
77-
78-
#[test]
79-
fn test_find_file_paths() {
80-
let example = "path/to/my_file.txt";
81-
assert_eq!(find_file_paths(example), vec!["/to/my_file.txt"]);
82-
83-
let example = "Check these paths: C:\\Users\\User\\file.txt, /home/user/docs/report.pdf";
84-
assert_eq!(
85-
find_file_paths(example),
86-
vec!["C:\\Users\\User\\file.txt", "/home/user/docs/report.pdf"]
87-
);
88-
89-
let example = "./file.txt";
90-
assert_eq!(find_file_paths(example), vec!["./file.txt"]);
91-
92-
let example = "./";
93-
assert_eq!(find_file_paths(example), Vec::<String>::new());
94-
95-
let example = "Some text with a path ./src/main.rs in it.";
96-
assert_eq!(find_file_paths(example), vec!["./src/main.rs"]);
97-
98-
let example = "Multiple paths: ./file1.txt, ./file2.txt, ./file3.txt";
99-
assert_eq!(
100-
find_file_paths(example),
101-
vec!["./file1.txt", "./file2.txt", "./file3.txt"]
102-
);
103-
104-
let example = "A path with spaces: /path/to/a_long_name_file.txt";
105-
assert_eq!(find_file_paths(example), vec!["/path/to/a_long_name_file.txt"]);
106-
107-
let example = "A relative path: ../parent/file.txt";
108-
assert_eq!(find_file_paths(example), vec!["../parent/file.txt"]);
109-
110-
let example = "Just the drive letter: C:\\";
111-
assert_eq!(find_file_paths(example), Vec::<String>::new());
112-
113-
let example = "A more complex windows path: D:\\MyDocuments\\Project\\file.pdf";
114-
assert_eq!(
115-
find_file_paths(example),
116-
vec!["D:\\MyDocuments\\Project\\file.pdf"]
117-
);
118-
119-
let example =
120-
"Mix of paths: ./local/file.txt and /absolute/file.txt and C:\\windows\\file.exe";
121-
assert_eq!(
122-
find_file_paths(example),
123-
vec![
124-
"./local/file.txt",
125-
"/absolute/file.txt",
126-
"C:\\windows\\file.exe"
127-
]
128-
);
129-
130-
let example = "No paths here.";
131-
assert_eq!(find_file_paths(example), Vec::<String>::new());
132-
133-
let example = "Path at the end: /opt/app/data";
134-
assert_eq!(find_file_paths(example), vec!["/opt/app/data"]);
135-
136-
let example =
137-
"This is a test with a long path: /very/long/path/to/a/deeply/nested/file.txt";
138-
assert_eq!(
139-
find_file_paths(example),
140-
vec!["/very/long/path/to/a/deeply/nested/file.txt"]
141-
);
142-
143-
let example = "This is a test with a long windows path: C:\\very\\long\\path\\to\\a\\deeply\\nested\\file.txt";
144-
assert_eq!(
145-
find_file_paths(example),
146-
vec!["C:\\very\\long\\path\\to\\a\\deeply\\nested\\file.txt"]
147-
);
148-
149-
let example = "This is a test with a long relative path: ./very/long/path/to/a/deeply/nested/file.txt";
150-
assert_eq!(
151-
find_file_paths(example),
152-
vec!["./very/long/path/to/a/deeply/nested/file.txt"]
153-
);
154-
}
15577
}

src/main.rs

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ impl LanguageServer for Backend {
133133

134134
if let Some(root_folder) = self.lsp_args.root_folder.clone() {
135135
let file_items = get_file_items(&current_line, &root_folder);
136-
file_items_to_completion_items(file_items, &mut completions);
136+
file_items_to_completion_items(file_items, &params, &mut completions);
137137
}
138138
}
139139
Ok(Some(CompletionResponse::Array(completions)))
@@ -235,16 +235,33 @@ fn snippets_to_completion_items(snippets: Vec<Snippet>, completions: &mut Vec<Co
235235
completions.append(&mut items);
236236
}
237237

238-
fn file_items_to_completion_items(file_items: Vec<String>, completions: &mut Vec<CompletionItem>) {
239-
let mut items: Vec<CompletionItem> = file_items
240-
.into_iter()
241-
.map(|file_item| CompletionItem {
242-
label: file_item.clone(),
238+
fn file_items_to_completion_items(file_items: Vec<(String, usize)>, params: &CompletionParams, completions: &mut Vec<CompletionItem>) {
239+
let position = &params.text_document_position.position;
240+
let line = position.line;
241+
let mut items: Vec<CompletionItem> = Vec::new();
242+
for file_item in file_items.iter() {
243+
let text_edit = TextEdit {
244+
new_text: file_item.0.clone(),
245+
range: Range {
246+
start: Position {
247+
line,
248+
character: file_item.1 as u32 + 1,
249+
},
250+
end: Position {
251+
line,
252+
character: (file_item.1 + file_item.0.len()) as u32,
253+
}
254+
}
255+
};
256+
let completion_item = CompletionItem {
257+
label: file_item.0.clone(),
243258
kind: Some(CompletionItemKind::FILE),
259+
text_edit: Some(CompletionTextEdit::Edit(text_edit)),
244260
..CompletionItem::default()
245-
})
246-
.collect();
247-
completions.append(&mut items);
261+
};
262+
items.push(completion_item);
263+
}
264+
completions.extend(items);
248265
}
249266

250267
impl Backend {

0 commit comments

Comments
 (0)