From f2918929b037cef8586fa63a8c4b62286d4d5038 Mon Sep 17 00:00:00 2001 From: Ahmet Alp Balkan Date: Tue, 17 Mar 2015 23:30:15 -0700 Subject: [PATCH 1/2] Vendor 'github.com/skarademir/naturalsort' Signed-off-by: Ahmet Alp Balkan --- Godeps/Godeps.json | 4 ++ .../skarademir/naturalsort/LICENSE.md | 21 +++++++ .../skarademir/naturalsort/README.md | 16 +++++ .../skarademir/naturalsort/naturalsort.go | 34 +++++++++++ .../naturalsort/naturalsort_test.go | 58 +++++++++++++++++++ 5 files changed, 133 insertions(+) create mode 100644 Godeps/_workspace/src/github.com/skarademir/naturalsort/LICENSE.md create mode 100644 Godeps/_workspace/src/github.com/skarademir/naturalsort/README.md create mode 100644 Godeps/_workspace/src/github.com/skarademir/naturalsort/naturalsort.go create mode 100644 Godeps/_workspace/src/github.com/skarademir/naturalsort/naturalsort_test.go diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index e932dd050a..bfc587fd1b 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -21,6 +21,10 @@ "ImportPath": "github.com/cenkalti/backoff", "Rev": "9831e1e25c874e0a0601b6dc43641071414eec7a" }, + { + "ImportPath": "github.com/skarademir/naturalsort", + "Rev": "9688a08870fba63de22ec85d167598bb677820ee" + }, { "ImportPath": "github.com/codegangsta/cli", "Comment": "1.2.0-64-ge1712f3", diff --git a/Godeps/_workspace/src/github.com/skarademir/naturalsort/LICENSE.md b/Godeps/_workspace/src/github.com/skarademir/naturalsort/LICENSE.md new file mode 100644 index 0000000000..af513860b4 --- /dev/null +++ b/Godeps/_workspace/src/github.com/skarademir/naturalsort/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 skarademir + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Godeps/_workspace/src/github.com/skarademir/naturalsort/README.md b/Godeps/_workspace/src/github.com/skarademir/naturalsort/README.md new file mode 100644 index 0000000000..89523853a3 --- /dev/null +++ b/Godeps/_workspace/src/github.com/skarademir/naturalsort/README.md @@ -0,0 +1,16 @@ +# naturalsort +A simple natural sorter for Go Strings +##Usage +Implements the `sort.Interface` + +called by `sort.Sort(NaturalSort([]string)` +###Example +`SampleStringArray := []string{"z24", "z2", "z15", "z1", + "z3", "z20", "z5", "z11", + "z 21", "z22"} + sort.Sort(NaturalSort(SampleStringArray))` +##Needless Description +Inspired by [Jeff Atwood's seminal blog post](http://blog.codinghorror.com/sorting-for-humans-natural-sort-order/) and +structured similarly to [Ian Griffiths' C# implementation](http://www.interact-sw.co.uk/iangblog/2007/12/13/natural-sorting). +This uses a regex to split the numeric and non-numeric portions of the string into a chunky array. Next, the left and right sides' +chunks are compared either by string comparrison (if either is a non-numeric chunk), or by integer (if both chunks are numeric) diff --git a/Godeps/_workspace/src/github.com/skarademir/naturalsort/naturalsort.go b/Godeps/_workspace/src/github.com/skarademir/naturalsort/naturalsort.go new file mode 100644 index 0000000000..b905943fab --- /dev/null +++ b/Godeps/_workspace/src/github.com/skarademir/naturalsort/naturalsort.go @@ -0,0 +1,34 @@ +package naturalsort + +import ( + "regexp" + "strconv" + "strings" +) + +type NaturalSort []string + +func (s NaturalSort) Len() int { + return len(s) +} +func (s NaturalSort) Swap(i, j int) { + s[i], s[j] = s[j], s[i] +} +func (s NaturalSort) Less(i, j int) bool { + r1 := regexp.MustCompilePOSIX(`^([^0-9]*)+|[0-9]+`) + + spliti := r1.FindAllString(strings.Replace(s[i], " ", "", -1), -1) + splitj := r1.FindAllString(strings.Replace(s[j], " ", "", -1), -1) + for index := range spliti { + if spliti[index] != splitj[index] { + inti, ei := strconv.Atoi(spliti[index]) + intj, ej := strconv.Atoi(splitj[index]) + if ei == nil && ej == nil { //if number + return inti < intj + } + return spliti[index] < splitj[index] + } + + } + return s[i] < s[j] +} diff --git a/Godeps/_workspace/src/github.com/skarademir/naturalsort/naturalsort_test.go b/Godeps/_workspace/src/github.com/skarademir/naturalsort/naturalsort_test.go new file mode 100644 index 0000000000..6f2ab622f4 --- /dev/null +++ b/Godeps/_workspace/src/github.com/skarademir/naturalsort/naturalsort_test.go @@ -0,0 +1,58 @@ +package naturalsort + +import ( + "reflect" + "sort" + "testing" +) + +func TestSortValid(t *testing.T) { + cases := []struct { + data, expected []string + }{ + { + nil, + nil, + }, + { + []string{}, + []string{}, + }, + { + []string{"a"}, + []string{"a"}, + }, + { + []string{"0"}, + []string{"0"}, + }, + { + []string{"1", "2", "30", "22", "0", "00", "3"}, + []string{"0", "00", "1", "2", "3", "22", "30"}, + }, + { + []string{"A1", "A0", "A21", "A11", "A111", "A2"}, + []string{"A0", "A1", "A2", "A11", "A21", "A111"}, + }, + { + []string{"A1BA1", "A11AA1", "A2AB0", "B1AA1", "A1AA1"}, + []string{"A1AA1", "A1BA1", "A2AB0", "A11AA1", "B1AA1"}, + }, + } + + for i, c := range cases { + sort.Sort(NaturalSort(c.data)) + if !reflect.DeepEqual(c.data, c.expected) { + t.Fatalf("Wrong order in test case #%d.\nExpected=%v\nGot=%v", i, c.expected, c.data) + } + } + +} + +func BenchmarkSort(b *testing.B) { + var data = [...]string{"A1BA1", "A11AA1", "A2AB0", "B1AA1", "A1AA1"} + for ii := 0; ii < b.N; ii++ { + d := NaturalSort(data[:]) + sort.Sort(d) + } +} From c4b83b49358e643895637ae273c534fa405a2ef7 Mon Sep 17 00:00:00 2001 From: Ahmet Alp Balkan Date: Tue, 17 Mar 2015 23:10:25 -0700 Subject: [PATCH 2/2] Add natural sorting by host name to `ls` cmd Signed-off-by: Ahmet Alp Balkan --- commands.go | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/commands.go b/commands.go index 1dcc04763e..b45bfbd94b 100644 --- a/commands.go +++ b/commands.go @@ -13,6 +13,7 @@ import ( log "github.com/Sirupsen/logrus" "github.com/codegangsta/cli" + "github.com/skarademir/naturalsort" "github.com/docker/machine/drivers" _ "github.com/docker/machine/drivers/amazonec2" @@ -57,18 +58,18 @@ type hostListItem struct { SwarmDiscovery string } -type hostListItemByName []hostListItem - -func (h hostListItemByName) Len() int { - return len(h) -} - -func (h hostListItemByName) Swap(i, j int) { - h[i], h[j] = h[j], h[i] -} - -func (h hostListItemByName) Less(i, j int) bool { - return strings.ToLower(h[i].Name) < strings.ToLower(h[j].Name) +func sortHostListItemsByName(items []hostListItem) { + m := make(map[string]hostListItem, len(items)) + s := make([]string, len(items)) + for i, v := range items { + name := strings.ToLower(v.Name) + m[name] = v + s[i] = name + } + sort.Sort(naturalsort.NaturalSort(s)) + for i, v := range s { + items[i] = m[v] + } } func confirmInput(msg string) bool { @@ -504,7 +505,7 @@ func cmdLs(c *cli.Context) { close(hostListItems) - sort.Sort(hostListItemByName(items)) + sortHostListItemsByName(items) for _, item := range items { activeString := ""