mirror of
https://github.com/spf13/cobra
synced 2025-05-05 12:57:22 +00:00
Merge b2f7bca857
into 37463cff2c
This commit is contained in:
commit
e1674bc9cd
2 changed files with 138 additions and 3 deletions
67
command.go
67
command.go
|
@ -31,6 +31,34 @@ import (
|
||||||
// FParseErrWhitelist configures Flag parse errors to be ignored
|
// FParseErrWhitelist configures Flag parse errors to be ignored
|
||||||
type FParseErrWhitelist flag.ParseErrorsWhitelist
|
type FParseErrWhitelist flag.ParseErrorsWhitelist
|
||||||
|
|
||||||
|
// TerminalColor is a type used for the names of the different
|
||||||
|
// colors in the terminal
|
||||||
|
type TerminalColor int
|
||||||
|
|
||||||
|
// Colors represents the different colors one can use in the terminal
|
||||||
|
const (
|
||||||
|
ColorBlack TerminalColor = iota + 30
|
||||||
|
ColorRed
|
||||||
|
ColorGreen
|
||||||
|
ColorYellow
|
||||||
|
ColorBlue
|
||||||
|
ColorMagenta
|
||||||
|
ColorCyan
|
||||||
|
ColorLightGray
|
||||||
|
)
|
||||||
|
|
||||||
|
// This sequence starts at 90, so we reset iota
|
||||||
|
const (
|
||||||
|
ColorDarkGray TerminalColor = iota + 90
|
||||||
|
ColorLightRed
|
||||||
|
ColorLightGreen
|
||||||
|
ColorLightYellow
|
||||||
|
ColorLightBlue
|
||||||
|
ColorLightMagenta
|
||||||
|
ColorLightCyan
|
||||||
|
ColorWhite
|
||||||
|
)
|
||||||
|
|
||||||
// Command is just that, a command for your application.
|
// Command is just that, a command for your application.
|
||||||
// E.g. 'go run ...' - 'run' is the command. Cobra requires
|
// E.g. 'go run ...' - 'run' is the command. Cobra requires
|
||||||
// you to define the usage and description as part of your command
|
// you to define the usage and description as part of your command
|
||||||
|
@ -47,6 +75,12 @@ type Command struct {
|
||||||
// Example: add [-F file | -D dir]... [-f format] profile
|
// Example: add [-F file | -D dir]... [-f format] profile
|
||||||
Use string
|
Use string
|
||||||
|
|
||||||
|
// DisableColors is a boolean used to disable the coloring in the command line
|
||||||
|
DisableColors bool
|
||||||
|
|
||||||
|
// Color represents the color to use to print the command in the terminal
|
||||||
|
Color TerminalColor
|
||||||
|
|
||||||
// Aliases is an array of aliases that can be used instead of the first word in Use.
|
// Aliases is an array of aliases that can be used instead of the first word in Use.
|
||||||
Aliases []string
|
Aliases []string
|
||||||
|
|
||||||
|
@ -473,10 +507,18 @@ var minNamePadding = 11
|
||||||
|
|
||||||
// NamePadding returns padding for the name.
|
// NamePadding returns padding for the name.
|
||||||
func (c *Command) NamePadding() int {
|
func (c *Command) NamePadding() int {
|
||||||
|
additionalPadding := c.additionalNamePadding()
|
||||||
if c.parent == nil || minNamePadding > c.parent.commandsMaxNameLen {
|
if c.parent == nil || minNamePadding > c.parent.commandsMaxNameLen {
|
||||||
return minNamePadding
|
return minNamePadding + additionalPadding
|
||||||
}
|
}
|
||||||
return c.parent.commandsMaxNameLen
|
return c.parent.commandsMaxNameLen + additionalPadding
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Command) additionalNamePadding() int {
|
||||||
|
// additionalPadding is used to pad non visible characters
|
||||||
|
// This happens for example when using colors, where \033[31m isn't seen
|
||||||
|
// but still is counted towards the padding
|
||||||
|
return len(c.ColoredName()) - len(c.Name())
|
||||||
}
|
}
|
||||||
|
|
||||||
// UsageTemplate returns usage template for the command.
|
// UsageTemplate returns usage template for the command.
|
||||||
|
@ -499,7 +541,7 @@ Examples:
|
||||||
{{.Example}}{{end}}{{if .HasAvailableSubCommands}}
|
{{.Example}}{{end}}{{if .HasAvailableSubCommands}}
|
||||||
|
|
||||||
Available Commands:{{range .Commands}}{{if (or .IsAvailableCommand (eq .Name "help"))}}
|
Available Commands:{{range .Commands}}{{if (or .IsAvailableCommand (eq .Name "help"))}}
|
||||||
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}
|
{{rpad .ColoredName .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}
|
||||||
|
|
||||||
Flags:
|
Flags:
|
||||||
{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}}
|
{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}}
|
||||||
|
@ -1309,6 +1351,25 @@ func (c *Command) Name() string {
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isColoringEnabled will be queried to know whether or not we should enable
|
||||||
|
// the coloring on a command. This will usually be called on the Root command
|
||||||
|
// and applied for every command.
|
||||||
|
func (c *Command) isColoringEnabled() bool {
|
||||||
|
_, noColorEnv := os.LookupEnv("NO_COLOR")
|
||||||
|
if c.DisableColors || noColorEnv {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// ColoredName returns the command's Name in the correct color if specified
|
||||||
|
func (c *Command) ColoredName() string {
|
||||||
|
if c.Color != 0 && c.Root().isColoringEnabled() {
|
||||||
|
return fmt.Sprintf("\033[%dm%s\033[0m", c.Color, c.Name())
|
||||||
|
}
|
||||||
|
return c.Name()
|
||||||
|
}
|
||||||
|
|
||||||
// HasAlias determines if a given string is an alias of the command.
|
// HasAlias determines if a given string is an alias of the command.
|
||||||
func (c *Command) HasAlias(s string) bool {
|
func (c *Command) HasAlias(s string) bool {
|
||||||
for _, a := range c.Aliases {
|
for _, a := range c.Aliases {
|
||||||
|
|
|
@ -3,6 +3,7 @@ package cobra
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
@ -2058,3 +2059,76 @@ func TestFParseErrWhitelistSiblingCommand(t *testing.T) {
|
||||||
}
|
}
|
||||||
checkStringContains(t, output, "unknown flag: --unknown")
|
checkStringContains(t, output, "unknown flag: --unknown")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func commandIsColoredRed(c *Command) error {
|
||||||
|
if c.Name() != "cmd" {
|
||||||
|
return fmt.Errorf("Unexpected name with Colored Command: %s", c.Name())
|
||||||
|
}
|
||||||
|
// If a color is specified, the ColoredName and the Name should be different
|
||||||
|
if c.Name() == c.ColoredName() {
|
||||||
|
return errors.New("Name and ColoredName should not give the same result")
|
||||||
|
}
|
||||||
|
if c.ColoredName() != "\033[31m"+c.Name()+"\033[0m" {
|
||||||
|
return errors.New("ColoredName should only add color to the name")
|
||||||
|
}
|
||||||
|
if c.additionalNamePadding() == 0 {
|
||||||
|
return errors.New("With a color, the additionalNamePadding should be more than 0")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func commandIsNotColored(c *Command) error {
|
||||||
|
if c.Name() != "cmd" {
|
||||||
|
return errors.New("Unexpected name with simple Command")
|
||||||
|
}
|
||||||
|
// If no color is specified, the ColoredName should equal the Name
|
||||||
|
if c.Name() != c.ColoredName() {
|
||||||
|
return errors.New("Name and ColoredName should give the same result")
|
||||||
|
}
|
||||||
|
if c.additionalNamePadding() != 0 {
|
||||||
|
return errors.New("With no color, the additionalNamePadding should be 0")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestColoredName(t *testing.T) {
|
||||||
|
c := &Command{
|
||||||
|
Use: "cmd",
|
||||||
|
}
|
||||||
|
err := commandIsNotColored(c)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
c = &Command{
|
||||||
|
Use: "cmd",
|
||||||
|
Color: ColorRed,
|
||||||
|
}
|
||||||
|
err = commandIsColoredRed(c)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestColoredNameWithNoColorSetup(t *testing.T) {
|
||||||
|
c := &Command{
|
||||||
|
Use: "cmd",
|
||||||
|
Color: ColorRed,
|
||||||
|
}
|
||||||
|
err := commandIsColoredRed(c)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
os.Setenv("NO_COLOR", "true")
|
||||||
|
err = commandIsNotColored(c)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
os.Unsetenv("NO_COLOR")
|
||||||
|
|
||||||
|
c.DisableColors = true
|
||||||
|
err = commandIsNotColored(c)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue