1+ use regex:: Regex ;
12use std:: ffi:: OsStr ;
23use std:: fs;
34use 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
2915pub 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) ]
4752mod 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