Repository: pacak/bpaf
Pull request #200 (2023-04-15 11:57:28)

Display env fallback for flags too
Fixes https://github.com/pacak/bpaf/issues/199


Patch:
diff --git a/src/info.rs b/src/info.rs
index 460e81e..09bf461 100644
--- a/src/info.rs
+++ b/src/info.rs
@@ -1,8 +1,5 @@
 //! Help message generation and rendering
 
-#![allow(clippy::write_with_newline)]
-use std::marker::PhantomData;
-
 use crate::{
     args::{Args, Conflict},
     item::Item,
@@ -82,7 +79,6 @@ pub(crate) fn check_conflicts(args: &Args) -> Option<String> {
 /// Created with [`to_options`](Parser::to_options)
 pub struct OptionParser<T> {
     pub(crate) inner: Box<dyn Parser<T>>,
-    pub(crate) inner_type: PhantomData<T>,
     pub(crate) info: Info,
 }
 
diff --git a/src/item.rs b/src/item.rs
index 113d325..4508a41 100644
--- a/src/item.rs
+++ b/src/item.rs
@@ -18,6 +18,7 @@ pub enum Item {
     Flag {
         name: ShortLong,
         shorts: Vec<char>,
+        env: Option<&'static str>,
         help: Option<String>,
     },
     Argument {
diff --git a/src/lib.rs b/src/lib.rs
index ab8bec9..aec1297 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1484,7 +1484,6 @@ pub trait Parser<T> {
     {
         OptionParser {
             info: info::Info::default(),
-            inner_type: PhantomData,
             inner: Box::new(self),
         }
     }
diff --git a/src/manpage.rs b/src/manpage.rs
index 4a2fc16..28e7b12 100644
--- a/src/manpage.rs
+++ b/src/manpage.rs
@@ -340,7 +340,7 @@ fn help_item(manpage: &mut Manpage, item: HelpItem, command_path: Option<&str>)
                 }
             }
         }
-        HelpItem::Flag { name, help } => {
+        HelpItem::Flag { name, help, env: _ } => {
             manpage.label(|l| {
                 l.shortlong(name);
             });
diff --git a/src/meta_help.rs b/src/meta_help.rs
index 231a7e3..1c05733 100644
--- a/src/meta_help.rs
+++ b/src/meta_help.rs
@@ -45,6 +45,7 @@ pub(crate) enum HelpItem<'a> {
     },
     Flag {
         name: ShortLong,
+        env: Option<&'static str>,
         help: Option<&'a str>,
     },
     Argument {
@@ -130,9 +131,11 @@ impl<'a> HelpItems<'a> {
             Item::Flag {
                 name,
                 help,
+                env,
                 shorts: _,
             } => self.flgs.push(HelpItem::Flag {
                 name: *name,
+                env: *env,
                 help: help.as_deref(),
             }),
             Item::Argument {
@@ -279,10 +282,12 @@ impl<'a> From<&'a crate::item::Item> for HelpItem<'a> {
             },
             Item::Flag {
                 name,
+                env,
                 help,
                 shorts: _,
             } => Self::Flag {
                 name: *name,
+                env: *env,
                 help: help.as_deref(),
             },
             Item::Argument {
@@ -359,10 +364,22 @@ fn write_help_item(buf: &mut Buffer, item: &HelpItem) {
                 buf.write_str(help, Style::Text);
             }
         }
-        HelpItem::Flag { name, help } => {
+        HelpItem::Flag { name, env, help } => {
             buf.margin(4);
             write_shortlong(buf, *name);
             buf.tabstop();
+            if let Some(env) = env {
+                let val = if std::env::var_os(env).is_some() {
+                    ": set"
+                } else {
+                    ": not set"
+                };
+                buf.write_str(&format!("[env:{}{}]", env, val), Style::Text);
+                if help.is_some() {
+                    buf.newline();
+                    buf.tabstop();
+                }
+            }
             if let Some(help) = help {
                 buf.write_str(help, Style::Text);
             }
diff --git a/src/params.rs b/src/params.rs
index bcbdbf4..06f6cc4 100644
--- a/src/params.rs
+++ b/src/params.rs
@@ -145,6 +145,7 @@ impl NamedArg {
         Item::Flag {
             name: ShortLong::from(self),
             help: self.help.clone(),
+            env: self.env.first().copied(),
             shorts: self.short.clone(),
         }
     }
diff --git a/src/structs.rs b/src/structs.rs
index 594d966..cd81e48 100644
--- a/src/structs.rs
+++ b/src/structs.rs
@@ -949,7 +949,12 @@ fn classify_anywhere(meta: Meta) -> Meta {
 
         let (name, shorts, help) = match iter.next() {
             Some(Meta::Item(item)) => match &**item {
-                Item::Flag { name, shorts, help } => (name, shorts, help),
+                Item::Flag {
+                    name,
+                    shorts,
+                    help,
+                    env: _,
+                } => (name, shorts, help),
                 _ => return meta,
             },
             _ => return meta,


Test patch:
diff --git a/tests/help_format.rs b/tests/help_format.rs
index 612219a..64e8757 100644
--- a/tests/help_format.rs
+++ b/tests/help_format.rs
@@ -198,7 +198,7 @@ fn anywhere_invariant_check() {
     #[derive(Debug, Clone, Bpaf)]
     #[allow(dead_code)]
     #[bpaf(anywhere)]
-    struct Foo {
+    struct Fooo {
         tag: (),
         #[bpaf(positional)]
         /// help
@@ -209,7 +209,7 @@ fn anywhere_invariant_check() {
 
     let a = short('a').switch();
     let b = short('b').switch();
-    let parser = construct!(a, foo(), b).to_options();
+    let parser = construct!(a, fooo(), b).to_options();
 
     parser.check_invariants(true);
 
@@ -368,3 +368,35 @@ Available options:
 
     assert_eq!(r, expected);
 }
+
+#[test]
+fn env_fallback_visible() {
+    let fonts_dir = long("fonts")
+        .env("OIKOS_FONTS")
+        .help("Load fonts from this directory")
+        .argument::<String>("DIR")
+        .optional();
+
+    let system_fonts = long("system-fonts")
+        .env("OIKOS_SYSTEM_FONTS")
+        .help("Search for additional fonts in system directories")
+        .switch();
+    let parser = construct!(fonts_dir, system_fonts).to_options();
+
+    let r = parser
+        .run_inner(Args::from(&["--help"]))
+        .unwrap_err()
+        .unwrap_stdout();
+
+    let expected = "\
+Usage: [--fonts DIR] [--system-fonts]
+
+Available options:
+        --fonts <DIR>   [env:OIKOS_FONTS: N/A]
+                        Load fonts from this directory
+        --system-fonts  [env:OIKOS_SYSTEM_FONTS: not set]
+                        Search for additional fonts in system directories
+    -h, --help          Prints help information
+";
+    assert_eq!(r, expected);
+}