From c9023294887ec5fe80d4cd87fa42330b9c5f84a8 Mon Sep 17 00:00:00 2001 From: "Anna (navi) Figueiredo Gomes" Date: Mon, 25 Sep 2023 12:59:26 +0200 Subject: handle errors propperly so it doesn't randomly crash (i'm actually learning rust wtf) Signed-off-by: Anna (navi) Figueiredo Gomes --- src/main.rs | 85 ++++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 59 insertions(+), 26 deletions(-) diff --git a/src/main.rs b/src/main.rs index 280afb1..3c35738 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,36 +1,68 @@ use swayipc::{Connection, WindowChange, EventType}; -use std::{env,fs::File, io::Read}; +use std::{env,fs::File, io::{Read, self}, num, fmt::Display}; use regex::Regex; struct WindowHider { - term: String + term: String, + regex: Regex, +} + +enum Error { + IoError(io::Error), + ParseIntError(num::ParseIntError), + RegexParseError(i32), + SwayIpcError(swayipc::Error) +} + +impl From for Error { + fn from(value: io::Error) -> Self { + Self::IoError(value) + } +} + +impl From for Error { + fn from(value: num::ParseIntError) -> Self { + Self::ParseIntError(value) + } +} + +impl From for Error { + fn from(value: swayipc::Error) -> Self { + Self::SwayIpcError(value) + } +} + +impl Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Error::IoError(err) => err.fmt(f), + Error::ParseIntError(err) => err.fmt(f), + Error::SwayIpcError(err) => err.fmt(f), + Error::RegexParseError(pid) => write!(f, "Failed to regex match for pid {pid}"), + } + } } impl WindowHider { - fn get_parent_term_pid(&self, pid: i32, is_root: bool) -> Option { - let mut file = String::new(); - File::open(format!("/proc/{pid}/stat")).expect("procfs stat doesn't exist").read_to_string(&mut file).unwrap(); - let re = Regex::new(r"\d+ \((.*)\) (\w) (\d+) \d+").unwrap().captures(&file).unwrap(); - let name = re.get(1).unwrap().as_str(); - let status = re.get(2).unwrap().as_str(); - let ppid = re.get(3).unwrap().as_str().parse::().unwrap(); - - println!("looking for {pid}. {name}, {status}, {ppid}"); + fn get_parent_term_pid(&self, pid: i32, is_root: bool) -> Result, Error> { + let mut buf = String::new(); + File::open(format!("/proc/{pid}/stat"))?.read_to_string(&mut buf)?; + + let Some((_, [name, ppid])) = self.regex.captures(&buf).map(|caps| caps.extract()) else { + return Err(Error::RegexParseError(pid)); + }; + + let ppid = ppid.parse::()?; + match name { - _ if name == self.term && !is_root => { - Some(pid) - }, - _ if name == "init" => { - None - } - _ => { - self.get_parent_term_pid(ppid, false) - } + "init" => Ok(None), + _ if name == self.term && !is_root => Ok(Some(pid)), + _ => self.get_parent_term_pid(ppid, false) } } - fn hide(&self, conn: &mut Connection, pid: i32) -> Result<(), swayipc::Error> { - let ppid = self.get_parent_term_pid(pid, true); + fn hide(&self, conn: &mut Connection, pid: i32) -> Result<(), Error> { + let ppid = self.get_parent_term_pid(pid, true)?; if let Some(ppid) = ppid { println!("found parent pid of {pid} as {ppid}"); conn.run_command(format!("[pid={ppid}] mark --add {pid}, move scratchpad"))?; @@ -38,7 +70,7 @@ impl WindowHider { Ok(()) } - fn show(&self, conn: &mut Connection, pid: i32) -> Result<(), swayipc::Error> { + fn show(&self, conn: &mut Connection, pid: i32) -> Result<(), Error> { conn.run_command(format!("[con_mark={pid}] move workspace current"))?; conn.run_command(format!("[con_mark={pid}] floating toggle"))?; Ok(()) @@ -59,7 +91,8 @@ fn main() -> Result<(), swayipc::Error> { } let wh = WindowHider { - term: args.remove(1) + term: args.remove(1), + regex: Regex::new(r"\d+ \((.*)\) \w (\d+) \d+").unwrap() }; for item in evs { @@ -70,14 +103,14 @@ fn main() -> Result<(), swayipc::Error> { if let Some(pid) = win.container.pid { match wh.hide(&mut conn, pid) { Ok(_) => {}, - Err(_) => println!("failed to hide terminal {pid}") + Err(err) => eprintln!("failed to hide terminal {pid}: {err}") }; } } else if win.change == WindowChange::Close { if let Some(pid) = win.container.pid { match wh.show(&mut conn, pid) { Ok(_) => {}, - Err(_) => println!("failed to show terminal {pid}") + Err(err) => eprintln!("failed to show terminal {pid}: {err}") }; } } -- cgit v1.2.3