From d7d549a4c886d082a56e51b7421414f77319c670 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fe=CC=81lix=20Saparelli?= Date: Sun, 22 Aug 2021 22:05:09 +1200 Subject: [PATCH] Add convenience modifiers on RuntimeConfig ourselves It's not exactly a builder, and this lets us flatten all the options at the top level instead of requiring the user to dig deeper into the action, fs, etc modules' WorkingData structs. --- lib/examples/print_out.rs | 13 ++++---- lib/src/config.rs | 63 ++++++++++++++++++++++++++++++++------ lib/tests/error_handler.rs | 13 ++++---- 3 files changed, 66 insertions(+), 23 deletions(-) diff --git a/lib/examples/print_out.rs b/lib/examples/print_out.rs index 13c6f75..5edf48c 100644 --- a/lib/examples/print_out.rs +++ b/lib/examples/print_out.rs @@ -12,16 +12,15 @@ async fn main() -> color_eyre::eyre::Result<()> { tracing_subscriber::fmt::init(); color_eyre::install()?; - let init = InitConfigBuilder::default() - .error_handler(Box::new(|err| async move { - eprintln!("Watchexec Runtime Error: {}", err); - Ok::<(), std::convert::Infallible>(()) - })) - .build()?; + let mut init = InitConfigBuilder::default(); + init.on_error(|err| async move { + eprintln!("Watchexec Runtime Error: {}", err); + Ok::<(), std::convert::Infallible>(()) + }); let runtime = RuntimeConfig::default(); - let wx = Watchexec::new(init, runtime)?; + let wx = Watchexec::new(init.build()?, runtime)?; wx.main(); sleep(Duration::from_secs(1)).await; diff --git a/lib/src/config.rs b/lib/src/config.rs index d319731..a8e4215 100644 --- a/lib/src/config.rs +++ b/lib/src/config.rs @@ -1,9 +1,11 @@ -use std::{fmt, sync::Arc, time::Duration}; +//! Configuration and builders for [`crate::Watchexec`]. + +use std::{fmt, path::Path, sync::Arc, time::Duration}; use atomic_take::AtomicTake; use derive_builder::Builder; -use crate::{action::Action, error::RuntimeError, handler::Handler}; +use crate::{action::Action, command::Shell, error::RuntimeError, fs::Watcher, handler::Handler}; /// Runtime configuration for [`Watchexec`][crate::Watchexec]. /// @@ -28,6 +30,38 @@ pub struct RuntimeConfig { pub action: crate::action::WorkingData, } +impl RuntimeConfig { + /// Set the pathset to be watched. + pub fn pathset(&mut self, pathset: I) -> &mut Self + where + I: IntoIterator, + P: AsRef, + { + self.fs.pathset = pathset.into_iter().map(|p| p.as_ref().into()).collect(); + self + } + + /// Set the file watcher type to use. + pub fn file_watcher(&mut self, watcher: Watcher) -> &mut Self { + self.fs.watcher = watcher; + self + } + + /// Set the action throttle. + pub fn action_throttle(&mut self, throttle: impl Into) -> &mut Self { + self.action.throttle = throttle.into(); + self + } + + /// Set the action handler. + /// + /// TODO: notes on how outcome is read immediately after handler returns + pub fn on_action(&mut self, handler: impl Handler + Send + 'static) -> &mut Self { + self.action.action_handler = Arc::new(AtomicTake::new(Box::new(handler) as _)); + self + } +} + /// Initialisation configuration for [`Watchexec`][crate::Watchexec]. /// /// This is used only for constructing the instance. @@ -45,20 +79,21 @@ pub struct InitConfig { /// `()` handler is used, which discards all errors. /// /// If the handler errors, [_that_ error][crate::error::RuntimeError::Handler] is immediately - /// given to the handler. If that second handler call errors as well, its error is ignored. + /// given to the handler. If this second handler call errors as well, its error is ignored. /// /// # Examples /// /// ``` /// # use std::convert::Infallible; /// # use watchexec::config::InitConfigBuilder; - /// InitConfigBuilder::default() - /// .error_handler(Box::new(|err| async move { - /// tracing::error!("{}", err); - /// Ok::<(), Infallible>(()) - /// })); + /// let mut init = InitConfigBuilder::default(); + /// init.on_error(|err| async move { + /// tracing::error!("{}", err); + /// Ok::<(), Infallible>(()) + /// }); /// ``` - #[builder(default = "Box::new(()) as _")] + #[builder(private, default = "Box::new(()) as _")] + // TODO: figure out how to remove the builder setter entirely pub error_handler: Box + Send>, /// Internal: the buffer size of the channel which carries runtime errors. @@ -76,6 +111,16 @@ pub struct InitConfig { pub event_channel_size: usize, } +impl InitConfigBuilder { + /// Set the runtime error handler. + /// + /// See the [documentation on the field][InitConfig#structfield.error_handler] for more details. + pub fn on_error(&mut self, handler: impl Handler + Send + 'static) -> &mut Self { + self.error_handler = Some(Box::new(handler) as _); + self + } +} + impl fmt::Debug for InitConfig { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("InitConfig") diff --git a/lib/tests/error_handler.rs b/lib/tests/error_handler.rs index 21c55e5..2160dfa 100644 --- a/lib/tests/error_handler.rs +++ b/lib/tests/error_handler.rs @@ -11,16 +11,15 @@ async fn main() -> color_eyre::eyre::Result<()> { tracing_subscriber::fmt::init(); color_eyre::install()?; - let init = InitConfigBuilder::default() - .error_handler(Box::new(|err| async move { - eprintln!("Watchexec Runtime Error: {}", err); - Ok::<(), std::convert::Infallible>(()) - })) - .build()?; + let mut init = InitConfigBuilder::default(); + init.on_error(|err| async move { + eprintln!("Watchexec Runtime Error: {}", err); + Ok::<(), std::convert::Infallible>(()) + }); let runtime = RuntimeConfig::default(); - let wx = Watchexec::new(init, runtime)?; + let wx = Watchexec::new(init.build()?, runtime)?; wx.main(); // TODO: induce an error here