summaryrefslogtreecommitdiff
path: root/alacritty/src/config/monitor.rs
diff options
context:
space:
mode:
Diffstat (limited to 'alacritty/src/config/monitor.rs')
-rw-r--r--alacritty/src/config/monitor.rs115
1 files changed, 72 insertions, 43 deletions
diff --git a/alacritty/src/config/monitor.rs b/alacritty/src/config/monitor.rs
index 2ed0c426..5d388182 100644
--- a/alacritty/src/config/monitor.rs
+++ b/alacritty/src/config/monitor.rs
@@ -1,57 +1,86 @@
+use std::fs;
use std::path::PathBuf;
use std::sync::mpsc;
use std::time::Duration;
+use log::{debug, error};
use notify::{watcher, DebouncedEvent, RecursiveMode, Watcher};
use alacritty_terminal::thread;
use crate::event::{Event, EventProxy};
-pub struct Monitor {
- _thread: ::std::thread::JoinHandle<()>,
-}
+pub fn watch(mut paths: Vec<PathBuf>, event_proxy: EventProxy) {
+ // Canonicalize all paths, filtering out the ones that do not exist.
+ paths = paths
+ .drain(..)
+ .filter_map(|path| match fs::canonicalize(&path) {
+ Ok(path) => Some(path),
+ Err(err) => {
+ error!("Unable to canonicalize config path {:?}: {}", path, err);
+ None
+ },
+ })
+ .collect();
+
+ // Don't monitor config if there is no path to watch.
+ if paths.is_empty() {
+ return;
+ }
+
+ // The Duration argument is a debouncing period.
+ let (tx, rx) = mpsc::channel();
+ let mut watcher = match watcher(tx, Duration::from_millis(10)) {
+ Ok(watcher) => watcher,
+ Err(err) => {
+ error!("Unable to watch config file: {}", err);
+ return;
+ },
+ };
+
+ thread::spawn_named("config watcher", move || {
+ // Get all unique parent directories.
+ let mut parents = paths
+ .iter()
+ .map(|path| {
+ let mut path = path.clone();
+ path.pop();
+ path
+ })
+ .collect::<Vec<PathBuf>>();
+ parents.sort_unstable();
+ parents.dedup();
-impl Monitor {
- pub fn new<P>(path: P, event_proxy: EventProxy) -> Monitor
- where
- P: Into<PathBuf>,
- {
- let path = path.into();
-
- Monitor {
- _thread: thread::spawn_named("config watcher", move || {
- let (tx, rx) = mpsc::channel();
- // The Duration argument is a debouncing period.
- let mut watcher =
- watcher(tx, Duration::from_millis(10)).expect("Unable to spawn file watcher");
- let config_path = ::std::fs::canonicalize(path).expect("canonicalize config path");
-
- // Get directory of config.
- let mut parent = config_path.clone();
- parent.pop();
-
- // Watch directory.
- watcher
- .watch(&parent, RecursiveMode::NonRecursive)
- .expect("watch alacritty.yml dir");
-
- loop {
- match rx.recv().expect("watcher event") {
- DebouncedEvent::Rename(..) => continue,
- DebouncedEvent::Write(path)
- | DebouncedEvent::Create(path)
- | DebouncedEvent::Chmod(path) => {
- if path != config_path {
- continue;
- }
-
- event_proxy.send_event(Event::ConfigReload(path));
- },
- _ => {},
+ // Watch all configuration file directories.
+ for parent in &parents {
+ if let Err(err) = watcher.watch(&parent, RecursiveMode::NonRecursive) {
+ debug!("Unable to watch config directory {:?}: {}", parent, err);
+ }
+ }
+
+ loop {
+ let event = match rx.recv() {
+ Ok(event) => event,
+ Err(err) => {
+ debug!("Config watcher channel dropped unexpectedly: {}", err);
+ break;
+ },
+ };
+
+ match event {
+ DebouncedEvent::Rename(..) => continue,
+ DebouncedEvent::Write(path)
+ | DebouncedEvent::Create(path)
+ | DebouncedEvent::Chmod(path) => {
+ if !paths.contains(&path) {
+ continue;
}
- }
- }),
+
+ // Always reload the primary configuration file.
+ event_proxy.send_event(Event::ConfigReload(paths[0].clone()));
+ },
+ _ => {},
+ }
}
- }
+ });
}