diff --git a/context.go b/context.go index 374060e..73086c8 100644 --- a/context.go +++ b/context.go @@ -279,6 +279,12 @@ func (c *Context) trace(node *Node) (err error) { // nolint: gocyclo case string: switch { + case v == "-": + fallthrough + default: // nolint + c.scan.Pop() + c.scan.PushTyped(token.Value, PositionalArgumentToken) + // Indicates end of parsing. All remaining arguments are treated as positional arguments only. case v == "--": c.scan.Pop() @@ -305,9 +311,6 @@ func (c *Context) trace(node *Node) (err error) { // nolint: gocyclo } c.scan.PushTyped(parts[0], FlagToken) - case v == "-": - return errors.New("expected short flag") - // Short flag. case strings.HasPrefix(v, "-"): c.scan.Pop() @@ -316,10 +319,6 @@ func (c *Context) trace(node *Node) (err error) { // nolint: gocyclo c.scan.PushTyped(tail, ShortFlagTailToken) } c.scan.PushTyped(v[1:2], ShortFlagToken) - - default: - c.scan.Pop() - c.scan.PushTyped(token.Value, PositionalArgumentToken) } default: c.scan.Pop() diff --git a/kong_test.go b/kong_test.go index 57f15b6..557894d 100644 --- a/kong_test.go +++ b/kong_test.go @@ -863,3 +863,19 @@ func TestMultipleDefaultCommands(t *testing.T) { _, err := p.Parse([]string{}) require.EqualError(t, err, "can't have more than one default command under ") } + +func TestLoneHpyhen(t *testing.T) { + var cli struct { + Flag string + Arg string `arg:"" optional:""` + } + p := mustNew(t, &cli) + + _, err := p.Parse([]string{"-"}) + require.NoError(t, err) + require.Equal(t, "-", cli.Arg) + + _, err = p.Parse([]string{"--flag", "-"}) + require.NoError(t, err) + require.Equal(t, "-", cli.Flag) +} diff --git a/scanner.go b/scanner.go index d913d07..11b78c3 100644 --- a/scanner.go +++ b/scanner.go @@ -78,13 +78,16 @@ func (t TokenType) IsAny(types ...TokenType) bool { // InferredType tries to infer the type of a token. func (t Token) InferredType() TokenType { - if t.Type == UntypedToken { - if v, ok := t.Value.(string); ok { - if strings.HasPrefix(v, "--") { - return FlagToken - } else if strings.HasPrefix(v, "-") { - return ShortFlagToken - } + if t.Type != UntypedToken { + return t.Type + } + if v, ok := t.Value.(string); ok { + if strings.HasPrefix(v, "--") { // nolint: gocritic + return FlagToken + } else if v == "-" { + return PositionalArgumentToken + } else if strings.HasPrefix(v, "-") { + return ShortFlagToken } } return t.Type diff --git a/scanner_test.go b/scanner_test.go index 9324a18..2b7d8d5 100644 --- a/scanner_test.go +++ b/scanner_test.go @@ -7,11 +7,13 @@ import ( ) func TestScannerTake(t *testing.T) { - s := Scan("a", "b", "c") - require.Equal(t, s.Pop().Value, "a") - require.Equal(t, s.Pop().Value, "b") - require.Equal(t, s.Pop().Value, "c") - require.Equal(t, s.Pop().Type, EOLToken) + s := Scan("a", "b", "c", "-") + require.Equal(t, "a", s.Pop().Value) + require.Equal(t, "b", s.Pop().Value) + require.Equal(t, "c", s.Pop().Value) + hyphen := s.Pop() + require.Equal(t, PositionalArgumentToken, hyphen.InferredType()) + require.Equal(t, EOLToken, s.Pop().Type) } func TestScannerPeek(t *testing.T) {