mirror of
https://github.com/mum4k/termdash.git
synced 2025-04-25 13:48:50 +08:00
A wrapper over the external runewidth package.
This commit is contained in:
parent
c9e65178e6
commit
43e15c302e
30
cell/runewidth/runewidth.go
Normal file
30
cell/runewidth/runewidth.go
Normal file
@ -0,0 +1,30 @@
|
||||
// runewidth is a wrapper over github.com/mattn/go-runewidth which gives
|
||||
// different treatment to certain runes with ambiguous width.
|
||||
package runewidth
|
||||
|
||||
import runewidth "github.com/mattn/go-runewidth"
|
||||
|
||||
// RuneWidth returns the number of cells needed to draw r.
|
||||
// Background in http://www.unicode.org/reports/tr11/.
|
||||
//
|
||||
// Treats runes used internally by termdash as single-cell (half-width) runes
|
||||
// regardless of the locale. I.e. runes that are used to draw lines, boxes,
|
||||
// indicate resize or text trimming was needed and runes used by the braille
|
||||
// canvas.
|
||||
//
|
||||
// This should be safe, since even in locales where these runes have ambiguous
|
||||
// width, we still place all the character content around them so they should
|
||||
// have be half-width.
|
||||
func RuneWidth(r rune) int {
|
||||
return runewidth.RuneWidth(r)
|
||||
}
|
||||
|
||||
// StringWidth is like RuneWidth, but returns the number of cells occupied by
|
||||
// all the runes in the string.
|
||||
func StringWidth(s string) int {
|
||||
var width int
|
||||
for _, r := range []rune(s) {
|
||||
width += RuneWidth(r)
|
||||
}
|
||||
return width
|
||||
}
|
97
cell/runewidth/runewidth_test.go
Normal file
97
cell/runewidth/runewidth_test.go
Normal file
@ -0,0 +1,97 @@
|
||||
package runewidth
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
runewidth "github.com/mattn/go-runewidth"
|
||||
)
|
||||
|
||||
func TestRuneWidth(t *testing.T) {
|
||||
tests := []struct {
|
||||
desc string
|
||||
runes []rune
|
||||
eastAsian bool
|
||||
want int
|
||||
}{
|
||||
{
|
||||
desc: "ascii characters",
|
||||
runes: []rune{'a', 'f', '#'},
|
||||
want: 1,
|
||||
},
|
||||
{
|
||||
desc: "non-printable characters from mattn/runewidth/runewidth_test",
|
||||
runes: []rune{'\x00', '\x01', '\u0300', '\u2028', '\u2029'},
|
||||
want: 0,
|
||||
},
|
||||
{
|
||||
desc: "half-width runes from mattn/runewidth/runewidth_test",
|
||||
runes: []rune{'セ', 'カ', 'イ', '☆'},
|
||||
want: 1,
|
||||
},
|
||||
{
|
||||
desc: "full-width runes from mattn/runewidth/runewidth_test",
|
||||
runes: []rune{'世', '界'},
|
||||
want: 2,
|
||||
},
|
||||
{
|
||||
desc: "ambiguous so double-width in eastAsian from mattn/runewidth/runewidth_test",
|
||||
runes: []rune{'☆'},
|
||||
eastAsian: true,
|
||||
want: 2,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
runewidth.DefaultCondition.EastAsianWidth = tc.eastAsian
|
||||
defer func() {
|
||||
runewidth.DefaultCondition.EastAsianWidth = false
|
||||
}()
|
||||
|
||||
for _, r := range tc.runes {
|
||||
if got := RuneWidth(r); got != tc.want {
|
||||
t.Errorf("RuneWidth(%v) => %v, want %v", r, got, tc.want)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringWidth(t *testing.T) {
|
||||
tests := []struct {
|
||||
desc string
|
||||
str string
|
||||
eastAsian bool
|
||||
want int
|
||||
}{
|
||||
{
|
||||
desc: "ascii characters",
|
||||
str: "hello",
|
||||
want: 5,
|
||||
},
|
||||
{
|
||||
desc: "string from mattn/runewidth/runewidth_test",
|
||||
str: "■㈱の世界①",
|
||||
want: 10,
|
||||
},
|
||||
{
|
||||
desc: "string in eastAsian from mattn/runewidth/runewidth_test",
|
||||
str: "■㈱の世界①",
|
||||
eastAsian: true,
|
||||
want: 12,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
runewidth.DefaultCondition.EastAsianWidth = tc.eastAsian
|
||||
defer func() {
|
||||
runewidth.DefaultCondition.EastAsianWidth = false
|
||||
}()
|
||||
|
||||
if got := StringWidth(tc.str); got != tc.want {
|
||||
t.Errorf("StringWidth(%q) => %v, want %v", tc.str, got, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user