Repository: google/argh (language: rust)

Issue:
Disable automatically generated help message 
Sometimes we want to manually define the help message to further reduce the binary size. Since this crate aims to reduce the binary size, I think this request is valid. We can define a default feature for automatically generated help messages, and users can disable it and use `EarlyExit` to manually print customized help messages.


Discussion / hints:

Fix patch:
diff --git a/argh/Cargo.toml b/argh/Cargo.toml
index fc6daba..557706c 100644
--- a/argh/Cargo.toml
+++ b/argh/Cargo.toml
@@ -16,3 +16,7 @@ argh_derive = { version = "0.1.12", path = "../argh_derive" }
 [dev-dependencies]
 once_cell = "1.10.0"
 trybuild = "1.0.63"
+
+[features]
+default = ["help"]
+help = ["argh_derive/help"]
diff --git a/argh_derive/Cargo.toml b/argh_derive/Cargo.toml
index dcc965f..a3be6ce 100644
--- a/argh_derive/Cargo.toml
+++ b/argh_derive/Cargo.toml
@@ -16,3 +16,6 @@ proc-macro2 = "1.0"
 quote = "1.0"
 syn = "2.0"
 argh_shared = { version = "0.1.12", path = "../argh_shared" }
+
+[features]
+help = []
diff --git a/argh_derive/src/lib.rs b/argh_derive/src/lib.rs
index 8b3b7ee..adad38e 100644
--- a/argh_derive/src/lib.rs
+++ b/argh_derive/src/lib.rs
@@ -21,6 +21,7 @@ use {
 
 mod args_info;
 mod errors;
+#[cfg(feature = "help")]
 mod help;
 mod parse_attrs;
 
@@ -363,9 +364,13 @@ fn impl_from_args_struct_from_args<'a>(
         quote_spanned! { impl_span => None }
     };
 
-    // Identifier referring to a value containing the name of the current command as an `&[&str]`.
-    let cmd_name_str_array_ident = syn::Ident::new("__cmd_name", impl_span);
-    let help = help::help(errors, cmd_name_str_array_ident, type_attrs, fields, subcommand);
+    let help = if cfg!(feature = "help") {
+        // Identifier referring to a value containing the name of the current command as an `&[&str]`.
+        let cmd_name_str_array_ident = syn::Ident::new("__cmd_name", impl_span);
+        help::help(errors, cmd_name_str_array_ident, type_attrs, fields, subcommand)
+    } else {
+        quote! { String::new() }
+    };
 
     let method_impl = quote_spanned! { impl_span =>
         fn from_args(__cmd_name: &[&str], __args: &[&str])
@@ -483,9 +488,13 @@ fn impl_from_args_struct_redact_arg_values<'a>(
         quote! { "no subcommand name" }
     };
 
-    // Identifier referring to a value containing the name of the current command as an `&[&str]`.
-    let cmd_name_str_array_ident = syn::Ident::new("__cmd_name", impl_span);
-    let help = help::help(errors, cmd_name_str_array_ident, type_attrs, fields, subcommand);
+    let help = if cfg!(feature = "help") {
+        // Identifier referring to a value containing the name of the current command as an `&[&str]`.
+        let cmd_name_str_array_ident = syn::Ident::new("__cmd_name", impl_span);
+        help::help(errors, cmd_name_str_array_ident, type_attrs, fields, subcommand)
+    } else {
+        quote! { String::new() }
+    };
 
     let method_impl = quote_spanned! { impl_span =>
         fn redact_arg_values(__cmd_name: &[&str], __args: &[&str]) -> std::result::Result<Vec<String>, argh::EarlyExit> {
@@ -597,8 +606,11 @@ fn top_or_sub_cmd_impl(
     type_attrs: &TypeAttrs,
     generic_args: &syn::Generics,
 ) -> TokenStream {
-    let description =
-        help::require_description(errors, name.span(), &type_attrs.description, "type");
+    let description = if cfg!(feature = "help") {
+        help::require_description(errors, name.span(), &type_attrs.description, "type")
+    } else {
+        String::new()
+    };
     let (impl_generics, ty_generics, where_clause) = generic_args.split_for_impl();
     if type_attrs.is_subcommand.is_none() {
         // Not a subcommand


Test patch: