diff options
author | Norbert Preining <norbert@preining.info> | 2021-05-23 03:00:39 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2021-05-23 03:00:39 +0000 |
commit | f1261b349e875b842745b63258c3e338cb1fe3bf (patch) | |
tree | b5d402b3e80818cde2c079a42249f3dcb9732247 /support/texlab/src/workspace/watch.rs | |
parent | 58aa1ac09b1d9e4769d0a0661cf12e2b2db41b14 (diff) |
CTAN sync 202105230300
Diffstat (limited to 'support/texlab/src/workspace/watch.rs')
-rw-r--r-- | support/texlab/src/workspace/watch.rs | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/support/texlab/src/workspace/watch.rs b/support/texlab/src/workspace/watch.rs new file mode 100644 index 0000000000..655872f603 --- /dev/null +++ b/support/texlab/src/workspace/watch.rs @@ -0,0 +1,107 @@ +use std::{ + path::PathBuf, + sync::{Arc, Mutex}, +}; + +use anyhow::Result; +use log::warn; +use notify::{RecommendedWatcher, RecursiveMode, Watcher}; +use rustc_hash::FxHashSet; + +use crate::{ + Document, DocumentLanguage, OpenHandler, Uri, Workspace, WorkspaceSource, WorkspaceSubset, +}; + +pub struct DocumentWatcher<W> { + workspace: Arc<W>, + watcher: Mutex<RecommendedWatcher>, + watched_paths: Mutex<FxHashSet<PathBuf>>, +} + +impl<W> DocumentWatcher<W> +where + W: Workspace + Send + Sync + 'static, +{ + pub fn new(workspace: Arc<W>) -> Result<Self> { + let watcher = Self::create_watcher(Arc::clone(&workspace))?; + Ok(Self { + workspace, + watcher: Mutex::new(watcher), + watched_paths: Mutex::default(), + }) + } + + fn create_watcher(workspace: Arc<W>) -> Result<RecommendedWatcher> { + let watcher = Watcher::new_immediate(move |event: notify::Result<notify::Event>| { + if let Ok(event) = event { + if event.kind.is_modify() { + for path in event.paths { + let _ = workspace.reload(path); + } + } + } + })?; + Ok(watcher) + } +} + +impl<W: Workspace> Workspace for DocumentWatcher<W> { + fn open( + &self, + uri: Arc<Uri>, + text: String, + language: DocumentLanguage, + source: WorkspaceSource, + ) -> Arc<Document> { + let document = self.workspace.open(uri, text, language, source); + if document.uri.scheme() == "file" { + if let Ok(mut path) = document.uri.to_file_path() { + path.pop(); + let mut watched_paths = self.watched_paths.lock().unwrap(); + if !watched_paths.contains(&path) { + if let Err(why) = self + .watcher + .lock() + .unwrap() + .watch(&path, RecursiveMode::NonRecursive) + { + warn!( + "Failed to watch folder of document \"{}\": {}", + document.uri, why + ); + } + watched_paths.insert(path); + } + } + } + document + } + + fn register_open_handler(&self, handler: OpenHandler) { + self.workspace.register_open_handler(handler); + } + + fn documents(&self) -> Vec<Arc<Document>> { + self.workspace.documents() + } + + fn has(&self, uri: &Uri) -> bool { + self.workspace.has(uri) + } + + fn get(&self, uri: &Uri) -> Option<Arc<Document>> { + self.workspace.get(uri) + } + + fn close(&self, uri: &Uri) { + self.workspace.close(uri) + } + + fn is_open(&self, uri: &Uri) -> bool { + self.workspace.is_open(uri) + } + + fn subset(&self, uri: Arc<Uri>) -> Option<WorkspaceSubset> { + self.workspace.subset(uri) + } +} |