Skip to content

Commit

Permalink
Optional arguments initializing from environment variables
Browse files Browse the repository at this point in the history
  • Loading branch information
vbogretsov committed Dec 26, 2020
1 parent 97dac4c commit 4553db7
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 2 deletions.
9 changes: 9 additions & 0 deletions README.md
Expand Up @@ -145,14 +145,23 @@ type Options struct {
Required bool
Validate func(args []string) error
Help string
Env argparse.Env
Default interface{}
}
```
where `argparse.Env` is:
```go
type Env struct {
Name string
Sep string
}
```

You can Set `Required` to let it know if it should ask for arguments.
Or you can set `Validate` as a lambda function to make it know while value is valid.
Or you can set `Help` for your beautiful help document.
Or you can set `Default` will set the default value if user does not provide a value.
Or you can set `Env` to set value from envirotnment variable if user does not provide a value.

Example:
```
Expand Down
12 changes: 12 additions & 0 deletions argparse.go
Expand Up @@ -88,6 +88,8 @@ type Parser struct {
// (e.g. as String does), then these are provided as args to function. If validation fails the error must be returned,
// which will be the output of `Parser.Parse` method.
//
// Options.Env - Environment variable that will be used to initialize an argument if its value is not provided.
//
// Options.Help - A help message to be displayed in Usage output. Can be of any length as the message will be
// formatted to fit max screen width of 100 characters.
//
Expand All @@ -99,6 +101,16 @@ type Options struct {
Validate func(args []string) error
Help string
Default interface{}
Env Env
}

// Env represents environment variable settings to initialize an arg
// Env.Name - environment variable name.
//
// Env.Sep - separator used for list values.
type Env struct {
Name string
Sep string
}

// NewParser creates new Parser object that will allow to add arguments for parsing
Expand Down
72 changes: 72 additions & 0 deletions argparse_test.go
Expand Up @@ -832,6 +832,42 @@ func TestIntSimple2(t *testing.T) {
}
}

func TestIntFromEnv(t *testing.T) {
testArgs := []string{"progname"}

envName := "PROGNAME_FLAG_ARG1"
envValue := "10"

p := NewParser("", "descriptiom")
i1 := p.Int("f", "flag-arg1", &Options{
Required: true,
Env: Env{Name: envName},
})

if err := os.Setenv(envName, envValue); err != nil {
t.Errorf("Test %s failed. Unable to set env %s=%s: %v", t.Name(), envName, envValue, err)
return
}
defer os.Unsetenv(envName)

err := p.Parse(testArgs)

if err != nil {
t.Errorf("Test %s don't expect error %v", t.Name(), err)
return
}

if i1 == nil {
t.Errorf("Test %s failed with flag1 being nil pointer", t.Name())
return
}

if *i1 != 10 {
t.Errorf("Test %s failed. Want: [%s], got: [%d]", t.Name(), envValue, *i1)
return
}
}

func TestIntFailSimple1(t *testing.T) {
testArgs := []string{"progname", "--flag-arg1", "string"}

Expand Down Expand Up @@ -1403,6 +1439,42 @@ func TestListAddArgumentFail(t *testing.T) {
}
}

func TestListFromEnv(t *testing.T) {
testArgs := []string{"progname"}

envName := "PROGNAME_FLAG_ARG1"
envValue := "a1,a2,a3"

p := NewParser("", "descriptiom")
l1 := p.List("f", "flag-arg1", &Options{
Env: Env{Name: envName, Sep: ","},
})

if err := os.Setenv(envName, envValue); err != nil {
t.Errorf("Test %s failed. Unable to set env %s=%s: %v", t.Name(), envName, envValue, err)
return
}
defer os.Unsetenv(envName)

err := p.Parse(testArgs)

if err != nil {
t.Errorf("Test %s don't expect error %v", t.Name(), err)
return
}

if l1 == nil {
t.Errorf("Test %s failed with flag1 being nil pointer", t.Name())
return
}

expected := []string{"a1", "a2", "a3"}
if reflect.DeepEqual(expected, l1) {
t.Errorf("Test %s failed. Want: [%s], got: [%v]", t.Name(), envValue, *l1)
return
}
}

func TestListSimple1(t *testing.T) {
testArgs := []string{"progname", "--flag-arg1", "test1", "--flag-arg1", "test2"}
list1Expect := []string{"test1", "test2"}
Expand Down
27 changes: 25 additions & 2 deletions command.go
Expand Up @@ -2,6 +2,7 @@ package argparse

import (
"fmt"
"os"
"strings"
)

Expand Down Expand Up @@ -118,13 +119,35 @@ func (o *Command) parseArguments(args *[]string) error {
}
}

if oarg.opts == nil {
continue
}

// Check for environment variable to initialize argument
if !oarg.parsed && oarg.opts.Env.Name != "" {
env := os.Getenv(oarg.opts.Env.Name)
if env != "" {
var argv []string
if oarg.opts.Env.Sep != "" {
argv = strings.Split(env, oarg.opts.Env.Sep)
} else {
argv = []string{env}
}
for _, v := range argv {
if err := oarg.parse([]string{v}, 1); err != nil {
return err
}
}
}
}

// Check if arg is required and not provided
if oarg.opts != nil && oarg.opts.Required && !oarg.parsed {
if !oarg.parsed && oarg.opts.Required {
return fmt.Errorf("[%s] is required", oarg.name())
}

// Check for argument default value and if provided try to type cast and assign
if oarg.opts != nil && oarg.opts.Default != nil && !oarg.parsed {
if !oarg.parsed && oarg.opts.Default != nil {
err := oarg.setDefault()
if err != nil {
return err
Expand Down

0 comments on commit 4553db7

Please sign in to comment.