mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-11-25 22:32:13 +02:00
Use utils.StringWidth to optimize rendering performance
runewidth.StringWidth is an expensive call, even if the input string is pure ASCII. Improve this by providing a wrapper that short-circuits the call to len if the input is ASCII. Benchmark results show that for non-ASCII strings it makes no noticable difference, but for ASCII strings it provides a more than 200x speedup. BenchmarkStringWidthAsciiOriginal-10 718135 1637 ns/op BenchmarkStringWidthAsciiOptimized-10 159197538 7.545 ns/op BenchmarkStringWidthNonAsciiOriginal-10 486290 2391 ns/op BenchmarkStringWidthNonAsciiOptimized-10 502286 2383 ns/op
This commit is contained in:
@@ -3,6 +3,7 @@ package utils
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/mattn/go-runewidth"
|
||||
"github.com/samber/lo"
|
||||
@@ -21,10 +22,22 @@ type ColumnConfig struct {
|
||||
Alignment Alignment
|
||||
}
|
||||
|
||||
func StringWidth(s string) int {
|
||||
// We are intentionally not using a range loop here, because that would
|
||||
// convert the characters to runes, which is unnecessary work in this case.
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] > unicode.MaxASCII {
|
||||
return runewidth.StringWidth(s)
|
||||
}
|
||||
}
|
||||
|
||||
return len(s)
|
||||
}
|
||||
|
||||
// WithPadding pads a string as much as you want
|
||||
func WithPadding(str string, padding int, alignment Alignment) string {
|
||||
uncoloredStr := Decolorise(str)
|
||||
width := runewidth.StringWidth(uncoloredStr)
|
||||
width := StringWidth(uncoloredStr)
|
||||
if padding < width {
|
||||
return str
|
||||
}
|
||||
@@ -144,7 +157,7 @@ func getPadWidths(stringArrays [][]string) []int {
|
||||
return MaxFn(stringArrays, func(stringArray []string) int {
|
||||
uncoloredStr := Decolorise(stringArray[i])
|
||||
|
||||
return runewidth.StringWidth(uncoloredStr)
|
||||
return StringWidth(uncoloredStr)
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -161,7 +174,7 @@ func MaxFn[T any](items []T, fn func(T) int) int {
|
||||
|
||||
// TruncateWithEllipsis returns a string, truncated to a certain length, with an ellipsis
|
||||
func TruncateWithEllipsis(str string, limit int) string {
|
||||
if runewidth.StringWidth(str) > limit && limit <= 2 {
|
||||
if StringWidth(str) > limit && limit <= 2 {
|
||||
return strings.Repeat(".", limit)
|
||||
}
|
||||
return runewidth.Truncate(str, limit, "…")
|
||||
|
||||
Reference in New Issue
Block a user