Repository: pacak/bpaf
Pull request #107 (2022-10-15 22:20:36)

Release 0.7.1
Mostly cosmetics and compatibility with strange things


Patch:
diff --git a/Cargo.toml b/Cargo.toml
index 2a99d89..6f0c7e5 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "bpaf"
-version = "0.7.0"
+version = "0.7.1"
 edition = "2021"
 categories = ["command-line-interface"]
 description = "A simple Command Line Argument Parser with parser combinators"
diff --git a/Changelog.md b/Changelog.md
index cc2789c..e210c20 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,5 +1,10 @@
 # Change Log
 
+## bpaf [0.7.1] - 2022-10-15
+- colors similar to cargo'some
+   thanks to @kramer425
+- support for empty structs/enums in `construct!`
+
 ## bpaf [0.7.0] - 2022-10-11
 - `pure_with` implementation
    thanks to @xitep
diff --git a/README.md b/README.md
index 7a69835..5c78513 100644
--- a/README.md
+++ b/README.md
@@ -372,21 +372,21 @@ Usage --user <ARG>
 	
 
 
- [__cargo_doc2readme_dependencies_info]: ggGkYW0AYXSEG52uRQSwBdezG6GWW8ODAbr5G6KRmT_WpUB5G9hPmBcUiIp6YXKEG-IPQtuM4VUFG47iETJwkSENG_GD7ukhn-KMG38J41C6yQn3YWSBgmRicGFmZTAuNy4w
- [__link0]: https://docs.rs/bpaf/0.7.0/bpaf/?search=_derive_tutorial
- [__link1]: https://docs.rs/bpaf/0.7.0/bpaf/?search=_combinatoric_tutorial
- [__link10]: https://docs.rs/bpaf/0.7.0/bpaf/?search=parsers::NamedArg::switch
- [__link11]: https://docs.rs/bpaf/0.7.0/bpaf/?search=parsers::NamedArg::argument
- [__link12]: https://docs.rs/bpaf/0.7.0/bpaf/?search=params::positional
- [__link13]: https://docs.rs/bpaf/0.7.0/bpaf/?search=parsers::NamedArg::argument
- [__link14]: https://docs.rs/bpaf/0.7.0/bpaf/?search=params::positional
- [__link15]: https://docs.rs/bpaf/0.7.0/bpaf/?search=bpaf::Parser::complete
- [__link17]: https://docs.rs/bpaf/0.7.0/bpaf/?search=info::OptionParser::run_inner
- [__link2]: https://docs.rs/bpaf/0.7.0/bpaf/?search=_unusual
- [__link3]: https://docs.rs/bpaf/0.7.0/bpaf/?search=_applicative
- [__link4]: https://docs.rs/bpaf/0.7.0/bpaf/?search=batteries
+ [__cargo_doc2readme_dependencies_info]: ggGkYW0AYXSEG52uRQSwBdezG6GWW8ODAbr5G6KRmT_WpUB5G9hPmBcUiIp6YXKEG-IPQtuM4VUFG47iETJwkSENG_GD7ukhn-KMG38J41C6yQn3YWSBgmRicGFmZTAuNy4x
+ [__link0]: https://docs.rs/bpaf/0.7.1/bpaf/?search=_derive_tutorial
+ [__link1]: https://docs.rs/bpaf/0.7.1/bpaf/?search=_combinatoric_tutorial
+ [__link10]: https://docs.rs/bpaf/0.7.1/bpaf/?search=parsers::NamedArg::switch
+ [__link11]: https://docs.rs/bpaf/0.7.1/bpaf/?search=parsers::NamedArg::argument
+ [__link12]: https://docs.rs/bpaf/0.7.1/bpaf/?search=params::positional
+ [__link13]: https://docs.rs/bpaf/0.7.1/bpaf/?search=parsers::NamedArg::argument
+ [__link14]: https://docs.rs/bpaf/0.7.1/bpaf/?search=params::positional
+ [__link15]: https://docs.rs/bpaf/0.7.1/bpaf/?search=bpaf::Parser::complete
+ [__link17]: https://docs.rs/bpaf/0.7.1/bpaf/?search=info::OptionParser::run_inner
+ [__link2]: https://docs.rs/bpaf/0.7.1/bpaf/?search=_unusual
+ [__link3]: https://docs.rs/bpaf/0.7.1/bpaf/?search=_applicative
+ [__link4]: https://docs.rs/bpaf/0.7.1/bpaf/?search=batteries
  [__link5]: https://github.com/pacak/bpaf/discussions/categories/q-a
- [__link6]: https://docs.rs/bpaf/0.7.0/bpaf/?search=_derive_tutorial
- [__link7]: https://docs.rs/bpaf/0.7.0/bpaf/?search=_combinatoric_tutorial
- [__link8]: https://docs.rs/bpaf/0.7.0/bpaf/?search=_applicative
- [__link9]: https://docs.rs/bpaf/0.7.0/bpaf/?search=bpaf::Parser::fallback
+ [__link6]: https://docs.rs/bpaf/0.7.1/bpaf/?search=_derive_tutorial
+ [__link7]: https://docs.rs/bpaf/0.7.1/bpaf/?search=_combinatoric_tutorial
+ [__link8]: https://docs.rs/bpaf/0.7.1/bpaf/?search=_applicative
+ [__link9]: https://docs.rs/bpaf/0.7.1/bpaf/?search=bpaf::Parser::fallback
diff --git a/bpaf_cauwugo/Cargo.toml b/bpaf_cauwugo/Cargo.toml
index 855c624..cebf885 100644
--- a/bpaf_cauwugo/Cargo.toml
+++ b/bpaf_cauwugo/Cargo.toml
@@ -12,7 +12,7 @@ description = "A cargo frontend with dynamic completion"
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
-bpaf = { version = "0.7.0", path = "../", features = ["derive", "autocomplete"] }
+bpaf = { version = "0.7.1", path = "../", features = ["derive", "autocomplete"] }
 cargo_metadata = "0.15.0"
 once_cell = "1.13.1"
 
diff --git a/bpaf_cauwugo/src/shared.rs b/bpaf_cauwugo/src/shared.rs
index 00c2ac4..cd6bcd4 100644
--- a/bpaf_cauwugo/src/shared.rs
+++ b/bpaf_cauwugo/src/shared.rs
@@ -31,6 +31,16 @@ pub struct CargoOpts {
     /// Number of parallel jobs, defaults to # of CPUs
     pub jobs: Option<usize>,
 
+    #[bpaf(short('F'), long)]
+    /// Space or comma separated list of features to activate
+    pub features: Vec<String>,
+
+    /// Do not activate the `default` feature
+    pub no_default_features: bool,
+
+    /// Activate all available features
+    pub all_features: bool,
+
     #[bpaf(argument("TRIPLE"), complete(complete_available_target), optional)]
     /// Build for the target triple
     pub target: Option<String>,
@@ -43,7 +53,10 @@ impl CargoOpts {
         pass_flag!(cmd, self.frozen, "--frozen");
         pass_flag!(cmd, self.locked, "--locked");
         pass_flag!(cmd, self.offline, "--offline");
+        pass_flag!(cmd, self.no_default_features, "--no_default_features");
+        pass_flag!(cmd, self.all_features, "--all-features");
         pass_arg!(cmd, self.jobs.map(|j| j.to_string()), "--jobs");
+        pass_arg!(cmd, &self.features, "--features");
     }
 }
 
diff --git a/src/_applicative.rs b/src/_applicative.rs
index 7ec811b..7891ce4 100644
--- a/src/_applicative.rs
+++ b/src/_applicative.rs
@@ -143,7 +143,7 @@
 //!     Mir
 //! }
 //!
-//! /// Format selection as enum - can represent any possible combination of formats
+//! /// Format selection as struct - can represent any possible combination of formats
 //! struct Formats {
 //!     intel: bool,
 //!     att: bool,
diff --git a/src/lib.rs b/src/lib.rs
index 8ed16b4..26e82ec 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -638,7 +638,7 @@ macro_rules! construct {
     };
 
     (@prepare $ty:tt [$($fields:tt)*]) => {
-        $crate::__cons_prepare!($ty [$($fields)*])
+        $crate::__cons_prepare!($ty [ $($fields)* ])
     };
 
     (@make [named [$($con:tt)+]] [$($fields:ident)*]) => { $($con)+ { $($fields),* } };
@@ -651,6 +651,9 @@ macro_rules! construct {
 #[cfg(not(feature = "autocomplete"))]
 /// to avoid extra parsing when autocomplete feature is off
 macro_rules! __cons_prepare {
+    ([named [$($con:tt)+]] []) => { $crate::pure($($con)+ { })};
+    ([pos   [$($con:tt)+]] []) => { $crate::pure($($con)+ ( ))};
+
     ([pos] [$field:ident]) => { $crate::ParseBox { inner: Box::new($field) } };
 
     ($ty:tt [$($fields:ident)+]) => {{
@@ -671,6 +674,9 @@ macro_rules! __cons_prepare {
 #[cfg(feature = "autocomplete")]
 /// for completion bpaf needs to observe all the failures in a branch
 macro_rules! __cons_prepare {
+    ([named [$($con:tt)+]] []) => { $crate::pure($($con)+ { })};
+    ([pos   [$($con:tt)+]] []) => { $crate::pure($($con)+ ( ))};
+
     ([pos] [$field:ident]) => { $crate::ParseBox { inner: Box::new($field) } };
 
     ($ty:tt [$($fields:ident)+]) => {{


Test patch:
diff --git a/bpaf_derive/src/top_tests.rs b/bpaf_derive/src/top_tests.rs
index be6ff6e..4d4b4ed 100644
--- a/bpaf_derive/src/top_tests.rs
+++ b/bpaf_derive/src/top_tests.rs
@@ -677,3 +677,22 @@ fn adjacent_for_struct() {
 
     assert_eq!(top.to_token_stream().to_string(), expected.to_string());
 }
+
+#[test]
+fn no_fields_declaration() {
+    let top: Top = parse_quote! {
+        struct Opts {}
+    };
+
+    let expected = quote! {
+        fn opts() -> impl ::bpaf::Parser<Opts> {
+            #[allow(unused_imports)]
+            use ::bpaf::Parser;
+            {
+                ::bpaf::construct!(Opts {})
+            }
+        }
+    };
+
+    assert_eq!(top.to_token_stream().to_string(), expected.to_string());
+}
diff --git a/tests/tests.rs b/tests/tests.rs
index 61f6622..f5154f4 100644
--- a/tests/tests.rs
+++ b/tests/tests.rs
@@ -1737,3 +1737,47 @@ fn parse_some_catch() {
         .unwrap_stderr();
     assert_eq!(r, "A");
 }
+
+#[test]
+fn empty_struct() {
+    #[derive(Debug, Clone, Eq, PartialEq)]
+    struct Foo {}
+    let parser = construct!(Foo {}).to_options();
+
+    let r = parser.run_inner(Args::from(&[])).unwrap();
+    assert_eq!(r, Foo {});
+
+    let r = parser
+        .run_inner(Args::from(&["--help"]))
+        .unwrap_err()
+        .unwrap_stdout();
+    assert_eq!(
+        r,
+        "
+Available options:
+    -h, --help  Prints help information
+"
+    );
+}
+
+#[test]
+fn empty_tuple() {
+    #[derive(Debug, Clone, Eq, PartialEq)]
+    struct Foo();
+    let parser = construct!(Foo()).to_options();
+
+    let r = parser.run_inner(Args::from(&[])).unwrap();
+    assert_eq!(r, Foo());
+
+    let r = parser
+        .run_inner(Args::from(&["--help"]))
+        .unwrap_err()
+        .unwrap_stdout();
+    assert_eq!(
+        r,
+        "
+Available options:
+    -h, --help  Prints help information
+"
+    );
+}