Skip to content

Commit

Permalink
Upgraded to latest rivo/uniseg. Also implemented basic emoji handling…
Browse files Browse the repository at this point in the history
… in StringWidth. See mattn#59
  • Loading branch information
rivo committed Sep 11, 2022
1 parent a8413cf commit 2e820a2
Show file tree
Hide file tree
Showing 8 changed files with 31 additions and 18 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yaml
Expand Up @@ -11,7 +11,7 @@ jobs:
strategy:
matrix:
os: [windows-latest, macos-latest, ubuntu-latest]
go: ["1.15", "1.16"]
go: ["1.18.x", "1.19.x"]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
Expand Down
6 changes: 2 additions & 4 deletions benchmark_test.go
Expand Up @@ -113,21 +113,19 @@ func benchString1Width(b *testing.B, eastAsianWidth bool, start, stop rune, want
return n
}
func BenchmarkString1WidthAll(b *testing.B) {
benchSink = benchString1Width(b, false, 0, utf8.MaxRune+1, 1295990)
benchSink = benchString1Width(b, false, 0, utf8.MaxRune+1, 1298422)
}
func BenchmarkString1Width768(b *testing.B) {
benchSink = benchString1Width(b, false, 0, 0x300, 702)
}
func BenchmarkString1WidthAllEastAsian(b *testing.B) {
benchSink = benchString1Width(b, true, 0, utf8.MaxRune+1, 1436664)
benchSink = benchString1Width(b, true, 0, utf8.MaxRune+1, 1439014)
}
func BenchmarkString1Width768EastAsian(b *testing.B) {
benchSink = benchString1Width(b, true, 0, 0x300, 794)
}

//
// tables
//
func benchTable(b *testing.B, tbl table) int {
n := 0
for i := 0; i < b.N; i++ {
Expand Down
4 changes: 2 additions & 2 deletions go.mod
@@ -1,5 +1,5 @@
module github.com/mattn/go-runewidth

go 1.9
go 1.18

require github.com/rivo/uniseg v0.3.1
require github.com/rivo/uniseg v0.4.2
2 changes: 2 additions & 0 deletions go.sum
@@ -1,2 +1,4 @@
github.com/rivo/uniseg v0.3.1 h1:SDPP7SHNl1L7KrEFCSJslJ/DM9DT02Nq2C61XrfHMmk=
github.com/rivo/uniseg v0.3.1/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rivo/uniseg v0.4.2 h1:YwD0ulJSJytLpiaWua0sBDusfsCZohxjxzVTYjwxfV8=
github.com/rivo/uniseg v0.4.2/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
18 changes: 10 additions & 8 deletions runewidth.go
Expand Up @@ -179,11 +179,12 @@ func (c *Condition) StringWidth(s string) (width int) {
for len(s) > 0 {
var chWidth int
cl, s, _, state = uniseg.FirstGraphemeClusterInString(s, state)
for _, r := range cl {
chWidth = c.RuneWidth(r)
if chWidth > 0 {
break // Our best guess at this point is to use the width of the first non-zero-width rune.
for index, r := range cl {
if index == 0 && inTable(r, emoji) {
chWidth = 2 // Not the optimal solution but it will work in most cases.
break
}
chWidth += c.RuneWidth(r)
}
width += chWidth
}
Expand All @@ -204,11 +205,12 @@ func (c *Condition) Truncate(s string, w int, tail string) string {
chWidth int
)
ch, substr, _, state = uniseg.FirstGraphemeClusterInString(substr, state)
for _, r := range ch {
chWidth = c.RuneWidth(r)
if chWidth > 0 {
break // See StringWidth() for details.
for index, r := range ch {
if index == 0 && inTable(r, emoji) {
chWidth = 2 // Not the optimal solution but it will work in most cases.
break
}
chWidth += c.RuneWidth(r)
}
if width+chWidth > w {
break
Expand Down
2 changes: 1 addition & 1 deletion runewidth_table.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions runewidth_test.go
Expand Up @@ -44,7 +44,7 @@ var tables = []tableInfo{
{combining, "combining", 465, "3cce13deb5e23f9f7327f2b1ef162328285a7dcf277a98302a8f7cdd43971268"},
{doublewidth, "doublewidth", 182440, "3d16eda8650dc2c92d6318d32f0b4a74fda5a278db2d4544b1dd65863394823c"},
{ambiguous, "ambiguous", 138739, "d05e339a10f296de6547ff3d6c5aee32f627f6555477afebd4a3b7e3cf74c9e3"},
{emoji, "emoji", 3535, "9ec17351601d49c535658de8d129c1d0ccda2e620669fc39a2faaee7dedcef6d"},
{emoji, "emoji", 3561, "3f1ae3b21ead544a59ab68fe541e8b098adc4fe1ffe3389a523a01dbfd8c1d75"},
{narrow, "narrow", 111, "fa897699c5e3cd9141c638d539331b0bdd508b874e22996c5e929767d455fc5a"},
{neutral, "neutral", 27333, "5455f5e75c307f70b4e9b2384dc5a8bcd91a4c5e2b24b2b185dfad4d860ee5c2"},
}
Expand Down Expand Up @@ -462,7 +462,7 @@ func TestZeroWidthJoiner(t *testing.T) {
{"\u200d🍳", 2},
{"👨\u200d👨", 2},
{"👨\u200d👨\u200d👧", 2},
{"🏳️\u200d🌈", 1},
{"🏳️\u200d🌈", 2},
{"あ👩\u200d🍳い", 6},
{"あ\u200d🍳い", 6},
{"あ\u200dい", 4},
Expand Down
11 changes: 11 additions & 0 deletions script/generate.go
@@ -1,3 +1,4 @@
//go:build ignore
// +build ignore

// Generate runewidth_table.go from data at https://unicode.org/
Expand Down Expand Up @@ -166,6 +167,16 @@ func emoji(out io.Writer, in io.Reader) error {
})
}

// We also want regional indicator symbols (flags) to be part of the Emoji
// table. They are U+1F1E6..U+1F1FF.
for index, r := range arr {
if r.lo >= 0x1f1ff {
arr = append(arr[:index+1], arr[index:]...)
arr[index] = rrange{lo: 0x1f1e6, hi: 0x1f1ff}
break
}
}

shapeup(&arr)
generate(out, "emoji", arr)

Expand Down

0 comments on commit 2e820a2

Please sign in to comment.