open-consul/command/flags/usage.go

116 lines
2.4 KiB
Go

package flags
import (
"bytes"
"flag"
"fmt"
"io"
"strings"
text "github.com/tonnerre/golang-text"
)
func Usage(txt string, cmdFlags, clientFlags, serverFlags *flag.FlagSet) string {
u := &Usager{
Usage: txt,
CmdFlags: cmdFlags,
HTTPClientFlags: clientFlags,
HTTPServerFlags: serverFlags,
}
return u.String()
}
type Usager struct {
Usage string
CmdFlags *flag.FlagSet
HTTPClientFlags *flag.FlagSet
HTTPServerFlags *flag.FlagSet
}
func (u *Usager) String() string {
out := new(bytes.Buffer)
out.WriteString(strings.TrimSpace(u.Usage))
out.WriteString("\n")
out.WriteString("\n")
httpFlags := u.HTTPClientFlags
if httpFlags == nil {
httpFlags = u.HTTPServerFlags
} else {
Merge(httpFlags, u.HTTPServerFlags)
}
if httpFlags != nil {
printTitle(out, "HTTP API Options")
httpFlags.VisitAll(func(f *flag.Flag) {
printFlag(out, f)
})
}
if u.CmdFlags != nil {
printTitle(out, "Command Options")
u.CmdFlags.VisitAll(func(f *flag.Flag) {
if flagContains(httpFlags, f) {
return
}
printFlag(out, f)
})
}
return strings.TrimRight(out.String(), "\n")
}
// printTitle prints a consistently-formatted title to the given writer.
func printTitle(w io.Writer, s string) {
fmt.Fprintf(w, "%s\n\n", s)
}
// printFlag prints a single flag to the given writer.
func printFlag(w io.Writer, f *flag.Flag) {
example, _ := flag.UnquoteUsage(f)
if example != "" {
fmt.Fprintf(w, " -%s=<%s>\n", f.Name, example)
} else {
fmt.Fprintf(w, " -%s\n", f.Name)
}
indented := wrapAtLength(f.Usage, 5)
fmt.Fprintf(w, "%s\n\n", indented)
}
// flagContains returns true if the given flag is contained in the given flag
// set or false otherwise.
func flagContains(fs *flag.FlagSet, f *flag.Flag) bool {
if fs == nil {
return false
}
var skip bool
fs.VisitAll(func(hf *flag.Flag) {
if skip {
return
}
if f.Name == hf.Name {
skip = true
return
}
})
return skip
}
// maxLineLength is the maximum width of any line.
const maxLineLength int = 72
// wrapAtLength wraps the given text at the maxLineLength, taking into account
// any provided left padding.
func wrapAtLength(s string, pad int) string {
wrapped := text.Wrap(s, maxLineLength-pad)
lines := strings.Split(wrapped, "\n")
for i, line := range lines {
lines[i] = strings.Repeat(" ", pad) + line
}
return strings.Join(lines, "\n")
}