Repository: kbknapp/clap-rs (rust)

Issue:
Support trailing comma for arg_enum!()
Would be great to support trailing comma for `arg_enum!()` macro, as Rust itself does and this error got me spend a few minutes trying to figure out if I got something (else) wrong in my definition.

Ref: <https://docs.rs/clap/2.27.1/clap/macro.arg_enum.html>


### Rust Version

rustc 1.23.0-nightly (e340996ff 2017-11-02)

### Affected Version of clap

2.27.1

### Expected Behavior Summary

Support trailing comma in `arg_enum!()`, like this:

```rust
arg_enum!{
    #[derive(Debug)]
    pub enum Foo {
        Bar,
        Baz,
        Qux,
    }
}
```

### Actual Behavior Summary

A trailing comma in `enum` definition results in this error:
```
error: no rules expected the token `}`
```

### Steps to Reproduce the issue

Add the above example to a clap app file.

### Sample Code or Link to Sample Code

See above.

### Debug output

N/A

Pull request description:
Support trailing comma in arg_enum! fields
This resolves #1097. A test was also included. Let me know if you'd like more tests or tweaks.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/kbknapp/clap-rs/1124)
<!-- Reviewable:end -->


Patch:
diff --git a/src/macros.rs b/src/macros.rs
index 395230b4..51bb95a7 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -345,6 +345,14 @@ macro_rules! arg_enum {
             }
         });
     };
+    ($(#[$($m:meta),+])+ pub enum $e:ident { $($v:ident $(=$val:expr)*,)+ } ) => {
+        arg_enum!(@impls
+            ($(#[$($m),+])+
+            pub enum $e {
+                $($v$(=$val)*),+
+            }) -> ($e, $($v),+)
+        );
+    };
     ($(#[$($m:meta),+])+ pub enum $e:ident { $($v:ident $(=$val:expr)*),+ } ) => {
         arg_enum!(@impls
             ($(#[$($m),+])+
@@ -353,7 +361,14 @@ macro_rules! arg_enum {
             }) -> ($e, $($v),+)
         );
     };
-    ($(#[$($m:meta),+])+ enum $e:ident { $($v:ident $(=$val:expr)*),+  } ) => {
+    ($(#[$($m:meta),+])+ enum $e:ident { $($v:ident $(=$val:expr)*,)+ } ) => {
+        arg_enum!($(#[$($m:meta),+])+
+            enum $e:ident {
+                $($v:ident $(=$val:expr)*),+
+            }
+        );
+    };
+    ($(#[$($m:meta),+])+ enum $e:ident { $($v:ident $(=$val:expr)*),+ } ) => {
         arg_enum!(@impls
             ($(#[$($m),+])+
             enum $e {
@@ -361,6 +376,11 @@ macro_rules! arg_enum {
             }) -> ($e, $($v),+)
         );
     };
+    (pub enum $e:ident { $($v:ident $(=$val:expr)*,)+ } ) => {
+        arg_enum!(pub enum $e:ident {
+            $($v:ident $(=$val:expr)*),+
+        });
+    };
     (pub enum $e:ident { $($v:ident $(=$val:expr)*),+ } ) => {
         arg_enum!(@impls
             (pub enum $e {
@@ -368,6 +388,11 @@ macro_rules! arg_enum {
             }) -> ($e, $($v),+)
         );
     };
+    (enum $e:ident { $($v:ident $(=$val:expr)*,)+ } ) => {
+        arg_enum!(enum $e:ident {
+            $($v:ident $(=$val:expr)*),+
+        });
+    };
     (enum $e:ident { $($v:ident $(=$val:expr)*),+ } ) => {
         arg_enum!(@impls
             (enum $e {


Test patch:
diff --git a/tests/macros.rs b/tests/macros.rs
index ae20e27b..fec61132 100644
--- a/tests/macros.rs
+++ b/tests/macros.rs
@@ -159,3 +159,15 @@ fn arg_enum() {
     }
     assert_eq!("Alpha".parse::<Greek>(), Ok(Greek::Alpha));
 }
+
+#[test]
+fn arg_enum_trailing_comma() {
+    arg_enum!{
+        #[derive(Debug, PartialEq, Copy, Clone)]
+        pub enum Greek {
+            Alpha,
+            Bravo,
+        }
+    }
+    assert_eq!("Alpha".parse::<Greek>(), Ok(Greek::Alpha));
+}