diff --git a/src/config/mod.rs b/src/config/mod.rs index 59960c496..696b86f88 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -39,7 +39,7 @@ pub use unix::*; lazy_static! { static ref HOME_DIR: PathBuf = dirs::home_dir().expect("can't find HOME dir"); static ref RUNTIME_DIR: PathBuf = compute_runtime_dir().unwrap(); - static ref CONFIG: ConfigHandle = ConfigHandle::new(); + static ref CONFIG: Configuration = Configuration::new(); } /// Discard the current configuration and replace it with @@ -49,13 +49,13 @@ pub fn use_default_configuration() { } /// Returns a handle to the current configuration -pub fn configuration() -> Arc { +pub fn configuration() -> ConfigHandle { CONFIG.get() } /// If there was an error loading the preferred configuration, /// return it, otherwise return the current configuration -pub fn configuration_result() -> Result, Error> { +pub fn configuration_result() -> Result { if let Some(error) = CONFIG.get_error() { failure::bail!("{}", error); } @@ -65,6 +65,7 @@ pub fn configuration_result() -> Result, Error> { struct ConfigInner { config: Arc, error: Option, + generation: usize, } impl ConfigInner { @@ -76,10 +77,12 @@ impl ConfigInner { Ok(config) => Self { config: Arc::new(config), error: None, + generation: 0, }, Err(err) => Self { config: Arc::new(Config::default_config()), error: Some(err.to_string()), + generation: 0, }, } } @@ -94,6 +97,7 @@ impl ConfigInner { Ok(config) => { self.config = Arc::new(config); self.error.take(); + self.generation += 1; } Err(err) => { self.error.replace(err.to_string()); @@ -107,14 +111,15 @@ impl ConfigInner { fn use_defaults(&mut self) { self.config = Arc::new(Config::default_config()); self.error.take(); + self.generation += 1; } } -pub struct ConfigHandle { +pub struct Configuration { inner: Mutex, } -impl ConfigHandle { +impl Configuration { pub fn new() -> Self { Self { inner: Mutex::new(ConfigInner::load()), @@ -122,8 +127,12 @@ impl ConfigHandle { } /// Returns the effective configuration. - pub fn get(&self) -> Arc { - Arc::clone(&self.inner.lock().unwrap().config) + pub fn get(&self) -> ConfigHandle { + let inner = self.inner.lock().unwrap(); + ConfigHandle { + config: Arc::clone(&inner.config), + generation: inner.generation, + } } /// Reset the configuration to defaults @@ -153,6 +162,29 @@ impl ConfigHandle { } } +#[derive(Clone, Debug)] +pub struct ConfigHandle { + config: Arc, + generation: usize, +} + +impl ConfigHandle { + /// Returns the generation number for the configuration, + /// allowing consuming code to know whether the config + /// has been reloading since they last derived some + /// information from the configuration + pub fn generation(&self) -> usize { + self.generation + } +} + +impl std::ops::Deref for ConfigHandle { + type Target = Config; + fn deref(&self) -> &Config { + &*self.config + } +} + #[derive(Debug, Deserialize, Clone)] pub struct Config { /// The font size, measured in points diff --git a/src/font/mod.rs b/src/font/mod.rs index 6335f369a..271c3b4cc 100644 --- a/src/font/mod.rs +++ b/src/font/mod.rs @@ -8,7 +8,6 @@ use self::hbwrap as harfbuzz; use std::cell::RefCell; use std::collections::HashMap; use std::rc::Rc; -use std::sync::Arc; pub mod system; pub use self::system::*; @@ -28,7 +27,7 @@ pub mod fontloader; #[cfg(any(target_os = "macos", windows))] pub mod fontloader_and_freetype; -use super::config::{configuration, Config, TextStyle}; +use super::config::{configuration, ConfigHandle, TextStyle}; use term::CellAttributes; type FontPtr = Rc>>; @@ -194,7 +193,7 @@ impl FontConfiguration { /// cell attributes. pub fn match_style<'a>( &self, - config: &'a Arc, + config: &'a ConfigHandle, attrs: &CellAttributes, ) -> &'a TextStyle { // a little macro to avoid boilerplate for matching the rules. diff --git a/src/frontend/gui/termwindow.rs b/src/frontend/gui/termwindow.rs index 353321c34..d15f0aad1 100644 --- a/src/frontend/gui/termwindow.rs +++ b/src/frontend/gui/termwindow.rs @@ -2,7 +2,7 @@ use super::quad::*; use super::renderstate::*; use super::utilsprites::RenderMetrics; use crate::clipboard::SystemClipboard; -use crate::config::{configuration, Config}; +use crate::config::{configuration, ConfigHandle}; use crate::font::{FontConfiguration, FontSystemSelection}; use crate::frontend::gui::tabbar::{TabBarItem, TabBarState}; use crate::frontend::{executor, front_end}; @@ -356,7 +356,7 @@ impl WindowCallbacks for TermWindow { impl TermWindow { pub fn new_window( - config: &Arc, + config: &ConfigHandle, fontconfig: &Rc, tab: &Rc, mux_window_id: MuxWindowId, diff --git a/src/main.rs b/src/main.rs index dbbadc0ac..e49479e94 100644 --- a/src/main.rs +++ b/src/main.rs @@ -342,7 +342,7 @@ impl SshParameters { } } -fn run_ssh(config: Arc, opts: &SshCommand) -> Fallible<()> { +fn run_ssh(config: config::ConfigHandle, opts: &SshCommand) -> Fallible<()> { let front_end_selection = opts.front_end.unwrap_or(config.front_end); let gui = front_end_selection.try_new()?; @@ -410,7 +410,7 @@ fn run_ssh(config: Arc, opts: &SshCommand) -> Fallible<()> { gui.run_forever() } -fn run_serial(config: Arc, opts: &SerialCommand) -> Fallible<()> { +fn run_serial(config: config::ConfigHandle, opts: &SerialCommand) -> Fallible<()> { let font_system = opts.font_system.unwrap_or(config.font_system); font_system.set_default(); @@ -437,7 +437,7 @@ fn run_serial(config: Arc, opts: &SerialCommand) -> Fallible<()> gui.run_forever() } -fn client_domains(config: &Arc) -> Vec { +fn client_domains(config: &config::ConfigHandle) -> Vec { let mut domains = vec![]; for unix_dom in &config.unix_domains { domains.push(ClientDomainConfig::Unix(unix_dom.clone())); @@ -453,7 +453,7 @@ fn client_domains(config: &Arc) -> Vec { domains } -fn run_mux_client(config: Arc, opts: &ConnectCommand) -> Fallible<()> { +fn run_mux_client(config: config::ConfigHandle, opts: &ConnectCommand) -> Fallible<()> { let client_config = client_domains(&config) .into_iter() .find(|c| c.name() == opts.domain_name) @@ -500,7 +500,7 @@ fn run_mux_client(config: Arc, opts: &ConnectCommand) -> Fallibl gui.run_forever() } -fn run_terminal_gui(config: Arc, opts: &StartCommand) -> Fallible<()> { +fn run_terminal_gui(config: config::ConfigHandle, opts: &StartCommand) -> Fallible<()> { #[cfg(unix)] { if opts.daemonize {