1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2024-12-12 11:15:00 +02:00
lazygit/pkg/utils/formatting.go
2021-10-31 22:33:39 +11:00

124 lines
2.8 KiB
Go

package utils
import (
"strings"
"github.com/mattn/go-runewidth"
)
// WithPadding pads a string as much as you want
func WithPadding(str string, padding int) string {
uncoloredStr := Decolorise(str)
width := runewidth.StringWidth(uncoloredStr)
if padding < width {
return str
}
return str + strings.Repeat(" ", padding-width)
}
func RenderDisplayStrings(displayStringsArr [][]string) string {
displayStringsArr = excludeBlankColumns(displayStringsArr)
padWidths := getPadWidths(displayStringsArr)
output := getPaddedDisplayStrings(displayStringsArr, padWidths)
return output
}
// 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, padWidths []int) string {
builder := strings.Builder{}
for i, stringArray := range stringArrays {
if len(stringArray) == 0 {
continue
}
for j, padWidth := range padWidths {
if len(stringArray)-1 < j {
continue
}
builder.WriteString(WithPadding(stringArray[j], padWidth))
builder.WriteString(" ")
}
if len(stringArray)-1 < len(padWidths) {
continue
}
builder.WriteString(stringArray[len(padWidths)])
if i < len(stringArrays)-1 {
builder.WriteString("\n")
}
}
return builder.String()
}
func getPadWidths(stringArrays [][]string) []int {
maxWidth := 0
for _, stringArray := range stringArrays {
if len(stringArray) > maxWidth {
maxWidth = len(stringArray)
}
}
if maxWidth-1 < 0 {
return []int{}
}
padWidths := make([]int, maxWidth-1)
for i := range padWidths {
for _, strings := range stringArrays {
uncoloredStr := Decolorise(strings[i])
width := runewidth.StringWidth(uncoloredStr)
if width > padWidths[i] {
padWidths[i] = width
}
}
}
return padWidths
}
// 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
}
}