forked from vitessio/vitess
-
Notifications
You must be signed in to change notification settings - Fork 1
/
flagutil.go
89 lines (77 loc) · 2.05 KB
/
flagutil.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
// Package flagutil contains flags that parse string lists and string
// maps.
package flagutil
import (
_ "flag"
"sort"
"strings"
)
// StringListValue is a []string flag that accepts a comma separated
// list of elements. To include an element containing a comma, quote
// it with a backslash '\'.
type StringListValue []string
func (value StringListValue) Get() interface{} {
return []string(value)
}
func parseListWithEscapes(v string, delimiter rune) (value []string) {
var escaped, lastWasDelimiter bool
var current []rune
for _, r := range v {
lastWasDelimiter = false
if !escaped {
switch r {
case delimiter:
value = append(value, string(current))
current = nil
lastWasDelimiter = true
continue
case '\\':
escaped = true
continue
}
}
escaped = false
current = append(current, r)
}
if len(current) != 0 || lastWasDelimiter {
value = append(value, string(current))
}
return value
}
func (value *StringListValue) Set(v string) error {
*value = parseListWithEscapes(v, ',')
return nil
}
func (value StringListValue) String() string {
parts := make([]string, len(value))
for i, v := range value {
parts[i] = strings.Replace(strings.Replace(v, "\\", "\\\\", -1), ",", `\,`, -1)
}
return strings.Join(parts, ",")
}
// StringMapValue is a map[string]string flag. It accepts a
// comma-separated list of key value pairs, of the form key:value. The
// keys cannot contain colons.
type StringMapValue map[string]string
func (value *StringMapValue) Set(v string) error {
dict := make(map[string]string)
pairs := parseListWithEscapes(v, ',')
for _, pair := range pairs {
parts := strings.SplitN(pair, ":", 2)
dict[parts[0]] = parts[1]
}
*value = dict
return nil
}
func (value StringMapValue) Get() interface{} {
return map[string]string(value)
}
func (value StringMapValue) String() string {
parts := make([]string, 0)
for k, v := range value {
parts = append(parts, k+":"+strings.Replace(v, ",", `\,`, -1))
}
// Generate the string deterministically.
sort.Strings(parts)
return strings.Join(parts, ",")
}