1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-01-22 05:29:44 +02:00
lazygit/pkg/utils/formatting.go

160 lines
3.8 KiB
Go
Raw Normal View History

2021-05-30 15:22:04 +10:00
package utils
2021-10-24 16:26:03 +11:00
import (
"strings"
2022-03-19 19:12:58 +11:00
"github.com/jesseduffield/generics/slices"
2021-10-24 16:26:03 +11:00
"github.com/mattn/go-runewidth"
2022-03-19 19:12:58 +11:00
"github.com/samber/lo"
2021-10-24 16:26:03 +11:00
)
2021-05-30 15:22:04 +10:00
type Alignment int
const (
AlignLeft Alignment = iota
AlignRight
)
type ColumnConfig struct {
Width int
Alignment Alignment
}
2021-05-30 15:22:04 +10:00
// WithPadding pads a string as much as you want
func WithPadding(str string, padding int, alignment Alignment) string {
2021-05-30 15:22:04 +10:00
uncoloredStr := Decolorise(str)
2021-10-24 18:18:08 +11:00
width := runewidth.StringWidth(uncoloredStr)
if padding < width {
2021-05-30 15:22:04 +10:00
return str
}
space := strings.Repeat(" ", padding-width)
if alignment == AlignLeft {
return str + space
} else {
return space + str
}
2021-05-30 15:22:04 +10:00
}
// defaults to left-aligning each column. If you want to set the alignment of
// each column, pass in a slice of Alignment values.
func RenderDisplayStrings(displayStringsArr [][]string, columnAlignments []Alignment) string {
2021-10-31 22:29:43 +11:00
displayStringsArr = excludeBlankColumns(displayStringsArr)
2021-05-30 15:22:04 +10:00
padWidths := getPadWidths(displayStringsArr)
columnConfigs := make([]ColumnConfig, len(padWidths))
for i, padWidth := range padWidths {
// gracefully handle when columnAlignments is shorter than padWidths
alignment := AlignLeft
if len(columnAlignments) > i {
alignment = columnAlignments[i]
}
columnConfigs[i] = ColumnConfig{
Width: padWidth,
Alignment: alignment,
}
}
output := getPaddedDisplayStrings(displayStringsArr, columnConfigs)
2021-05-30 15:22:04 +10:00
2021-10-31 22:29:43 +11:00
return output
2021-05-30 15:22:04 +10:00
}
2021-10-31 22:29:43 +11:00
// NOTE: this mutates the input slice for the sake of performance
func excludeBlankColumns(displayStringsArr [][]string) [][]string {
if len(displayStringsArr) == 0 {
return displayStringsArr
}
// if all rows share a blank column, we want to remove that column
toRemove := []int{}
outer:
for i := range displayStringsArr[0] {
for _, strings := range displayStringsArr {
if strings[i] != "" {
continue outer
}
}
toRemove = append(toRemove, i)
}
if len(toRemove) == 0 {
return displayStringsArr
}
// remove the columns
for i, strings := range displayStringsArr {
for j := len(toRemove) - 1; j >= 0; j-- {
strings = append(strings[:toRemove[j]], strings[toRemove[j]+1:]...)
}
displayStringsArr[i] = strings
}
return displayStringsArr
}
func getPaddedDisplayStrings(stringArrays [][]string, columnConfigs []ColumnConfig) string {
2021-10-31 22:29:43 +11:00
builder := strings.Builder{}
2021-05-30 15:22:04 +10:00
for i, stringArray := range stringArrays {
if len(stringArray) == 0 {
continue
}
for j, columnConfig := range columnConfigs {
2021-05-30 15:22:04 +10:00
if len(stringArray)-1 < j {
continue
}
builder.WriteString(WithPadding(stringArray[j], columnConfig.Width, columnConfig.Alignment))
2021-10-31 22:29:43 +11:00
builder.WriteString(" ")
2021-05-30 15:22:04 +10:00
}
if len(stringArray)-1 < len(columnConfigs) {
2021-05-30 15:22:04 +10:00
continue
}
builder.WriteString(stringArray[len(columnConfigs)])
2021-10-31 22:29:43 +11:00
if i < len(stringArrays)-1 {
builder.WriteString("\n")
}
2021-05-30 15:22:04 +10:00
}
2021-10-31 22:29:43 +11:00
return builder.String()
2021-05-30 15:22:04 +10:00
}
2021-10-24 16:26:03 +11:00
func getPadWidths(stringArrays [][]string) []int {
2022-03-19 19:12:58 +11:00
maxWidth := slices.MaxBy(stringArrays, func(stringArray []string) int {
return len(stringArray)
})
2021-10-24 16:26:03 +11:00
if maxWidth-1 < 0 {
return []int{}
}
2022-03-19 19:12:58 +11:00
return slices.Map(lo.Range(maxWidth-1), func(i int) int {
return slices.MaxBy(stringArrays, func(stringArray []string) int {
uncoloredStr := Decolorise(stringArray[i])
return runewidth.StringWidth(uncoloredStr)
})
})
2021-10-24 16:26:03 +11:00
}
2021-10-30 20:15:50 +11:00
// 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 <= 3 {
return strings.Repeat(".", limit)
}
return runewidth.Truncate(str, limit, "...")
}
func SafeTruncate(str string, limit int) string {
if len(str) > limit {
return str[0:limit]
} else {
return str
}
}
2022-01-19 18:32:27 +11:00
2022-11-07 16:35:36 +11:00
const COMMIT_HASH_SHORT_SIZE = 8
2022-01-19 18:32:27 +11:00
func ShortSha(sha string) string {
2022-11-07 16:35:36 +11:00
if len(sha) < COMMIT_HASH_SHORT_SIZE {
2022-01-19 18:32:27 +11:00
return sha
}
2022-11-07 16:35:36 +11:00
return sha[:COMMIT_HASH_SHORT_SIZE]
2022-01-19 18:32:27 +11:00
}