Repository: alecthomas/kong (go)

Issue:
Support parsing integer literals
When typing a long integer number, using underscore characters between successive digits can improve readability. For instance, for the number `1000000000`, it becomes `1_000_000_000` with underscore characters. This is easy to read. This is also the format defined in the Go spec https://go.dev/ref/spec#Integer_literals

> For readability, an underscore character _ may appear after a base prefix or between successive digits; such underscores do not change the literal's value. 

Kong cannot parse an int string like `1_000`. It would return an error

```
expected a valid 64 bit int but got "10_000_000"
```

Pull request description:
Support parsing integer literals
Resolve #528

Patch:
diff --git a/mapper.go b/mapper.go
index db3f24e..7e97836 100644
--- a/mapper.go
+++ b/mapper.go
@@ -387,7 +387,7 @@ func intDecoder(bits int) MapperFunc { //nolint: dupl
 		default:
 			return fmt.Errorf("expected an int but got %q (%T)", t, t.Value)
 		}
-		n, err := strconv.ParseInt(sv, 10, bits)
+		n, err := strconv.ParseInt(sv, 0, bits)
 		if err != nil {
 			return fmt.Errorf("expected a valid %d bit int but got %q", bits, sv)
 		}
@@ -416,7 +416,7 @@ func uintDecoder(bits int) MapperFunc { //nolint: dupl
 		default:
 			return fmt.Errorf("expected an int but got %q (%T)", t, t.Value)
 		}
-		n, err := strconv.ParseUint(sv, 10, bits)
+		n, err := strconv.ParseUint(sv, 0, bits)
 		if err != nil {
 			return fmt.Errorf("expected a valid %d bit uint but got %q", bits, sv)
 		}


Test patch:
diff --git a/mapper_test.go b/mapper_test.go
index 947f836..dd04119 100644
--- a/mapper_test.go
+++ b/mapper_test.go
@@ -395,6 +395,31 @@ func TestNumbers(t *testing.T) {
 			I64: math.MinInt64,
 		}, cli)
 	})
+	t.Run("Integer literals", func(t *testing.T) {
+		integerLiterals := "10_0"
+
+		_, err := p.Parse([]string{
+			fmt.Sprintf("--i-8=%s", integerLiterals),
+			fmt.Sprintf("--i-16=%s", integerLiterals),
+			fmt.Sprintf("--i-32=%s", integerLiterals),
+			fmt.Sprintf("--i-64=%s", integerLiterals),
+			fmt.Sprintf("--u-8=%s", integerLiterals),
+			fmt.Sprintf("--u-16=%s", integerLiterals),
+			fmt.Sprintf("--u-32=%s", integerLiterals),
+			fmt.Sprintf("--u-64=%s", integerLiterals),
+		})
+		assert.NoError(t, err)
+		assert.Equal(t, CLI{
+			I8:  int8(100),
+			I16: int16(100),
+			I32: int32(100),
+			I64: int64(100),
+			U8:  uint8(100),
+			U16: uint16(100),
+			U32: uint32(100),
+			U64: uint64(100),
+		}, cli)
+	})
 }
 
 func TestJSONLargeNumber(t *testing.T) {