Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ type ValueValidator interface {
IsValidValue(value string) error
}

// Defaulter is the interface implemented by types that can provide dynamic
// default values at runtime.
type Defaulter interface {
Default() ([]string, error)
}

func getBase(options multiTag, base int) (int, error) {
sbase := options.Get("base")

Expand Down
8 changes: 8 additions & 0 deletions group.go
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,14 @@ func (g *Group) scanStruct(realval reflect.Value, sfield *reflect.StructField, h
option.shortAndLongName())
}

if defaulter, ok := option.value.Interface().(Defaulter); ok {
def, err := defaulter.Default()
if err != nil {
return err
}
option.Default = def
}

g.options = append(g.options, option)
}

Expand Down
39 changes: 39 additions & 0 deletions parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,45 @@ func TestNoDefaultsForBools(t *testing.T) {
}
}

func TestDynamicDefaults(t *testing.T) {
var opts struct {
DD DynamicDefault `short:"d"`
}
_, err := ParseArgs(&opts, []string{"test"})
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
if opts.DD != 42 {
t.Errorf("Dynamic default value not provided; expected 42 but was %d", opts.DD)
}
}

func TestDynamicDefaultError(t *testing.T) {
var opts struct {
DD DynamicDefaultError `short:"d"`
}
_, err := ParseArgs(&opts, []string{"test"})
if err == nil {
t.Fatalf("Expected error, was none")
}
const expected = "couldn't provide default"
if !strings.Contains(err.Error(), expected) {
t.Errorf("Expected error %q to contain substring %q", err, expected)
}
}

type DynamicDefault int

func (dd DynamicDefault) Default() ([]string, error) {
return []string{"42"}, nil
}

type DynamicDefaultError int

func (dd DynamicDefaultError) Default() ([]string, error) {
return nil, errors.New("couldn't provide default")
}

func TestUnquoting(t *testing.T) {
var tests = []struct {
arg string
Expand Down