Allow "bare" tags and moved tag tests into tag_test.go. Fixes #19

This commit is contained in:
Gerald Kaszuba
2018-06-01 11:24:18 +10:00
committed by Alec Thomas
parent fdc7230e22
commit ed123d1c06
4 changed files with 122 additions and 69 deletions
+1 -1
View File
@@ -49,7 +49,7 @@ func buildNode(v reflect.Value, typ NodeType, seenFlags map[string]bool) *Node {
name = strings.ToLower(dashedString(ft.Name)) name = strings.ToLower(dashedString(ft.Name))
} }
tag := parseTag(fv, ft.Tag.Get("kong")) tag := parseTag(fv, ft)
// Nested structs are either commands or args. // Nested structs are either commands or args.
if ft.Type.Kind() == reflect.Struct && (tag.Cmd || tag.Arg) { if ft.Type.Kind() == reflect.Struct && (tag.Cmd || tag.Arg) {
-58
View File
@@ -246,64 +246,6 @@ func TestMixedRequiredArgs(t *testing.T) {
}) })
} }
func TestDefaultValueForOptionalArg(t *testing.T) {
var cli struct {
Arg string `kong:"arg,optional,default='👌'"`
}
p := mustNew(t, &cli)
_, err := p.Parse(nil)
require.NoError(t, err)
require.Equal(t, "👌", cli.Arg)
}
func TestNoValueInTag(t *testing.T) {
var cli struct {
Empty1 string `kong:"default"`
Empty2 string `kong:"default="`
}
p := mustNew(t, &cli)
_, err := p.Parse(nil)
require.NoError(t, err)
require.Equal(t, "", cli.Empty1)
require.Equal(t, "", cli.Empty2)
}
func TestCommaInQuotes(t *testing.T) {
var cli struct {
Numbers string `kong:"default='1,2'"`
}
p := mustNew(t, &cli)
_, err := p.Parse(nil)
require.NoError(t, err)
require.Equal(t, "1,2", cli.Numbers)
}
func TestBadString(t *testing.T) {
var cli struct {
Numbers string `kong:"default='yay'n"`
}
_, err := New(&cli)
require.Error(t, err)
}
func TestNoQuoteEnd(t *testing.T) {
var cli struct {
Numbers string `kong:"default='yay"`
}
_, err := New(&cli)
require.Error(t, err)
}
func TestEscapedQuote(t *testing.T) {
var cli struct {
DoYouKnow string `kong:"default='i don\\'t know'"`
}
p := mustNew(t, &cli)
_, err := p.Parse(nil)
require.NoError(t, err)
require.Equal(t, "i don't know", cli.DoYouKnow)
}
func TestInvalidDefaultErrors(t *testing.T) { func TestInvalidDefaultErrors(t *testing.T) {
var cli struct { var cli struct {
Flag int `kong:"default='foo'"` Flag int `kong:"default='foo'"`
+26 -10
View File
@@ -26,9 +26,15 @@ type Tag struct {
items map[string]string items map[string]string
} }
func parseCSV(s string) map[string]string { type tagChars struct {
d := map[string]string{} sep, quote, assign rune
}
var kongChars = tagChars{sep: ',', quote: '\'', assign: '='}
var bareChars = tagChars{sep: ' ', quote: '"', assign: ':'}
func parseCSV(s string, chr tagChars) map[string]string {
d := map[string]string{}
key := []rune{} key := []rune{}
value := []rune{} value := []rune{}
quotes := false quotes := false
@@ -51,23 +57,23 @@ func parseCSV(s string) map[string]string {
} else { } else {
eof = true eof = true
} }
if !quotes && r == ',' { if !quotes && r == chr.sep {
add() add()
continue continue
} }
if r == '=' && inKey { if r == chr.assign && inKey {
inKey = false inKey = false
continue continue
} }
if r == '\\' { if r == '\\' {
if next == '\'' { if next == chr.quote {
idx++ idx++
r = '\'' r = chr.quote
} }
} else if r == '\'' { } else if r == chr.quote {
if quotes { if quotes {
quotes = false quotes = false
if next == ',' || eof { if next == chr.sep || eof {
continue continue
} }
fail("%v has an unexpected char at pos %v", s, idx) fail("%v has an unexpected char at pos %v", s, idx)
@@ -91,7 +97,17 @@ func parseCSV(s string) map[string]string {
return d return d
} }
func parseTag(fv reflect.Value, s string) *Tag { func getTagInfo(ft reflect.StructField) (string, tagChars) {
s, ok := ft.Tag.Lookup("kong")
if ok {
return s, kongChars
}
return string(ft.Tag), bareChars
}
func parseTag(fv reflect.Value, ft reflect.StructField) *Tag {
s, chars := getTagInfo(ft)
t := &Tag{ t := &Tag{
items: map[string]string{}, items: map[string]string{},
} }
@@ -99,7 +115,7 @@ func parseTag(fv reflect.Value, s string) *Tag {
return t return t
} }
t.items = parseCSV(s) t.items = parseCSV(s, chars)
t.Cmd = t.Has("cmd") t.Cmd = t.Has("cmd")
t.Arg = t.Has("arg") t.Arg = t.Has("arg")
+95
View File
@@ -0,0 +1,95 @@
package kong
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestDefaultValueForOptionalArg(t *testing.T) {
var cli struct {
Arg string `kong:"arg,optional,default='👌'"`
}
p := mustNew(t, &cli)
_, err := p.Parse(nil)
require.NoError(t, err)
require.Equal(t, "👌", cli.Arg)
}
func TestNoValueInTag(t *testing.T) {
var cli struct {
Empty1 string `kong:"default"`
Empty2 string `kong:"default="`
}
p := mustNew(t, &cli)
_, err := p.Parse(nil)
require.NoError(t, err)
require.Equal(t, "", cli.Empty1)
require.Equal(t, "", cli.Empty2)
}
func TestCommaInQuotes(t *testing.T) {
var cli struct {
Numbers string `kong:"default='1,2'"`
}
p := mustNew(t, &cli)
_, err := p.Parse(nil)
require.NoError(t, err)
require.Equal(t, "1,2", cli.Numbers)
}
func TestBadString(t *testing.T) {
var cli struct {
Numbers string `kong:"default='yay'n"`
}
_, err := New(&cli)
require.Error(t, err)
}
func TestNoQuoteEnd(t *testing.T) {
var cli struct {
Numbers string `kong:"default='yay"`
}
_, err := New(&cli)
require.Error(t, err)
}
func TestEscapedQuote(t *testing.T) {
var cli struct {
DoYouKnow string `kong:"default='i don\\'t know'"`
}
p := mustNew(t, &cli)
_, err := p.Parse(nil)
require.NoError(t, err)
require.Equal(t, "i don't know", cli.DoYouKnow)
}
func TestBareTags(t *testing.T) {
var cli struct {
Cmd struct {
Arg string `arg`
Flag string `required default:"👌"`
} `cmd`
}
p := mustNew(t, &cli)
_, err := p.Parse([]string{"cmd", "arg", "--flag=hi"})
require.NoError(t, err)
require.Equal(t, "hi", cli.Cmd.Flag)
require.Equal(t, "arg", cli.Cmd.Arg)
}
func TestBareTagsWithJsonTag(t *testing.T) {
var cli struct {
Cmd struct {
Arg string `json:"-" optional arg`
Flag string `json:"best_flag" default:"\"'👌'\""`
} `cmd json:"CMD"`
}
p := mustNew(t, &cli)
_, err := p.Parse([]string{"cmd"})
require.NoError(t, err)
require.Equal(t, "\"'👌'\"", cli.Cmd.Flag)
require.Equal(t, "", cli.Cmd.Arg)
}