Add support for environment variables
This commit is contained in:
parent
c9155bb0c3
commit
8dd29d34bf
35
README.md
35
README.md
|
@ -54,6 +54,41 @@ Input: src.txt
|
||||||
Output: [x.out y.out z.out]
|
Output: [x.out y.out z.out]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Environment variables
|
||||||
|
|
||||||
|
```go
|
||||||
|
var args struct {
|
||||||
|
Workers int `arg:"env"`
|
||||||
|
}
|
||||||
|
arg.MustParse(&args)
|
||||||
|
fmt.Println("Workers:", args.Workers)
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
$ WORKERS=4 ./example
|
||||||
|
Workers: 4
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
$ WORKERS=4 ./example --workers=6
|
||||||
|
Workers: 6
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also override the name of the environment variable:
|
||||||
|
|
||||||
|
```go
|
||||||
|
var args struct {
|
||||||
|
Workers int `arg:"env:NUM_WORKERS"`
|
||||||
|
}
|
||||||
|
arg.MustParse(&args)
|
||||||
|
fmt.Println("Workers:", args.Workers)
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
$ NUM_WORKERS=4 ./example
|
||||||
|
Workers: 4
|
||||||
|
```
|
||||||
|
|
||||||
### Usage strings
|
### Usage strings
|
||||||
```go
|
```go
|
||||||
var args struct {
|
var args struct {
|
||||||
|
|
17
parse.go
17
parse.go
|
@ -18,6 +18,7 @@ type spec struct {
|
||||||
required bool
|
required bool
|
||||||
positional bool
|
positional bool
|
||||||
help string
|
help string
|
||||||
|
env string
|
||||||
wasPresent bool
|
wasPresent bool
|
||||||
isBool bool
|
isBool bool
|
||||||
}
|
}
|
||||||
|
@ -130,6 +131,13 @@ func NewParser(dests ...interface{}) (*Parser, error) {
|
||||||
spec.positional = true
|
spec.positional = true
|
||||||
case key == "help":
|
case key == "help":
|
||||||
spec.help = value
|
spec.help = value
|
||||||
|
case key == "env":
|
||||||
|
// Use override name if provided
|
||||||
|
if value != "" {
|
||||||
|
spec.env = value
|
||||||
|
} else {
|
||||||
|
spec.env = strings.ToUpper(field.Name)
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unrecognized tag '%s' on field %s", key, tag)
|
return nil, fmt.Errorf("unrecognized tag '%s' on field %s", key, tag)
|
||||||
}
|
}
|
||||||
|
@ -179,6 +187,15 @@ func process(specs []*spec, args []string) error {
|
||||||
if spec.short != "" {
|
if spec.short != "" {
|
||||||
optionMap[spec.short] = spec
|
optionMap[spec.short] = spec
|
||||||
}
|
}
|
||||||
|
if spec.env != "" {
|
||||||
|
if value, found := os.LookupEnv(spec.env); found {
|
||||||
|
err := setScalar(spec.dest, value)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error processing environment variable %s: %v", spec.env, err)
|
||||||
|
}
|
||||||
|
spec.wasPresent = true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// process each string from the command line
|
// process each string from the command line
|
||||||
|
|
|
@ -357,3 +357,53 @@ func TestMustParse(t *testing.T) {
|
||||||
assert.Equal(t, "bar", args.Foo)
|
assert.Equal(t, "bar", args.Foo)
|
||||||
assert.NotNil(t, parser)
|
assert.NotNil(t, parser)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEnvironmentVariable(t *testing.T) {
|
||||||
|
var args struct {
|
||||||
|
Foo string `arg:"env"`
|
||||||
|
}
|
||||||
|
os.Setenv("FOO", "bar")
|
||||||
|
os.Args = []string{"example"}
|
||||||
|
MustParse(&args)
|
||||||
|
assert.Equal(t, "bar", args.Foo)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEnvironmentVariableOverrideName(t *testing.T) {
|
||||||
|
var args struct {
|
||||||
|
Foo string `arg:"env:BAZ"`
|
||||||
|
}
|
||||||
|
os.Setenv("BAZ", "bar")
|
||||||
|
os.Args = []string{"example"}
|
||||||
|
MustParse(&args)
|
||||||
|
assert.Equal(t, "bar", args.Foo)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEnvironmentVariableOverrideArgument(t *testing.T) {
|
||||||
|
var args struct {
|
||||||
|
Foo string `arg:"env"`
|
||||||
|
}
|
||||||
|
os.Setenv("FOO", "bar")
|
||||||
|
os.Args = []string{"example", "--foo", "baz"}
|
||||||
|
MustParse(&args)
|
||||||
|
assert.Equal(t, "baz", args.Foo)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEnvironmentVariableError(t *testing.T) {
|
||||||
|
var args struct {
|
||||||
|
Foo int `arg:"env"`
|
||||||
|
}
|
||||||
|
os.Setenv("FOO", "bar")
|
||||||
|
os.Args = []string{"example"}
|
||||||
|
err := Parse(&args)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEnvironmentVariableRequired(t *testing.T) {
|
||||||
|
var args struct {
|
||||||
|
Foo string `arg:"env,required"`
|
||||||
|
}
|
||||||
|
os.Setenv("FOO", "bar")
|
||||||
|
os.Args = []string{"example"}
|
||||||
|
MustParse(&args)
|
||||||
|
assert.Equal(t, "bar", args.Foo)
|
||||||
|
}
|
||||||
|
|
|
@ -10,9 +10,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestWriteUsage(t *testing.T) {
|
func TestWriteUsage(t *testing.T) {
|
||||||
expectedUsage := "usage: example [--name NAME] [--value VALUE] [--verbose] [--dataset DATASET] [--optimize OPTIMIZE] [--ids IDS] INPUT [OUTPUT [OUTPUT ...]]\n"
|
expectedUsage := "usage: example [--name NAME] [--value VALUE] [--verbose] [--dataset DATASET] [--optimize OPTIMIZE] [--ids IDS] [--workers WORKERS] INPUT [OUTPUT [OUTPUT ...]]\n"
|
||||||
|
|
||||||
expectedHelp := `usage: example [--name NAME] [--value VALUE] [--verbose] [--dataset DATASET] [--optimize OPTIMIZE] [--ids IDS] INPUT [OUTPUT [OUTPUT ...]]
|
expectedHelp := `usage: example [--name NAME] [--value VALUE] [--verbose] [--dataset DATASET] [--optimize OPTIMIZE] [--ids IDS] [--workers WORKERS] INPUT [OUTPUT [OUTPUT ...]]
|
||||||
|
|
||||||
positional arguments:
|
positional arguments:
|
||||||
input
|
input
|
||||||
|
@ -26,6 +26,8 @@ options:
|
||||||
--optimize OPTIMIZE, -O OPTIMIZE
|
--optimize OPTIMIZE, -O OPTIMIZE
|
||||||
optimization level
|
optimization level
|
||||||
--ids IDS Ids
|
--ids IDS Ids
|
||||||
|
--workers WORKERS, -w WORKERS
|
||||||
|
number of workers to start
|
||||||
--help, -h display this help and exit
|
--help, -h display this help and exit
|
||||||
`
|
`
|
||||||
var args struct {
|
var args struct {
|
||||||
|
@ -37,6 +39,7 @@ options:
|
||||||
Dataset string `arg:"help:dataset to use"`
|
Dataset string `arg:"help:dataset to use"`
|
||||||
Optimize int `arg:"-O,help:optimization level"`
|
Optimize int `arg:"-O,help:optimization level"`
|
||||||
Ids []int64 `arg:"help:Ids"`
|
Ids []int64 `arg:"help:Ids"`
|
||||||
|
Workers int `arg:"-w,env:WORKERS,help:number of workers to start"`
|
||||||
}
|
}
|
||||||
args.Name = "Foo Bar"
|
args.Name = "Foo Bar"
|
||||||
args.Value = 42
|
args.Value = 42
|
||||||
|
|
Loading…
Reference in New Issue