diff --git a/Cargo.lock b/Cargo.lock index 37051bc1..2cd2834c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -476,9 +476,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.39" +version = "4.5.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd60e63e9be68e5fb56422e397cf9baddded06dae1d2e523401542383bc72a9f" +checksum = "1c1f056bae57e3e54c3375c41ff79619ddd13460a17d7438712bd0d83fda4ff8" dependencies = [ "clap_builder", "clap_derive", @@ -486,9 +486,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.39" +version = "4.5.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89cc6392a1f72bbeb820d71f32108f61fdaf18bc526e1d23954168a67759ef51" +checksum = "b3e7f4214277f3c7aa526a59dd3fbe306a370daee1f8b7b8c987069cd8e888a8" dependencies = [ "anstream", "anstyle", @@ -498,9 +498,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.32" +version = "4.5.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" +checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -2535,7 +2535,7 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1961e2ef424c1424204d3a5d6975f934f56b6d50ff5732382d84ebf460e147f7" dependencies = [ - "heck 0.5.0", + "heck 0.4.1", "proc-macro2", "quote", "syn 2.0.98", diff --git a/Cargo.toml b/Cargo.toml index 174b2a1c..34861ebf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,7 +44,7 @@ ignore = "0.4.18" postgres-types = { version = "0.2.4", features = ["derive"] } cron = { version = "0.15.0" } bytes = "1.1.0" -clap = { version = "4", features = ["derive"] } +clap = { version = "4", features = ["derive", "string"] } hmac = "0.12.1" subtle = "2.6.1" sha2 = "0.10.9" diff --git a/src/zulip/commands.rs b/src/zulip/commands.rs index ad66cbe8..46e54306 100644 --- a/src/zulip/commands.rs +++ b/src/zulip/commands.rs @@ -175,11 +175,25 @@ pub struct PingGoalsArgs { /// Helper function to parse CLI arguments without any colored help or error output. pub fn parse_cli<'a, T: Parser, I: Iterator>(input: I) -> anyhow::Result { + fn allow_title_case(sub: clap::Command) -> clap::Command { + let name = sub.get_name(); + let alias = name + .chars() + .enumerate() + .map(|(i, c)| if i == 0 { c.to_ascii_uppercase() } else { c }) + .collect::(); + sub.alias(alias) + // Recursively allow title-case subcommands + .mut_subcommands(allow_title_case) + } + // Add a fake first argument, which is expected by clap let input = std::iter::once("triagebot").chain(input); let matches = T::command() .color(ColorChoice::Never) + // Allow title-case subcommands + .mut_subcommands(allow_title_case) .try_get_matches_from(input)?; let value = T::from_arg_matches(&matches)?; Ok(value) @@ -234,6 +248,11 @@ mod tests { assert_eq!(parse_chat(&["whoami"]), ChatCommand::Whoami); } + #[test] + fn whoami_uppercased_command() { + assert_eq!(parse_chat(&["Whoami"]), ChatCommand::Whoami); + } + #[test] fn lookup_command() { assert_eq!( @@ -259,6 +278,14 @@ mod tests { ); } + #[test] + fn work_uppercased_command() { + assert_eq!( + parse_chat(&["Work", "Show"]), + ChatCommand::Work(WorkqueueCmd::Show) + ); + } + #[test] fn end_meeting_command() { assert_eq!(parse_stream(&["end-meeting"]), StreamCommand::EndMeeting);