-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathflag_help_sections.go
122 lines (96 loc) · 2.61 KB
/
flag_help_sections.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
package cobrautil
import (
"fmt"
"regexp"
"sort"
"strings"
"github.com/spf13/cobra"
)
type FlagHelpSection struct {
Title string
PrefixMatch string
ExactMatch []string
NoneMatch bool
}
func (s FlagHelpSection) Matches(name string) bool {
if len(s.PrefixMatch) > 0 && strings.HasPrefix(name, s.PrefixMatch+"-") {
return true
}
for _, em := range s.ExactMatch {
if name == em {
return true
}
}
return false
}
type flagLine struct {
Line string
SectionIdxs []int
}
func (l flagLine) InSectionIdx(idx int) bool {
for _, i := range l.SectionIdxs {
if i == idx {
return true
}
}
return false
}
var (
flagHelpFuncCount = 0
flagNameRegexp = regexp.MustCompile("^\\s+(\\-[a-z], )?\\-\\-([a-z\\-]+)\\s+")
)
func FlagHelpSectionsUsageTemplate(sections []FlagHelpSection) string {
flagHelpFuncCount += 1
flagHelpFuncName := fmt.Sprintf("flagsWithSections%d", flagHelpFuncCount)
cobra.AddTemplateFunc(flagHelpFuncName, func(str string) string {
lines := strings.Split(str, "\n")
flags := map[string]flagLine{}
flagNames := []string{}
for _, line := range lines {
match := flagNameRegexp.FindStringSubmatch(line)
flagName := match[2]
if _, found := flags[flagName]; found {
panic("Expected to not find multiple flags with same name")
}
fline := flagLine{Line: line}
noneMatchIdx := -1
for i, section := range sections {
if section.Matches(flagName) {
fline.SectionIdxs = append(fline.SectionIdxs, i)
}
if section.NoneMatch {
noneMatchIdx = i
}
}
if len(fline.SectionIdxs) == 0 {
fline.SectionIdxs = []int{noneMatchIdx}
}
flags[flagName] = fline
flagNames = append(flagNames, flagName)
}
sort.Strings(flagNames)
sectionsResult := []string{}
for i, section := range sections {
result := section.Title + "\n"
for _, name := range flagNames {
fline := flags[name]
if fline.InSectionIdx(i) {
result += fline.Line + "\n"
}
}
sectionsResult = append(sectionsResult, result)
}
return strings.TrimSpace(strings.Join(sectionsResult, "\n"))
})
unmodifiedCmd := &cobra.Command{}
usageTemplate := unmodifiedCmd.UsageTemplate()
const defaultTpl = `{{if .HasAvailableLocalFlags}}
Flags:
{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}`
if !strings.Contains(usageTemplate, defaultTpl) {
panic("Expected to find available flags section in spf13/cobra default usage template")
}
newTpl := fmt.Sprintf(`{{if .HasAvailableLocalFlags}}
{{.LocalFlags.FlagUsages | trimTrailingWhitespaces | %s}}{{end}}`, flagHelpFuncName)
return strings.Replace(usageTemplate, defaultTpl, newTpl, 1)
}