Add methods to configure tagger filter

This commit is contained in:
Félix Saparelli 2021-09-28 22:21:51 +13:00
parent 4fda3c477b
commit f3c74bd151
No known key found for this signature in database
GPG Key ID: B948C4BAE44FC474
2 changed files with 90 additions and 0 deletions

View File

@ -11,6 +11,7 @@ use crate::event::{Event, Tag};
use crate::filter::Filterer;
mod parse;
pub mod swaplock;
pub struct TaggedFilterer {
/// The directory the project is in, its "root".
@ -102,6 +103,14 @@ pub struct Filter {
}
impl TaggedFilterer {
pub fn new(root: impl Into<PathBuf>, workdir: impl Into<PathBuf>) -> Arc<Self> {
Arc::new(Self {
root: root.into(),
workdir: workdir.into(),
filters: swaplock::SwapLock::new(HashMap::new()),
})
}
fn match_tag(&self, filter: &Filter, tag: &Tag) -> Result<Option<bool>, RuntimeError> {
trace!(?tag, matcher=?filter.on, "matching filter to tag");
match (tag, filter.on) {
@ -124,6 +133,44 @@ impl TaggedFilterer {
.map(Some)
}
pub async fn add_filter(&self, filter: Filter) -> Result<(), RuntimeError> {
debug!(?filter, "adding filter to filterer");
self.filters
.change(|filters| {
filters.entry(filter.on).or_default().push(filter);
})
.await
.map_err(|err| RuntimeError::FilterChange { action: "add", err })?;
Ok(())
}
pub async fn remove_filter(&self, filter: &Filter) -> Result<(), RuntimeError> {
debug!(?filter, "removing filter from filterer");
self.filters
.change(|filters| {
filters
.entry(filter.on)
.or_default()
.retain(|f| f != filter);
})
.await
.map_err(|err| RuntimeError::FilterChange {
action: "remove",
err,
})?;
Ok(())
}
pub async fn clear_filters(&self) -> Result<(), RuntimeError> {
debug!("removing all filters from filterer");
self.filters
.replace(Default::default())
.await
.map_err(|err| RuntimeError::FilterChange {
action: "clear all",
err,
})?;
Ok(())
}
}

View File

@ -0,0 +1,43 @@
use std::fmt;
use tokio::sync::watch::{channel, error::SendError, Receiver, Ref, Sender};
pub struct SwapLock<T: Clone> {
r: Receiver<T>,
s: Sender<T>,
}
impl<T> SwapLock<T>
where
T: Clone,
{
pub fn new(inner: T) -> Self {
let (s, r) = channel(inner);
Self { r, s }
}
pub fn borrow(&self) -> Ref<'_, T> {
self.r.borrow()
}
pub async fn change(&self, f: impl FnOnce(&mut T)) -> Result<(), SendError<T>> {
let mut new = self.r.borrow().clone();
f(&mut new);
self.s.send(new)
}
pub async fn replace(&self, new: T) -> Result<(), SendError<T>> {
self.s.send(new)
}
}
impl<T> fmt::Debug for SwapLock<T>
where
T: fmt::Debug + Clone,
{
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
f.debug_struct("SwapLock")
.field("(watch)", &self.r)
.finish()
}
}