2021-10-30 08:42:43 +02:00
|
|
|
package authors
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/md5"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/gookit/color"
|
|
|
|
"github.com/jesseduffield/lazygit/pkg/gui/style"
|
|
|
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
|
|
|
"github.com/lucasb-eyer/go-colorful"
|
|
|
|
"github.com/mattn/go-runewidth"
|
|
|
|
)
|
|
|
|
|
2021-10-30 09:00:28 +02:00
|
|
|
// if these being global variables causes trouble we can wrap them in a struct
|
|
|
|
// attached to the gui state.
|
2021-12-07 12:10:29 +02:00
|
|
|
var (
|
|
|
|
authorInitialCache = make(map[string]string)
|
|
|
|
authorNameCache = make(map[string]string)
|
|
|
|
authorStyleCache = make(map[string]style.TextStyle)
|
|
|
|
)
|
|
|
|
|
|
|
|
const authorNameWildcard = "*"
|
2021-10-30 08:42:43 +02:00
|
|
|
|
|
|
|
func ShortAuthor(authorName string) string {
|
|
|
|
if value, ok := authorInitialCache[authorName]; ok {
|
|
|
|
return value
|
|
|
|
}
|
|
|
|
|
|
|
|
initials := getInitials(authorName)
|
|
|
|
if initials == "" {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
value := AuthorStyle(authorName).Sprint(initials)
|
|
|
|
authorInitialCache[authorName] = value
|
|
|
|
|
|
|
|
return value
|
|
|
|
}
|
|
|
|
|
|
|
|
func LongAuthor(authorName string) string {
|
|
|
|
if value, ok := authorNameCache[authorName]; ok {
|
|
|
|
return value
|
|
|
|
}
|
|
|
|
|
2023-05-21 04:06:22 +02:00
|
|
|
paddedAuthorName := utils.WithPadding(authorName, 17, utils.AlignLeft)
|
2021-10-30 08:42:43 +02:00
|
|
|
truncatedName := utils.TruncateWithEllipsis(paddedAuthorName, 17)
|
|
|
|
value := AuthorStyle(authorName).Sprint(truncatedName)
|
|
|
|
authorNameCache[authorName] = value
|
|
|
|
|
|
|
|
return value
|
|
|
|
}
|
|
|
|
|
|
|
|
func AuthorStyle(authorName string) style.TextStyle {
|
|
|
|
if value, ok := authorStyleCache[authorName]; ok {
|
|
|
|
return value
|
|
|
|
}
|
|
|
|
|
2021-12-11 05:24:38 +02:00
|
|
|
// use the unified style whatever the author name is
|
2021-12-07 12:10:29 +02:00
|
|
|
if value, ok := authorStyleCache[authorNameWildcard]; ok {
|
|
|
|
return value
|
|
|
|
}
|
|
|
|
|
2021-10-30 08:42:43 +02:00
|
|
|
value := trueColorStyle(authorName)
|
|
|
|
|
|
|
|
authorStyleCache[authorName] = value
|
|
|
|
|
|
|
|
return value
|
|
|
|
}
|
|
|
|
|
|
|
|
func trueColorStyle(str string) style.TextStyle {
|
|
|
|
hash := md5.Sum([]byte(str))
|
|
|
|
c := colorful.Hsl(randFloat(hash[0:4])*360.0, 0.6+0.4*randFloat(hash[4:8]), 0.4+randFloat(hash[8:12])*0.2)
|
|
|
|
|
|
|
|
return style.New().SetFg(style.NewRGBColor(color.RGB(uint8(c.R*255), uint8(c.G*255), uint8(c.B*255))))
|
|
|
|
}
|
|
|
|
|
|
|
|
func randFloat(hash []byte) float64 {
|
|
|
|
return float64(randInt(hash, 100)) / 100
|
|
|
|
}
|
|
|
|
|
|
|
|
func randInt(hash []byte, max int) int {
|
|
|
|
sum := 0
|
|
|
|
for _, b := range hash {
|
|
|
|
sum = (sum + int(b)) % max
|
|
|
|
}
|
|
|
|
return sum
|
|
|
|
}
|
|
|
|
|
|
|
|
func getInitials(authorName string) string {
|
|
|
|
if authorName == "" {
|
|
|
|
return authorName
|
|
|
|
}
|
|
|
|
|
|
|
|
firstRune := getFirstRune(authorName)
|
|
|
|
if runewidth.RuneWidth(firstRune) > 1 {
|
|
|
|
return string(firstRune)
|
|
|
|
}
|
|
|
|
|
|
|
|
split := strings.Split(authorName, " ")
|
|
|
|
if len(split) == 1 {
|
|
|
|
return utils.LimitStr(authorName, 2)
|
|
|
|
}
|
|
|
|
|
|
|
|
return utils.LimitStr(split[0], 1) + utils.LimitStr(split[1], 1)
|
|
|
|
}
|
|
|
|
|
|
|
|
func getFirstRune(str string) rune {
|
|
|
|
// just using the loop for the sake of getting the first rune
|
|
|
|
for _, r := range str {
|
|
|
|
return r
|
|
|
|
}
|
|
|
|
// should never land here
|
|
|
|
return 0
|
|
|
|
}
|
2021-10-30 09:00:28 +02:00
|
|
|
|
|
|
|
func SetCustomAuthors(customAuthorColors map[string]string) {
|
2022-02-01 07:23:55 +02:00
|
|
|
authorStyleCache = utils.SetCustomColors(customAuthorColors)
|
2021-10-30 09:00:28 +02:00
|
|
|
}
|