summaryrefslogtreecommitdiff
path: root/src/config.rs
diff options
context:
space:
mode:
authorJoe Wilm <joe@jwilm.com>2016-10-27 10:05:04 -0700
committerJoe Wilm <joe@jwilm.com>2016-10-27 10:16:08 -0700
commit06ea6c8e565af0fdddc4de80f59435cfe05670c2 (patch)
tree76f5b8b667862da0bde080fc694761052bf46ff5 /src/config.rs
parent0958c0f0f28664fe2f48ad1b552b69b0ced731c1 (diff)
downloadalacritty-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.rs68
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);
+ };
+ }
+ }
+ }
+ }
+ }
+ }))
+ }
+}