summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIllia Volochii <[email protected]>2018-04-26 21:10:44 +0300
committerIllia Volochii <[email protected]>2018-04-26 21:10:44 +0300
commit75bf1a1525e860418b617b6440255fddd2eed205 (patch)
tree7d0e517277a2f398fecaa7dfb4ad874274277c8d
parent074ee5f759999d103724b5594e33901adeb28e73 (diff)
Fix providing multiple values via environment variables
-rw-r--r--README.md16
-rw-r--r--parse.go19
-rw-r--r--parse_test.go36
3 files changed, 70 insertions, 1 deletions
diff --git a/README.md b/README.md
index e8b62a4..362f455 100644
--- a/README.md
+++ b/README.md
@@ -94,6 +94,22 @@ $ NUM_WORKERS=4 ./example
Workers: 4
```
+You should use a JSON array of strings (value will be converted if
+necessary) in the case of multiple values:
+
+```go
+var args struct {
+ Workers []int `arg:"env"`
+}
+arg.MustParse(&args)
+fmt.Println("Workers:", args.Workers)
+```
+
+```
+$ WORKERS='["1", "99"]' ./example
+Workers: [1 99]
+```
+
### Usage strings
```go
var args struct {
diff --git a/parse.go b/parse.go
index 1416223..03b6c07 100644
--- a/parse.go
+++ b/parse.go
@@ -2,6 +2,7 @@ package arg
import (
"encoding"
+ "encoding/json"
"errors"
"fmt"
"os"
@@ -275,7 +276,23 @@ func process(specs []*spec, args []string) error {
}
if spec.env != "" {
if value, found := os.LookupEnv(spec.env); found {
- err := scalar.ParseValue(spec.dest, value)
+ var err error
+ if spec.multiple {
+ // expect a JSON array of strings in an environment
+ // variable in the case of multiple values
+ var values []string
+ err = json.Unmarshal([]byte(value), &values)
+ if err != nil {
+ return fmt.Errorf(
+ "error processing environment variable %s (it should be a JSON array of strings):\n%v",
+ spec.env,
+ err,
+ )
+ }
+ err = setSlice(spec.dest, values, !spec.separate)
+ } else {
+ err = scalar.ParseValue(spec.dest, value)
+ }
if err != nil {
return fmt.Errorf("error processing environment variable %s: %v", spec.env, err)
}
diff --git a/parse_test.go b/parse_test.go
index 1461c02..579d8b7 100644
--- a/parse_test.go
+++ b/parse_test.go
@@ -580,6 +580,42 @@ func TestEnvironmentVariableRequired(t *testing.T) {
assert.Equal(t, "bar", args.Foo)
}
+func TestEnvironmentVariableSliceArgumentString(t *testing.T) {
+ var args struct {
+ Foo []string `arg:"env"`
+ }
+ setenv(t, "FOO", "[\"bar\", \"baz\"]")
+ MustParse(&args)
+ assert.Equal(t, []string{"bar", "baz"}, args.Foo)
+}
+
+func TestEnvironmentVariableSliceArgumentInteger(t *testing.T) {
+ var args struct {
+ Foo []int `arg:"env"`
+ }
+ setenv(t, "FOO", "[\"1\", \"99\"]")
+ MustParse(&args)
+ assert.Equal(t, []int{1, 99}, args.Foo)
+}
+
+func TestEnvironmentVariableSliceArgumentFloat(t *testing.T) {
+ var args struct {
+ Foo []float32 `arg:"env"`
+ }
+ setenv(t, "FOO", "[\"1.1\", \"99.9\"]")
+ MustParse(&args)
+ assert.Equal(t, []float32{1.1, 99.9}, args.Foo)
+}
+
+func TestEnvironmentVariableSliceArgumentBool(t *testing.T) {
+ var args struct {
+ Foo []bool `arg:"env"`
+ }
+ setenv(t, "FOO", "[\"true\", \"false\", \"0\", \"1\"]")
+ MustParse(&args)
+ assert.Equal(t, []bool{true, false, false, true}, args.Foo)
+}
+
type textUnmarshaler struct {
val int
}