diff options
Diffstat (limited to '.config/awesome/quarrel/native/src/lenses/mod.rs')
| -rw-r--r-- | .config/awesome/quarrel/native/src/lenses/mod.rs | 121 |
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))); } } |
