diff --git a/application.go b/application.go index 0d07738..43242aa 100644 --- a/application.go +++ b/application.go @@ -23,6 +23,7 @@ import ( "fmt" "io" "sort" + "strings" "sync" "time" @@ -168,6 +169,7 @@ func (a *Application) Command(name string) *Command { // there is only one. Returns nil if the command does not exist of if the fuzzy // matching find more than one. func (a *Application) BestCommand(name string) *Command { + name = strings.ToLower(name) if c := a.Command(name); c != nil { return c } @@ -188,6 +190,7 @@ func (a *Application) BestCommand(name string) *Command { // Category returns the named CommandCategory on App. Returns nil if the category does not exist func (a *Application) Category(name string) *CommandCategory { + name = strings.ToLower(name) if a.Categories == nil { return nil } @@ -315,6 +318,7 @@ func (a *Application) setup() { registerAutocompleteCommands(a) for _, c := range a.Commands { + c.normalizeCommandNames() if c.HelpName == "" { c.HelpName = fmt.Sprintf("%s %s", a.HelpName, c.FullName()) } diff --git a/command.go b/command.go index deb04f3..aba96d7 100644 --- a/command.go +++ b/command.go @@ -76,6 +76,15 @@ func Hide() bool { return true } +func (c *Command) normalizeCommandNames() { + c.Category = strings.ToLower(c.Category) + c.Name = strings.ToLower(c.Name) + c.HelpName = strings.ToLower(c.HelpName) + for _, alias := range c.Aliases { + alias.Name = strings.ToLower(alias.Name) + } +} + // FullName returns the full name of the command. // For subcommands this ensures that parent commands are part of the command path func (c *Command) FullName() string { diff --git a/command_test.go b/command_test.go index 03e863b..2aeb7a4 100644 --- a/command_test.go +++ b/command_test.go @@ -112,6 +112,38 @@ func TestCommand_Run_DoesNotOverwriteErrorFromBefore(t *testing.T) { } } +func TestCaseInsensitiveCommandNames(t *testing.T) { + app := Application{} + app.ErrWriter = io.Discard + projectList := &Command{Name: "project:LIST", Aliases: []*Alias{{Name: "FOO"}}} + projectLink := &Command{Name: "PROJECT:link"} + app.Commands = []*Command{ + projectList, + projectLink, + } + + app.setup() + + if c := app.BestCommand("project:list"); c != projectList { + t.Fatalf("expected project:list, got %v", c) + } + if c := app.BestCommand("Project:lISt"); c != projectList { + t.Fatalf("expected project:list, got %v", c) + } + if c := app.BestCommand("project:link"); c != projectLink { + t.Fatalf("expected project:link, got %v", c) + } + if c := app.BestCommand("project:Link"); c != projectLink { + t.Fatalf("expected project:link, got %v", c) + } + if c := app.BestCommand("foo"); c != projectList { + t.Fatalf("expected project:link, got %v", c) + } + if c := app.BestCommand("FoO"); c != projectList { + t.Fatalf("expected project:link, got %v", c) + } +} + func TestFuzzyCommandNames(t *testing.T) { app := Application{} app.ErrWriter = io.Discard