Skip to content

Commit

Permalink
Fixes #161, CPU names are sorted strictly as strings rather than lexo…
Browse files Browse the repository at this point in the history
…graphically.
  • Loading branch information
xxxserxxx committed Jan 26, 2021
1 parent 4cea91b commit 2f0eca1
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 10 deletions.
86 changes: 76 additions & 10 deletions termui/linegraph.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package termui
import (
"image"
"sort"
"strconv"
"unicode"

. "github.com/gizak/termui/v3"
drawille "github.com/xxxserxxx/gotop/v4/termui/drawille-go"
Expand All @@ -27,6 +29,8 @@ type LineGraph struct {
LineColors map[string]Color
LabelStyles map[string]Modifier
DefaultLineColor Color

seriesList numbered
}

func NewLineGraph() *LineGraph {
Expand Down Expand Up @@ -54,18 +58,20 @@ func (self *LineGraph) Draw(buf *Buffer) {
colors[i] = make([]Color, self.Inner.Dy()+2)
}

// sort the series so that overlapping data will overlap the same way each time
seriesList := make([]string, len(self.Data))
i := 0
for seriesName := range self.Data {
seriesList[i] = seriesName
i++
if len(self.seriesList) != len(self.Data) {
// sort the series so that overlapping data will overlap the same way each time
self.seriesList = make(numbered, len(self.Data))
i := 0
for seriesName := range self.Data {
self.seriesList[i] = seriesName
i++
}
sort.Sort(self.seriesList)
}
sort.Strings(seriesList)

// draw lines in reverse order so that the first color defined in the colorscheme is on top
for i := len(seriesList) - 1; i >= 0; i-- {
seriesName := seriesList[i]
for i := len(self.seriesList) - 1; i >= 0; i-- {
seriesName := self.seriesList[i]
seriesData := self.Data[seriesName]
seriesLineColor, ok := self.LineColors[seriesName]
if !ok {
Expand Down Expand Up @@ -128,7 +134,7 @@ func (self *LineGraph) Draw(buf *Buffer) {
maxWid := 0
xoff := 0 // X offset for additional columns of text
yoff := 0 // Y offset for resetting column to top of widget
for i, seriesName := range seriesList {
for i, seriesName := range self.seriesList {
if yoff+i+2 > self.Inner.Dy() {
xoff += maxWid + 2
yoff = -i
Expand Down Expand Up @@ -159,3 +165,63 @@ func (self *LineGraph) Draw(buf *Buffer) {

}
}

// A string containing an integer
type numbered []string

func (n numbered) Len() int { return len(n) }
func (n numbered) Swap(i, j int) { n[i], n[j] = n[j], n[i] }
func (n numbered) Less(i, j int) bool {
a := n[i]
b := n[j]
for i := 0; i < len(a); i++ {
ac := a[i]
if unicode.IsDigit(rune(ac)) {
j := i + 1
for ; j < len(a); j++ {
if !unicode.IsDigit(rune(a[j])) {
break
}
if j >= len(b) {
return false
}
if !unicode.IsDigit(rune(b[j])) {
return false
}
}
an, err := strconv.Atoi(a[i:j])
if err != nil {
return true
}
if j > len(b) {
return false
}
for ; j < len(b); j++ {
if !unicode.IsDigit(rune(b[j])) {
break
}
}
bn, err := strconv.Atoi(b[i:j])
if err != nil {
return true
}
if an < bn {
return true
} else if bn < an {
return false
}
i = j
}
if i >= len(a) {
return true
} else if i >= len(b) {
return false
}
if ac < b[i] {
return true
} else if b[i] < ac {
return false
}
}
return true
}
60 changes: 60 additions & 0 deletions termui/linegraph_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package termui

import "testing"
import "sort"

func TestLess(t *testing.T) {
tests := []struct {
a, b string
e bool
}{
{a: "abc", b: "def", e: true},
{a: "abc", b: "abc", e: true},
{a: "def", b: "abc", e: false},
{a: "1", b: "10", e: true},
{a: "1", b: "2", e: true},
{a: "a2", b: "2", e: false},
{a: "a2", b: "a10", e: true},
{a: "a20", b: "a2", e: false},
{a: "abc20", b: "def2", e: true},
{a: "abc20", b: "abc2", e: false},
{a: "abc20", b: "abc20", e: true},
{a: "abc30", b: "abc20", e: false},
{a: "abc20a", b: "abc20", e: false},
{a: "abc20", b: "abc20a", e: true},
{a: "abc20", b: "abc2a", e: false},
{a: "abc20", b: "abc3a", e: false},
{a: "abc20", b: "abc2abc", e: false},
}
for _, k := range tests {
n := numbered([]string{k.a, k.b})
g := n.Less(0, 1)
if g != k.e {
t.Errorf("%s < %s: expected %v, got %v", k.a, k.b, k.e, g)
}
}
}

func TestSort(t *testing.T) {
tests := []struct {
in, ex numbered
}{
{
in: numbered{"abc", "def", "abc", "abc", "def", "abc", "1", "10", "1", "2", "a2", "2", "a2", "a10", "a20", "a2", "abc20", "def2", "abc20", "abc2", "abc20", "abc20", "abc30", "abc20", "abc20a", "abc20", "abc20", "abc20a", "abc20", "abc2a"},
ex: numbered{"1", "1", "2", "2", "10", "a2", "a2", "a2", "a10", "a20", "abc", "abc", "abc", "abc", "abc2", "abc2a", "abc20", "abc20", "abc20", "abc20", "abc20", "abc20", "abc20", "abc20", "abc20a", "abc20a", "abc30", "def", "def", "def2"},
},
{
in: numbered{"CPU12", "CPU11", "CPU9", "CPU3", "CPU4", "CPU0", "CPU6", "CPU7", "CPU8", "CPU5", "CPU10", "CPU1", "CPU2"},
ex: numbered{"CPU0", "CPU1", "CPU2", "CPU3", "CPU4", "CPU5", "CPU6", "CPU7", "CPU8", "CPU9", "CPU10", "CPU11", "CPU12"},
},
}

for _, k := range tests {
sort.Sort(k.in)
for i, v := range k.in {
if v != k.ex[i] {
t.Errorf("failed to properly sort\n\texpected: %v\n\tgot: %v", k.ex, k.in)
}
}
}
}

0 comments on commit 2f0eca1

Please sign in to comment.