diff --git a/clap_derive/src/attrs.rs b/clap_derive/src/attrs.rs index 2cc1acd3540e..cbed9fdef8b0 100644 --- a/clap_derive/src/attrs.rs +++ b/clap_derive/src/attrs.rs @@ -80,6 +80,10 @@ pub enum CasingStyle { ScreamingSnake, /// Keep all letters lowercase and indicate word boundaries with underscores. Snake, + /// Keep all letters lowercase and remove word boundaries. + Lower, + /// Keep all letters uppercase and remove word boundaries. + Upper, /// Use the original attribute name defined in the code. Verbatim, } @@ -206,6 +210,8 @@ impl CasingStyle { "pascal" | "pascalcase" => cs(Pascal), "screamingsnake" | "screamingsnakecase" => cs(ScreamingSnake), "snake" | "snakecase" => cs(Snake), + "lower" | "lowercase" => cs(Lower), + "upper" | "uppercase" => cs(Upper), "verbatim" | "verbatimcase" => cs(Verbatim), s => abort!(name, "unsupported casing: `{}`", s), } @@ -226,6 +232,8 @@ impl Name { Camel => s.to_mixed_case(), ScreamingSnake => s.to_shouty_snake_case(), Snake => s.to_snake_case(), + Lower => s.to_snake_case().replace("_", ""), + Upper => s.to_shouty_snake_case().replace("_", ""), Verbatim => s, }; quote_spanned!(ident.span()=> #s) @@ -246,6 +254,8 @@ impl Name { Camel => s.to_mixed_case(), ScreamingSnake => s.to_shouty_snake_case(), Snake => s.to_snake_case(), + Lower => s.to_snake_case(), + Upper => s.to_shouty_snake_case(), Verbatim => s, }; diff --git a/clap_derive/tests/argument_naming.rs b/clap_derive/tests/argument_naming.rs index 7b977f7ab939..a5a86739eb86 100644 --- a/clap_derive/tests/argument_naming.rs +++ b/clap_derive/tests/argument_naming.rs @@ -288,3 +288,31 @@ fn test_rename_all_is_propagation_can_be_overridden() { Opt::parse_from(&["test", "SECOND_VARIANT", "--foo-option"]) ); } + +#[test] +fn test_lower_is_renamed() { + #[derive(Clap, Debug, PartialEq)] + struct Opt { + #[clap(rename_all = "lower", long)] + foo_option: bool, + } + + assert_eq!( + Opt { foo_option: true }, + Opt::parse_from(&["test", "--foooption"]) + ); +} + +#[test] +fn test_upper_is_renamed() { + #[derive(Clap, Debug, PartialEq)] + struct Opt { + #[clap(rename_all = "upper", long)] + foo_option: bool, + } + + assert_eq!( + Opt { foo_option: true }, + Opt::parse_from(&["test", "--FOOOPTION"]) + ); +}