Skip to content

Commit 91fc7cb

Browse files
committed
fix file item completion
1 parent 1a5d849 commit 91fc7cb

File tree

4 files changed

+199
-93
lines changed

4 files changed

+199
-93
lines changed

Cargo.lock

Lines changed: 40 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "basecode-lsp"
3-
version = "0.1.4"
3+
version = "0.1.5"
44
edition = "2021"
55

66
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -9,6 +9,7 @@ edition = "2021"
99
clap = { version = "4.5.28", features = ["derive"] }
1010
glob = "0.3.2"
1111
home = "0.5.11"
12+
regex = "1.11.1"
1213
serde_json = "1.0.138"
1314
simple-log = "2.1.1"
1415
tokio = { version = "1.43.0", features = ["full"] }

src/file.rs

Lines changed: 105 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,15 @@
1+
use regex::Regex;
12
use std::ffi::OsStr;
23
use std::fs;
34
use std::path::Path;
5+
use std::path::PathBuf;
46

5-
pub fn get_file_path_prefix(line: &str, character: i32) -> String {
6-
let mut prefix = Vec::new();
7-
let line: Vec<char> = line.chars().collect();
8-
let mut i = (character - 1).min(line.len() as i32 - 1);
9-
let mut start = -1;
10-
let mut found_sep = false;
11-
while i >= 0 {
12-
let c = line[i as usize];
13-
if c == '/' {
14-
found_sep = true;
15-
}
16-
if c == '/' || c == '.' {
17-
start = i;
18-
}
19-
prefix.push(c);
20-
i -= 1;
21-
}
22-
if start < 0 || !found_sep {
23-
return String::new();
24-
}
25-
prefix.reverse();
26-
prefix[start as usize..].iter().collect()
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()
2713
}
2814

2915
pub fn list_all_file_items(path: &Path) -> Vec<String> {
@@ -43,35 +29,29 @@ pub fn list_all_file_items(path: &Path) -> Vec<String> {
4329
result
4430
}
4531

32+
pub fn get_file_items(text: &str, root_folder: &str) -> Vec<String> {
33+
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();
41+
}
42+
let possible = list_all_file_items(&root);
43+
file_items.extend(possible);
44+
// info!("file path: {}", file_path);
45+
}
46+
file_items.sort();
47+
file_items.dedup();
48+
file_items
49+
}
50+
4651
#[cfg(test)]
4752
mod tests {
4853
use super::*;
4954

50-
#[test]
51-
fn test_get_file_path_prefix() {
52-
let prefix = get_file_path_prefix("./a", 3);
53-
assert_eq!("./a", prefix);
54-
55-
let prefix = get_file_path_prefix("./some/path/to/here", 19);
56-
assert_eq!("./some/path/to/here", prefix);
57-
58-
let prefix = get_file_path_prefix(" ./a/b/c/d/e.cc", 12);
59-
assert_eq!("./a/b/c/d/", prefix);
60-
61-
let prefix = get_file_path_prefix("no_prefix", 5);
62-
assert_eq!("", prefix);
63-
64-
let prefix = get_file_path_prefix("/abs/path/to/file", 10);
65-
assert_eq!("/abs/path/", prefix);
66-
67-
let prefix = get_file_path_prefix("../foo/bar", 3);
68-
assert_eq!("../", prefix);
69-
70-
let prefix = get_file_path_prefix("../foo/bar", 7);
71-
assert_eq!("../foo/", prefix);
72-
}
73-
74-
7555
#[test]
7656
fn test_list_all_files() {
7757
let items = list_all_file_items(Path::new("./"));
@@ -94,4 +74,82 @@ mod tests {
9474
let items = list_all_file_items(Path::new("doesnt_exist"));
9575
assert_eq!(0, items.len());
9676
}
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+
}
97155
}

0 commit comments

Comments
 (0)