1use crate::extensions::base::ExtensionInfo;
2use crate::extensions::manager::{ExtensionsManager, LoadedExtension};
3use crate::filesystems::{FileFormat, Filesystem, LocalFilesystem};
4use crate::messaging::ExtensionMessages;
5pub use crate::state_persistors::memory::MemoryPersistor;
6use crate::state_persistors::Persistor;
7use crate::{Errors, ExtensionErrors, LanguageServer, ManifestInfo};
8use serde::{Deserialize, Serialize};
9use std::collections::HashMap;
10use std::fmt;
11use std::sync::Arc;
12use tokio::sync::Mutex;
13
14#[derive(Clone)]
15pub enum TokenFlags {
16 All(String),
17}
18
19#[derive(Clone, Default)]
21pub struct StatesList {
22 states: HashMap<u8, Arc<Mutex<State>>>,
23 provided_tokens: Vec<TokenFlags>,
24}
25
26impl StatesList {
27 pub fn new() -> Self {
29 Self {
30 states: HashMap::new(),
31 provided_tokens: Vec::new(),
32 }
33 }
34
35 pub fn with_tokens(mut self, tokens: &[TokenFlags]) -> Self {
36 self.provided_tokens = tokens.to_vec();
37 self
38 }
39
40 pub fn get_state_by_id(&self, id: u8) -> Option<Arc<Mutex<State>>> {
42 self.states.get(&id).cloned()
43 }
44
45 pub fn with_state(mut self, state: State) -> Self {
47 let mut state = state;
48
49 for token in &self.provided_tokens {
50 match token {
51 TokenFlags::All(token) => {
52 state.tokens.push(token.clone());
53 }
54 }
55 }
56
57 self.states
58 .insert(state.data.id, Arc::new(Mutex::new(state.to_owned())));
59
60 self
61 }
62
63 pub async fn notify_extensions(&self, message: ExtensionMessages) {
65 let state_id = message.get_state_id();
66 let state = self.states.get(&state_id);
67 if let Some(state) = state {
68 let state = state.lock().await;
69 state.notify_extensions(message);
70 }
71 }
72}
73
74#[derive(Serialize, Deserialize, Debug, Clone)]
76#[serde(tag = "tab_type")]
77pub enum TabData {
78 TextEditor {
80 path: String,
81 filesystem: String,
82 format: FileFormat,
83 filename: String,
84 id: String,
85 },
86 Basic {
88 title: String,
89 id: String,
90 },
91}
92#[derive(Serialize, Deserialize, Clone, Debug, Default)]
93struct ViewPanel {
94 selected_tab_id: Option<String>,
95 tabs: Vec<TabData>,
96}
97
98type TabsViews = Vec<ViewPanel>;
99
100#[derive(Serialize, Deserialize, Clone, Debug)]
102pub struct StateData {
103 pub id: u8,
104 opened_tabs: Vec<TabsViews>,
105}
106
107impl Default for StateData {
108 fn default() -> Self {
109 Self {
110 id: 1,
111 opened_tabs: Vec::default(),
112 }
113 }
114}
115
116#[derive(Clone)]
118pub struct State {
119 filesystems: HashMap<String, Arc<Mutex<Box<dyn Filesystem + Send>>>>,
120 extensions_manager: ExtensionsManager,
121 persistor: Option<Arc<Mutex<Box<dyn Persistor + Send>>>>,
122 pub data: StateData,
123 tokens: Vec<String>,
124 language_servers: HashMap<String, LanguageServer>,
125}
126
127impl fmt::Debug for State {
128 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
129 f.debug_struct("State")
130 .field("opened_tabs", &self.data.opened_tabs)
131 .field("id", &self.data.id)
132 .finish()
133 }
134}
135
136impl Default for State {
137 fn default() -> Self {
142 let mut filesystems = HashMap::new();
143
144 let local_fs: Box<dyn Filesystem + Send> = Box::new(LocalFilesystem::new());
146 filesystems.insert("local".to_string(), Arc::new(Mutex::new(local_fs)));
147
148 Self {
149 data: StateData::default(),
150 filesystems,
151 extensions_manager: ExtensionsManager::default(),
152 tokens: Vec::new(),
153 persistor: None,
154 language_servers: HashMap::new(),
155 }
156 }
157}
158
159impl State {
160 pub fn new(
161 id: u8,
162 extensions_manager: ExtensionsManager,
163 mut persistor: Box<dyn Persistor + Send>,
164 ) -> Self {
165 let state = persistor.load();
167
168 State {
169 data: StateData { id, ..state },
170 extensions_manager,
171 persistor: Some(Arc::new(Mutex::new(persistor))),
172 ..Default::default()
173 }
174 }
175
176 pub fn get_fs_by_name(
178 &self,
179 filesystem: &str,
180 ) -> Option<Arc<Mutex<Box<dyn Filesystem + Send>>>> {
181 return self.filesystems.get(filesystem).cloned();
182 }
183
184 pub fn has_token(&self, token: &str) -> bool {
186 self.tokens.contains(&token.to_owned())
187 }
188
189 pub async fn run_extensions(&self) {
191 for ext in &self.extensions_manager.extensions {
192 if let LoadedExtension::ExtensionInstance { plugin, .. } = ext {
193 let mut ext_plugin = plugin.lock().await;
194 ext_plugin.unload();
195 ext_plugin.init();
196 }
197 }
198 }
199
200 pub fn notify_extensions(&self, message: ExtensionMessages) {
202 for ext in &self.extensions_manager.extensions {
203 if let LoadedExtension::ExtensionInstance { plugin, .. } = ext {
204 let ext_plugin = plugin.clone();
205 let message = message.clone();
206 tokio::spawn(async move {
207 let mut ext_plugin = ext_plugin.lock().await;
208 ext_plugin.notify(message.clone());
209 });
210 }
211 }
212 }
213
214 pub fn get_ext_info_by_id(&self, ext_id: &str) -> Result<ManifestInfo, Errors> {
216 let extensions = &self.extensions_manager.extensions;
217 let result = extensions.iter().find_map(|extension| {
218 if let LoadedExtension::ManifestFile { manifest } = extension {
219 if manifest.info.extension.id == ext_id {
220 Some(manifest.info.clone())
221 } else {
222 None
223 }
224 } else if let LoadedExtension::ManifestBuiltin { info, .. } = extension {
225 if info.extension.id == ext_id {
226 Some(info.clone())
227 } else {
228 None
229 }
230 } else {
231 None
232 }
233 });
234
235 result.ok_or(Errors::Ext(ExtensionErrors::ExtensionNotFound))
236 }
237
238 pub fn get_ext_run_info_by_id(&self, ext_id: &str) -> Result<ExtensionInfo, Errors> {
240 let extensions = &self.extensions_manager.extensions;
241 let result = extensions.iter().find_map(|extension| {
242 if let LoadedExtension::ExtensionInstance { info, .. } = extension {
243 if info.id == ext_id {
244 Some(info.clone())
245 } else {
246 None
247 }
248 } else {
249 None
250 }
251 });
252
253 result.ok_or(Errors::Ext(ExtensionErrors::ExtensionNotFound))
254 }
255
256 pub fn get_ext_list_by_id(&self) -> Vec<String> {
258 let extensions = &self.extensions_manager.extensions;
259
260 extensions
261 .iter()
262 .filter_map(|extension| {
263 if let LoadedExtension::ManifestBuiltin { info, .. } = extension {
264 Some(info.extension.id.to_string())
265 } else if let LoadedExtension::ManifestFile { manifest } = extension {
266 Some(manifest.info.extension.id.to_string())
267 } else {
268 None
269 }
270 })
271 .collect::<Vec<String>>()
272 }
273
274 pub async fn update(&mut self, new_data: StateData) {
276 self.data.opened_tabs = new_data.opened_tabs;
277
278 if let Some(persistor) = &self.persistor {
279 persistor.lock().await.save(&self.data);
280 }
281 }
282
283 pub async fn register_language_servers(
285 &mut self,
286 language_servers: HashMap<String, LanguageServer>,
287 ) {
288 self.language_servers.extend(language_servers);
289 }
290
291 pub async fn get_all_language_servers(&self) -> Vec<LanguageServer> {
293 self.language_servers
294 .values()
295 .cloned()
296 .collect::<Vec<LanguageServer>>()
297 }
298}
299
300#[cfg(test)]
304mod tests {
305
306 use crate::extensions::base::{Extension, ExtensionInfo};
307 use crate::extensions::manager::ExtensionsManager;
308 use crate::messaging::ExtensionMessages;
309 use crate::state::MemoryPersistor;
310
311 use super::State;
312
313 fn get_sample_extension_info() -> ExtensionInfo {
314 ExtensionInfo {
315 id: "sample".to_string(),
316 name: "sample".to_string(),
317 }
318 }
319
320 fn get_sample_extension() -> Box<dyn Extension + Send> {
321 struct SampleExtension;
322
323 impl Extension for SampleExtension {
324 fn get_info(&self) -> ExtensionInfo {
325 get_sample_extension_info()
326 }
327
328 fn init(&mut self) {
329 todo!()
330 }
331
332 fn unload(&mut self) {
333 todo!()
334 }
335
336 fn notify(&mut self, _message: ExtensionMessages) {
337 todo!()
338 }
339 }
340
341 Box::new(SampleExtension)
342 }
343
344 #[test]
345 fn get_info() {
346 let mut manager = ExtensionsManager::default();
347 manager.register("sample", get_sample_extension());
348 let test_state = State::new(0, manager, Box::new(MemoryPersistor::new()));
349
350 let ext_info = test_state.get_ext_run_info_by_id("sample");
351 assert!(ext_info.is_ok());
352
353 let ext_info = ext_info.unwrap();
354 assert_eq!(get_sample_extension_info(), ext_info);
355 }
356}