Mountain/RPC/CocoonService/FileSystem/
FindFiles.rs1use globset::Glob;
5use tonic::{Response, Status};
6
7use crate::{
8 RPC::CocoonService::CocoonServiceImpl,
9 Vine::Generated::{FindFilesRequest, FindFilesResponse},
10 dev_log,
11};
12
13pub async fn Fn(Service:&CocoonServiceImpl, Request:FindFilesRequest) -> Result<Response<FindFilesResponse>, Status> {
14 dev_log!("cocoon", "[CocoonService] Finding files with pattern: {}", Request.pattern);
15
16 let Matcher = Glob::new(&Request.pattern)
17 .map_err(|Error| {
18 Status::invalid_argument(format!("find_files: invalid pattern '{}': {}", Request.pattern, Error))
19 })?
20 .compile_matcher();
21
22 let Roots:Vec<std::path::PathBuf> = {
23 match Service.environment.ApplicationState.Workspace.WorkspaceFolders.lock() {
24 Ok(Guard) => Guard.iter().map(|F| std::path::PathBuf::from(F.URI.path())).collect(),
25
26 Err(_) => Vec::new(),
27 }
28 };
29
30 let SearchRoots = if Roots.is_empty() {
31 vec![std::env::current_dir().unwrap_or_default()]
32 } else {
33 Roots
34 };
35
36 let mut URIs = Vec::new();
37
38 fn WalkAndCollect(
39 Directory:&std::path::Path,
40
41 Root:&std::path::Path,
42
43 Matcher:&globset::GlobMatcher,
44
45 Results:&mut Vec<String>,
46 ) {
47 if let Ok(Entries) = std::fs::read_dir(Directory) {
48 for Entry in Entries.flatten() {
49 let EntryPath = Entry.path();
50
51 if EntryPath.is_dir() {
52 WalkAndCollect(&EntryPath, Root, Matcher, Results);
53 } else if let Ok(Relative) = EntryPath.strip_prefix(Root) {
54 if Matcher.is_match(Relative) {
55 Results.push(format!("file://{}", EntryPath.display()));
56 }
57 }
58 }
59 }
60 }
61
62 for Root in &SearchRoots {
63 WalkAndCollect(Root, Root, &Matcher, &mut URIs);
64 }
65
66 dev_log!(
67 "cocoon",
68 "[CocoonService] find_files: {} results for pattern '{}'",
69 URIs.len(),
70 Request.pattern
71 );
72
73 Ok(Response::new(FindFilesResponse { uris:URIs }))
74}