-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathhelp.go
More file actions
106 lines (88 loc) · 2.37 KB
/
help.go
File metadata and controls
106 lines (88 loc) · 2.37 KB
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
package clip
import (
_ "embed"
"fmt"
"io"
"maps"
"slices"
"strings"
"text/template"
)
// newHelpContext creates a helpContext from a Context.
func newHelpContext(ctx *Context) *helpContext {
maxCmdNameLen := 0
for _, cmd := range ctx.command.visibleCommands {
if len(cmd.Name()) > maxCmdNameLen {
maxCmdNameLen = len(cmd.Name())
}
}
return &helpContext{
Context: ctx,
maxCmdNameLen: maxCmdNameLen,
}
}
// helpContext is a wrapper around context with methods for printing help.
type helpContext struct {
*Context
maxCmdNameLen int
}
func (ctx *helpContext) FullName() string {
name := ctx.command.Name()
for cur := ctx.Parent(); cur != nil; cur = cur.Parent() {
name = fmt.Sprintf("%s %s", cur.command.Name(), name)
}
return name
}
// VisibleCommands is the list of sub-commands in order.
func (ctx *helpContext) VisibleCommands() []*Command { return ctx.command.visibleCommands }
// VisibleFlags is the list of flags in order.
func (ctx *helpContext) VisibleFlags() []*flagDef {
flagNames := slices.Sorted(maps.Keys(ctx.command.flagSet.byName))
var flags []*flagDef
for _, name := range flagNames {
flag := ctx.command.flagSet.byName[name]
if !flag.Hidden() {
flags = append(flags, flag)
}
}
return flags
}
//go:embed help.tmpl
var helpTemplate string
// WriteHelp writes the command's help text to the given writer.
func WriteHelp(w io.Writer, ctx *Context) error {
hctx := newHelpContext(ctx)
t := template.New("help").Funcs(template.FuncMap{
"join": stringsJoin,
"pad": pad,
"padCommand": getCommandPadder(hctx),
"printFlagShort": printFlagShort,
})
t = template.Must(t.Parse(helpTemplate))
return t.Execute(w, hctx)
}
func getCommandPadder(ctx *helpContext) func(string) string {
s := fmt.Sprintf("%%-%ds", ctx.maxCmdNameLen+2)
return func(text string) string {
return fmt.Sprintf(s, text)
}
}
func printFlagShort(short string) string {
if short == "" {
return " "
}
return fmt.Sprintf("-%s, ", short)
}
// stringsJoin reverse the args for [strings.Join] to work better with templates.
func stringsJoin(sep string, s []string) string {
return strings.Join(s, sep)
}
// pad a string with a number of leading spaces on each new line.
func pad(size int, text string) string {
padding := strings.Repeat(" ", size)
return padding + strings.ReplaceAll(
strings.TrimSpace(text),
"\n",
"\n"+padding,
)
}