diff --git a/Cargo.lock b/Cargo.lock index 12da9b9..5b2f9b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -24,9 +24,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "bitflags" @@ -42,20 +42,53 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "3.0.1" +version = "3.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1121e32687f7f90b905d4775273305baa4f32cd418923e9b0fa726533221857" +checksum = "d646c7ade5eb07c4aa20e907a922750df0c448892513714fd3e4acbc7130829f" dependencies = [ "atty", "bitflags", + "clap_derive", + "clap_lex", "indexmap", - "lazy_static", - "os_str_bytes", + "once_cell", "strsim", "termcolor", "textwrap", ] +[[package]] +name = "clap_derive" +version = "3.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "759bf187376e1afa7b85b959e6a664a3e7a95203415dba952ad19139e798f902" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "ctrlc" +version = "3.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b37feaa84e6861e00a1f5e5aa8da3ee56d605c9992d33e082786754828e20865" +dependencies = [ + "nix", + "winapi", +] + [[package]] name = "env_logger" version = "0.7.1" @@ -71,9 +104,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.3" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ "cfg-if", "libc", @@ -82,9 +115,15 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.11.2" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +checksum = "607c8a29735385251a339424dd462993c0fed8fa09d378f259377df08c126022" + +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" [[package]] name = "hermit-abi" @@ -106,55 +145,63 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.7.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" +checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" dependencies = [ "autocfg", "hashbrown", ] -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - [[package]] name = "libc" -version = "0.2.98" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790" +checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" [[package]] name = "log" -version = "0.4.14" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if", ] [[package]] name = "memchr" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] -name = "os_str_bytes" -version = "6.0.0" +name = "nix" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" +checksum = "8f17df307904acd05aa8e32e97bb20f2a0df1728bbc2d771ae8f9a90463441e9" dependencies = [ - "memchr", + "bitflags", + "cfg-if", + "libc", ] +[[package]] +name = "once_cell" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" + +[[package]] +name = "os_str_bytes" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa" + [[package]] name = "ppv-lite86" -version = "0.2.10" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "pretty_env_logger" @@ -166,22 +213,63 @@ dependencies = [ "log", ] +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" +dependencies = [ + "unicode-ident", +] + [[package]] name = "quick-error" version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +[[package]] +name = "quote" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" +dependencies = [ + "proc-macro2", +] + [[package]] name = "rand" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -203,20 +291,11 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core", -] - [[package]] name = "regex" -version = "1.5.4" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" dependencies = [ "aho-corasick", "memchr", @@ -225,9 +304,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.25" +version = "0.6.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" [[package]] name = "strsim" @@ -235,26 +314,50 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "syn" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "termcolor" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" dependencies = [ "winapi-util", ] [[package]] name = "textwrap" -version = "0.14.2" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" + +[[package]] +name = "unicode-ident" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" +checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wallpaper" -version = "0.3.0" +version = "1.0.0" dependencies = [ "clap", + "ctrlc", "log", "pretty_env_logger", "rand", @@ -262,9 +365,9 @@ dependencies = [ [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "winapi" diff --git a/Cargo.toml b/Cargo.toml index db34027..f32c5d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "wallpaper" -version = "0.3.0" -edition = "2018" +version = "1.0.0" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -10,11 +10,19 @@ name = "wallpaperd" path = "src/daemon/daemon.rs" [[bin]] -name = "wp_cli" +name = "wp" path = "src/cli/client.rs" +[lib] +name = "common" +path = "src/common/lib.rs" + +[profile.release] +strip = true # Automatically strip symbols from the binary. + [dependencies] -log = "0.4.14" +log = "0.4.17" pretty_env_logger = "0.4.0" -rand = "0.8.4" -clap = { version = "3.0.1", features = ["cargo", "env"] } +rand = "0.8.5" +clap = { version = "3.2.11", features = ["derive", "cargo"] } +ctrlc = { version = "3.2.2", features = ["termination"] } diff --git a/src/cli/client.rs b/src/cli/client.rs index 8ca4c7c..d130a72 100644 --- a/src/cli/client.rs +++ b/src/cli/client.rs @@ -1,5 +1,4 @@ -use clap::{app_from_crate, arg, App, Arg}; -use std::env; +use clap::Parser; use std::io::prelude::*; use std::os::unix::net::UnixStream; use std::path::PathBuf; @@ -7,99 +6,44 @@ use std::str::FromStr; use log::info; +#[derive(Parser)] +#[clap(version)] +pub struct Cli { + /// Socket for communication + #[clap(short, long, value_parser, value_name = "FILE")] + socket: Option, + #[clap(subcommand)] + command: common::Command, +} + fn main() { pretty_env_logger::init(); - let matches = app_from_crate!() - .arg(arg!(-s - -socket[PATH])) - .subcommand(App::new("next").about("Show next image")) - .subcommand(App::new("stop").about("Stop the daemon")) - .subcommand(App::new("prev").about("Show the previous image")) - .subcommand( - App::new("mode") - .about("Change the image order") - .subcommand(App::new("linear").visible_alias("lin")) - .subcommand(App::new("random").visible_alias("rng")) - .subcommand(App::new("static").arg(Arg::new("[PATH]").required(false))), - ) - .subcommand( - App::new("fallback") - .about("Display the fallback image") - .alias("save"), - ) - .subcommand(App::new("update").about("Update the Image cache")) - .subcommand(App::new("shuffle").about("Shuffle image order")) - .subcommand( - App::new("interval") - .arg(arg!()) - .about("Set image change interval"), - ) - .subcommand( - App::new("get") - .about("Get information about the current settings") - .subcommand(App::new("wallpaper").visible_alias("wp")) - .subcommand(App::new("duration").visible_alias("dur")) - .subcommand(App::new("mode").visible_alias("m")), - ) - .get_matches(); - - let socket_path = match matches.value_of("socket") { - Some(val) => PathBuf::from_str(val).expect("Invalid socket path"), - None => { - if let Ok(path) = std::env::var("XDG_RUNTIME_DIR") { - PathBuf::from_str(&format!("{}/wallpaperd", path)).expect("Invalid XDG_RUNTIME_DIR") - } else { - PathBuf::from_str("/tmp/wallpaperd").unwrap() - } + let cli = Cli::parse(); + let socket = cli.socket.unwrap_or_else(|| { + if let Ok(path) = std::env::var("XDG_RUNTIME_DIR") { + let mut pathbuf = PathBuf::new(); + pathbuf.push(path); + pathbuf.push("wallpaperd"); + pathbuf + } else { + PathBuf::from_str("/tmp/wallpaperd").unwrap() } - }; - let mut socket = UnixStream::connect(socket_path).expect("Socket not found"); + }); - let args = match matches.subcommand() { - Some(("next", _)) => "next".to_owned(), - Some(("prev", _)) => "prev".to_owned(), - Some(("stop", _)) => "stop".to_owned(), - Some(("update", _)) => "update".to_owned(), - Some(("shuffle", _)) => "shuffle".to_owned(), - Some(("fallback", _)) => "save".to_owned(), - Some(("mode", sub_matches)) => match sub_matches.subcommand() { - Some(("random", _)) => "rng".to_owned(), - Some(("linear", _)) => "linear".to_owned(), - Some(("static", sub_matches)) => match sub_matches.value_of("PATH") { - Some(path) => { - format!("hold {}", path) - } - None => "hold".to_owned(), - }, - Some((_, _)) => "help".to_owned(), - None => "help".to_owned(), - }, - Some(("get", sub_matches)) => match sub_matches.subcommand() { - Some(("wallpaper", _)) => "get wp".to_owned(), - Some(("duration", _)) => "get duration".to_owned(), - Some(("mode", _)) => "get action".to_owned(), - Some((_, _)) => "help".to_owned(), - None => "help".to_owned(), - }, - Some(("interval", sub_matches)) => { - let msg = format!( - "interval {}", - sub_matches.value_of("SECONDS").expect("Interval missing") - ); - msg - } - Some((_, _)) => "help".to_owned(), - None => "help".to_owned(), - }; + let mut socket = UnixStream::connect(socket).expect("Socket not found"); + + //TODO make not shit + let args = cli.command.to_string(); let len = args.len(); info!("Sending {:?}", args); { socket.write(&len.to_ne_bytes()).unwrap(); + socket.write(args.trim().as_bytes()).unwrap(); info!("{:?}", &len.to_ne_bytes()); info!("{:?}", args.trim().as_bytes()); - socket.write(args.trim().as_bytes()).unwrap(); socket.flush().unwrap(); } diff --git a/src/common/lib.rs b/src/common/lib.rs new file mode 100644 index 0000000..f463799 --- /dev/null +++ b/src/common/lib.rs @@ -0,0 +1,90 @@ +use std::{fmt::Display, path::PathBuf, time::Duration}; + +use clap::{Args, Subcommand}; + +#[derive(Subcommand)] +pub enum Command { + /// Show the next image + Next, + /// Exit the daemon + Stop, + /// Show the previous image + Previous, + /// Set the mode + #[clap(subcommand)] + Mode(ModeArgs), + /// Display the fallback wallpaper + /// If called again displays the previous image + Fallback, + /// Update the directory cache + Update, + /// Shuffle the directory cache + Shuffle, + /// Set the interval for new images in seconds + Interval(IntervalDuration), + /// Query information about the current state + #[clap(subcommand)] + Get(GetArgs), +} + +#[derive(Args)] +pub struct IntervalDuration { + #[clap(parse(try_from_str = parse_duration))] + pub duration: Duration, +} + +#[derive(Subcommand)] +pub enum ModeArgs { + Linear, + Random, + Static(Image), +} + +#[derive(Args)] +pub struct Image { + #[clap(short, long)] + pub path: Option, +} + +#[derive(Subcommand)] +pub enum GetArgs { + Wallpaper, + Duration, + Mode, +} + +fn parse_duration(arg: &str) -> Result { + let seconds = arg.parse()?; + Ok(std::time::Duration::from_secs(seconds)) +} + +impl Display for Command { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let args = match self { + Command::Next => "next".to_string(), + Command::Stop => "stop".to_string(), + Command::Previous => "previous".to_string(), + Command::Mode(mode) => match mode { + ModeArgs::Linear => "mode linear".to_string(), + ModeArgs::Random => "mode random".to_string(), + ModeArgs::Static(img) => { + if let Some(path) = &img.path { + format!("mode static {}", path.to_string_lossy()) + } else { + "mode static".to_string() + } + } + }, + Command::Fallback => "fallback".to_string(), + Command::Update => "update".to_string(), + Command::Shuffle => "shuffle".to_string(), + Command::Interval(dur) => format!("interval {}", dur.duration.as_secs()), + Command::Get(what) => match what { + GetArgs::Wallpaper => "get wallpaper".to_string(), + GetArgs::Duration => "get duration".to_string(), + GetArgs::Mode => "get mode".to_string(), + }, + }; + write!(f, "{args}") + } +} diff --git a/src/daemon/args.rs b/src/daemon/args.rs deleted file mode 100644 index 6d622d8..0000000 --- a/src/daemon/args.rs +++ /dev/null @@ -1,82 +0,0 @@ -use std::{convert::TryFrom, path::PathBuf, time::Duration}; - -pub enum MessageArgs { - Wallpaper, - Action, - Duration, -} - -impl TryFrom<&str> for MessageArgs { - type Error = &'static str; - - fn try_from(value: &str) -> Result { - use MessageArgs::*; - match value.to_lowercase().as_str() { - "wallpaper" | "wp" => Ok(Wallpaper), - "action" | "ac" => Ok(Action), - "duration" | "dur" => Ok(Duration), - _ => Err("Not recognized"), - } - } -} - -pub enum Args { - Help, - Stop, - Next, - Prev, - RNG, - Linear, - Hold(Option), - Update, - Save, - Shuffle, - Interval(Duration), - Get(MessageArgs), -} - -impl TryFrom<&str> for Args { - type Error = &'static str; - - fn try_from(value: &str) -> Result { - use Args::*; - let value = value.to_lowercase(); - let splits: Vec<&str> = value.split(' ').collect(); - let tupl = (splits.get(0).unwrap_or(&"").to_owned(), splits.get(1)); - match tupl.0 { - "stop" => Ok(Stop), - "next" => Ok(Next), - "prev" => Ok(Prev), - "rng" => Ok(RNG), - "linear" | "lin" => Ok(Linear), - "hold" => { - let string: Option = match tupl.1 { - Some(val) => Some(val.into()), - None => None, - }; - Ok(Hold(string)) - } - "update" => Ok(Update), - "save" => Ok(Save), - "shuffle" | "shl" => Ok(Shuffle), - "interval" | "int" => { - let d = Duration::new(tupl.1.unwrap_or(&"").parse::().unwrap_or(60), 0); - Ok(Interval(d)) - } - "get" => { - if let Some(arg) = tupl.1 { - match *arg { - "ac" | "action" => Ok(Get(MessageArgs::Action)), - "dur" | "duration" => Ok(Get(MessageArgs::Duration)), - "wp" | "wallpaper" => Ok(Get(MessageArgs::Wallpaper)), - _ => Err("Not recognized"), - } - } else { - Err("Not recognized") - } - } - "help" => Ok(Help), - _ => Err("Not recognized"), - } - } -} diff --git a/src/daemon/daemon.rs b/src/daemon/daemon.rs index dae0224..6a96485 100644 --- a/src/daemon/daemon.rs +++ b/src/daemon/daemon.rs @@ -1,7 +1,7 @@ -use std::convert::TryFrom; -use std::fs; -use std::io::Read; +use std::fs::{self, File}; +use std::io::{Read, Write}; use std::os::unix::net::*; +use std::os::unix::prelude::{FromRawFd, RawFd}; use std::path::PathBuf; use std::process::exit; use std::str::FromStr; @@ -9,37 +9,15 @@ use std::sync::{Arc, Mutex}; use std::thread::{self, sleep}; use std::time::Duration; +use clap::{Args, Parser, Subcommand}; use log::info; -mod args; +use common; + mod state; use state::State; -use clap::{app_from_crate, arg}; - -const HELP: &str = "Usage: - wp