Produce a more useful error when flag-like values are used for flag values.

eg.  myapp: error: --log-level: expected string value but got "--foo" (long flag); perhaps try --log-level="--foo"?
This commit is contained in:
Alec Thomas
2019-06-21 10:23:09 +10:00
parent 1076f5ee1f
commit 95de7d2f0d
4 changed files with 28 additions and 14 deletions
+18 -11
View File
@@ -3,8 +3,6 @@ package kong
import (
"fmt"
"strings"
"github.com/pkg/errors"
)
// TokenType is the type of a token.
@@ -14,11 +12,11 @@ type TokenType int
const (
UntypedToken TokenType = iota
EOLToken
FlagToken // --<flag>
FlagValueToken // =<value>
ShortFlagToken // -<short>[<tail]
ShortFlagTailToken // <tail>
PositionalArgumentToken // <arg>
FlagToken // --<flag>
FlagValueToken // =<value>
ShortFlagToken // -<short>[<tail]
ShortFlagTailToken // <tail>
PositionalArgumentToken // <arg>
)
func (t TokenType) String() string {
@@ -142,13 +140,22 @@ func (s *Scanner) Pop() Token {
return arg
}
type expectedError struct {
context string
token Token
}
func (e *expectedError) Error() string {
return fmt.Sprintf("expected %s value but got %q (%s)", e.context, e.token, e.token.InferredType())
}
// PopValue pops a value token, or returns an error.
//
// "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) {
t := s.Pop()
if !t.IsValue() {
return t, errors.Errorf("expected %s value but got %q (%s)", context, t, t.InferredType())
return t, &expectedError{context, t}
}
return t, nil
}
@@ -157,9 +164,9 @@ func (s *Scanner) PopValue(context string) (Token, error) {
//
// "context" is used to assist the user if the value can not be popped, eg. "expected <context> value but got <type>"
func (s *Scanner) PopValueInto(context string, target interface{}) error {
t := s.Pop()
if !t.IsValue() {
return errors.Errorf("expected %s value but got %q (%s)", context, t, t.InferredType())
t, err := s.PopValue(context)
if err != nil {
return err
}
return jsonTranscode(t.Value, target)
}