argvToInnerJSON converts the argv tail (everything AFTER the subcommand) into (positional, innerJSON). positional is any leading bare token(s) before the first flag (joined by spaces); innerJSON is the {key:value|[...]} object built from the --flag pairs.
(argv []string, arrayKeys, intKeys map[string]bool)
| 32 | // first flag (joined by spaces); innerJSON is the {key:value|[...]} object built |
| 33 | // from the --flag pairs. |
| 34 | func argvToInnerJSON(argv []string, arrayKeys, intKeys map[string]bool) (positional, innerJSON string) { |
| 35 | values := map[string][]string{} |
| 36 | var order []string |
| 37 | var pos []string |
| 38 | seenFlag := false |
| 39 | |
| 40 | for i := 0; i < len(argv); i++ { |
| 41 | a := argv[i] |
| 42 | if strings.HasPrefix(a, "--") { |
| 43 | seenFlag = true |
| 44 | key := strings.TrimLeft(a, "-") |
| 45 | var inlineVal string |
| 46 | hasInline := false |
| 47 | if eq := strings.IndexByte(key, '='); eq >= 0 { // --key=value spelling |
| 48 | inlineVal = trimQuotes(key[eq+1:]) |
| 49 | key = key[:eq] |
| 50 | hasInline = true |
| 51 | } |
| 52 | if _, ok := values[key]; !ok { |
| 53 | order = append(order, key) |
| 54 | } |
| 55 | switch { |
| 56 | case hasInline: |
| 57 | values[key] = append(values[key], inlineVal) |
| 58 | case i+1 < len(argv) && !strings.HasPrefix(argv[i+1], "--"): |
| 59 | values[key] = append(values[key], argv[i+1]) |
| 60 | i++ |
| 61 | default: |
| 62 | values[key] = append(values[key], "\x00bool") // sentinel for bare flag |
| 63 | } |
| 64 | continue |
| 65 | } |
| 66 | if !seenFlag { |
| 67 | pos = append(pos, a) |
| 68 | } |
| 69 | } |
| 70 | |
| 71 | obj := map[string]interface{}{} |
| 72 | for _, k := range order { |
| 73 | vs := values[k] |
| 74 | switch { |
| 75 | case arrayKeys[k] || len(vs) > 1: |
| 76 | obj[k] = vs |
| 77 | case len(vs) == 1 && vs[0] == "\x00bool": |
| 78 | obj[k] = true |
| 79 | case len(vs) == 1 && intKeys[k]: |
| 80 | if n, err := strconv.Atoi(strings.TrimSpace(vs[0])); err == nil { |
| 81 | obj[k] = n |
| 82 | } else { |
| 83 | obj[k] = vs[0] |
| 84 | } |
| 85 | case len(vs) == 1: |
| 86 | obj[k] = vs[0] |
| 87 | } |
| 88 | } |
| 89 | b, _ := json.Marshal(obj) |
| 90 | return strings.Join(pos, " "), string(b) |
| 91 | } |