diff options
author | Joe Wilm <joe@jwilm.com> | 2016-10-27 10:05:04 -0700 |
---|---|---|
committer | Joe Wilm <joe@jwilm.com> | 2016-10-27 10:16:08 -0700 |
commit | 06ea6c8e565af0fdddc4de80f59435cfe05670c2 (patch) | |
tree | 76f5b8b667862da0bde080fc694761052bf46ff5 /src/config.rs | |
parent | 0958c0f0f28664fe2f48ad1b552b69b0ced731c1 (diff) | |
download | alacritty-06ea6c8e565af0fdddc4de80f59435cfe05670c2.tar.gz alacritty-06ea6c8e565af0fdddc4de80f59435cfe05670c2.zip |
Move config reloading to separate thread
This feature was previously shoved into the renderer due to initial
proof of concept. Now, providing config updates to other systems is
possible. This will be especially important for key bindings!
Diffstat (limited to 'src/config.rs')
-rw-r--r-- | src/config.rs | 68 |
1 files changed, 58 insertions, 10 deletions
diff --git a/src/config.rs b/src/config.rs index 27fcf3ca..f3e68dca 100644 --- a/src/config.rs +++ b/src/config.rs @@ -7,11 +7,13 @@ use std::env; use std::fs; use std::io::{self, Read}; use std::path::{Path, PathBuf}; +use std::sync::mpsc; use ::Rgb; use font::Size; use serde_yaml; use serde::{self, Error as SerdeError}; +use notify::{Watcher as WatcherApi, RecommendedWatcher as FileWatcher, op}; /// Top-level config type #[derive(Debug, Deserialize, Default)] @@ -232,7 +234,7 @@ impl Config { /// /// 1. `$HOME/.config/alacritty.yml` /// 2. `$HOME/.alacritty.yml` - pub fn load() -> Result<Config> { + pub fn load() -> Result<(Config, PathBuf)> { let home = env::var("HOME")?; // First path @@ -240,15 +242,17 @@ impl Config { path.push(".config"); path.push("alacritty.yml"); - // Fallback path - let mut alt_path = PathBuf::from(&home); - alt_path.push(".alacritty.yml"); - - match Config::load_from(&path) { + match Config::load_from(path) { Ok(c) => Ok(c), Err(e) => { match e { - Error::NotFound => Config::load_from(&alt_path), + Error::NotFound => { + // Fallback path + let mut alt_path = PathBuf::from(&home); + alt_path.push(".alacritty.yml"); + + Config::load_from(alt_path) + }, _ => Err(e), } } @@ -315,9 +319,10 @@ impl Config { self.render_timer } - fn load_from<P: AsRef<Path>>(path: P) -> Result<Config> { - let raw = Config::read_file(path)?; - Ok(serde_yaml::from_str(&raw[..])?) + fn load_from<P: Into<PathBuf>>(path: P) -> Result<(Config, PathBuf)> { + let path = path.into(); + let raw = Config::read_file(path.as_path())?; + Ok((serde_yaml::from_str(&raw[..])?, path)) } fn read_file<P: AsRef<Path>>(path: P) -> Result<String> { @@ -525,3 +530,46 @@ impl Default for Font { } } } + +pub struct Watcher(::std::thread::JoinHandle<()>); + +pub trait OnConfigReload { + fn on_config_reload(&mut self, Config); +} + +impl Watcher { + pub fn new<H: OnConfigReload + Send + 'static>(path: PathBuf, mut handler: H) -> Watcher { + Watcher(::util::thread::spawn_named("config watcher", move || { + let (tx, rx) = mpsc::channel(); + let mut watcher = FileWatcher::new(tx).unwrap(); + watcher.watch(&path).expect("watch alacritty yml"); + + let config_path = path.as_path(); + + loop { + let event = rx.recv().expect("watcher event"); + let ::notify::Event { path, op } = event; + + if let Ok(op) = op { + if op.contains(op::RENAME) { + continue; + } + + if op.contains(op::IGNORED) { + if let Some(path) = path.as_ref() { + if let Err(err) = watcher.watch(&path) { + err_println!("failed to establish watch on {:?}: {:?}", path, err); + } + + if path == config_path { + if let Ok((config, _)) = Config::load() { + handler.on_config_reload(config); + }; + } + } + } + } + } + })) + } +} |