-
-
Notifications
You must be signed in to change notification settings - Fork 105
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'origin' into pulak/DEV-2327
- Loading branch information
Showing
14 changed files
with
346 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
package templates | ||
|
||
import ( | ||
"fmt" | ||
"io" | ||
"strings" | ||
|
||
"github.com/mitchellh/go-wordwrap" | ||
"github.com/spf13/pflag" | ||
) | ||
|
||
const ( | ||
defaultOffset = 10 | ||
minWidth = 80 | ||
flagIndent = " " | ||
nameIndentWidth = 4 | ||
minDescWidth = 20 | ||
) | ||
|
||
type HelpFlagPrinter struct { | ||
wrapLimit uint | ||
out io.Writer | ||
maxFlagLen int | ||
} | ||
|
||
func NewHelpFlagPrinter(out io.Writer, wrapLimit uint, flags *pflag.FlagSet) *HelpFlagPrinter { | ||
if out == nil { | ||
panic("output writer cannot be nil") | ||
} | ||
if flags == nil { | ||
panic("flag set cannot be nil") | ||
} | ||
if wrapLimit < minWidth { | ||
wrapLimit = minWidth | ||
} | ||
|
||
return &HelpFlagPrinter{ | ||
wrapLimit: wrapLimit, | ||
out: out, | ||
maxFlagLen: calculateMaxFlagLength(flags), | ||
} | ||
} | ||
|
||
func calculateMaxFlagLength(flags *pflag.FlagSet) int { | ||
maxLen := 0 | ||
flags.VisitAll(func(flag *pflag.Flag) { | ||
length := len(flagIndent) | ||
|
||
if len(flag.Shorthand) > 0 { | ||
if flag.Value.Type() != "bool" { | ||
length += len(fmt.Sprintf("-%s, --%s %s", flag.Shorthand, flag.Name, flag.Value.Type())) | ||
} else { | ||
length += len(fmt.Sprintf("-%s, --%s", flag.Shorthand, flag.Name)) | ||
} | ||
} else { | ||
if flag.Value.Type() != "bool" { | ||
length += len(fmt.Sprintf(" --%s %s", flag.Name, flag.Value.Type())) | ||
} else { | ||
length += len(fmt.Sprintf(" --%s", flag.Name)) | ||
} | ||
} | ||
|
||
if length > maxLen { | ||
maxLen = length | ||
} | ||
}) | ||
return maxLen | ||
} | ||
|
||
func (p *HelpFlagPrinter) PrintHelpFlag(flag *pflag.Flag) { | ||
nameIndent := nameIndentWidth | ||
|
||
flagName := "" | ||
if flag.Shorthand != "" { | ||
if flag.Value.Type() != "bool" { | ||
flagName = fmt.Sprintf("%s-%s, --%s %s", strings.Repeat(" ", nameIndent), | ||
flag.Shorthand, flag.Name, flag.Value.Type()) | ||
} else { | ||
flagName = fmt.Sprintf("%s-%s, --%s", strings.Repeat(" ", nameIndent), | ||
flag.Shorthand, flag.Name) | ||
} | ||
} else { | ||
if flag.Value.Type() != "bool" { | ||
flagName = fmt.Sprintf("%s --%s %s", strings.Repeat(" ", nameIndent), | ||
flag.Name, flag.Value.Type()) | ||
} else { | ||
flagName = fmt.Sprintf("%s --%s", strings.Repeat(" ", nameIndent), | ||
flag.Name) | ||
} | ||
} | ||
|
||
flagSection := fmt.Sprintf("%-*s", p.maxFlagLen, flagName) | ||
descIndent := p.maxFlagLen + 4 | ||
|
||
description := flag.Usage | ||
if flag.DefValue != "" { | ||
description = fmt.Sprintf("%s (default %q)", description, flag.DefValue) | ||
} | ||
|
||
descWidth := int(p.wrapLimit) - descIndent | ||
if descWidth < minDescWidth { | ||
descWidth = minDescWidth | ||
} | ||
|
||
wrapped := wordwrap.WrapString(description, uint(descWidth)) | ||
lines := strings.Split(wrapped, "\n") | ||
|
||
if _, err := fmt.Fprintf(p.out, "%-*s%s\n", descIndent, flagSection, lines[0]); err != nil { | ||
return | ||
} | ||
|
||
// Print remaining lines with proper indentation | ||
for _, line := range lines[1:] { | ||
if _, err := fmt.Fprintf(p.out, "%s%s\n", strings.Repeat(" ", descIndent), line); err != nil { | ||
return | ||
} | ||
} | ||
|
||
if _, err := fmt.Fprintln(p.out); err != nil { | ||
return | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package templates | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
|
||
"github.com/spf13/cobra" | ||
"github.com/spf13/pflag" | ||
) | ||
|
||
// Templater handles the generation and management of command usage templates. | ||
type Templater struct { | ||
UsageTemplate string | ||
} | ||
|
||
// SetCustomUsageFunc configures a custom usage template for the provided cobra command. | ||
// It returns an error if the command is nil. | ||
func SetCustomUsageFunc(cmd *cobra.Command) error { | ||
if cmd == nil { | ||
return fmt.Errorf("command cannot be nil") | ||
} | ||
t := &Templater{ | ||
UsageTemplate: MainUsageTemplate(), | ||
} | ||
|
||
cmd.SetUsageTemplate(t.UsageTemplate) | ||
return nil | ||
} | ||
|
||
// MainUsageTemplate returns the usage template for the root command and wrap cobra flag usages to the terminal width | ||
func MainUsageTemplate() string { | ||
return `Usage:{{if .Runnable}} | ||
{{.UseLine}}{{end}}{{if .HasAvailableSubCommands}} | ||
{{.CommandPath}} [command]{{end}}{{if gt (len .Aliases) 0}} | ||
Aliases: | ||
{{.NameAndAliases}}{{end}}{{if .HasExample}} | ||
Examples: | ||
{{.Example}}{{end}}{{if .HasAvailableSubCommands}} | ||
Available Commands:{{range .Commands}}{{if (or .IsAvailableCommand (eq .Name "help"))}} | ||
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}} | ||
Flags: | ||
{{wrappedFlagUsages .LocalFlags | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}} | ||
Global Flags: | ||
{{wrappedFlagUsages .InheritedFlags | trimTrailingWhitespaces}}{{end}}{{if .HasHelpSubCommands}} | ||
Additional help topics:{{range .Commands}}{{if .IsAdditionalHelpTopicCommand}} | ||
{{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableSubCommands}} | ||
Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}} | ||
` | ||
} | ||
|
||
// Default terminal width if actual width cannot be determined | ||
const maxWidth = 80 | ||
|
||
// WrappedFlagUsages formats the flag usage string to fit within the terminal width | ||
func WrappedFlagUsages(f *pflag.FlagSet) string { | ||
var builder strings.Builder | ||
printer := NewHelpFlagPrinter(&builder, maxWidth, f) | ||
|
||
printer.maxFlagLen = calculateMaxFlagLength(f) | ||
|
||
f.VisitAll(func(flag *pflag.Flag) { | ||
printer.PrintHelpFlag(flag) | ||
}) | ||
|
||
return builder.String() | ||
} |
Oops, something went wrong.