Merge pull request #293 from andreykurilin/sort_commands

Sort commands by their names
This commit is contained in:
Eric Paris 2016-06-15 10:36:14 -04:00 committed by GitHub
commit bc81c21bd0
3 changed files with 62 additions and 1 deletions

View File

@ -41,6 +41,10 @@ var initializers []func()
// Set this to true to enable it // Set this to true to enable it
var EnablePrefixMatching = false var EnablePrefixMatching = false
//EnableCommandSorting controls sorting of the slice of commands, which is turned on by default.
//To disable sorting, set it to false.
var EnableCommandSorting = true
//AddTemplateFunc adds a template function that's available to Usage and Help //AddTemplateFunc adds a template function that's available to Usage and Help
//template generation. //template generation.
func AddTemplateFunc(name string, tmplFunc interface{}) { func AddTemplateFunc(name string, tmplFunc interface{}) {

View File

@ -21,6 +21,7 @@ import (
"io" "io"
"os" "os"
"path/filepath" "path/filepath"
"sort"
"strings" "strings"
flag "github.com/spf13/pflag" flag "github.com/spf13/pflag"
@ -103,6 +104,8 @@ type Command struct {
commandsMaxUseLen int commandsMaxUseLen int
commandsMaxCommandPathLen int commandsMaxCommandPathLen int
commandsMaxNameLen int commandsMaxNameLen int
// is commands slice are sorted or not
commandsAreSorted bool
flagErrorBuf *bytes.Buffer flagErrorBuf *bytes.Buffer
@ -721,8 +724,20 @@ func (c *Command) ResetCommands() {
c.helpCommand = nil c.helpCommand = nil
} }
//Commands returns a slice of child commands. // Sorts commands by their names
type commandSorterByName []*Command
func (c commandSorterByName) Len() int { return len(c) }
func (c commandSorterByName) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
func (c commandSorterByName) Less(i, j int) bool { return c[i].Name() < c[j].Name() }
// Commands returns a sorted slice of child commands.
func (c *Command) Commands() []*Command { func (c *Command) Commands() []*Command {
// do not sort commands if it already sorted or sorting was disabled
if EnableCommandSorting && !c.commandsAreSorted{
sort.Sort(commandSorterByName(c.commands))
c.commandsAreSorted = true
}
return c.commands return c.commands
} }
@ -751,6 +766,7 @@ func (c *Command) AddCommand(cmds ...*Command) {
x.SetGlobalNormalizationFunc(c.globNormFunc) x.SetGlobalNormalizationFunc(c.globNormFunc)
} }
c.commands = append(c.commands, x) c.commands = append(c.commands, x)
c.commandsAreSorted = false
} }
} }

View File

@ -133,3 +133,44 @@ func Test_DisableFlagParsing(t *testing.T) {
t.Errorf("expected: %v, got: %v", as, targs) t.Errorf("expected: %v, got: %v", as, targs)
} }
} }
func TestCommandsAreSorted(t *testing.T) {
EnableCommandSorting = true
originalNames := []string{"middle", "zlast", "afirst"}
expectedNames := []string{"afirst", "middle", "zlast"}
var tmpCommand = &Command{Use: "tmp"}
for _, name := range(originalNames) {
tmpCommand.AddCommand(&Command{Use: name})
}
for i, c := range(tmpCommand.Commands()) {
if expectedNames[i] != c.Name() {
t.Errorf("expected: %s, got: %s", expectedNames[i], c.Name())
}
}
EnableCommandSorting = true
}
func TestEnableCommandSortingIsDisabled(t *testing.T) {
EnableCommandSorting = false
originalNames := []string{"middle", "zlast", "afirst"}
var tmpCommand = &Command{Use: "tmp"}
for _, name := range(originalNames) {
tmpCommand.AddCommand(&Command{Use: name})
}
for i, c := range(tmpCommand.Commands()) {
if originalNames[i] != c.Name() {
t.Errorf("expected: %s, got: %s", originalNames[i], c.Name())
}
}
EnableCommandSorting = true
}