diff options
Diffstat (limited to 'vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/autohelp.go')
-rw-r--r-- | vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/autohelp.go | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/autohelp.go b/vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/autohelp.go new file mode 100644 index 000000000..082c53e27 --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/autohelp.go @@ -0,0 +1,121 @@ +package command + +import ( + "flag" + "fmt" + "sort" + "strings" + + wordwrap "github.com/mitchellh/go-wordwrap" + "github.com/ryanuber/columnize" +) + +// AutoHelp specifies the necessary methods required to have their help +// completely generated for them. +type AutoHelp interface { + Usage() string + Description() string + InitOpts() + VisitAllFlags(func(f *flag.Flag)) +} + +// MakeHelp generates a help string based on the capabilities of the Command +func MakeHelp(c AutoHelp) string { + usageText := c.Usage() + + // If the length of Usage() is zero, then assume this is a hidden + // command. + if len(usageText) == 0 { + return "" + } + + descriptionText := wordwrap.WrapString(c.Description(), 60) + descrLines := strings.Split(descriptionText, "\n") + prefixedLines := make([]string, len(descrLines)) + for i := range descrLines { + prefixedLines[i] = " " + descrLines[i] + } + descriptionText = strings.Join(prefixedLines, "\n") + + c.InitOpts() + flags := []*flag.Flag{} + c.VisitAllFlags(func(f *flag.Flag) { + flags = append(flags, f) + }) + optionsText := OptionsHelpOutput(flags) + + var helpOutput string + switch { + case len(optionsText) == 0 && len(descriptionText) == 0: + helpOutput = usageText + case len(optionsText) == 0: + helpOutput = fmt.Sprintf(`Usage: %s + +%s`, + usageText, descriptionText) + case len(descriptionText) == 0 && len(optionsText) > 0: + helpOutput = fmt.Sprintf(`Usage: %s + +Options: + +%s`, + usageText, optionsText) + default: + helpOutput = fmt.Sprintf(`Usage: %s + +%s + +Options: + +%s`, + usageText, descriptionText, optionsText) + } + + return strings.TrimSpace(helpOutput) +} + +// ByOptName implements sort.Interface for flag.Flag based on the Name field. +type ByName []*flag.Flag + +func (a ByName) Len() int { return len(a) } +func (a ByName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a ByName) Less(i, j int) bool { + // Bubble up single-char args to the top of the list + switch { + case len(a[i].Name) == 1 && len(a[j].Name) != 1: + return true + case len(a[i].Name) != 1 && len(a[j].Name) == 1: + return false + default: + // Case-insensitive sort. Use case as a tie breaker, however. + a1 := strings.ToLower(a[i].Name) + a2 := strings.ToLower(a[j].Name) + if a1 == a2 { + return a[i].Name < a[j].Name + } else { + return a1 < a2 + } + } +} + +// OptionsHelpOutput returns a string of formatted options +func OptionsHelpOutput(flags []*flag.Flag) string { + sort.Sort(ByName(flags)) + + var output []string + for _, f := range flags { + if len(f.Usage) == 0 { + continue + } + + output = append(output, fmt.Sprintf("-%s | %s", f.Name, f.Usage)) + } + + optionsOutput := columnize.Format(output, &columnize.Config{ + Delim: "|", + Glue: " ", + Prefix: " ", + Empty: "", + }) + return optionsOutput +} |