From c13c5574309e05144f75d4c137f6f07a22cc393b Mon Sep 17 00:00:00 2001 From: Mohammad Banisaeid Date: Mon, 25 Dec 2023 11:13:04 +0100 Subject: [PATCH] Add `completion` command (#33) This PR adds `completion` command to generate shell completion for Bash, zsh, and other shell types. --- Cargo.lock | 12 +++++++++++- Cargo.toml | 3 ++- README.md | 4 +++- src/main.rs | 28 +++++++++++++++++++++++++--- 4 files changed, 41 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bdbd0ad..ea8ce33 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -215,6 +215,15 @@ dependencies = [ "textwrap", ] +[[package]] +name = "clap_complete" +version = "3.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f7a2e0a962c45ce25afce14220bc24f9dade0a1787f185cecf96bfba7847cd8" +dependencies = [ + "clap", +] + [[package]] name = "clap_derive" version = "3.2.25" @@ -676,13 +685,14 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "humble-cli" -version = "0.13.1" +version = "0.14.0" dependencies = [ "anyhow", "assert_cmd", "byte-unit", "chrono", "clap", + "clap_complete", "dirs", "futures-util", "indicatif", diff --git a/Cargo.toml b/Cargo.toml index ebb0d92..2e84ff4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "humble-cli" authors = ["Mohammad Banisaeid "] -version = "0.13.1" +version = "0.14.0" license = "MIT" description = "The missing CLI for downloading your Humble Bundle purchases" documentation = "https://github.com/smbl64/humble-cli" @@ -26,6 +26,7 @@ anyhow = "1.0" byte-unit = { version = "4.0", default-features = false } chrono = { version = "0.4", features = ["serde"] } clap = { version = "3.1", features = ["cargo", "derive"] } +clap_complete = "3.2" dirs = "4.0.0" futures-util = "0.3" indicatif = "0.16" diff --git a/README.md b/README.md index 80f7457..96e57e2 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,8 @@ Use `humble-cli auth ""` to store the authentication key local After that you will have access to the following sub-commands: ``` -$ humble-cli 0.13.1 +$ humble-cli --help +humble-cli 0.14.0 The missing Humble Bundle CLI USAGE: @@ -48,6 +49,7 @@ OPTIONS: SUBCOMMANDS: auth Set the authentication session key + completion Generate shell completions details Print details of a certain bundle [aliases: info] download Selectively download items from a bundle [aliases: d] help Print this message or the help of the given subcommand(s) diff --git a/src/main.rs b/src/main.rs index 22ddccb..520bb21 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,8 @@ +use std::io; + use anyhow::Context; use clap::{builder::ValueParser, value_parser, Arg, Command}; +use clap_complete::Shell; use humble_cli::prelude::*; fn main() { @@ -44,6 +47,17 @@ fn run() -> Result<(), anyhow::Error> { ) ); + let completion_subcommand = Command::new("completion") + .about("Generate shell completions") + .arg( + Arg::new("SHELL") + .help("Shell type to generate completions for") + .possible_values(&["bash", "elvish", "fish", "powershell", "zsh"]) + .takes_value(true) + .required(true) + .value_parser(value_parser!(Shell)), + ); + let list_choices_subcommand = Command::new("list-choices") .about("List your current Humble Choices") .arg( @@ -164,20 +178,28 @@ fn run() -> Result<(), anyhow::Error> { details_subcommand, download_subcommand, search_subcommand, + completion_subcommand, ]; let crate_name = clap::crate_name!(); - let matches = clap::Command::new(crate_name) + let mut root = clap::Command::new(crate_name) .about("The missing Humble Bundle CLI") .version(clap::crate_version!()) .after_help("Note: `humble-cli -h` prints a short and concise overview while `humble-cli --help` gives all details.") .subcommand_required(true) .arg_required_else_help(true) - .subcommands(sub_commands) - .get_matches(); + .subcommands(sub_commands); + let matches = root.clone().get_matches(); return match matches.subcommand() { + Some(("completion", sub_matches)) => { + if let Some(g) = sub_matches.get_one::("SHELL").copied() { + let crate_name = clap::crate_name!(); + clap_complete::generate(g, &mut root, crate_name, &mut io::stdout()); + } + Ok(()) + } Some(("auth", sub_matches)) => { let session_key = sub_matches.value_of("SESSION-KEY").unwrap(); auth(session_key)