From a17914549d157939bcd530087e8a6f09f681d1a4 Mon Sep 17 00:00:00 2001 From: Andy Arthur Date: Thu, 21 May 2020 16:56:27 -0500 Subject: [PATCH] ugh parsing --- go/libraries/utils/argparser/args_test.go | 21 +++++++++-- go/libraries/utils/argparser/parser.go | 44 +++++++++-------------- 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/go/libraries/utils/argparser/args_test.go b/go/libraries/utils/argparser/args_test.go index bb43ea9ba0..817ed5491c 100644 --- a/go/libraries/utils/argparser/args_test.go +++ b/go/libraries/utils/argparser/args_test.go @@ -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}, diff --git a/go/libraries/utils/argparser/parser.go b/go/libraries/utils/argparser/parser.go index fc3c8d6e65..620f9f7034 100644 --- a/go/libraries/utils/argparser/parser.go +++ b/go/libraries/utils/argparser/parser.go @@ -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) } }