aboutsummaryrefslogtreecommitdiff
path: root/.config/awesome/quarrel/native/src/lenses/mod.rs
diff options
context:
space:
mode:
authordelta <darkussdelta@gmail.com>2025-10-29 16:35:38 +0100
committerdelta <darkussdelta@gmail.com>2025-10-29 16:35:38 +0100
commitd7c66522cf365f516babcfeb1d4a2d36c3ea41af (patch)
tree30c7d6103037b31170ae6d8fd58e3849e3cea823 /.config/awesome/quarrel/native/src/lenses/mod.rs
parentdf418700b7d776f03ee5b58daa2d497cddb45aca (diff)
a small refactor
Diffstat (limited to '.config/awesome/quarrel/native/src/lenses/mod.rs')
-rw-r--r--.config/awesome/quarrel/native/src/lenses/mod.rs121
1 files changed, 95 insertions, 26 deletions
diff --git a/.config/awesome/quarrel/native/src/lenses/mod.rs b/.config/awesome/quarrel/native/src/lenses/mod.rs
index 6eb5b58..bb7f727 100644
--- a/.config/awesome/quarrel/native/src/lenses/mod.rs
+++ b/.config/awesome/quarrel/native/src/lenses/mod.rs
@@ -1,13 +1,66 @@
pub mod application;
pub mod calculator;
+use std::sync::Arc;
+
+use itertools::Itertools;
use mlua::{
prelude::*,
LuaSerdeExt,
};
-use serde::{Serialize, Deserialize};
+use rayon::iter::FromParallelIterator;
+use serde::{
+ Deserialize,
+ Serialize,
+};
+
+#[derive(Clone, Debug)]
+pub enum Entries {
+ Multiple(Vec<Entry>),
+ Single(Entry),
+ None
+}
-#[derive(Deserialize, Serialize, Clone)]
+impl FromIterator<Entry> for Entries {
+ fn from_iter<T: IntoIterator<Item = Entry>>(iter: T) -> Self {
+ let mut iter = iter.into_iter();
+ match (iter.next(), iter.next()) {
+ (None, None) => Self::None,
+ (Some(first), None) => Self::Single(first),
+ (None, Some(_)) => unreachable!(),
+ (Some(first), Some(second)) => {
+ let mut vec = Vec::from([first, second]);
+ vec.extend(iter);
+ Self::Multiple(vec)
+ },
+ }
+ }
+}
+
+impl From<Vec<Entry>> for Entries {
+ fn from(entries: Vec<Entry>) -> Self {
+ match entries.len() {
+ 0 => Self::None,
+ 1 => {
+ let entry = entries.into_iter().exactly_one().unwrap();
+ Self::Single(entry)
+ },
+ _ => Self::Multiple(entries)
+ }
+ }
+}
+
+impl IntoLua for Entries {
+ fn into_lua(self, lua: &Lua) -> LuaResult<LuaValue> {
+ match self {
+ Entries::Multiple(entries) => entries.into_lua(lua),
+ Entries::Single(entry) => entry.into_lua(lua),
+ Entries::None => Ok(LuaValue::Nil)
+ }
+ }
+}
+
+#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct Entry {
pub message: String,
pub exec: Option<(String, bool)>,
@@ -15,7 +68,7 @@ pub struct Entry {
impl IntoLua for Entry {
fn into_lua(self, lua: &Lua) -> LuaResult<LuaValue> {
- return lua.to_value(&self)
+ return lua.to_value(&self);
}
}
@@ -25,55 +78,71 @@ impl FromLua for Entry {
}
}
-#[derive(Default)]
+#[derive(Default, Clone, Debug)]
pub enum Cache {
- Valid(Vec<Entry>),
+ Valid(Entries),
#[default]
- Stale
+ Stale,
}
-pub struct _Lense<T: Lense>(pub T);
+pub struct _Lense<T: Lense>(pub Arc<T>);
pub trait Lense {
const NAME: &'static str;
- fn set_cache(&mut self, cache: Cache);
- fn get_cache(&self) -> &Cache;
+ fn init() -> Arc<Self>;
+
+ fn set_cache(&self, cache: Cache);
+ fn get_cache(&self) -> Cache;
+
+ fn set_interrupt(&self, interrupt: bool);
+ fn get_interrupt(&self) -> bool;
- fn query(lua: &Lua, input: String) -> Result<Vec<Entry>, anyhow::Error>;
+ fn entries(&self, lua: &Lua, input: String) -> Result<Entries, anyhow::Error>;
+ fn filter(&self, entries: Entries, input: String) -> Entries {
+ let entry_contains = |entry: &Entry| {
+ entry.message.to_lowercase().contains(&input.to_lowercase())
+ };
+ match entries {
+ Entries::Multiple(entries) => entries.into_iter()
+ .filter(entry_contains)
+ .collect(),
+ Entries::Single(entry) => if entry_contains(&entry) { Entries::Single(entry) } else { Entries::None }
+ Entries::None => Entries::None
+ }
+ }
}
impl<T: Lense + 'static> LuaUserData for _Lense<T> {
fn add_fields<F: LuaUserDataFields<Self>>(fields: &mut F) {
- // fields.add_field_method_get("cache", |lua, this| {
- // let cache = this.0.get_cache();
- // match cache {
- // Cache::Valid(cache) => Ok(cache.clone().into_lua(lua)?),
- // Cache::Stale => Ok(LuaNil)
- // }
- // });
-
- // fields.add_field_method_set("cache", |_, this, cache: Vec<Entry>| {
- // Ok(this.0.set_cache(Cache::Valid(cache)))
- // });
-
- fields.add_field_method_get("stale", |_, this| Ok(matches!(this.0.get_cache(), Cache::Stale)));
+ fields.add_field_method_get("stale", |_, this| {
+ Ok(matches!(this.0.get_cache(), Cache::Stale))
+ });
fields.add_field("name", T::NAME);
}
fn add_methods<M: LuaUserDataMethods<Self>>(methods: &mut M) {
methods.add_method_mut("query", |lua, this, input: String| {
+ this.0.set_interrupt(false); // reset interrupt so that we can use the lense again
return Ok(match this.0.get_cache() {
- Cache::Valid(entries) => entries.clone(),
+ Cache::Valid(entries) => this.0.filter(entries.clone(), input),
Cache::Stale => {
- let entries = T::query(lua, input).map_err(LuaError::external)?;
+ let entries = this.0.entries(lua, input.clone()).map_err(LuaError::external)?;
+ let mut entries = this.0.filter(entries, input);
+ match entries {
+ Entries::Multiple(ref mut entries) => entries.sort_by(|a, b| a.message.cmp(&b.message)),
+ _ => {}
+ }
this.0.set_cache(Cache::Valid(entries.clone()));
entries
}
});
});
- methods.add_method_mut("mark_stale", |_, this, _: ()| Ok(this.0.set_cache(Cache::Stale)) );
+ methods.add_method_mut("mark_stale", |_, this, _: ()| {
+ Ok(this.0.set_cache(Cache::Stale))
+ });
+ methods.add_method_mut("interrupt", |_, this, _: ()| Ok(this.0.set_interrupt(true)));
}
}