Skip to content

Commit

Permalink
Consider case when sorting strings
Browse files Browse the repository at this point in the history
This makes sorting flags and other sections consistent with how most
command line tools function, by placing both flags `-A` and `-a` before
a flag `-B`.
  • Loading branch information
rliebz committed Oct 28, 2017
1 parent 7bc6a0a commit b44660a
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 3 deletions.
2 changes: 1 addition & 1 deletion category.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ type CommandCategory struct {
}

func (c CommandCategories) Less(i, j int) bool {
return c[i].Name < c[j].Name
return lexicographicLess(c[i].Name, c[j].Name)
}

func (c CommandCategories) Len() int {
Expand Down
2 changes: 1 addition & 1 deletion command.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func (c CommandsByName) Len() int {
}

func (c CommandsByName) Less(i, j int) bool {
return c[i].Name < c[j].Name
return lexicographicLess(c[i].Name, c[j].Name)
}

func (c CommandsByName) Swap(i, j int) {
Expand Down
2 changes: 1 addition & 1 deletion flag.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func (f FlagsByName) Len() int {
}

func (f FlagsByName) Less(i, j int) bool {
return f[i].GetName() < f[j].GetName()
return lexicographicLess(f[i].GetName(), f[j].GetName())
}

func (f FlagsByName) Swap(i, j int) {
Expand Down
29 changes: 29 additions & 0 deletions sort.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package cli

import "unicode"

// lexicographicLess compares strings alphabetically considering case.
func lexicographicLess(i, j string) bool {
iRunes := []rune(i)
jRunes := []rune(j)

lenShared := len(iRunes)
if lenShared > len(jRunes) {
lenShared = len(jRunes)
}

for index := 0; index < lenShared; index++ {
ir := iRunes[index]
jr := jRunes[index]

if lir, ljr := unicode.ToLower(ir), unicode.ToLower(jr); lir != ljr {
return lir < ljr
}

if ir != jr {
return ir < jr
}
}

return i < j
}
30 changes: 30 additions & 0 deletions sort_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package cli

import "testing"

var lexicographicLessTests = []struct {
i string
j string
expected bool
}{
{"", "a", true},
{"a", "", false},
{"a", "a", false},
{"a", "A", false},
{"A", "a", true},
{"aa", "a", false},
{"a", "aa", true},
{"a", "b", true},
{"a", "B", true},
{"A", "b", true},
{"A", "B", true},
}

func TestLexicographicLess(t *testing.T) {
for _, test := range lexicographicLessTests {
actual := lexicographicLess(test.i, test.j)
if test.expected != actual {
t.Errorf(`expected string "%s" to come before "%s"`, test.i, test.j)
}
}
}

0 comments on commit b44660a

Please sign in to comment.