Fix fullwidth rune handling.
This commit is contained in:
parent
f3b451c887
commit
84a4bbd440
24
src/utils/runes.go
Normal file
24
src/utils/runes.go
Normal file
|
@ -0,0 +1,24 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
rw "github.com/mattn/go-runewidth"
|
||||
)
|
||||
|
||||
func TruncateFront(s string, w int, prefix string) string {
|
||||
if rw.StringWidth(s) <= w {
|
||||
return s
|
||||
}
|
||||
r := []rune(s)
|
||||
pw := rw.StringWidth(prefix)
|
||||
w -= pw
|
||||
width := 0
|
||||
i := len(r) - 1
|
||||
for ; i >= 0; i-- {
|
||||
cw := rw.RuneWidth(r[i])
|
||||
width += cw
|
||||
if width > w {
|
||||
break
|
||||
}
|
||||
}
|
||||
return prefix + string(r[i+1:len(r)])
|
||||
}
|
50
src/utils/runes_test.go
Normal file
50
src/utils/runes_test.go
Normal file
|
@ -0,0 +1,50 @@
|
|||
package utils
|
||||
|
||||
import "testing"
|
||||
|
||||
const (
|
||||
ELLIPSIS = "…"
|
||||
)
|
||||
|
||||
func TestTruncateFront(t *testing.T) {
|
||||
tests := []struct {
|
||||
s string
|
||||
w int
|
||||
prefix string
|
||||
want string
|
||||
}{
|
||||
{"", 0, ELLIPSIS, ""},
|
||||
{"", 1, ELLIPSIS, ""},
|
||||
{"", 10, ELLIPSIS, ""},
|
||||
|
||||
{"abcdef", 0, ELLIPSIS, ELLIPSIS},
|
||||
{"abcdef", 1, ELLIPSIS, ELLIPSIS},
|
||||
{"abcdef", 2, ELLIPSIS, ELLIPSIS + "f"},
|
||||
{"abcdef", 5, ELLIPSIS, ELLIPSIS + "cdef"},
|
||||
{"abcdef", 6, ELLIPSIS, "abcdef"},
|
||||
{"abcdef", 10, ELLIPSIS, "abcdef"},
|
||||
|
||||
{"abcdef", 0, "...", "..."},
|
||||
{"abcdef", 1, "...", "..."},
|
||||
{"abcdef", 3, "...", "..."},
|
||||
{"abcdef", 4, "...", "...f"},
|
||||
{"abcdef", 5, "...", "...ef"},
|
||||
{"abcdef", 6, "...", "abcdef"},
|
||||
{"abcdef", 10, "...", "abcdef"},
|
||||
|
||||
{"⦅full~width⦆", 15, ".", "⦅full~width⦆"},
|
||||
{"⦅full~width⦆", 14, ".", ".full~width⦆"},
|
||||
{"⦅full~width⦆", 13, ".", ".ull~width⦆"},
|
||||
{"⦅full~width⦆", 10, ".", ".~width⦆"},
|
||||
{"⦅full~width⦆", 9, ".", ".width⦆"},
|
||||
{"⦅full~width⦆", 8, ".", ".width⦆"},
|
||||
{"⦅full~width⦆", 3, ".", ".⦆"},
|
||||
{"⦅full~width⦆", 2, ".", "."},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
if got := TruncateFront(test.s, test.w, test.prefix); got != test.want {
|
||||
t.Errorf("TruncateFront(%q, %d, %q) = %q; want %q", test.s, test.w, test.prefix, got, test.want)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@ import (
|
|||
ui "github.com/cjbassi/gotop/src/termui"
|
||||
"github.com/cjbassi/gotop/src/utils"
|
||||
tui "github.com/gizak/termui/v3"
|
||||
rw "github.com/mattn/go-runewidth"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -123,7 +124,8 @@ func (self *ProcWidget) HandleEvent(e tui.Event) bool {
|
|||
self.SetEditingFilter(false)
|
||||
case "<Backspace>":
|
||||
if self.filter != "" {
|
||||
self.filter = self.filter[:len(self.filter)-1]
|
||||
r := []rune(self.filter)
|
||||
self.filter = string(r[:len(r)-1])
|
||||
self.update()
|
||||
}
|
||||
case "<Space>":
|
||||
|
@ -143,6 +145,8 @@ func (self *ProcWidget) Draw(buf *tui.Buffer) {
|
|||
}
|
||||
|
||||
func (self *ProcWidget) drawFilter(buf *tui.Buffer) {
|
||||
padding := 2
|
||||
|
||||
style := self.TitleStyle
|
||||
label := " Filter: "
|
||||
if self.editingFilter {
|
||||
|
@ -151,24 +155,34 @@ func (self *ProcWidget) drawFilter(buf *tui.Buffer) {
|
|||
}
|
||||
cursorStyle := tui.NewStyle(style.Bg, style.Fg, tui.ModifierClear)
|
||||
|
||||
p := image.Pt(self.Min.X+2, self.Max.Y-1)
|
||||
p := image.Pt(self.Min.X+padding, self.Max.Y-1)
|
||||
buf.SetString(label, style, p)
|
||||
p.X += utf8.RuneCountInString(label)
|
||||
p.X += rw.StringWidth(label)
|
||||
|
||||
maxLen := self.Max.X - p.X - 5
|
||||
filter := self.filter
|
||||
if l := utf8.RuneCountInString(filter); l > maxLen {
|
||||
filter = ELLIPSIS + filter[l-maxLen+1:]
|
||||
tail := " "
|
||||
if self.editingFilter {
|
||||
tail = "] "
|
||||
}
|
||||
|
||||
maxLen := self.Max.X - p.X - padding - rw.StringWidth(tail)
|
||||
if self.editingFilter {
|
||||
maxLen -= 1 // for cursor
|
||||
}
|
||||
|
||||
filter := utils.TruncateFront(self.filter, maxLen, ELLIPSIS)
|
||||
buf.SetString(filter, self.TitleStyle, p)
|
||||
p.X += utf8.RuneCountInString(filter)
|
||||
p.X += rw.StringWidth(filter)
|
||||
|
||||
if self.editingFilter {
|
||||
buf.SetString(CURSOR, cursorStyle, p)
|
||||
p.X += 1
|
||||
remaining := self.Max.X - 2 - p.X
|
||||
buf.SetString(fmt.Sprintf("%*s", remaining, "] "), style, p)
|
||||
p.X += rw.StringWidth(CURSOR)
|
||||
|
||||
if remaining := maxLen - rw.StringWidth(filter); remaining > 0 {
|
||||
buf.SetString(strings.Repeat(" ", remaining), self.TitleStyle, p)
|
||||
p.X += remaining
|
||||
}
|
||||
}
|
||||
buf.SetString(tail, style, p)
|
||||
}
|
||||
|
||||
func (self *ProcWidget) filterProcs(procs []Proc) []Proc {
|
||||
|
|
Loading…
Reference in New Issue
Block a user