File: authors.go

package info (click to toggle)
lazygit 0.50.0%2Bds1-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,808 kB
  • sloc: sh: 128; makefile: 76
file content (141 lines) | stat: -rw-r--r-- 3,407 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
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"
)

type authorNameCacheKey struct {
	authorName string
	truncateTo int
}

// if these being global variables causes trouble we can wrap them in a struct
// attached to the gui state.
var (
	authorInitialCache = make(map[string]string)
	authorNameCache    = make(map[authorNameCacheKey]string)
	authorStyleCache   = make(map[string]*style.TextStyle)
)

const authorNameWildcard = "*"

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, length int) string {
	cacheKey := authorNameCacheKey{authorName: authorName, truncateTo: length}
	if value, ok := authorNameCache[cacheKey]; ok {
		return value
	}

	paddedAuthorName := utils.WithPadding(authorName, length, utils.AlignLeft)
	truncatedName := utils.TruncateWithEllipsis(paddedAuthorName, length)
	value := AuthorStyle(authorName).Sprint(truncatedName)
	authorNameCache[cacheKey] = value

	return value
}

// AuthorWithLength returns a representation of the author that fits into a
// given maximum length:
// - if the length is less than 2, it returns an empty string
// - if the length is 2, it returns the initials
// - otherwise, it returns the author name truncated to the maximum length
func AuthorWithLength(authorName string, length int) string {
	if length < 2 {
		return ""
	}

	if length == 2 {
		return ShortAuthor(authorName)
	}

	return LongAuthor(authorName, length)
}

func AuthorStyle(authorName string) *style.TextStyle {
	if value, ok := authorStyleCache[authorName]; ok {
		return value
	}

	// use the unified style whatever the author name is
	if value, ok := authorStyleCache[authorNameWildcard]; ok {
		return value
	}

	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
}

func SetCustomAuthors(customAuthorColors map[string]string) {
	authorStyleCache = utils.SetCustomColors(customAuthorColors)
}