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:
parent
5b933762c2
commit
ec3a28df43
@ -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()
|
||||
|
@ -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},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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")
|
||||
|
@ -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)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user