1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2024-12-02 09:21:40 +02:00

Right-align key labels in menu

I find this makes it look a little nicer
This commit is contained in:
Jesse Duffield 2023-05-21 12:06:22 +10:00
parent 5b933762c2
commit ec3a28df43
8 changed files with 124 additions and 43 deletions

View File

@ -13,6 +13,8 @@ type ListContextTrait struct {
c *ContextCommon
list types.IList
getDisplayStrings func(startIdx int, length int) [][]string
// alignment for each column. If nil, the default is left alignment
columnAlignments []utils.Alignment
}
func (self *ListContextTrait) IsListContext() {}
@ -52,7 +54,10 @@ func (self *ListContextTrait) HandleFocusLost(opts types.OnFocusLostOpts) error
// OnFocus assumes that the content of the context has already been rendered to the view. OnRender is the function which actually renders the content to the view
func (self *ListContextTrait) HandleRender() error {
self.list.RefreshSelectedIdx()
content := utils.RenderDisplayStrings(self.getDisplayStrings(0, self.list.Len()))
content := utils.RenderDisplayStrings(
self.getDisplayStrings(0, self.list.Len()),
self.columnAlignments,
)
self.GetViewTrait().SetContent(content)
self.c.Render()
self.setFooter()

View File

@ -5,6 +5,7 @@ import (
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
"github.com/jesseduffield/lazygit/pkg/gui/style"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils"
"github.com/samber/lo"
)
@ -37,6 +38,7 @@ func NewMenuContext(
getDisplayStrings: viewModel.GetDisplayStrings,
list: viewModel,
c: c,
columnAlignments: []utils.Alignment{utils.AlignRight, utils.AlignLeft},
},
}
}

View File

@ -17,6 +17,6 @@ func (self *ViewportListContextTrait) FocusLine() {
startIdx, length := self.GetViewTrait().ViewPortYBounds()
displayStrings := self.ListContextTrait.getDisplayStrings(startIdx, length)
content := utils.RenderDisplayStrings(displayStrings)
content := utils.RenderDisplayStrings(displayStrings, nil)
self.GetViewTrait().SetViewPortContent(content)
}

View File

@ -42,7 +42,7 @@ func LongAuthor(authorName string) string {
return value
}
paddedAuthorName := utils.WithPadding(authorName, 17)
paddedAuthorName := utils.WithPadding(authorName, 17, utils.AlignLeft)
truncatedName := utils.TruncateWithEllipsis(paddedAuthorName, 17)
value := AuthorStyle(authorName).Sprint(truncatedName)
authorNameCache[authorName] = value

View File

@ -35,7 +35,7 @@ func getBranchDisplayStrings(b *models.Branch, fullDescription bool, diffed bool
}
coloredName := nameTextStyle.Sprint(displayName)
branchStatus := utils.WithPadding(ColoredBranchStatus(b, tr), 2)
branchStatus := utils.WithPadding(ColoredBranchStatus(b, tr), 2, utils.AlignLeft)
coloredName = fmt.Sprintf("%s %s", coloredName, branchStatus)
recencyColor := style.FgCyan

View File

@ -283,7 +283,7 @@ func TestGetCommitListDisplayStrings(t *testing.T) {
s.showYouAreHereLabel,
)
renderedResult := utils.RenderDisplayStrings(result)
renderedResult := utils.RenderDisplayStrings(result, nil)
t.Logf("\n%s", renderedResult)
assert.EqualValues(t, s.expected, renderedResult)

View File

@ -8,20 +8,52 @@ import (
"github.com/samber/lo"
)
type Alignment int
const (
AlignLeft Alignment = iota
AlignRight
)
type ColumnConfig struct {
Width int
Alignment Alignment
}
// WithPadding pads a string as much as you want
func WithPadding(str string, padding int) string {
func WithPadding(str string, padding int, alignment Alignment) string {
uncoloredStr := Decolorise(str)
width := runewidth.StringWidth(uncoloredStr)
if padding < width {
return str
}
return str + strings.Repeat(" ", padding-width)
space := strings.Repeat(" ", padding-width)
if alignment == AlignLeft {
return str + space
} else {
return space + str
}
}
func RenderDisplayStrings(displayStringsArr [][]string) string {
// 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 {
displayStringsArr = excludeBlankColumns(displayStringsArr)
padWidths := getPadWidths(displayStringsArr)
output := getPaddedDisplayStrings(displayStringsArr, padWidths)
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)
return output
}
@ -59,23 +91,23 @@ outer:
return displayStringsArr
}
func getPaddedDisplayStrings(stringArrays [][]string, padWidths []int) string {
func getPaddedDisplayStrings(stringArrays [][]string, columnConfigs []ColumnConfig) string {
builder := strings.Builder{}
for i, stringArray := range stringArrays {
if len(stringArray) == 0 {
continue
}
for j, padWidth := range padWidths {
for j, columnConfig := range columnConfigs {
if len(stringArray)-1 < j {
continue
}
builder.WriteString(WithPadding(stringArray[j], padWidth))
builder.WriteString(WithPadding(stringArray[j], columnConfig.Width, columnConfig.Alignment))
builder.WriteString(" ")
}
if len(stringArray)-1 < len(padWidths) {
if len(stringArray)-1 < len(columnConfigs) {
continue
}
builder.WriteString(stringArray[len(padWidths)])
builder.WriteString(stringArray[len(columnConfigs)])
if i < len(stringArrays)-1 {
builder.WriteString("\n")

View File

@ -6,34 +6,49 @@ import (
"github.com/stretchr/testify/assert"
)
// TestWithPadding is a function.
func TestWithPadding(t *testing.T) {
type scenario struct {
str string
padding int
expected string
str string
padding int
alignment Alignment
expected string
}
scenarios := []scenario{
{
"hello world !",
1,
"hello world !",
str: "hello world !",
padding: 1,
alignment: AlignLeft,
expected: "hello world !",
},
{
"hello world !",
14,
"hello world ! ",
str: "hello world !",
padding: 14,
alignment: AlignLeft,
expected: "hello world ! ",
},
{
"Güçlü",
7,
"Güçlü ",
str: "hello world !",
padding: 14,
alignment: AlignRight,
expected: " hello world !",
},
{
str: "Güçlü",
padding: 7,
alignment: AlignLeft,
expected: "Güçlü ",
},
{
str: "Güçlü",
padding: 7,
alignment: AlignRight,
expected: " Güçlü",
},
}
for _, s := range scenarios {
assert.EqualValues(t, s.expected, WithPadding(s.str, s.padding))
assert.EqualValues(t, s.expected, WithPadding(s.str, s.padding, s.alignment))
}
}
@ -144,39 +159,66 @@ func TestTruncateWithEllipsis(t *testing.T) {
func TestRenderDisplayStrings(t *testing.T) {
type scenario struct {
input [][]string
expected string
input [][]string
columnAlignments []Alignment
expected string
}
tests := []scenario{
{
[][]string{{""}, {""}},
"",
input: [][]string{{""}, {""}},
columnAlignments: nil,
expected: "",
},
{
[][]string{{"a"}, {""}},
"a\n",
input: [][]string{{"a"}, {""}},
columnAlignments: nil,
expected: "a\n",
},
{
[][]string{{"a"}, {"b"}},
"a\nb",
input: [][]string{{"a"}, {"b"}},
columnAlignments: nil,
expected: "a\nb",
},
{
[][]string{{"a", "b"}, {"c", "d"}},
"a b\nc d",
input: [][]string{{"a", "b"}, {"c", "d"}},
columnAlignments: nil,
expected: "a b\nc d",
},
{
[][]string{{"a", "", "c"}, {"d", "", "f"}},
"a c\nd f",
input: [][]string{{"a", "", "c"}, {"d", "", "f"}},
columnAlignments: nil,
expected: "a c\nd f",
},
{
[][]string{{"a", "", "c", ""}, {"d", "", "f", ""}},
"a c\nd f",
input: [][]string{{"a", "", "c", ""}, {"d", "", "f", ""}},
columnAlignments: nil,
expected: "a c\nd f",
},
{
input: [][]string{{"abc", "", "d", ""}, {"e", "", "f", ""}},
columnAlignments: nil,
expected: "abc d\ne f",
},
{
input: [][]string{{"abc", "", "d", ""}, {"e", "", "f", ""}},
columnAlignments: []Alignment{AlignLeft, AlignLeft}, // same as nil (default)
expected: "abc d\ne f",
},
{
input: [][]string{{"abc", "", "d", ""}, {"e", "", "f", ""}},
columnAlignments: []Alignment{AlignRight, AlignLeft},
expected: "abc d\n e f",
},
{
input: [][]string{{"abc", "", "d", ""}, {"e", "", "f", ""}},
columnAlignments: []Alignment{AlignRight}, // gracefully defaults unspecified columns to left-align
expected: "abc d\n e f",
},
}
for _, test := range tests {
output := RenderDisplayStrings(test.input)
output := RenderDisplayStrings(test.input, test.columnAlignments)
if !assert.EqualValues(t, output, test.expected) {
t.Errorf("RenderDisplayStrings(%v) = %v, want %v", test.input, output, test.expected)
}