diff options
Diffstat (limited to 'alacritty/src/config/monitor.rs')
-rw-r--r-- | alacritty/src/config/monitor.rs | 115 |
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())); + }, + _ => {}, + } } - } + }); } |