update errors

This commit is contained in:
Alex Janka 2024-07-25 14:16:10 +10:00
parent 2a25fca874
commit a6ee8faf31
3 changed files with 46 additions and 43 deletions

1
Cargo.lock generated
View file

@ -662,6 +662,7 @@ dependencies = [
"pretty_env_logger", "pretty_env_logger",
"serde", "serde",
"swayipc-async", "swayipc-async",
"thiserror",
"tokio", "tokio",
"toml", "toml",
] ]

View file

@ -13,3 +13,4 @@ lab = "0.11.0"
directories = "5.0.1" directories = "5.0.1"
toml = "0.8.15" toml = "0.8.15"
serde = { version = "1.0.204", features = ["derive"] } serde = { version = "1.0.204", features = ["derive"] }
thiserror = "1.0.63"

View file

@ -2,27 +2,31 @@ use futures_util::StreamExt;
use lab::Lab; use lab::Lab;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug)] #[derive(thiserror::Error, Debug)]
struct NoMatchingConfig; enum Error {
#[error("no matching config")]
NoMatchingConfig,
#[error("couldnt parse hex")]
HexParse,
#[error(transparent)]
Swayipc(#[from] swayipc_async::Error),
#[error(transparent)]
Io(#[from] std::io::Error),
#[error("couldn't set cell")]
SetCell,
#[error(transparent)]
TomlDe(#[from] toml::de::Error),
#[error(transparent)]
TomlSer(#[from] toml::ser::Error),
}
impl std::fmt::Display for NoMatchingConfig { impl<T> From<tokio::sync::SetError<T>> for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn from(_: tokio::sync::SetError<T>) -> Self {
write!(f, "no config for client.focused") Self::SetCell
} }
} }
impl std::error::Error for NoMatchingConfig {} type Res<T> = Result<T, Error>;
#[derive(Debug)]
struct HexParse;
impl std::fmt::Display for HexParse {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "invalid hex colour")
}
}
impl std::error::Error for HexParse {}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
struct Config { struct Config {
@ -68,7 +72,7 @@ static DEFAULT_COLOURS_NO_INDICATOR: tokio::sync::OnceCell<String> =
static DEFAULT_BORDER: tokio::sync::OnceCell<Lab> = tokio::sync::OnceCell::const_new(); static DEFAULT_BORDER: tokio::sync::OnceCell<Lab> = tokio::sync::OnceCell::const_new();
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> { async fn main() -> Res<()> {
if std::env::var_os("RUST_LOG").is_none() { if std::env::var_os("RUST_LOG").is_none() {
std::env::set_var("RUST_LOG", "info"); std::env::set_var("RUST_LOG", "info");
} }
@ -109,9 +113,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
Ok(()) Ok(())
} }
fn parse_config() -> Result<(), Box<dyn std::error::Error>> { fn parse_config() -> Res<()> {
let dirs = directories::ProjectDirs::from("com", "alexjanka", "sway-flash-indicator") let dirs = directories::ProjectDirs::from("com", "alexjanka", "sway-flash-indicator")
.ok_or(NoMatchingConfig)?; .ok_or(Error::NoMatchingConfig)?;
let config_dir = dirs.config_dir(); let config_dir = dirs.config_dir();
if let Ok(false) = config_dir.try_exists() { if let Ok(false) = config_dir.try_exists() {
@ -137,21 +141,19 @@ fn parse_config() -> Result<(), Box<dyn std::error::Error>> {
Ok(()) Ok(())
} }
async fn get_sway_config( async fn get_sway_config(connection: &mut swayipc_async::Connection) -> Res<()> {
connection: &mut swayipc_async::Connection,
) -> Result<(), Box<dyn std::error::Error>> {
let config = connection.get_config().await?; let config = connection.get_config().await?;
let default_colours = config let default_colours = config
.config .config
.split('\n') .split('\n')
.find(|v| v.contains("client.focused")) .find(|v| v.contains("client.focused"))
.ok_or(NoMatchingConfig)? .ok_or(Error::NoMatchingConfig)?
.trim(); .trim();
let default_border = default_colours let default_border = default_colours
.split_whitespace() .split_whitespace()
.nth(2) .nth(2)
.ok_or(NoMatchingConfig)?; .ok_or(Error::NoMatchingConfig)?;
DEFAULT_BORDER.set(parse_hex(default_border)?)?; DEFAULT_BORDER.set(parse_hex(default_border)?)?;
DEFAULT_COLOURS.set(default_colours.to_string())?; DEFAULT_COLOURS.set(default_colours.to_string())?;
@ -162,19 +164,19 @@ async fn get_sway_config(
Ok(()) Ok(())
} }
fn parse_hex(hex: &str) -> Result<Lab, HexParse> { fn parse_hex(hex: &str) -> Res<Lab> {
let hex = hex.strip_prefix('#').unwrap_or(hex); let hex = hex.strip_prefix('#').unwrap_or(hex);
let r = u8::from_str_radix(&hex[..2], 16).map_err(|_| HexParse)?; let r = u8::from_str_radix(&hex[..2], 16).map_err(|_| Error::HexParse)?;
let g = u8::from_str_radix(&hex[2..4], 16).map_err(|_| HexParse)?; let g = u8::from_str_radix(&hex[2..4], 16).map_err(|_| Error::HexParse)?;
let b = u8::from_str_radix(&hex[4..], 16).map_err(|_| HexParse)?; let b = u8::from_str_radix(&hex[4..], 16).map_err(|_| Error::HexParse)?;
Ok(Lab::from_rgb(&[r, g, b])) Ok(Lab::from_rgb(&[r, g, b]))
} }
async fn interpolate_task() -> Result<(), Box<dyn std::error::Error>> { async fn interpolate_task() -> Res<()> {
let mut connection = swayipc_async::Connection::new().await?; let mut connection = swayipc_async::Connection::new().await?;
let to = DEFAULT_BORDER.get().ok_or(NoMatchingConfig)?; let to = DEFAULT_BORDER.get().ok_or(Error::NoMatchingConfig)?;
let config = CONFIG.get().ok_or(NoMatchingConfig)?; let config = CONFIG.get().ok_or(Error::NoMatchingConfig)?;
let per_frame = 1.0 / config.frames_anim as f32; let per_frame = 1.0 / config.frames_anim as f32;
let (d_l, d_a, d_b) = ( let (d_l, d_a, d_b) = (
(to.l - config.flash_colour.l) * per_frame, (to.l - config.flash_colour.l) * per_frame,
@ -183,10 +185,8 @@ async fn interpolate_task() -> Result<(), Box<dyn std::error::Error>> {
); );
let mut c = config.flash_colour; let mut c = config.flash_colour;
{ connection.run_command(set_command(&c)?).await?;
let command = set_command(&c)?;
connection.run_command(command).await?;
}
let dur_per_frame = std::time::Duration::from_secs_f64(1.0 / config.refresh_rate as f64); let dur_per_frame = std::time::Duration::from_secs_f64(1.0 / config.refresh_rate as f64);
tokio::time::sleep(dur_per_frame * config.frames_delay).await; tokio::time::sleep(dur_per_frame * config.frames_delay).await;
@ -194,22 +194,23 @@ async fn interpolate_task() -> Result<(), Box<dyn std::error::Error>> {
c.l += d_l; c.l += d_l;
c.a += d_a; c.a += d_a;
c.b += d_b; c.b += d_b;
{
let command = set_command(&c)?; connection.run_command(set_command(&c)?).await?;
connection.run_command(command).await?;
}
tokio::time::sleep(dur_per_frame).await; tokio::time::sleep(dur_per_frame).await;
} }
connection connection
.run_command(DEFAULT_COLOURS.get().ok_or(NoMatchingConfig)?) .run_command(DEFAULT_COLOURS.get().ok_or(Error::NoMatchingConfig)?)
.await?; .await?;
Ok(()) Ok(())
} }
fn set_command(colour: &Lab) -> Result<String, Box<dyn std::error::Error>> { fn set_command(colour: &Lab) -> Res<String> {
let [r, g, b] = colour.to_rgb(); let [r, g, b] = colour.to_rgb();
Ok(format!( Ok(format!(
"{} #{r:02x}{g:02x}{b:02x}", "{} #{r:02x}{g:02x}{b:02x}",
DEFAULT_COLOURS_NO_INDICATOR.get().ok_or(NoMatchingConfig)? DEFAULT_COLOURS_NO_INDICATOR
.get()
.ok_or(Error::NoMatchingConfig)?
)) ))
} }