From b3530d7c4a102935fa26498a160ee1dc6c1e9c03 Mon Sep 17 00:00:00 2001 From: delta Date: Fri, 4 Jul 2025 00:38:29 +0200 Subject: :3 --- .config/awesome/quarrel/native/src/http.rs | 22 ++++ .../quarrel/native/src/lenses/application.rs | 85 ++++++------ .../quarrel/native/src/lenses/calculator.rs | 47 ++++--- .config/awesome/quarrel/native/src/lenses/entry.rs | 19 --- .config/awesome/quarrel/native/src/lenses/mod.rs | 78 ++++++++++- .config/awesome/quarrel/native/src/lib.rs | 14 +- .config/awesome/quarrel/native/src/moondrop.rs | 3 + .config/awesome/quarrel/native/src/mpd.rs | 142 --------------------- .config/awesome/quarrel/native/src/net/mod.rs | 4 +- .config/awesome/quarrel/native/src/util.rs | 3 +- 10 files changed, 190 insertions(+), 227 deletions(-) create mode 100644 .config/awesome/quarrel/native/src/http.rs delete mode 100644 .config/awesome/quarrel/native/src/lenses/entry.rs create mode 100644 .config/awesome/quarrel/native/src/moondrop.rs delete mode 100644 .config/awesome/quarrel/native/src/mpd.rs (limited to '.config/awesome/quarrel/native/src') diff --git a/.config/awesome/quarrel/native/src/http.rs b/.config/awesome/quarrel/native/src/http.rs new file mode 100644 index 0000000..e995556 --- /dev/null +++ b/.config/awesome/quarrel/native/src/http.rs @@ -0,0 +1,22 @@ +use ureq::{Agent, agent}; +use std::{sync::LazyLock, thread}; +use mlua::prelude::*; + +static AGENT: LazyLock = LazyLock::new(|| agent()); + +struct Stream(ureq::Body); + +pub fn get(_: &Lua, url: String, callback: LuaFunction, err_callback: LuaFunction) -> LuaResult<()> { + thread::spawn(|| { + match AGENT.get(url).call() { + Ok(body) => { + + }, + Err(err) => { + err_callback.call(err.to_string()); + } + } + // callback.call::<>() + }); + Ok(()) +} diff --git a/.config/awesome/quarrel/native/src/lenses/application.rs b/.config/awesome/quarrel/native/src/lenses/application.rs index 72aba8d..89b7bb4 100644 --- a/.config/awesome/quarrel/native/src/lenses/application.rs +++ b/.config/awesome/quarrel/native/src/lenses/application.rs @@ -1,6 +1,5 @@ use std::{ - fs::read_dir, - path::PathBuf, + fs::read_dir, path::PathBuf }; use freedesktop_entry_parser as fd; @@ -8,12 +7,54 @@ use mlua::prelude::*; use rayon::prelude::*; use url::Url; -use crate::lenses::entry::{ - entries_to_lua_table, +use crate::lenses::{ Entry, + Lense, + Cache }; -fn parse_entry(entry: &fd::Entry, path: &PathBuf) -> Result { +#[derive(Default)] +pub struct Application(pub Cache); + +impl Lense for Application { + const NAME: &str = "Application"; + + fn get_cache(&self) -> &Cache { + &self.0 + } + + fn set_cache(&mut self, cache: Cache) { + self.0 = cache; + } + + fn query(_: &Lua, input: String) -> Result, anyhow::Error> { + let applications_dir = "/usr/share/applications"; + let entries = read_dir(applications_dir)? + .map(|result| result.map(|e| e.path())) + .collect::, std::io::Error>>()?; + + let parsed_entries: Vec = entries + .into_par_iter() + .filter(|path| path.extension().is_some_and(|ext| ext == "desktop")) + .filter_map(|path| { + parse_entry(path).ok().flatten() + }) + .collect(); + + Ok( + parsed_entries + .into_iter() + .filter(|entry| entry.message.to_lowercase().contains(&input.to_lowercase())) + .collect(), + ) + } +} + +fn parse_entry(path: PathBuf) -> Result, ()> { + let Ok(entry) = fd::parse_entry(&path) else { + return Err(()) + }; + let section = entry.section("Desktop Entry"); let name = section.attr("Name").ok_or(())?.to_string(); @@ -38,14 +79,14 @@ fn parse_entry(entry: &fd::Entry, path: &PathBuf) -> Result { } } 'c' => new_exec.replace_range(index..index + 2, &name), - 'k' => new_exec.replace_range(index..index + 2, Url::from_file_path(path)?.as_str()), + 'k' => new_exec.replace_range(index..index + 2, Url::from_file_path(&path)?.as_str()), 'f' | 'u' | 'v' | 'm' | 'd' | 'n' => new_exec.replace_range(index..index + 2, ""), _ => continue, } } - Ok(Entry { + Ok(Some(Entry { message: name, exec: Some(( new_exec, @@ -55,33 +96,5 @@ fn parse_entry(entry: &fd::Entry, path: &PathBuf) -> Result { .parse() .map_err(drop)?, )), - provider: "Application".to_string(), - }) -} - -pub fn query(lua: &Lua, input: String) -> LuaResult { - let applications_dir = "/usr/share/applications"; - let entries = read_dir(applications_dir)? - .map(|result| result.map(|e| e.path())) - .collect::, std::io::Error>>()?; - - let parsed_entries: Vec = entries - .into_par_iter() - .filter(|path| matches!(path.extension(), Some(ext) if ext == "desktop")) - .filter_map(|path| { - let Ok(entry) = fd::parse_entry(&path) else { - return None - }; - - parse_entry(&entry, &path).ok() - }) - .collect(); - - Ok(entries_to_lua_table( - parsed_entries - .into_iter() - .filter(|entry| entry.message.to_lowercase().contains(&input.to_lowercase())) - .collect(), - lua, - )) + })) } diff --git a/.config/awesome/quarrel/native/src/lenses/calculator.rs b/.config/awesome/quarrel/native/src/lenses/calculator.rs index 07f1ee2..640bdeb 100644 --- a/.config/awesome/quarrel/native/src/lenses/calculator.rs +++ b/.config/awesome/quarrel/native/src/lenses/calculator.rs @@ -5,25 +5,36 @@ use cpc::{ }; use mlua::prelude::*; -use crate::lenses::entry::{ - entries_to_lua_table, +use crate::lenses::{ Entry, + Cache, + Lense }; -pub fn query(lua: &Lua, input: String) -> LuaResult { - let result = match eval(input.trim(), true, Unit::Celsius, false) { - Ok(result) => { - format!("{result}") - } - Err(_) => return lua.create_table(), - }; - - Ok(entries_to_lua_table( - vec![Entry { - message: result, - exec: None, - provider: "Calculator".to_string(), - }], - lua, - )) +pub struct Calculator; + +impl Lense for Calculator { + const NAME: &str = "Calculator"; + + fn get_cache(&self) -> &Cache { + &Cache::Stale + } + + fn set_cache(&mut self, _: Cache) {} + + fn query(_: &Lua, input: String) -> Result, anyhow::Error> { + let result = match eval(input.trim(), true, Unit::Celsius, false) { + Ok(result) => { + format!("{result}") + } + Err(err) => { return Err(anyhow::anyhow!(err)); }, + }; + + Ok(vec![Entry { + message: result, + exec: None, + }; 1] + ) + } } + diff --git a/.config/awesome/quarrel/native/src/lenses/entry.rs b/.config/awesome/quarrel/native/src/lenses/entry.rs deleted file mode 100644 index c7ac09e..0000000 --- a/.config/awesome/quarrel/native/src/lenses/entry.rs +++ /dev/null @@ -1,19 +0,0 @@ -use mlua::{ - prelude::*, - LuaSerdeExt, -}; -use serde::Serialize; - -#[derive(Serialize, Clone)] -pub struct Entry { - pub message: String, - pub exec: Option<(String, bool)>, - pub provider: String, -} - -pub fn entries_to_lua_table(entries: Vec, lua: &Lua) -> LuaTable { - match lua.to_value(&entries).unwrap() { - LuaValue::Table(t) => t, - _ => unreachable!(), - } -} diff --git a/.config/awesome/quarrel/native/src/lenses/mod.rs b/.config/awesome/quarrel/native/src/lenses/mod.rs index d0db6f7..6eb5b58 100644 --- a/.config/awesome/quarrel/native/src/lenses/mod.rs +++ b/.config/awesome/quarrel/native/src/lenses/mod.rs @@ -1,3 +1,79 @@ pub mod application; pub mod calculator; -pub mod entry; + +use mlua::{ + prelude::*, + LuaSerdeExt, +}; +use serde::{Serialize, Deserialize}; + +#[derive(Deserialize, Serialize, Clone)] +pub struct Entry { + pub message: String, + pub exec: Option<(String, bool)>, +} + +impl IntoLua for Entry { + fn into_lua(self, lua: &Lua) -> LuaResult { + return lua.to_value(&self) + } +} + +impl FromLua for Entry { + fn from_lua(value: LuaValue, lua: &Lua) -> LuaResult { + return lua.from_value(value); + } +} + +#[derive(Default)] +pub enum Cache { + Valid(Vec), + #[default] + Stale +} + +pub struct _Lense(pub T); + +pub trait Lense { + const NAME: &'static str; + + fn set_cache(&mut self, cache: Cache); + fn get_cache(&self) -> &Cache; + + fn query(lua: &Lua, input: String) -> Result, anyhow::Error>; +} + +impl LuaUserData for _Lense { + fn add_fields>(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| { + // 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("name", T::NAME); + } + + fn add_methods>(methods: &mut M) { + methods.add_method_mut("query", |lua, this, input: String| { + return Ok(match this.0.get_cache() { + Cache::Valid(entries) => entries.clone(), + Cache::Stale => { + let entries = T::query(lua, input).map_err(LuaError::external)?; + this.0.set_cache(Cache::Valid(entries.clone())); + entries + } + }); + }); + + methods.add_method_mut("mark_stale", |_, this, _: ()| Ok(this.0.set_cache(Cache::Stale)) ); + } +} diff --git a/.config/awesome/quarrel/native/src/lib.rs b/.config/awesome/quarrel/native/src/lib.rs index 472313e..4f1780d 100644 --- a/.config/awesome/quarrel/native/src/lib.rs +++ b/.config/awesome/quarrel/native/src/lib.rs @@ -1,29 +1,29 @@ mod lenses; -mod mpd; mod net; +// mod http; mod util; +mod moondrop; use mlua::prelude::*; +use lenses::{ _Lense }; #[mlua::lua_module] fn qnative(lua: &Lua) -> LuaResult { let lenses = lua.create_table()?; - lenses.set("1", lua.create_function(lenses::calculator::query)?)?; - lenses.set("2", lua.create_function(lenses::application::query)?)?; + lenses.push(_Lense(lenses::calculator::Calculator))?; + lenses.push(_Lense(lenses::application::Application::default()))?; + // lenses.set("1", lua.create_function(lenses::calculator::Application::query)?)?; + // lenses.set("2", lua.create_function(lenses::application::Application::query)?)?; let util = lua.create_table()?; util.set("decode_html", lua.create_function(util::decode_html)?)?; util.set("open_file", lua.create_function(util::FileHandle::new)?)?; - let mpd = lua.create_table()?; - mpd.set("init", lua.create_function(mpd::init)?)?; - let net = lua.create_table()?; net.set("get_essid", lua.create_function(net::get_first_essid)?)?; let exports = lua.create_table()?; exports.set("lenses", lenses)?; - exports.set("mpd", mpd)?; exports.set("net", net)?; exports.set("util", util)?; diff --git a/.config/awesome/quarrel/native/src/moondrop.rs b/.config/awesome/quarrel/native/src/moondrop.rs new file mode 100644 index 0000000..d416ef6 --- /dev/null +++ b/.config/awesome/quarrel/native/src/moondrop.rs @@ -0,0 +1,3 @@ +use mdrop::Moondrop; + + diff --git a/.config/awesome/quarrel/native/src/mpd.rs b/.config/awesome/quarrel/native/src/mpd.rs deleted file mode 100644 index 08c9e42..0000000 --- a/.config/awesome/quarrel/native/src/mpd.rs +++ /dev/null @@ -1,142 +0,0 @@ -use std::{ - ffi::c_void, - fs::File, - net::TcpStream, - path::PathBuf, - sync::mpsc::channel, -}; - -use dirs::home_dir; -use gdk_pixbuf::{ - ffi::GdkPixbuf, - glib::translate::IntoGlibPtr, - traits::PixbufLoaderExt, - Pixbuf, - PixbufLoader, -}; -use mlua::{ - prelude::*, - LuaSerdeExt, -}; -use mpd::Client; -use once_cell::sync::Lazy; -use symphonia::{ - core::{ - formats::FormatOptions, - io::{ - MediaSourceStream, - MediaSourceStreamOptions, - }, - meta::MetadataOptions, - probe::Hint, - }, - default::get_probe, -}; - -static MPD_MUSIC_PATH: Lazy = Lazy::new(|| { - [ - home_dir().expect("home directory should be set"), - "Music".into(), - ] - .iter() - .collect() -}); - -static COVER_FORMATS: [&str; 2] = ["png", "jpg"]; - -pub struct Connection(Client); - -impl LuaUserData for Connection { - fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { - methods.add_method_mut("status", |lua, this: &mut Connection, (): ()| { - lua.to_value(&this.0.status().map_err(LuaError::external)?) - }); - - methods.add_method_mut("song", |lua, this: &mut Connection, (): ()| { - Ok( - if let Some(song) = this.0.currentsong().map_err(LuaError::external)? { - lua.to_value(&song)? - } else { - LuaNil - }, - ) - }); - - methods.add_method( - "get_cover_pixbuf", - |_, _: &Connection, file: String| { - let song_path = MPD_MUSIC_PATH.join(file); - let mut has_external_cover = false; - let mut cover_path = PathBuf::new(); - - for format in COVER_FORMATS { - let cover = song_path - .parent() - .unwrap() - .to_owned() - .join(format!("cover.{}", format)); - if cover.exists() { - has_external_cover = cover.exists(); - cover_path = cover; - break; - } - } - - let mss = MediaSourceStream::new( - Box::new(File::open(song_path)?), - MediaSourceStreamOptions::default(), - ); - - let mut probed = get_probe() - .format( - &Hint::default(), - mss, - &FormatOptions::default(), - &MetadataOptions::default(), - ) - .map_err(LuaError::external)?; - - let visuals; - - if let Some(metadata) = probed.format.metadata().skip_to_latest() { - visuals = metadata.visuals(); - if visuals.is_empty() && has_external_cover { - let pixbuf = Pixbuf::from_file(cover_path).map_err(LuaError::external)?; - - return Ok(( - Some(LuaLightUserData(unsafe { - >::into_glib_ptr(pixbuf) - .cast::() - })), - Some(true), - )); - } - - let loader = PixbufLoader::new(); - loader - .write(visuals.first().unwrap().data.as_ref()) - .map_err(LuaError::external)?; - loader.close().map_err(LuaError::external)?; - - return Ok(( - Some(LuaLightUserData(unsafe { - >::into_glib_ptr( - loader.pixbuf().expect("Pixbuf should be initialized"), - ) - .cast::() - })), - Some(false), - )); - } - - Ok((None, None)) - }, - ); - } -} - -pub fn init(_: &Lua, _: ()) -> LuaResult { - Ok(Connection( - Client::connect("localhost:6600").map_err(LuaError::external)?, - )) -} diff --git a/.config/awesome/quarrel/native/src/net/mod.rs b/.config/awesome/quarrel/native/src/net/mod.rs index 96c853e..dbd87b9 100644 --- a/.config/awesome/quarrel/native/src/net/mod.rs +++ b/.config/awesome/quarrel/native/src/net/mod.rs @@ -9,7 +9,7 @@ use std::{ c_void, }, mem::size_of, - os::fd::RawFd, + os::fd::{IntoRawFd, RawFd}, }; use mlua::prelude::*; @@ -108,7 +108,7 @@ fn get_first_socket() -> LuaResult { for family in families { if let Ok(socket) = open_socket(family, SockType::Datagram, SockFlag::empty(), None) { - return Ok(socket); + return Ok(socket.into_raw_fd()); } } diff --git a/.config/awesome/quarrel/native/src/util.rs b/.config/awesome/quarrel/native/src/util.rs index 85a2574..41096d8 100644 --- a/.config/awesome/quarrel/native/src/util.rs +++ b/.config/awesome/quarrel/native/src/util.rs @@ -1,7 +1,6 @@ use std::{ cell::RefCell, fs::File, - fs::OpenOptions, io::{ Read, Seek, @@ -49,7 +48,7 @@ enum StringOrNumber { pub struct FileHandle(Rc>); impl LuaUserData for FileHandle { - fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { + fn add_methods<'lua, M: LuaUserDataMethods>(methods: &mut M) { methods.add_method("read", |lua, this: &FileHandle, mode: String| { let content = this.read()?; Ok(lua.to_value(&match ReadMode::from_str(&mode).unwrap() { -- cgit v1.2.3