lspkit_server/
workspace.rs1use std::path::{Path, PathBuf};
8use std::sync::{Arc, RwLock};
9
10#[non_exhaustive]
12#[derive(Debug, Clone, PartialEq, Eq, Hash)]
13pub struct WorkspaceFolder {
14 pub root: PathBuf,
16 pub name: String,
18}
19
20impl WorkspaceFolder {
21 #[must_use]
23 pub fn new(root: impl Into<PathBuf>, name: impl Into<String>) -> Self {
24 Self {
25 root: root.into(),
26 name: name.into(),
27 }
28 }
29}
30
31#[derive(Debug, Clone, Default)]
33pub struct Workspace {
34 folders: Arc<RwLock<Vec<WorkspaceFolder>>>,
35}
36
37impl Workspace {
38 #[must_use]
40 pub fn new() -> Self {
41 Self::default()
42 }
43
44 pub fn set_folders(&self, folders: Vec<WorkspaceFolder>) {
46 if let Ok(mut guard) = self.folders.write() {
47 *guard = folders;
48 }
49 }
50
51 pub fn add(&self, folder: WorkspaceFolder) {
53 if let Ok(mut guard) = self.folders.write() {
54 guard.push(folder);
55 }
56 }
57
58 pub fn remove(&self, root: &Path) {
60 if let Ok(mut guard) = self.folders.write() {
61 guard.retain(|f| f.root != root);
62 }
63 }
64
65 #[must_use]
67 pub fn folders(&self) -> Vec<WorkspaceFolder> {
68 self.folders
69 .read()
70 .map_or_else(|_| Vec::new(), |g| g.clone())
71 }
72
73 #[must_use]
75 pub fn folder_for(&self, path: &Path) -> Option<WorkspaceFolder> {
76 self.folders
77 .read()
78 .ok()
79 .and_then(|guard| guard.iter().find(|f| path.starts_with(&f.root)).cloned())
80 }
81
82 #[must_use]
84 pub fn len(&self) -> usize {
85 self.folders.read().map_or(0, |g| g.len())
86 }
87
88 #[must_use]
90 pub fn is_empty(&self) -> bool {
91 self.len() == 0
92 }
93}