mcfg: implement SourceCLI.TailCallback (though I'm not convinced about the naming or necessity of it)
This commit is contained in:
parent
f5cea76cb7
commit
ea72c49935
29
mcfg/cli.go
29
mcfg/cli.go
@ -37,6 +37,12 @@ type SourceCLI struct {
|
|||||||
Args []string // if nil then os.Args[1:] is used
|
Args []string // if nil then os.Args[1:] is used
|
||||||
|
|
||||||
DisableHelpPage bool
|
DisableHelpPage bool
|
||||||
|
|
||||||
|
// Normally if any unexpected Arg value is encountered Parse will error out.
|
||||||
|
// If instead TailCallback is set then it will be called whenever the first
|
||||||
|
// unexpected Arg is encountered, and will not error out. TailCallback will
|
||||||
|
// be given a slice of Args starting at the first unexpected element.
|
||||||
|
TailCallback func([]string)
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -61,12 +67,12 @@ func (cli SourceCLI) Parse(params []Param) ([]ParamValue, error) {
|
|||||||
var (
|
var (
|
||||||
key string
|
key string
|
||||||
p Param
|
p Param
|
||||||
pvOk bool
|
pOk bool
|
||||||
pvStrVal string
|
pvStrVal string
|
||||||
pvStrValOk bool
|
pvStrValOk bool
|
||||||
)
|
)
|
||||||
for _, arg := range args {
|
for i, arg := range args {
|
||||||
if pvOk {
|
if pOk {
|
||||||
pvStrVal = arg
|
pvStrVal = arg
|
||||||
pvStrValOk = true
|
pvStrValOk = true
|
||||||
} else if !cli.DisableHelpPage && arg == cliHelpArg {
|
} else if !cli.DisableHelpPage && arg == cliHelpArg {
|
||||||
@ -76,7 +82,7 @@ func (cli SourceCLI) Parse(params []Param) ([]ParamValue, error) {
|
|||||||
} else {
|
} else {
|
||||||
for key, p = range pM {
|
for key, p = range pM {
|
||||||
if arg == key {
|
if arg == key {
|
||||||
pvOk = true
|
pOk = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,24 +90,27 @@ func (cli SourceCLI) Parse(params []Param) ([]ParamValue, error) {
|
|||||||
if !strings.HasPrefix(arg, prefix) {
|
if !strings.HasPrefix(arg, prefix) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
pvOk = true
|
pOk = true
|
||||||
pvStrVal = strings.TrimPrefix(arg, prefix)
|
pvStrVal = strings.TrimPrefix(arg, prefix)
|
||||||
pvStrValOk = true
|
pvStrValOk = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if !pvOk {
|
if !pOk {
|
||||||
|
if cli.TailCallback != nil {
|
||||||
|
cli.TailCallback(args[i:])
|
||||||
|
return pvs, nil
|
||||||
|
}
|
||||||
ctx := mctx.Annotate(context.Background(), "param", arg)
|
ctx := mctx.Annotate(context.Background(), "param", arg)
|
||||||
return nil, merr.New("unexpected config parameter", ctx)
|
return nil, merr.New("unexpected config parameter", ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// pvOk is always true at this point, and so pv is filled in
|
// pOk is always true at this point, and so p is filled in
|
||||||
|
|
||||||
// As a special case for CLI, if a boolean has no value set it means it
|
// As a special case for CLI, if a boolean has no value set it means it
|
||||||
// is true.
|
// is true.
|
||||||
if p.IsBool && !pvStrValOk {
|
if p.IsBool && !pvStrValOk {
|
||||||
pvStrVal = "true"
|
pvStrVal = "true"
|
||||||
pvStrValOk = true
|
|
||||||
} else if !pvStrValOk {
|
} else if !pvStrValOk {
|
||||||
// everything else should have a value. if pvStrVal isn't filled it
|
// everything else should have a value. if pvStrVal isn't filled it
|
||||||
// means the next arg should be one. Continue the loop, it'll get
|
// means the next arg should be one. Continue the loop, it'll get
|
||||||
@ -117,11 +126,11 @@ func (cli SourceCLI) Parse(params []Param) ([]ParamValue, error) {
|
|||||||
|
|
||||||
key = ""
|
key = ""
|
||||||
p = Param{}
|
p = Param{}
|
||||||
pvOk = false
|
pOk = false
|
||||||
pvStrVal = ""
|
pvStrVal = ""
|
||||||
pvStrValOk = false
|
pvStrValOk = false
|
||||||
}
|
}
|
||||||
if pvOk && !pvStrValOk {
|
if pOk && !pvStrValOk {
|
||||||
ctx := mctx.Annotate(p.Context, "param", key)
|
ctx := mctx.Annotate(p.Context, "param", key)
|
||||||
return nil, merr.New("param expected a value", ctx)
|
return nil, merr.New("param expected a value", ctx)
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mediocregopher/mediocre-go-lib/mrand"
|
"github.com/mediocregopher/mediocre-go-lib/mrand"
|
||||||
|
"github.com/mediocregopher/mediocre-go-lib/mtest/massert"
|
||||||
"github.com/mediocregopher/mediocre-go-lib/mtest/mchk"
|
"github.com/mediocregopher/mediocre-go-lib/mtest/mchk"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@ -103,3 +104,52 @@ func TestSourceCLI(t *T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSourceCLITailCallback(t *T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
ctx, _ = WithInt(ctx, "foo", 5, "")
|
||||||
|
ctx, _ = WithBool(ctx, "bar", "")
|
||||||
|
|
||||||
|
var tail []string
|
||||||
|
src := SourceCLI{TailCallback: func(gotTail []string) {
|
||||||
|
tail = gotTail
|
||||||
|
}}
|
||||||
|
|
||||||
|
type testCase struct {
|
||||||
|
args []string
|
||||||
|
expTail []string
|
||||||
|
}
|
||||||
|
|
||||||
|
cases := []testCase{
|
||||||
|
{
|
||||||
|
args: []string{"--foo", "5"},
|
||||||
|
expTail: []string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
args: []string{"--foo", "5", "a", "b", "c"},
|
||||||
|
expTail: []string{"a", "b", "c"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
args: []string{"--foo=5", "a", "b", "c"},
|
||||||
|
expTail: []string{"a", "b", "c"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
args: []string{"--foo", "5", "--bar"},
|
||||||
|
expTail: []string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
args: []string{"--foo", "5", "--bar", "a", "b", "c"},
|
||||||
|
expTail: []string{"a", "b", "c"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range cases {
|
||||||
|
tail = []string{}
|
||||||
|
src.Args = tc.args
|
||||||
|
err := Populate(ctx, src)
|
||||||
|
massert.Require(t, massert.Comment(massert.All(
|
||||||
|
massert.Nil(err),
|
||||||
|
massert.Equal(tc.expTail, tail),
|
||||||
|
), "tc: %#v", tc))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user