Files
kong/tag.go
T
2018-05-21 09:25:19 -04:00

137 lines
2.4 KiB
Go

package kong
import (
"fmt"
"reflect"
"strings"
"unicode/utf8"
)
type Tag struct {
Cmd bool
Arg bool
Required bool
Optional bool
Help string
Type string
Default string
Format string
Placeholder string
Env string
Short rune
}
func parseCSV(s string) ([]string, error) {
num := 0
parts := []string{}
current := []rune{}
add := func() {
parts = append(parts, string(current))
current = []rune{}
num++
}
quotes := false
runes := []rune(s)
for idx := 0; idx < len(runes); idx++ {
r := runes[idx]
next := rune(0)
eof := false
if idx < len(runes)-1 {
next = runes[idx+1]
} else {
eof = true
}
if !quotes && r == ',' {
add()
continue
}
if r == '\\' {
if next == '\'' {
idx++
r = '\''
}
} else if r == '\'' {
if quotes {
quotes = false
if next == ',' || eof {
continue
}
return parts, fmt.Errorf("%v has an unexpected char at pos %v", s, idx)
} else {
quotes = true
continue
}
}
current = append(current, r)
}
if quotes {
return parts, fmt.Errorf("%v is not quoted properly", s)
}
add()
return parts, nil
}
func parseTag(fv reflect.Value, s string) (*Tag, error) {
t := &Tag{}
if s == "" {
return t, nil
}
parts, err := parseCSV(s)
if err != nil {
return t, err
}
for _, part := range parts {
is := func(m string) bool { return part == m }
value := func(m string) (string, bool) {
split := strings.SplitN(part, "=", 2)
if split[0] != m {
return "", false
}
if len(split) == 1 {
return "", true
}
return split[1], true
}
if is("cmd") {
t.Cmd = true
} else if is("arg") {
t.Arg = true
} else if is("required") {
t.Required = true
} else if is("optional") {
t.Optional = true
} else if v, ok := value("default"); ok {
t.Default = v
} else if v, ok := value("help"); ok {
t.Help = v
} else if v, ok := value("type"); ok {
t.Type = v
} else if v, ok := value("placeholder"); ok {
t.Placeholder = v
} else if v, ok := value("env"); ok {
t.Env = v
} else if v, ok := value("rune"); ok {
t.Short, _ = utf8.DecodeRuneInString(v)
if t.Short == utf8.RuneError {
t.Short = 0
}
} else {
return t, fmt.Errorf("%v is an unknown kong key", part)
}
}
if t.Placeholder == "" {
t.Placeholder = strings.ToUpper(dashedString(fv.Type().Name()))
}
return t, nil
}