-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathprint.go
141 lines (126 loc) · 3.01 KB
/
print.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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package flagstruct
import (
"flag"
"fmt"
"reflect"
"time"
)
// This is a copy of flag.UnquoteUsage that doesn't rely on flag.Flag.
// Unfortunately, this is the only way around, since we have no access to the
// flag types.
func unquoteUsage(u string, value interface{}) (name string, usage string) {
// Look for a back-quoted name, but avoid the strings package.
usage = u
for i := 0; i < len(usage); i++ {
// Also allow ~, because we can't use ` in struct tag easily.
if usage[i] == '~' || usage[i] == '`' {
for j := i + 1; j < len(usage); j++ {
if usage[j] == '~' || usage[j] == '`' {
name = usage[i+1 : j]
usage = usage[:i] + name + usage[j+1:]
return name, usage
}
}
break // Only one back quote; use type name.
}
}
// No explicit name, so use type if we can find one.
name = "value"
switch value.(type) {
case bool:
name = ""
case time.Duration:
name = "duration"
case float64:
name = "float"
case int, int64:
name = "int"
case string:
name = "string"
case uint, uint64:
name = "uint"
}
return
}
// Copied from flag.
func isZeroValue(value string) bool {
switch value {
case "false":
return true
case "":
return true
case "0":
return true
}
return false
}
// PrintDefaults prints to standard error the default values of all
// defined command-line flags in the set. This is copied from flag, adjusted
// to allow ~ quotes in default values.
func (s *FlagSet) PrintDefaults() {
s.VisitAll(func(f *flag.Flag) {
buf := fmt.Sprintf(" -%s", f.Name)
val := f.Value.(flag.Getter).Get()
name, usage := unquoteUsage(f.Usage, val)
if len(name) > 0 {
buf += " " + name
}
if len(buf) <= 4 {
buf += "\t"
} else {
buf += "\n \t"
}
buf += usage
if !isZeroValue(f.DefValue) {
if _, ok := val.(string); ok {
buf += fmt.Sprintf(" (default %q)", f.DefValue)
} else {
buf += fmt.Sprintf(" (default %v)", f.DefValue)
}
}
fmt.Fprint(s.out(), buf, "\n")
})
}
// PrintStruct prints flags based on the struct passed to `conf`.
func (s *FlagSet) PrintStruct(conf interface{}) {
v := reflect.ValueOf(conf).Elem()
t := reflect.TypeOf(conf).Elem()
for i, l := 0, t.NumField(); i < l; i++ {
ft, fv := t.Field(i), v.Field(i)
// _ can be used to separate sections.
if ft.Name == "_" {
fmt.Fprint(s.out(), "\n")
continue
}
// Skip unexported fields.
if ft.PkgPath != "" {
continue
}
name, usage := ft.Tag.Get("flag"), ft.Tag.Get("usage")
if name == "" {
continue
}
typn, usage := unquoteUsage(usage, fv.Interface())
val := fv.Interface()
buf := fmt.Sprintf(" -%s", name)
if len(typn) > 0 {
buf += " " + typn
}
// Usage on same-line for short flags
if len(buf) <= 4 {
buf += "\t"
} else {
buf += "\n \t"
}
buf += usage
// Add default value if non-zero
if val != reflect.Zero(fv.Type()).Interface() {
if _, ok := val.(string); ok {
buf += fmt.Sprintf(" (default %q)", val)
} else {
buf += fmt.Sprintf(" (default %v)", val)
}
}
fmt.Fprint(s.out(), buf, "\n")
}
}