summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Duffield <jessedduffield@gmail.com>2023-05-21 12:06:22 +1000
committerJesse Duffield <jessedduffield@gmail.com>2023-05-21 12:09:43 +1000
commitec3a28df4313e20aa3d73a9951c5679950e4cf04 (patch)
tree5ed6968bb8035f4344e410754fb585ba2eac8fc4
parent5b933762c2c0d7d8c1b26720a2d4c39b57e1af6e (diff)
Right-align key labels in menu
I find this makes it look a little nicer
-rw-r--r--pkg/gui/context/list_context_trait.go7
-rw-r--r--pkg/gui/context/menu_context.go2
-rw-r--r--pkg/gui/context/viewport_list_context_trait.go2
-rw-r--r--pkg/gui/presentation/authors/authors.go2
-rw-r--r--pkg/gui/presentation/branches.go2
-rw-r--r--pkg/gui/presentation/commits_test.go2
-rw-r--r--pkg/utils/formatting.go50
-rw-r--r--pkg/utils/formatting_test.go100
8 files changed, 124 insertions, 43 deletions
diff --git a/pkg/gui/context/list_context_trait.go b/pkg/gui/context/list_context_trait.go
index 74ff2f388..5dd9b50e0 100644
--- a/pkg/gui/context/list_context_trait.go
+++ b/pkg/gui/context/list_context_trait.go
@@ -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()
diff --git a/pkg/gui/context/menu_context.go b/pkg/gui/context/menu_context.go
index 667ea228b..6f84a8274 100644
--- a/pkg/gui/context/menu_context.go
+++ b/pkg/gui/context/menu_context.go
@@ -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},
},
}
}
diff --git a/pkg/gui/context/viewport_list_context_trait.go b/pkg/gui/context/viewport_list_context_trait.go
index b89dea832..120e9f967 100644
--- a/pkg/gui/context/viewport_list_context_trait.go
+++ b/pkg/gui/context/viewport_list_context_trait.go
@@ -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)
}
diff --git a/pkg/gui/presentation/authors/authors.go b/pkg/gui/presentation/authors/authors.go
index d4eb8e465..8f6325841 100644
--- a/pkg/gui/presentation/authors/authors.go
+++ b/pkg/gui/presentation/authors/authors.go
@@ -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
diff --git a/pkg/gui/presentation/branches.go b/pkg/gui/presentation/branches.go
index 7d68b04d5..bb4570654 100644
--- a/pkg/gui/presentation/branches.go
+++ b/pkg/gui/presentation/branches.go
@@ -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
diff --git a/pkg/gui/presentation/commits_test.go b/pkg/gui/presentation/commits_test.go
index 55155a704..a976d4809 100644
--- a/pkg/gui/presentation/commits_test.go
+++ b/pkg/gui/presentation/commits_test.go
@@ -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)
diff --git a/pkg/utils/formatting.go b/pkg/utils/formatting.go
index 657d1d2eb..2a900d207 100644
--- a/pkg/utils/formatting.go
+++ b/pkg/utils/formatting.go
@@ -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")
diff --git a/pkg/utils/formatting_test.go b/pkg/utils/formatting_test.go
index 5b9393d50..27c1d172c 100644
--- a/pkg/utils/formatting_test.go
+++ b/pkg/utils/formatting_test.go
@@ -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 ! ",
+ },
+ {
+ str: "hello world !",
+ padding: 14,
+ alignment: AlignRight,
+ expected: " hello world !",
},
{
- "Güçlü",
- 7,
- "Güçlü ",
+ 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",
+ },
+ {
+ input: [][]string{{"a"}, {"b"}},
+ columnAlignments: nil,
+ expected: "a\nb",
+ },
+ {
+ input: [][]string{{"a", "b"}, {"c", "d"}},
+ columnAlignments: nil,
+ expected: "a b\nc d",
+ },
+ {
+ input: [][]string{{"a", "", "c"}, {"d", "", "f"}},
+ columnAlignments: nil,
+ expected: "a c\nd f",
+ },
+ {
+ input: [][]string{{"a", "", "c", ""}, {"d", "", "f", ""}},
+ columnAlignments: nil,
+ expected: "a c\nd f",
},
{
- [][]string{{"a"}, {"b"}},
- "a\nb",
+ input: [][]string{{"abc", "", "d", ""}, {"e", "", "f", ""}},
+ columnAlignments: nil,
+ expected: "abc d\ne f",
},
{
- [][]string{{"a", "b"}, {"c", "d"}},
- "a b\nc d",
+ input: [][]string{{"abc", "", "d", ""}, {"e", "", "f", ""}},
+ columnAlignments: []Alignment{AlignLeft, AlignLeft}, // same as nil (default)
+ expected: "abc d\ne f",
},
{
- [][]string{{"a", "", "c"}, {"d", "", "f"}},
- "a c\nd f",
+ input: [][]string{{"abc", "", "d", ""}, {"e", "", "f", ""}},
+ columnAlignments: []Alignment{AlignRight, AlignLeft},
+ expected: "abc d\n e f",
},
{
- [][]string{{"a", "", "c", ""}, {"d", "", "f", ""}},
- "a c\nd 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)
}