diff --git a/CHANGELOG.md b/CHANGELOG.md index 560010b7..bc89a741 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ All notable changes to eww will be listed here, starting at changes since versio - Add `unindent` property to the label widget, allowing to disable removal of leading spaces (By: nrv) - Switch to stable rust toolchain (1.76) - Add `tooltip` widget, which allows setting a custom tooltip (not only text), to a widget (By: Rayzeq) +- Add `eww shell-completions` command, generating completion scripts for different shells ## [0.4.0] (04.09.2022) diff --git a/Cargo.lock b/Cargo.lock index 8521083b..46f00af6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -372,6 +372,15 @@ dependencies = [ "strsim 0.11.0", ] +[[package]] +name = "clap_complete" +version = "4.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "885e4d7d5af40bfb99ae6f9433e292feac98d452dcb3ec3d25dfe7552b77da8c" +dependencies = [ + "clap", +] + [[package]] name = "clap_derive" version = "4.5.0" @@ -616,6 +625,7 @@ dependencies = [ "cairo-sys-rs", "chrono", "clap", + "clap_complete", "codespan-reporting", "derive_more", "eww_shared_util", diff --git a/Cargo.toml b/Cargo.toml index ae2ef084..3262870d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ cached = "0.48.0" chrono = "0.4.26" chrono-tz = "0.8.2" clap = {version = "4.5.1", features = ["derive"] } +clap_complete = "4.5.1" codespan-reporting = "0.11" derive_more = "0.99" extend = "1.2" diff --git a/crates/eww/Cargo.toml b/crates/eww/Cargo.toml index 05522768..18e07d98 100644 --- a/crates/eww/Cargo.toml +++ b/crates/eww/Cargo.toml @@ -38,6 +38,7 @@ anyhow.workspace = true bincode.workspace = true chrono.workspace = true clap = {workspace = true, features = ["derive"] } +clap_complete.workspace = true codespan-reporting.workspace = true derive_more.workspace = true extend.workspace = true diff --git a/crates/eww/src/client.rs b/crates/eww/src/client.rs index 616c3872..c9f14ab2 100644 --- a/crates/eww/src/client.rs +++ b/crates/eww/src/client.rs @@ -6,6 +6,7 @@ use crate::{ paths::EwwPaths, }; use anyhow::{Context, Result}; +use clap::CommandFactory as _; use std::{ io::{Read, Write}, os::unix::net::UnixStream, @@ -20,6 +21,9 @@ pub fn handle_client_only_action(paths: &EwwPaths, action: ActionClientOnly) -> .spawn()? .wait()?; } + ActionClientOnly::ShellCompletions { shell } => { + clap_complete::generate(shell, &mut opts::RawOpt::command(), "eww", &mut std::io::stdout()); + } } Ok(()) } diff --git a/crates/eww/src/opts.rs b/crates/eww/src/opts.rs index 526aa3c7..2446d8c4 100644 --- a/crates/eww/src/opts.rs +++ b/crates/eww/src/opts.rs @@ -28,7 +28,7 @@ pub struct Opt { #[derive(Parser, Debug, Serialize, Deserialize, PartialEq)] #[clap(author = "ElKowar")] #[clap(version, about)] -struct RawOpt { +pub(super) struct RawOpt { /// Write out debug logs. (To read the logs, run `eww logs`). #[arg(long = "debug", global = true)] log_debug: bool, @@ -75,6 +75,13 @@ pub enum ActionClientOnly { /// Print and watch the eww logs #[command(name = "logs")] Logs, + + /// Generate a shell completion script + ShellCompletions { + #[arg(short, long)] + #[serde(with = "serde_shell")] + shell: clap_complete::shells::Shell, + }, } #[derive(Subcommand, Debug, Serialize, Deserialize, PartialEq)] @@ -303,3 +310,19 @@ where fn parse_duration(s: &str) -> Result { DynVal::from_string(s.to_owned()).as_duration() } + +mod serde_shell { + use std::str::FromStr as _; + + use clap_complete::Shell; + use serde::{Deserialize as _, Deserializer, Serialize as _, Serializer}; + + pub fn serialize(shell: &Shell, serializer: S) -> Result { + shell.to_string().serialize(serializer) + } + + pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result { + let s = String::deserialize(deserializer)?; + Shell::from_str(&s).map_err(serde::de::Error::custom) + } +}