diff --git a/src/main.rs b/src/main.rs index f14cf6a..343cd75 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,7 +27,7 @@ use breadx::{ use lazy_static::lazy_static; -use tokio::sync::mpsc::unbounded_channel; +use tokio::sync::mpsc; mod config; mod msg_listener; @@ -41,8 +41,8 @@ pub enum XcrabError { Io(std::io::Error), Toml(toml::de::Error), Var(std::env::VarError), - FromStr(String), ClientDoesntExist, + Custom(String), } impl From for XcrabError { @@ -71,7 +71,7 @@ impl From for XcrabError { impl From for XcrabError { fn from(v: String) -> Self { - Self::FromStr(v) + Self::Custom(v) } } @@ -91,7 +91,7 @@ impl Display for XcrabError { 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::Custom(fe) => Display::fmt(fe, f)?, Self::ClientDoesntExist => Display::fmt("client didn't exist", f)?, } @@ -137,7 +137,7 @@ async fn main() -> Result<()> { conn.ungrab_server_async().await?; - let (send, mut recv) = unbounded_channel(); + let (send, mut recv) = mpsc::unbounded_channel(); tokio::spawn(msg_listener::listener_task( CONFIG.msg.clone().unwrap_or_default().socket_path, diff --git a/src/msg_listener.rs b/src/msg_listener.rs index d5311aa..04b5fbb 100644 --- a/src/msg_listener.rs +++ b/src/msg_listener.rs @@ -17,6 +17,7 @@ use crate::x11::client::XcrabWindowManager; use crate::Result; use breadx::AsyncDisplay; use std::path::Path; +use std::str::FromStr; use tokio::io::AsyncReadExt; use tokio::net::UnixListener; use tokio::sync::mpsc::UnboundedSender; @@ -67,20 +68,32 @@ pub enum Action { Close, } -impl std::str::FromStr for Action { +impl FromStr for Action { + // TODO: why + // there are conventions for this you know, like making it `impl Error`!!! + // thats why its *not* recommended to use () if there is no meaningful error data! 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 Err(format!("Unknown action: {}", v[0])), - }; + macro_rules! eq_ignore_ascii_case_match { + (($scrutinee:expr) { $($s:literal => $v:expr,)+ else => $else:expr $(,)? }) => { + $( + if $scrutinee.eq_ignore_ascii_case($s) { + $v + } else + )+ { + $else + } + }; + } - Ok(a) + eq_ignore_ascii_case_match!((s) { + "close" => Ok(Close), + else => Err(format!("Unknown action: {}", s)), + }) } } @@ -92,9 +105,11 @@ impl Action { ) -> Result<()> { #[allow(clippy::enum_glob_use)] use Action::*; + match self { Close => manager.destroy_focused_client(conn).await?, } + Ok(()) } } diff --git a/src/x11/client.rs b/src/x11/client.rs index 29fdf0d..f7e8575 100644 --- a/src/x11/client.rs +++ b/src/x11/client.rs @@ -137,14 +137,12 @@ enum RectangleContents { Client(Client), } -#[allow(clippy::module_name_repetitions)] #[derive(Debug, Clone)] struct Pane { children: Vec, directionality: Directionality, } -#[allow(clippy::module_name_repetitions)] #[derive(Debug, Clone, Copy)] struct Client { frame: FramedWindow,