From c2feec3698c625da72d36f49a059a0f38bbcee52 Mon Sep 17 00:00:00 2001 From: Danilo Spinella Date: Fri, 8 Nov 2024 11:29:18 +0100 Subject: [PATCH] feat(cli): Add status command Fixes #99. --- Cargo.lock | 2 ++ cli/Cargo.toml | 2 ++ cli/src/main.rs | 57 +++++++++++++++++++++++++++++++++++++++- cli/src/opts.rs | 6 +++++ daemon/src/ipc_server.rs | 15 +++++++++++ ipc/src/lib.rs | 14 +++++++--- 6 files changed, 92 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 31e0226..4c507d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2317,6 +2317,8 @@ dependencies = [ "clap", "clap_complete", "clap_mangen", + "humantime", + "humantime-serde", "serde", "serde_json", "wpaperd-ipc", diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 34b33bd..89ab08f 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -17,6 +17,8 @@ wpaperd-ipc = { path = "../ipc", version = "1.0.0" } clap = { version = "4.5.20", features = ["derive", "wrap_help"] } serde = { version = "1.0.210", features = ["derive"] } serde_json = "1.0.131" +humantime-serde = "1.1.1" +humantime = "2.1.0" [build-dependencies] clap = { version = "4.5.20", features = ["derive", "cargo"] } diff --git a/cli/src/main.rs b/cli/src/main.rs index ac45385..ca4c966 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -4,11 +4,11 @@ use std::{ io::{Read, Write}, os::unix::net::UnixStream, path::PathBuf, + time::Duration, }; use clap::Parser; use serde::Serialize; -use serde_json::to_string; use wpaperd_ipc::{socket_path, IpcError, IpcMessage, IpcResponse}; use crate::opts::{Opts, SubCmd}; @@ -53,7 +53,14 @@ fn main() { SubCmd::TogglePauseWallpaper { monitors } => IpcMessage::TogglePauseWallpaper { monitors: monitors.into_iter().map(unquote).collect(), }, + SubCmd::GetStatus { json, monitors } => { + json_resp = json; + IpcMessage::GetStatus { + monitors: monitors.into_iter().map(unquote).collect(), + } + } }; + conn.write_all(&serde_json::to_vec(&msg).unwrap()).unwrap(); let mut buf = String::new(); conn.read_to_string(&mut buf).unwrap(); @@ -86,6 +93,54 @@ fn main() { } } } + IpcResponse::DisplaysStatus { entries } => { + /// Clean up the duration for human readability + /// remove the milliseconds and the leading 0s + fn clean_duration(duration: Duration) -> Duration { + let duration = duration.as_secs(); + Duration::from_secs(if duration < 60 { + duration + } else if duration < 60 * 60 { + // if the duration is in minutes, remove the seconds + duration - duration % 60 + // duration is in hours, remove the minutes and seconds + } else { + duration - duration % (60 * 60) + }) + } + if json_resp { + #[derive(Serialize)] + struct Item { + display: String, + status: String, + #[serde(rename = "duration_left", with = "humantime_serde")] + duration_left: Option, + } + let val = entries + .into_iter() + .map(|(display, status, duration_left)| Item { + display, + status, + duration_left: duration_left.map(clean_duration), + }) + .collect::>(); + println!( + "{}", + serde_json::to_string(&val).expect("json encoding to work") + ); + } else { + for (monitor, status, duration_left) in entries { + println!( + "{monitor}: {status}{}", + if let Some(d) = duration_left { + format!(" ({} left)", humantime::format_duration(clean_duration(d))) + } else { + "".to_string() + } + ); + } + } + } IpcResponse::Ok => (), }, Err(err) => match err { diff --git a/cli/src/opts.rs b/cli/src/opts.rs index c0e8154..5f80e78 100644 --- a/cli/src/opts.rs +++ b/cli/src/opts.rs @@ -28,4 +28,10 @@ pub enum SubCmd { ResumeWallpaper { monitors: Vec }, #[clap(visible_alias = "toggle-pause")] TogglePauseWallpaper { monitors: Vec }, + #[clap(visible_alias = "status")] + GetStatus { + #[clap(short, long)] + json: bool, + monitors: Vec, + }, } diff --git a/daemon/src/ipc_server.rs b/daemon/src/ipc_server.rs index 3076bb5..c65cd68 100644 --- a/daemon/src/ipc_server.rs +++ b/daemon/src/ipc_server.rs @@ -158,6 +158,21 @@ pub fn handle_message( IpcResponse::Ok }) } + + IpcMessage::GetStatus { monitors } => { + check_monitors(wpaperd, &monitors).map(|_| IpcResponse::DisplaysStatus { + entries: collect_surfaces(wpaperd, monitors) + .iter() + .map(|surface| { + ( + surface.name().to_string(), + surface.status().to_string(), + surface.get_remaining_duration(), + ) + }) + .collect(), + }) + } }; let mut stream = BufWriter::new(ustream); diff --git a/ipc/src/lib.rs b/ipc/src/lib.rs index 3196cc3..81869a3 100644 --- a/ipc/src/lib.rs +++ b/ipc/src/lib.rs @@ -1,4 +1,4 @@ -use std::path::PathBuf; +use std::{path::PathBuf, time::Duration}; use serde::{Deserialize, Serialize}; use xdg::{BaseDirectories, BaseDirectoriesError}; @@ -13,12 +13,20 @@ pub enum IpcMessage { TogglePauseWallpaper { monitors: Vec }, AllWallpapers, ReloadWallpaper { monitors: Vec }, + GetStatus { monitors: Vec }, } #[derive(Serialize, Deserialize)] pub enum IpcResponse { - CurrentWallpaper { path: PathBuf }, - AllWallpapers { entries: Vec<(String, PathBuf)> }, + CurrentWallpaper { + path: PathBuf, + }, + AllWallpapers { + entries: Vec<(String, PathBuf)>, + }, + DisplaysStatus { + entries: Vec<(String, String, Option)>, + }, Ok, }