ugh parsing

This commit is contained in:
Andy Arthur
2020-05-21 16:56:27 -05:00
parent 7286431588
commit a17914549d
2 changed files with 35 additions and 30 deletions

View File

@@ -24,6 +24,7 @@ import (
var forceOpt = &Option{"force", "f", "", OptionalFlag, "force desc", nil}
var messageOpt = &Option{"message", "m", "msg", OptionalValue, "msg desc", nil}
var fileTypeOpt = &Option{"file-type", "", "", OptionalValue, "file type", nil}
func TestParsing(t *testing.T) {
tests := []struct {
@@ -88,6 +89,13 @@ func TestParsing(t *testing.T) {
expectedOpts: map[string]string{"message": "value"},
expectedArgs: []string{"b", "c"},
},
{
name: "message colon value",
options: []*Option{forceOpt, messageOpt},
args: []string{"b", "--message:value", "c"},
expectedOpts: map[string]string{"message": "value"},
expectedArgs: []string{"b", "c"},
},
{
name: "empty string",
options: []*Option{forceOpt, messageOpt},
@@ -96,11 +104,11 @@ func TestParsing(t *testing.T) {
expectedArgs: []string{"b", ""},
},
{
name: "force abbrev w/o space",
name: "value attached to flag",
options: []*Option{forceOpt},
args: []string{"bbb", "-fccc"},
args: []string{"-fvalue"},
expectedOpts: map[string]string{"force": ""},
expectedArgs: []string{"bbb", "ccc"},
expectedArgs: []string{"value"},
},
{
name: "-mvalue",
@@ -157,6 +165,13 @@ func TestParsing(t *testing.T) {
expectedOpts: map[string]string{"message": "value", "force": ""},
expectedArgs: []string{},
},
{
name: "file-type not force",
options: []*Option{forceOpt, messageOpt, fileTypeOpt},
args: []string{"--file-type=csv"},
expectedOpts: map[string]string{"file-type": "csv"},
expectedArgs: []string{},
},
{
name: "unsupported arg",
options: []*Option{forceOpt, messageOpt},

View File

@@ -126,30 +126,11 @@ func (ap *ArgParser) SupportsInt(name, abbrev, valDesc, desc string) *ArgParser
return ap
}
func oldSplitOption(optStr string) (string, *string) {
optStr = strings.TrimLeft(optStr, "-")
idx := strings.IndexAny(optStr, optNameValDelimChars)
if idx == -1 {
return strings.TrimSpace(optStr), nil
}
argName := strings.TrimSpace(optStr[:idx])
argValue := strings.TrimSpace(optStr[idx+1:])
if len(argValue) == 0 {
return argName, nil
}
return argName, &argValue
}
// modal options in order of descending string length
func (ap *ArgParser) sortedModalOptions() []string {
smo := make([]string, 0, len(ap.Supported))
for s, opt := range ap.NameOrAbbrevToOpt {
if opt.OptType == OptionalFlag {
if opt.OptType == OptionalFlag && s != "" {
smo = append(smo, s)
}
}
@@ -161,13 +142,22 @@ func (ap *ArgParser) matchModalOptions(arg string) (matches []*Option, rest stri
rest = arg
// try to match longest options first
candidateOptNames := ap.sortedModalOptions()
candidateFlagNames := ap.sortedModalOptions()
kontinue := true
for kontinue {
kontinue = false
for i, on := range candidateOptNames {
// stop if we see a value option
for _, vo := range ap.sortedValueOptions() {
lv := len(vo)
isValOpt := len(rest) >= lv && rest[:lv] == vo
if isValOpt {
return matches, rest
}
}
for i, on := range candidateFlagNames {
lo := len(on)
isMatch := len(rest) >= lo && rest[:lo] == on
if isMatch {
@@ -176,12 +166,12 @@ func (ap *ArgParser) matchModalOptions(arg string) (matches []*Option, rest stri
matches = append(matches, m)
// only match options once
head := candidateOptNames[:i]
head := candidateFlagNames[:i]
var tail []string
if i+1 < len(candidateOptNames) {
tail = candidateOptNames[i+1:]
if i+1 < len(candidateFlagNames) {
tail = candidateFlagNames[i+1:]
}
candidateOptNames = append(head, tail...)
candidateFlagNames = append(head, tail...)
kontinue = true
break
@@ -194,7 +184,7 @@ func (ap *ArgParser) matchModalOptions(arg string) (matches []*Option, rest stri
func (ap *ArgParser) sortedValueOptions() []string {
vos := make([]string, 0, len(ap.Supported))
for s, opt := range ap.NameOrAbbrevToOpt {
if opt.OptType == OptionalValue {
if opt.OptType == OptionalValue && s != "" {
vos = append(vos, s)
}
}