1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-06-08 23:56:15 +02:00

better formatting

This commit is contained in:
Jesse Duffield 2021-10-31 22:29:43 +11:00
parent f91892b8f1
commit 9989c96321
4 changed files with 110 additions and 29 deletions

View File

@ -2,12 +2,27 @@ package utils
import ( import (
"regexp" "regexp"
"sync"
) )
var decoloriseCache = make(map[string]string)
var decoloriseMutex sync.Mutex
// Decolorise strips a string of color // Decolorise strips a string of color
func Decolorise(str string) string { func Decolorise(str string) string {
decoloriseMutex.Lock()
defer decoloriseMutex.Unlock()
if decoloriseCache[str] != "" {
return decoloriseCache[str]
}
re := regexp.MustCompile(`\x1B\[([0-9]{1,3}(;[0-9]{1,3})*)?[mGK]`) re := regexp.MustCompile(`\x1B\[([0-9]{1,3}(;[0-9]{1,3})*)?[mGK]`)
return re.ReplaceAllString(str, "") ret := re.ReplaceAllString(str, "")
decoloriseCache[str] = ret
return ret
} }
func IsValidHexValue(v string) bool { func IsValidHexValue(v string) bool {

View File

@ -17,14 +17,48 @@ func WithPadding(str string, padding int) string {
} }
func RenderDisplayStrings(displayStringsArr [][]string) string { func RenderDisplayStrings(displayStringsArr [][]string) string {
displayStringsArr = excludeBlankColumns(displayStringsArr)
padWidths := getPadWidths(displayStringsArr) padWidths := getPadWidths(displayStringsArr)
paddedDisplayStrings := getPaddedDisplayStrings(displayStringsArr, padWidths) output := getPaddedDisplayStrings(displayStringsArr, padWidths)
return strings.Join(paddedDisplayStrings, "\n") return output
} }
func getPaddedDisplayStrings(stringArrays [][]string, padWidths []int) []string { // NOTE: this mutates the input slice for the sake of performance
paddedDisplayStrings := make([]string, len(stringArrays)) 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 { for i, stringArray := range stringArrays {
if len(stringArray) == 0 { if len(stringArray) == 0 {
continue continue
@ -33,14 +67,19 @@ func getPaddedDisplayStrings(stringArrays [][]string, padWidths []int) []string
if len(stringArray)-1 < j { if len(stringArray)-1 < j {
continue continue
} }
paddedDisplayStrings[i] += WithPadding(stringArray[j], padWidth) + " " builder.WriteString(WithPadding(stringArray[j], padWidth))
builder.WriteString(" ")
} }
if len(stringArray)-1 < len(padWidths) { if len(stringArray)-1 < len(padWidths) {
continue continue
} }
paddedDisplayStrings[i] += stringArray[len(padWidths)] builder.WriteString(stringArray[len(padWidths)])
if i < len(stringArrays)-1 {
builder.WriteString("\n")
}
} }
return paddedDisplayStrings return builder.String()
} }
func getPadWidths(stringArrays [][]string) []int { func getPadWidths(stringArrays [][]string) []int {

View File

@ -37,27 +37,6 @@ func TestWithPadding(t *testing.T) {
} }
} }
// TestGetPaddedDisplayStrings is a function.
func TestGetPaddedDisplayStrings(t *testing.T) {
type scenario struct {
stringArrays [][]string
padWidths []int
expected []string
}
scenarios := []scenario{
{
[][]string{{"a", "b"}, {"c", "d"}},
[]int{1},
[]string{"a b", "c d"},
},
}
for _, s := range scenarios {
assert.EqualValues(t, s.expected, getPaddedDisplayStrings(s.stringArrays, s.padWidths))
}
}
func TestGetPadWidths(t *testing.T) { func TestGetPadWidths(t *testing.T) {
type scenario struct { type scenario struct {
input [][]string input [][]string
@ -162,3 +141,44 @@ func TestTruncateWithEllipsis(t *testing.T) {
assert.EqualValues(t, s.expected, TruncateWithEllipsis(s.str, s.limit)) assert.EqualValues(t, s.expected, TruncateWithEllipsis(s.str, s.limit))
} }
} }
func TestRenderDisplayStrings(t *testing.T) {
type scenario struct {
input [][]string
expected string
}
tests := []scenario{
{
[][]string{{""}, {""}},
"",
},
{
[][]string{{"a"}, {""}},
"a\n",
},
{
[][]string{{"a"}, {"b"}},
"a\nb",
},
{
[][]string{{"a", "b"}, {"c", "d"}},
"a b\nc d",
},
{
[][]string{{"a", "", "c"}, {"d", "", "f"}},
"a c\nd f",
},
{
[][]string{{"a", "", "c", ""}, {"d", "", "f", ""}},
"a c\nd f",
},
}
for _, test := range tests {
output := RenderDisplayStrings(test.input)
if !assert.EqualValues(t, output, test.expected) {
t.Errorf("RenderDisplayStrings(%v) = %v, want %v", test.input, output, test.expected)
}
}
}

View File

@ -52,6 +52,13 @@ func Min(x, y int) int {
return y return y
} }
func Max(x, y int) int {
if x > y {
return x
}
return y
}
func AsJson(i interface{}) string { func AsJson(i interface{}) string {
bytes, _ := json.MarshalIndent(i, "", " ") bytes, _ := json.MarshalIndent(i, "", " ")
return string(bytes) return string(bytes)