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