chore: optionally allow parsing of hyphen-prefixied flag parameters
This allows for eg. `foo --number -10`, `foo --flag -bar`. Fixes #478, #315.
This commit is contained in:
+1
-1
@@ -99,7 +99,7 @@ type Context struct {
|
|||||||
// This just constructs a new trace. To fully apply the trace you must call Reset(), Resolve(),
|
// This just constructs a new trace. To fully apply the trace you must call Reset(), Resolve(),
|
||||||
// Validate() and Apply().
|
// Validate() and Apply().
|
||||||
func Trace(k *Kong, args []string) (*Context, error) {
|
func Trace(k *Kong, args []string) (*Context, error) {
|
||||||
s := Scan(args...)
|
s := Scan(args...).AllowHyphenPrefixedParameters(k.allowHyphenated)
|
||||||
c := &Context{
|
c := &Context{
|
||||||
Kong: k,
|
Kong: k,
|
||||||
Args: args,
|
Args: args,
|
||||||
|
|||||||
@@ -56,16 +56,17 @@ type Kong struct {
|
|||||||
registry *Registry
|
registry *Registry
|
||||||
ignoreFields []*regexp.Regexp
|
ignoreFields []*regexp.Regexp
|
||||||
|
|
||||||
noDefaultHelp bool
|
noDefaultHelp bool
|
||||||
usageOnError usageOnError
|
allowHyphenated bool
|
||||||
help HelpPrinter
|
usageOnError usageOnError
|
||||||
shortHelp HelpPrinter
|
help HelpPrinter
|
||||||
helpFormatter HelpValueFormatter
|
shortHelp HelpPrinter
|
||||||
helpOptions HelpOptions
|
helpFormatter HelpValueFormatter
|
||||||
helpFlag *Flag
|
helpOptions HelpOptions
|
||||||
groups []Group
|
helpFlag *Flag
|
||||||
vars Vars
|
groups []Group
|
||||||
flagNamer func(string) string
|
vars Vars
|
||||||
|
flagNamer func(string) string
|
||||||
|
|
||||||
// Set temporarily by Options. These are applied after build().
|
// Set temporarily by Options. These are applied after build().
|
||||||
postBuildOptions []Option
|
postBuildOptions []Option
|
||||||
|
|||||||
+36
-9
@@ -1043,15 +1043,6 @@ func TestParentBindings(t *testing.T) {
|
|||||||
assert.Equal(t, "foo", cli.Command.value)
|
assert.Equal(t, "foo", cli.Command.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNumericParamErrors(t *testing.T) {
|
|
||||||
var cli struct {
|
|
||||||
Name string
|
|
||||||
}
|
|
||||||
parser := mustNew(t, &cli)
|
|
||||||
_, err := parser.Parse([]string{"--name", "-10"})
|
|
||||||
assert.EqualError(t, err, `--name: expected string value but got "-10" (short flag); perhaps try --name="-10"?`)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDefaultValueIsHyphen(t *testing.T) {
|
func TestDefaultValueIsHyphen(t *testing.T) {
|
||||||
var cli struct {
|
var cli struct {
|
||||||
Flag string `default:"-"`
|
Flag string `default:"-"`
|
||||||
@@ -2677,3 +2668,39 @@ func TestProviderWithoutError(t *testing.T) {
|
|||||||
err = kctx.Run()
|
err = kctx.Run()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParseHyphenParameter(t *testing.T) {
|
||||||
|
type shortFlag struct {
|
||||||
|
Flag string `short:"f"`
|
||||||
|
Other string `short:"o"`
|
||||||
|
Numeric int `short:"n"`
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("ShortFlag", func(t *testing.T) {
|
||||||
|
actual := &shortFlag{}
|
||||||
|
_, err := mustNew(t, actual, kong.WithHyphenPrefixedParameters(true)).Parse([]string{"-f", "-foo"})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, &shortFlag{Flag: "-foo"}, actual)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("LongFlag", func(t *testing.T) {
|
||||||
|
actual := &shortFlag{}
|
||||||
|
_, err := mustNew(t, actual, kong.WithHyphenPrefixedParameters(true)).Parse([]string{"--flag", "-foo"})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, &shortFlag{Flag: "-foo"}, actual)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("ParamMatchesFlag", func(t *testing.T) {
|
||||||
|
actual := &shortFlag{}
|
||||||
|
_, err := mustNew(t, actual, kong.WithHyphenPrefixedParameters(true)).Parse([]string{"--flag", "-oo"})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, &shortFlag{Flag: "-oo"}, actual)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("NegativeNumber", func(t *testing.T) {
|
||||||
|
actual := &shortFlag{}
|
||||||
|
_, err := mustNew(t, actual, kong.WithHyphenPrefixedParameters(true)).Parse([]string{"--numeric", "-10"})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, &shortFlag{Numeric: -10}, actual)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
+10
@@ -55,6 +55,16 @@ func Exit(exit func(int)) Option {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithHyphenPrefixedParameters enables or disables hyphen-prefixed parameters.
|
||||||
|
//
|
||||||
|
// These are disabled by default.
|
||||||
|
func WithHyphenPrefixedParameters(enable bool) Option {
|
||||||
|
return OptionFunc(func(k *Kong) error {
|
||||||
|
k.allowHyphenated = enable
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
type embedded struct {
|
type embedded struct {
|
||||||
strct any
|
strct any
|
||||||
tags []string
|
tags []string
|
||||||
|
|||||||
+11
-2
@@ -111,7 +111,8 @@ func (t Token) IsValue() bool {
|
|||||||
//
|
//
|
||||||
// [{FlagToken, "foo"}, {FlagValueToken, "bar"}]
|
// [{FlagToken, "foo"}, {FlagValueToken, "bar"}]
|
||||||
type Scanner struct {
|
type Scanner struct {
|
||||||
args []Token
|
allowHyphenated bool
|
||||||
|
args []Token
|
||||||
}
|
}
|
||||||
|
|
||||||
// ScanAsType creates a new Scanner from args with the given type.
|
// ScanAsType creates a new Scanner from args with the given type.
|
||||||
@@ -133,6 +134,14 @@ func ScanFromTokens(tokens ...Token) *Scanner {
|
|||||||
return &Scanner{args: tokens}
|
return &Scanner{args: tokens}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AllowHyphenPrefixedParameters enables or disables hyphen-prefixed flag parameters on this Scanner.
|
||||||
|
//
|
||||||
|
// Disabled by default.
|
||||||
|
func (s *Scanner) AllowHyphenPrefixedParameters(enable bool) *Scanner {
|
||||||
|
s.allowHyphenated = enable
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
// Len returns the number of input arguments.
|
// Len returns the number of input arguments.
|
||||||
func (s *Scanner) Len() int {
|
func (s *Scanner) Len() int {
|
||||||
return len(s.args)
|
return len(s.args)
|
||||||
@@ -162,7 +171,7 @@ func (e *expectedError) Error() string {
|
|||||||
// "context" is used to assist the user if the value can not be popped, eg. "expected <context> value but got <type>"
|
// "context" is used to assist the user if the value can not be popped, eg. "expected <context> value but got <type>"
|
||||||
func (s *Scanner) PopValue(context string) (Token, error) {
|
func (s *Scanner) PopValue(context string) (Token, error) {
|
||||||
t := s.Pop()
|
t := s.Pop()
|
||||||
if !t.IsValue() {
|
if !s.allowHyphenated && !t.IsValue() {
|
||||||
return t, &expectedError{context, t}
|
return t, &expectedError{context, t}
|
||||||
}
|
}
|
||||||
return t, nil
|
return t, nil
|
||||||
|
|||||||
Reference in New Issue
Block a user