Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgraded rivo/uniseg to latest version, switched StringWidth/Truncate to speedier version #63

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
strategy:
matrix:
os: [windows-latest, macos-latest, ubuntu-latest]
go: ["1.15", "1.16"]
go: ["1.15.x", "1.16.x"]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
Expand Down
6 changes: 2 additions & 4 deletions benchmark_test.go
Original file line number Diff line number Diff line change
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
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module github.com/mattn/go-runewidth

go 1.9
go 1.16

require github.com/rivo/uniseg v0.2.0
69 changes: 59 additions & 10 deletions runewidth.go → runewidth_go117.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
//go:build !go1.18
// +build !go1.18

package runewidth

import (
"os"
"strings"

"github.com/rivo/uniseg"
)
Expand Down Expand Up @@ -177,11 +181,12 @@ func (c *Condition) StringWidth(s string) (width int) {
g := uniseg.NewGraphemes(s)
for g.Next() {
var chWidth int
for _, r := range g.Runes() {
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 g.Str() {
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 @@ -194,24 +199,63 @@ func (c *Condition) Truncate(s string, w int, tail string) string {
return s
}
w -= c.StringWidth(tail)
var width, pos int
g := uniseg.NewGraphemes(s)
for g.Next() {
var chWidth int
ch := g.Str()
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
}
width += chWidth
pos += len(ch)
}
return s[:pos] + tail
}

// TruncateLeft cuts w cells from the beginning of the `s`.
func (c *Condition) TruncateLeft(s string, w int, prefix string) string {
if c.StringWidth(s) <= w {
return prefix
}

var width int
pos := len(s)

g := uniseg.NewGraphemes(s)
for g.Next() {
var chWidth int
for _, r := range g.Runes() {
chWidth = c.RuneWidth(r)
if chWidth > 0 {
break // See StringWidth() for details.
ch := g.Str()
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 {
pos, _ = g.Positions()
if width < w {
_, pos = g.Positions()
prefix += strings.Repeat(" ", width+chWidth-w)
} else {
pos, _ = g.Positions()
}

break
}

width += chWidth
}
return s[:pos] + tail

return prefix + s[pos:]
}

// Wrap return string wrapped with w cells
Expand Down Expand Up @@ -291,6 +335,11 @@ func Truncate(s string, w int, tail string) string {
return DefaultCondition.Truncate(s, w, tail)
}

// TruncateLeft cuts w cells from the beginning of the `s`.
func TruncateLeft(s string, w int, prefix string) string {
return DefaultCondition.TruncateLeft(s, w, prefix)
}

// Wrap return string wrapped with w cells
func Wrap(s string, w int) string {
return DefaultCondition.Wrap(s, w)
Expand Down