mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-10-05 21:46:49 -04:00
Decolorise stores its result in a cache keyed by the string it was given, but the lookup treats an empty result as a miss, so a string that decolorises to nothing is recomputed on every call. Recomputing it means compiling two regexes, and that costs 4534ns against 24.7ns for a string the cache does answer for. Empty cells are everywhere in the list panels, and RenderDisplayStrings measures every cell twice, once to work out the column widths and once to pad it. A commits panel showing 50 lines with one empty column spends about 0.45ms of every render on this. Read the cache with the two-value form, so that an empty result counts as an answer, and compile the two regexes once at package level. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
70 lines
1.4 KiB
Go
70 lines
1.4 KiB
Go
package utils
|
|
|
|
import (
|
|
"regexp"
|
|
"sync"
|
|
|
|
"github.com/gookit/color"
|
|
"github.com/jesseduffield/lazygit/pkg/gui/style"
|
|
"github.com/samber/lo"
|
|
)
|
|
|
|
var (
|
|
decoloriseCache = make(map[string]string)
|
|
decoloriseMutex sync.RWMutex
|
|
|
|
colorCodeRe = regexp.MustCompile(`\x1B\[([0-9]{1,3}(;[0-9]{1,3})*)?[mGK]`)
|
|
linkRe = regexp.MustCompile(`\x1B]8;[^;]*;(.*?)(\x1B.|\x07)`)
|
|
)
|
|
|
|
// Decolorise strips a string of color
|
|
func Decolorise(str string) string {
|
|
decoloriseMutex.RLock()
|
|
val, ok := decoloriseCache[str]
|
|
decoloriseMutex.RUnlock()
|
|
|
|
if ok {
|
|
return val
|
|
}
|
|
|
|
ret := colorCodeRe.ReplaceAllString(str, "")
|
|
ret = linkRe.ReplaceAllString(ret, "")
|
|
|
|
decoloriseMutex.Lock()
|
|
decoloriseCache[str] = ret
|
|
decoloriseMutex.Unlock()
|
|
|
|
return ret
|
|
}
|
|
|
|
func IsValidHexValue(v string) bool {
|
|
if len(v) != 4 && len(v) != 7 {
|
|
return false
|
|
}
|
|
|
|
if v[0] != '#' {
|
|
return false
|
|
}
|
|
|
|
for _, char := range v[1:] {
|
|
switch char {
|
|
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F':
|
|
continue
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
func SetCustomColors(customColors map[string]string) map[string]*style.TextStyle {
|
|
return lo.MapValues(customColors, func(c string, key string) *style.TextStyle {
|
|
if s, ok := style.ColorMap[c]; ok {
|
|
return &s.Foreground
|
|
}
|
|
value := style.New().SetFg(style.NewRGBColor(color.HEX(c, false)))
|
|
return &value
|
|
})
|
|
}
|