From 261e1bd48a7d6013a920542c934c3cf42e125313 Mon Sep 17 00:00:00 2001 From: Michael Lorant Date: Sat, 27 Jan 2024 20:25:21 +1100 Subject: [PATCH] Improve maximum width of characters in a string The function `maxRuneWidth` was using a flawed approach by only evaluating strings based on each rune. The `uniseg` package provides a more accurate method based on grapheme clusters. This change switches over to the improved implementation which should achieve better results when determining the maximum width of all grapheme clusters in a string. Signed-off-by: Michael Lorant --- .github/workflows/build.yml | 2 +- borders.go | 13 +++++++++---- go.mod | 4 ++-- go.sum | 5 ++--- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2b48198d..f804b0cd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,7 +4,7 @@ jobs: test: strategy: matrix: - go-version: [~1.17, ^1] + go-version: [~1.18, ^1] os: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.os }} env: diff --git a/borders.go b/borders.go index d84bfec4..6ef90d56 100644 --- a/borders.go +++ b/borders.go @@ -3,9 +3,9 @@ package lipgloss import ( "strings" - "github.com/mattn/go-runewidth" "github.com/muesli/reflow/ansi" "github.com/muesli/termenv" + "github.com/rivo/uniseg" ) // Border contains a series of values which comprise the various parts of a @@ -423,13 +423,18 @@ func (s Style) styleBorder(border string, fg, bg TerminalColor) string { return style.Styled(border) } -func maxRuneWidth(str string) (width int) { - for _, r := range str { - w := runewidth.RuneWidth(r) +func maxRuneWidth(str string) int { + var width int + + state := -1 + for len(str) > 0 { + var w int + _, str, w, state = uniseg.FirstGraphemeClusterInString(str, state) if w > width { width = w } } + return width } diff --git a/go.mod b/go.mod index 0123aabb..bcdf3ad6 100644 --- a/go.mod +++ b/go.mod @@ -2,18 +2,18 @@ module github.com/charmbracelet/lipgloss retract v0.7.0 // v0.7.0 introduces a bug that causes some apps to freeze. -go 1.17 +go 1.18 require ( github.com/mattn/go-runewidth v0.0.15 github.com/muesli/reflow v0.3.0 github.com/muesli/termenv v0.15.2 + github.com/rivo/uniseg v0.4.4 ) require ( github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mattn/go-isatty v0.0.18 // indirect - github.com/rivo/uniseg v0.2.0 // indirect golang.org/x/sys v0.12.0 // indirect ) diff --git a/go.sum b/go.sum index cba58dc9..66be9561 100644 --- a/go.sum +++ b/go.sum @@ -5,7 +5,6 @@ github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= -github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= @@ -13,9 +12,9 @@ github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKt github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo= github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= +github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=