From 296c807c72f8fd13b80d0a48aca3dd938fdff6f8 Mon Sep 17 00:00:00 2001 From: Yash Karandikar Date: Wed, 6 Jul 2022 21:47:37 +0530 Subject: [PATCH] Deserialize and eval Action --- src/config.rs | 23 ++++++++++++++++++++++- src/main.rs | 22 +++++++++++++--------- src/msg_listener.rs | 27 +++++++++++++++++++++------ 3 files changed, 56 insertions(+), 16 deletions(-) diff --git a/src/config.rs b/src/config.rs index 6d8e0e9..b8a63df 100644 --- a/src/config.rs +++ b/src/config.rs @@ -15,6 +15,7 @@ #![allow(dead_code, clippy::module_name_repetitions)] +use crate::msg_listener::Action; use crate::Result; use breadx::auto::xproto::KeyButMask; use serde::{ @@ -32,8 +33,9 @@ pub struct XcrabConfig { gap_size: Option, outer_gap_size: Option, pub msg: Option, + #[allow(clippy::zero_sized_map_values)] // TODO: Action will be expanded in the future #[serde(default)] - pub binds: HashMap, + pub binds: HashMap, } #[derive(Clone, Debug, Deserialize)] @@ -105,6 +107,25 @@ fn get_home() -> Result { Ok(std::env::var("HOME")?) } +struct ActionVisitor; +impl<'de> Visitor<'de> for ActionVisitor { + type Value = Action; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("a valid WM action") + } + + fn visit_str(self, value: &str) -> std::result::Result { + value.parse().map_err(|s| E::custom(s)) + } +} + +impl<'de> Deserialize<'de> for Action { + fn deserialize>(deserializer: D) -> std::result::Result { + deserializer.deserialize_str(ActionVisitor) + } +} + #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] pub struct Keybind { pub key: char, diff --git a/src/main.rs b/src/main.rs index 3fe6ce7..a4be610 100644 --- a/src/main.rs +++ b/src/main.rs @@ -41,6 +41,7 @@ pub enum XcrabError { Io(std::io::Error), Toml(toml::de::Error), Var(std::env::VarError), + FromStr(String), ClientDoesntExist, } @@ -68,6 +69,12 @@ impl From for XcrabError { } } +impl From for XcrabError { + fn from(v: String) -> Self { + Self::FromStr(v) + } +} + lazy_static! { pub static ref CONFIG: config::XcrabConfig = config::load_file().unwrap_or_default(); } @@ -75,10 +82,11 @@ lazy_static! { impl Display for XcrabError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Self::Bread(be) => Display::fmt(&be, f)?, - Self::Io(ie) => Display::fmt(&ie, f)?, - Self::Toml(te) => Display::fmt(&te, f)?, - Self::Var(ve) => Display::fmt(&ve, f)?, + Self::Bread(be) => Display::fmt(be, f)?, + Self::Io(ie) => Display::fmt(ie, f)?, + Self::Toml(te) => Display::fmt(te, f)?, + Self::Var(ve) => Display::fmt(ve, f)?, + Self::FromStr(fe) => Display::fmt(fe, f)?, Self::ClientDoesntExist => Display::fmt("client didn't exist", f)?, } @@ -212,11 +220,7 @@ async fn process_event( { for (&bind, action) in &CONFIG.binds { if bind.key == c && bind.mods == ev.state { - // TODO: parse action into an enum & match it - if action == "close" { - manager.destroy_focused_client(conn).await?; - return Ok(()); - } + action.eval(manager, conn).await?; } } } diff --git a/src/msg_listener.rs b/src/msg_listener.rs index df2f2e3..d5311aa 100644 --- a/src/msg_listener.rs +++ b/src/msg_listener.rs @@ -55,10 +55,9 @@ pub async fn on_recv( manager: &mut XcrabWindowManager, conn: &mut Dpy, ) -> Result<()> { - match &*data { - "close" => manager.destroy_focused_client(conn).await?, - _ => println!("{}", data), - } + let a: Action = data.parse()?; + a.eval(manager, conn).await?; + Ok(()) } @@ -68,18 +67,34 @@ pub enum Action { Close, } -impl FromStr for Action { +impl std::str::FromStr for Action { type Err = String; fn from_str(s: &str) -> std::result::Result { + #[allow(clippy::enum_glob_use)] use Action::*; let v: Vec = s.split(' ').map(str::to_ascii_lowercase).collect(); let a = match v[0].as_str() { "close" => Close, - _ => return format!("Unknown action: {}", v[0]), + _ => return Err(format!("Unknown action: {}", v[0])), }; Ok(a) } } + +impl Action { + pub async fn eval( + &self, + manager: &mut XcrabWindowManager, + conn: &mut Dpy, + ) -> Result<()> { + #[allow(clippy::enum_glob_use)] + use Action::*; + match self { + Close => manager.destroy_focused_client(conn).await?, + } + Ok(()) + } +}