Repository: google/argh
Pull request #169 (2023-08-08 19:35:18)

Change `from_str_fn` to take expression paths
This changes `from_str_fn` to take expression paths, rather than simple idents. This makes it easier to use functions from external modules, or with static methods.


Patch:
diff --git a/argh/Cargo.toml b/argh/Cargo.toml
index 5611f66..fc6daba 100644
--- a/argh/Cargo.toml
+++ b/argh/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "argh"
-version = "0.1.11"
+version = "0.1.12"
 authors = ["Taylor Cramer <cramertj@google.com>", "Benjamin Brittain <bwb@google.com>", "Erick Tryzelaar <etryzelaar@google.com>"]
 edition = "2018"
 keywords = ["args", "arguments", "derive", "cli"]
@@ -10,8 +10,8 @@ repository = "https://github.com/google/argh"
 readme = "README.md"
 
 [dependencies]
-argh_shared = { version = "0.1.11", path = "../argh_shared" }
-argh_derive = { version = "0.1.11", path = "../argh_derive" }
+argh_shared = { version = "0.1.12", path = "../argh_shared" }
+argh_derive = { version = "0.1.12", path = "../argh_derive" }
 
 [dev-dependencies]
 once_cell = "1.10.0"
diff --git a/argh_derive/Cargo.toml b/argh_derive/Cargo.toml
index 354419f..dcc965f 100644
--- a/argh_derive/Cargo.toml
+++ b/argh_derive/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "argh_derive"
-version = "0.1.11"
+version = "0.1.12"
 authors = ["Taylor Cramer <cramertj@google.com>", "Benjamin Brittain <bwb@google.com>", "Erick Tryzelaar <etryzelaar@google.com>"]
 edition = "2018"
 license = "BSD-3-Clause"
@@ -15,4 +15,4 @@ proc-macro = true
 proc-macro2 = "1.0"
 quote = "1.0"
 syn = "2.0"
-argh_shared = { version = "0.1.11", path = "../argh_shared" }
+argh_shared = { version = "0.1.12", path = "../argh_shared" }
diff --git a/argh_derive/src/parse_attrs.rs b/argh_derive/src/parse_attrs.rs
index 10ebcb5..f968ca7 100644
--- a/argh_derive/src/parse_attrs.rs
+++ b/argh_derive/src/parse_attrs.rs
@@ -13,7 +13,7 @@ use {
 pub struct FieldAttrs {
     pub default: Option<syn::LitStr>,
     pub description: Option<Description>,
-    pub from_str_fn: Option<syn::Ident>,
+    pub from_str_fn: Option<syn::ExprPath>,
     pub field_type: Option<FieldType>,
     pub long: Option<syn::LitStr>,
     pub short: Option<syn::LitChar>,
@@ -209,7 +209,7 @@ fn parse_attr_fn_name(
     errors: &Errors,
     m: &syn::MetaList,
     attr_name: &str,
-    slot: &mut Option<syn::Ident>,
+    slot: &mut Option<syn::ExprPath>,
 ) {
     if let Some(first) = slot {
         errors.duplicate_attrs(attr_name, first, m);
diff --git a/argh_shared/Cargo.toml b/argh_shared/Cargo.toml
index 83c8da8..8e07308 100644
--- a/argh_shared/Cargo.toml
+++ b/argh_shared/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "argh_shared"
-version = "0.1.11"
+version = "0.1.12"
 authors = ["Taylor Cramer <cramertj@google.com>", "Benjamin Brittain <bwb@google.com>", "Erick Tryzelaar <etryzelaar@google.com>"]
 edition = "2018"
 license = "BSD-3-Clause"


Test patch:
diff --git a/argh/tests/lib.rs b/argh/tests/lib.rs
index 713c73d..dbd3b48 100644
--- a/argh/tests/lib.rs
+++ b/argh/tests/lib.rs
@@ -81,6 +81,48 @@ fn custom_from_str_example() {
     assert_eq!(f.five, 5);
 }
 
+#[test]
+fn nested_from_str_example() {
+    #[derive(FromArgs)]
+    /// Goofy thing.
+    struct FiveStruct {
+        /// always five
+        #[argh(option, from_str_fn(nested::always_five))]
+        five: usize,
+    }
+
+    pub mod nested {
+        pub fn always_five(_value: &str) -> Result<usize, String> {
+            Ok(5)
+        }
+    }
+
+    let f = FiveStruct::from_args(&["cmdname"], &["--five", "woot"]).expect("failed to five");
+    assert_eq!(f.five, 5);
+}
+
+#[test]
+fn method_from_str_example() {
+    #[derive(FromArgs)]
+    /// Goofy thing.
+    struct FiveStruct {
+        /// always five
+        #[argh(option, from_str_fn(AlwaysFive::<usize>::always_five))]
+        five: usize,
+    }
+
+    struct AlwaysFive<T>(T);
+
+    impl AlwaysFive<usize> {
+        fn always_five(_value: &str) -> Result<usize, String> {
+            Ok(5)
+        }
+    }
+
+    let f = FiveStruct::from_args(&["cmdname"], &["--five", "woot"]).expect("failed to five");
+    assert_eq!(f.five, 5);
+}
+
 #[test]
 fn subcommand_example() {
     #[derive(FromArgs, PartialEq, Debug)]