summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Duffield <jessedduffield@gmail.com>2020-02-25 20:55:36 +1100
committerJesse Duffield <jessedduffield@gmail.com>2020-02-25 21:21:07 +1100
commitf94d0be2c9b0eaaf539d2cdcfaf258f754162a2e (patch)
tree0fa95e6348ca35d0938d263b007d9c471a09731e
parent9fd9fd6816925debe64aa21269cdba5ec74ed5e9 (diff)
refactor the way we render lists
-rw-r--r--pkg/commands/branch.go37
-rw-r--r--pkg/commands/commit_file.go23
-rw-r--r--pkg/commands/commit_list_builder.go2
-rw-r--r--pkg/commands/commit_list_builder_test.go167
-rw-r--r--pkg/commands/file.go22
-rw-r--r--pkg/commands/remote_branch.go12
-rw-r--r--pkg/commands/tag.go5
-rw-r--r--pkg/gui/branches_panel.go13
-rw-r--r--pkg/gui/commit_files_panel.go9
-rw-r--r--pkg/gui/commits_panel.go8
-rw-r--r--pkg/gui/files_panel.go12
-rw-r--r--pkg/gui/gui.go11
-rw-r--r--pkg/gui/presentation/branches.go48
-rw-r--r--pkg/gui/presentation/commit_files.go35
-rw-r--r--pkg/gui/presentation/commits.go2
-rw-r--r--pkg/gui/presentation/files.go36
-rw-r--r--pkg/gui/presentation/remote_branches.go23
-rw-r--r--pkg/gui/presentation/remotes.go20
-rw-r--r--pkg/gui/presentation/stash_entries.go20
-rw-r--r--pkg/gui/presentation/tags.go20
-rw-r--r--pkg/gui/reflog_panel.go6
-rw-r--r--pkg/gui/remote_branches_panel.go6
-rw-r--r--pkg/gui/remotes_panel.go8
-rw-r--r--pkg/gui/stash_panel.go17
-rw-r--r--pkg/gui/status_panel.go4
-rw-r--r--pkg/gui/tags_panel.go6
-rw-r--r--pkg/gui/view_helpers.go14
-rw-r--r--pkg/utils/utils.go51
-rw-r--r--pkg/utils/utils_test.go158
29 files changed, 250 insertions, 545 deletions
diff --git a/pkg/commands/branch.go b/pkg/commands/branch.go
index 42d43507f..8da8918d1 100644
--- a/pkg/commands/branch.go
+++ b/pkg/commands/branch.go
@@ -1,15 +1,5 @@
package commands
-import (
- "fmt"
- "strings"
-
- "github.com/jesseduffield/lazygit/pkg/theme"
-
- "github.com/fatih/color"
- "github.com/jesseduffield/lazygit/pkg/utils"
-)
-
// Branch : A git branch
// duplicating this for now
type Branch struct {
@@ -17,31 +7,4 @@ type Branch struct {
Recency string
Pushables string
Pullables string
- Selected bool
-}
-
-// GetDisplayStrings returns the display string of branch
-func (b *Branch) GetDisplayStrings(isFocused bool) []string {
- displayName := utils.ColoredString(b.Name, GetBranchColor(b.Name))
- if isFocused && b.Selected && b.Pushables != "" && b.Pullables != "" {
- displayName = fmt.Sprintf("%s ā†‘%sā†“%s", displayName, b.Pushables, b.Pullables)
- }
-
- return []string{b.Recency, displayName}
-}
-
-// GetBranchColor branch color
-func GetBranchColor(name string) color.Attribute {
- branchType := strings.Split(name, "/")[0]
-
- switch branchType {
- case "feature":
- return color.FgGreen
- case "bugfix":
- return color.FgYellow
- case "hotfix":
- return color.FgRed
- default:
- return theme.DefaultTextColor
- }
}
diff --git a/pkg/commands/commit_file.go b/pkg/commands/commit_file.go
index ddd09b23b..03614be24 100644
--- a/pkg/commands/commit_file.go
+++ b/pkg/commands/commit_file.go
@@ -1,10 +1,5 @@
package commands
-import (
- "github.com/fatih/color"
- "github.com/jesseduffield/lazygit/pkg/theme"
-)
-
// CommitFile : A git commit file
type CommitFile struct {
Sha string
@@ -22,21 +17,3 @@ const (
// PART is for when you're only talking about specific lines that have been modified
PART
)
-
-// GetDisplayStrings is a function.
-func (f *CommitFile) GetDisplayStrings(isFocused bool) []string {
- yellow := color.New(color.FgYellow)
- green := color.New(color.FgGreen)
- defaultColor := color.New(theme.DefaultTextColor)
-
- var colour *color.Color
- switch f.Status {
- case UNSELECTED:
- colour = defaultColor
- case WHOLE:
- colour = green
- case PART:
- colour = yellow
- }
- return []string{colour.Sprint(f.DisplayString)}
-}
diff --git a/pkg/commands/commit_list_builder.go b/pkg/commands/commit_list_builder.go
index 1e621f4e4..aa701d6bd 100644
--- a/pkg/commands/commit_list_builder.go
+++ b/pkg/commands/commit_list_builder.go
@@ -58,7 +58,7 @@ func (c *CommitListBuilder) extractCommitFromLine(line string) *Commit {
date := split[1]
author := split[2]
extraInfo := strings.TrimSpace(split[3])
- message := strings.Join(split[4:len(split)], SEPARATION_CHAR)
+ message := strings.Join(split[4:], SEPARATION_CHAR)
tags := []string{}
if extraInfo != "" {
diff --git a/pkg/commands/commit_list_builder_test.go b/pkg/commands/commit_list_builder_test.go
index c4ded4bb9..541dfd99c 100644
--- a/pkg/commands/commit_list_builder_test.go
+++ b/pkg/commands/commit_list_builder_test.go
@@ -149,170 +149,3 @@ func TestCommitListBuilderGetMergeBase(t *testing.T) {
})
}
}
-
-// TestCommitListBuilderGetLog is a function.
-func TestCommitListBuilderGetLog(t *testing.T) {
- type scenario struct {
- testName string
- command func(string, ...string) *exec.Cmd
- test func(string)
- }
-
- scenarios := []scenario{
- {
- "Retrieves logs",
- func(cmd string, args ...string) *exec.Cmd {
- assert.EqualValues(t, "git", cmd)
- assert.EqualValues(t, []string{"log", "--decorate", "--oneline", "-30", "--abbrev=20"}, args)
-
- return exec.Command("echo", "6f0b32f commands/git : add GetCommits tests refactor\n9d9d775 circle : remove new line")
- },
- func(output string) {
- assert.EqualValues(t, "6f0b32f commands/git : add GetCommits tests refactor\n9d9d775 circle : remove new line\n", output)
- },
- },
- {
- "An error occurred when retrieving logs",
- func(cmd string, args ...string) *exec.Cmd {
- assert.EqualValues(t, "git", cmd)
- assert.EqualValues(t, []string{"log", "--decorate", "--oneline", "-30", "--abbrev=20"}, args)
- return exec.Command("test")
- },
- func(output string) {
- assert.Empty(t, output)
- },
- },
- }
-
- for _, s := range scenarios {
- t.Run(s.testName, func(t *testing.T) {
- c := NewDummyCommitListBuilder()
- c.OSCommand.SetCommand(s.command)
- s.test(c.getLog(true))
- })
- }
-}
-
-// TestCommitListBuilderGetCommits is a function.
-func TestCommitListBuilderGetCommits(t *testing.T) {
- type scenario struct {
- testName string
- command func(string, ...string) *exec.Cmd
- test func([]*Commit, error)
- }
-
- scenarios := []scenario{
- {
- "No data found",
- func(cmd string, args ...string) *exec.Cmd {
- assert.EqualValues(t, "git", cmd)
-
- switch args[0] {
- case "rev-list":
- assert.EqualValues(t, []string{"rev-list", "@{u}..HEAD", "--abbrev-commit"}, args)
- return exec.Command("echo")
- case "log":
- assert.EqualValues(t, []string{"log", "--decorate", "--oneline", "-30", "--abbrev=20"}, args)
- return exec.Command("echo")
- case "merge-base":
- assert.EqualValues(t, []string{"merge-base", "HEAD", "master"}, args)
- return exec.Command("test")
- case "symbolic-ref":
- assert.EqualValues(t, []string{"symbolic-ref", "--short", "HEAD"}, args)
- return exec.Command("echo", "master")
- }
-
- return nil
- },
- func(commits []*Commit, err error) {
- assert.NoError(t, err)
- assert.Len(t, commits, 0)
- },
- },
- {
- "GetCommits returns 2 commits, 1 unpushed, the other merged",
- func(cmd string, args ...string) *exec.Cmd {
- assert.EqualValues(t, "git", cmd)
-
- switch args[0] {
- case "rev-list":
- assert.EqualValues(t, []string{"rev-list", "@{u}..HEAD", "--abbrev-commit"}, args)
- return exec.Command("echo", "8a2bb0e")
- case "log":
- assert.EqualValues(t, []string{"log", "--decorate", "--oneline", "-30", "--abbrev=20"}, args)
- return exec.Command("echo", "8a2bb0e commit 1\n78976bc commit 2")
- case "merge-base":
- assert.EqualValues(t, []string{"merge-base", "HEAD", "master"}, args)
- return exec.Command("echo", "78976bc")
- case "symbolic-ref":
- assert.EqualValues(t, []string{"symbolic-ref", "--short", "HEAD"}, args)
- return exec.Command("echo", "master")
- }
-
- return nil
- },
- func(commits []*Commit, err error) {
- assert.NoError(t, err)
- assert.Len(t, commits, 2)
- assert.EqualValues(t, []*Commit{
- {
- Sha: "8a2bb0e",
- Name: "commit 1",
- Status: "unpushed",
- DisplayString: "8a2bb0e commit 1",
- },
- {
- Sha: "78976bc",
- Name: "commit 2",
- Status: "merged",
- DisplayString: "78976bc commit 2",
- },
- }, commits)
- },
- },
- {
- "GetCommits bubbles up an error from setCommitMergedStatuses",
- func(cmd string, args ...string) *exec.Cmd {
- assert.EqualValues(t, "git", cmd)
-
- switch args[0] {
- case "rev-list":
- assert.EqualValues(t, []string{"rev-list", "@{u}..HEAD", "--abbrev-commit"}, args)
- return exec.Command("echo", "8a2bb0e")
- case "log":
- assert.EqualValues(t, []string{"log", "--decorate", "--oneline", "-30", "--abbrev=20"}, args)
- return exec.Command("echo", "8a2bb0e commit 1\n78976bc commit 2")
- case "merge-base":
- assert.EqualValues(t, []string{"merge-base", "HEAD", "master"}, args)
- return exec.Command("echo", "78976bc")
- case "symbolic-ref":
- assert.EqualValues(t, []string{"symbolic-ref", "--short", "HEAD"}, args)
- // here's where we are returning the error
- return exec.Command("test")
- case "branch":
- assert.EqualValues(t, []string{"branch", "--contains"}, args)
- // here too
- return exec.Command("test")
- case "rev-parse":
- assert.EqualValues(t, []string{"rev-parse", "--short", "HEAD"}, args)
- // here too
- return exec.Command("test")
- }
-
- return nil
- },
- func(commits []*Commit, err error) {
- assert.Error(t, err)
- assert.Len(t, commits, 0)
- },
- },
- }
-
- for _, s := range scenarios {
- t.Run(s.testName, func(t *testing.T) {
- c := NewDummyCommitListBuilder()
- c.OSCommand.SetCommand(s.command)
- s.test(c.GetCommits(true))
- })
- }
-}
diff --git a/pkg/commands/file.go b/pkg/commands/file.go
index 3c4e13f06..37a1dcccb 100644
--- a/pkg/commands/file.go
+++ b/pkg/commands/file.go
@@ -1,7 +1,5 @@
package commands
-import "github.com/fatih/color"
-
// File : A file from git status
// duplicating this for now
type File struct {
@@ -16,23 +14,3 @@ type File struct {
Type string // one of 'file', 'directory', and 'other'
ShortStatus string // e.g. 'AD', ' A', 'M ', '??'
}
-
-// GetDisplayStrings returns the display string of a file
-func (f *File) GetDisplayStrings(isFocused bool) []string {
- // potentially inefficient to be instantiating these color
- // objects with each render
- red := color.New(color.FgRed)
- green := color.New(color.FgGreen)
- if !f.Tracked && !f.HasStagedChanges {
- return []string{red.Sprint(f.DisplayString)}
- }
-
- output := green.Sprint(f.DisplayString[0:1])
- output += red.Sprint(f.DisplayString[1:3])
- if f.HasUnstagedChanges {
- output += red.Sprint(f.Name)
- } else {
- output += green.Sprint(f.Name)
- }
- return []string{output}
-}
diff --git a/pkg/commands/remote_branch.go b/pkg/commands/remote_branch.go
index 5016dc5bd..0435a050f 100644
--- a/pkg/commands/remote_branch.go
+++ b/pkg/commands/remote_branch.go
@@ -1,19 +1,7 @@
package commands
-import (
- "github.com/jesseduffield/lazygit/pkg/utils"
-)
-
// Remote Branch : A git remote branch
type RemoteBranch struct {
Name string
- Selected bool
RemoteName string
}
-
-// GetDisplayStrings returns the display string of branch
-func (b *RemoteBranch) GetDisplayStrings(isFocused bool) []string {
- displayName := utils.ColoredString(b.Name, GetBranchColor(b.Name))
-
- return []string{displayName}
-}
diff --git a/pkg/commands/tag.go b/pkg/commands/tag.go
index 99a4a7f0e..b6910b4b0 100644
--- a/pkg/commands/tag.go
+++ b/pkg/commands/tag.go
@@ -4,8 +4,3 @@ package commands
type Tag struct {
Name string
}
-
-// GetDisplayStrings returns the display string of a remote
-func (r *Tag) GetDisplayStrings(isFocused bool) []string {
- return []string{r.Name}
-}
diff --git a/pkg/gui/branches_panel.go b/pkg/gui/branches_panel.go
index 5ecb563f2..90d8a2758 100644
--- a/pkg/gui/branches_panel.go
+++ b/pkg/gui/branches_panel.go
@@ -6,6 +6,7 @@ import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands"
+ "github.com/jesseduffield/lazygit/pkg/gui/presentation"
"github.com/jesseduffield/lazygit/pkg/utils"
)
@@ -57,13 +58,6 @@ func (gui *Gui) handleBranchSelect(g *gocui.Gui, v *gocui.View) error {
func (gui *Gui) RenderSelectedBranchUpstreamDifferences() error {
return gui.newTask("branches", func(stop chan struct{}) error {
- // here we tell the selected branch that it is selected.
- // this is necessary for showing stats on a branch that is selected, because
- // the displaystring function doesn't have access to gui state to tell if it's selected
- for i, branch := range gui.State.Branches {
- branch.Selected = i == gui.State.Panels.Branches.SelectedLine
- }
-
branch := gui.getSelectedBranch()
branch.Pushables, branch.Pullables = gui.GitCommand.GetBranchUpstreamDifferenceCount(branch.Name)
@@ -73,7 +67,10 @@ func (gui *Gui) RenderSelectedBranchUpstreamDifferences() error {
default:
}
- return gui.renderListPanel(gui.getBranchesView(), gui.State.Branches)
+ branchesView := gui.getBranchesView()
+ displayStrings := presentation.GetBranchListDisplayStrings(gui.State.Branches, gui.currentViewName() == "branches", gui.State.Panels.Branches.SelectedLine)
+ gui.renderDisplayStrings(branchesView, displayStrings)
+ return nil
})
}
diff --git a/pkg/gui/commit_files_panel.go b/pkg/gui/commit_files_panel.go
index fbfeeb11c..63458926b 100644
--- a/pkg/gui/commit_files_panel.go
+++ b/pkg/gui/commit_files_panel.go
@@ -4,6 +4,7 @@ import (
"github.com/go-errors/errors"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands"
+ "github.com/jesseduffield/lazygit/pkg/gui/presentation"
)
func (gui *Gui) getSelectedCommitFile(g *gocui.Gui) *commands.CommitFile {
@@ -112,11 +113,11 @@ func (gui *Gui) refreshCommitFilesView() error {
gui.refreshSelectedLine(&gui.State.Panels.CommitFiles.SelectedLine, len(gui.State.CommitFiles))
- if err := gui.renderListPanel(gui.getCommitFilesView(), gui.State.CommitFiles); err != nil {
- return err
- }
+ commitsFileView := gui.getCommitFilesView()
+ displayStrings := presentation.GetCommitFileListDisplayStrings(gui.State.CommitFiles)
+ gui.renderDisplayStrings(commitsFileView, displayStrings)
- return gui.handleCommitFileSelect(gui.g, gui.getCommitFilesView())
+ return gui.handleCommitFileSelect(gui.g, commitsFileView)
}
func (gui *Gui) handleOpenOldCommitFile(g *gocui.Gui, v *gocui.View) error {
diff --git a/pkg/gui/commits_panel.go b/pkg/gui/commits_panel.go
index e42aabfd0..fe6b7acb9 100644
--- a/pkg/gui/commits_panel.go
+++ b/pkg/gui/commits_panel.go
@@ -632,7 +632,13 @@ func (gui *Gui) switchCommitsPanelContext(context string) error {
commitsView.TabIndex = contextTabIndexMap[context]
- switch context {
+ return gui.refreshCommitsViewWithSelection()
+}
+
+func (gui *Gui) refreshCommitsViewWithSelection() error {
+ commitsView := gui.getCommitsView()
+
+ switch commitsView.Context {
case "branch-commits":
return gui.renderBranchCommitsWithSelection()
case "reflog-commits":
diff --git a/pkg/gui/files_panel.go b/pkg/gui/files_panel.go
index 9e81009ea..4e00dc523 100644
--- a/pkg/gui/files_panel.go
+++ b/pkg/gui/files_panel.go
@@ -12,7 +12,7 @@ import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands"
- "github.com/jesseduffield/lazygit/pkg/utils"
+ "github.com/jesseduffield/lazygit/pkg/gui/presentation"
)
// list panel functions
@@ -103,14 +103,8 @@ func (gui *Gui) refreshFiles() error {
}
gui.g.Update(func(g *gocui.Gui) error {
-
- filesView.Clear()
- isFocused := gui.g.CurrentView().Name() == "files"
- list, err := utils.RenderList(gui.State.Files, isFocused)
- if err != nil {
- return err
- }
- fmt.Fprint(filesView, list)
+ displayStrings := presentation.GetFileListDisplayStrings(gui.State.Files)
+ gui.renderDisplayStrings(filesView, displayStrings)
if g.CurrentView() == filesView || (g.CurrentView() == gui.getMainView() && g.CurrentView().Context == "merging") {
newSelectedFile, _ := gui.getSelectedFile(gui.g)
diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go
index 4cf435b8f..70c3c3f51 100644
--- a/pkg/gui/gui.go
+++ b/pkg/gui/gui.go
@@ -24,6 +24,7 @@ import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands"
"github.com/jesseduffield/lazygit/pkg/config"
+ "github.com/jesseduffield/lazygit/pkg/gui/presentation"
"github.com/jesseduffield/lazygit/pkg/i18n"
"github.com/jesseduffield/lazygit/pkg/tasks"
"github.com/jesseduffield/lazygit/pkg/theme"
@@ -270,7 +271,7 @@ func NewGui(log *logrus.Entry, gitCommand *commands.GitCommand, oSCommand *comma
func (gui *Gui) nextScreenMode(g *gocui.Gui, v *gocui.View) error {
gui.State.ScreenMode = utils.NextIntInCycle([]int{SCREEN_NORMAL, SCREEN_HALF, SCREEN_FULL}, gui.State.ScreenMode)
// commits render differently depending on whether we're in fullscreen more or not
- if err := gui.renderBranchCommitsWithSelection(); err != nil {
+ if err := gui.refreshCommitsViewWithSelection(); err != nil {
return err
}
@@ -280,7 +281,7 @@ func (gui *Gui) nextScreenMode(g *gocui.Gui, v *gocui.View) error {
func (gui *Gui) prevScreenMode(g *gocui.Gui, v *gocui.View) error {
gui.State.ScreenMode = utils.PrevIntInCycle([]int{SCREEN_NORMAL, SCREEN_HALF, SCREEN_FULL}, gui.State.ScreenMode)
// commits render differently depending on whether we're in fullscreen more or not
- if err := gui.renderBranchCommitsWithSelection(); err != nil {
+ if err := gui.refreshCommitsViewWithSelection(); err != nil {
return err
}
@@ -382,10 +383,8 @@ func (gui *Gui) onFocusLost(v *gocui.View, newView *gocui.View) error {
case "branches":
if v.Context == "local-branches" {
// This stops the branches panel from showing the upstream/downstream changes to the selected branch, when it loses focus
- // inside renderListPanel it checks to see if the panel has focus
- if err := gui.renderListPanel(gui.getBranchesView(), gui.State.Branches); err != nil {
- return err
- }
+ displayStrings := presentation.GetBranchListDisplayStrings(gui.State.Branches, false, -1)
+ gui.renderDisplayStrings(gui.getBranchesView(), displayStrings)
}
case "main":
// if we have lost focus to a first-class panel, we need to do some cleanup
diff --git a/pkg/gui/presentation/branches.go b/pkg/gui/presentation/branches.go
new file mode 100644
index 000000000..3b918116b
--- /dev/null
+++ b/pkg/gui/presentation/branches.go
@@ -0,0 +1,48 @@
+package presentation
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/fatih/color"
+ "github.com/jesseduffield/lazygit/pkg/commands"
+ "github.com/jesseduffield/lazygit/pkg/theme"
+ "github.com/jesseduffield/lazygit/pkg/utils"
+)
+
+func GetBranchListDisplayStrings(branches []*commands.Branch, isFocused bool, selectedLine int) [][]string {
+ lines := make([][]string, len(branches))
+
+ for i := range branches {
+ showUpstreamDifferences := isFocused && i == selectedLine
+ lines[i] = getBranchDisplayStrings(branches[i], showUpstreamDifferences)
+ }
+
+ return lines
+}
+
+// getBranchDisplayStrings returns the display string of branch
+func getBranchDisplayStrings(b *commands.Branch, showUpstreamDifferences bool) []string {
+ displayName := utils.ColoredString(b.Name, GetBranchColor(b.Name))
+ if showUpstreamDifferences && b.Pushables != "" && b.Pullables != "" {
+ displayName = fmt.Sprintf("%s ā†‘%sā†“%s", displayName, b.Pushables, b.Pullables)
+ }
+
+ return []string{b.Recency, displayName}
+}
+
+// GetBranchColor branch color
+func GetBranchColor(name string) color.Attribute {
+ branchType := strings.Split(name, "/")[0]
+
+ switch branchType {
+ case "feature":
+ return color.FgGreen
+ case "bugfix":
+ return color.FgYellow
+ case "hotfix":
+ return color.FgRed
+ default:
+ return theme.DefaultTextColor
+ }
+}
diff --git a/pkg/gui/presentation/commit_files.go b/pkg/gui/presentation/commit_files.go
new file mode 100644
index 000000000..4ea0f85db
--- /dev/null
+++ b/pkg/gui/presentation/commit_files.go
@@ -0,0 +1,35 @@
+package presentation
+
+import (
+ "github.com/fatih/color"
+ "github.com/jesseduffield/lazygit/pkg/commands"
+ "github.com/jesseduffield/lazygit/pkg/theme"
+)
+
+func GetCommitFileListDisplayStrings(branches []*commands.CommitFile) [][]string {
+ lines := make([][]string, len(branches))
+
+ for i := range branches {
+ lines[i] = getCommitFileDisplayStrings(branches[i])
+ }
+
+ return lines
+}
+
+// getCommitFileDisplayStrings returns the display string of branch
+func getCommitFileDisplayStrings(f *commands.CommitFile) []string {
+ yellow := color.New(color.FgYellow)
+ green := color.New(color.FgGreen)
+ defaultColor := color.New(theme.DefaultTextColor)
+
+ var colour *color.Color
+ switch f.Status {
+ case commands.UNSELECTED:
+ colour = defaultColor
+ case commands.WHOLE:
+ colour = green
+ case commands.PART:
+ colour = yellow
+ }
+ return []string{colour.Sprint(f.DisplayString)}
+}
diff --git a/pkg/gui/presentation/commits.go b/pkg/gui/presentation/commits.go
index 04dbb0780..740abab78 100644
--- a/pkg/gui/presentation/commits.go
+++ b/pkg/gui/presentation/commits.go
@@ -67,7 +67,7 @@ func getFullDescriptionDisplayStringsForCommit(c *commands.Commit) []string {
secondColumnString := blue.Sprint(truncatedDate)
if c.Action != "" {
secondColumnString = cyan.Sprint(c.Action)
- } else if len(c.Tags) > 0 {
+ } else if c.ExtraInfo != "" {
tagColor := color.New(color.FgMagenta, color.Bold)
tagString = utils.ColoredStringDirect(c.ExtraInfo, tagColor) + " "
}
diff --git a/pkg/gui/presentation/files.go b/pkg/gui/presentation/files.go
new file mode 100644
index 000000000..589e8aecc
--- /dev/null
+++ b/pkg/gui/presentation/files.go
@@ -0,0 +1,36 @@
+package presentation
+
+import (
+ "github.com/fatih/color"
+ "github.com/jesseduffield/lazygit/pkg/commands"
+)
+
+func GetFileListDisplayStrings(files []*commands.File) [][]string {
+ lines := make([][]string, len(files))
+
+ for i := range files {
+ lines[i] = getFileDisplayStrings(files[i])
+ }
+
+ return lines
+}
+
+// getFileDisplayStrings returns the display string of branch
+func getFileDisplayStrings(f *commands.File) []string {
+ // potentially inefficient to be instantiating these color
+ // objects with each render
+ red := color.New(color.FgRed)
+ green := color.New(color.FgGreen)
+ if !f.Tracked && !f.HasStagedChanges {
+ return []string{red.Sprint(f.DisplayString)}
+ }
+
+ output := green.Sprint(f.DisplayString[0:1])
+ output += red.Sprint(f.DisplayString[1:3])
+ if f.HasUnstagedChanges {
+ output += red.Sprint(f.Name)
+ } else {
+ output += green.Sprint(f.Name)
+ }
+ return []string{output}
+}
diff --git a/pkg/gui/presentation/remote_branches.go b/pkg/gui/presentation/remote_branches.go
new file mode 100644
index 000000000..d3094c8cb
--- /dev/null
+++ b/pkg/gui/presentation/remote_branches.go
@@ -0,0 +1,23 @@
+package presentation
+
+import (
+ "github.com/jesseduffield/lazygit/pkg/commands"
+ "github.com/jesseduffield/lazygit/pkg/utils"
+)
+
+func GetRemoteBranchListDisplayStrings(branches []*commands.RemoteBranch) [][]string {
+ lines := make([][]string, len(branches))
+
+ for i := range branches {
+ lines[i] = getRemoteBranchDisplayStrings(branches[i])
+ }
+
+ return lines
+}
+
+// getRemoteBranchDisplayStrings returns the display string of branch
+func getRemoteBranchDisplayStrings(b *commands.RemoteBranch) []string {
+ displayName := utils.ColoredString(b.Name, GetBranchColor(b.Name))
+
+ return []string{displayName}
+}
diff --git a/pkg/gui/presentation/remotes.go b/pkg/gui/presentation/remotes.go
new file mode 100644
index 000000000..24fcd0b97
--- /dev/null
+++ b/pkg/gui/presentation/remotes.go
@@ -0,0 +1,20 @@
+package presentation
+
+import (
+ "github.com/jesseduffield/lazygit/pkg/commands"
+)
+
+func GetRemoteListDisplayStrings(remotes []*commands.Remote) [][]string {
+ lines := make([][]string, len(remotes))
+
+ for i := range remotes {
+ lines[i] = getRemoteDisplayStrings(remotes[i])
+ }
+
+ return lines
+}
+
+// getRemoteDisplayStrings returns the display string of branch
+func getRemoteDisplayStrings(r *commands.Remote) []string {
+ return []string{r.Name}
+}
diff --git a/pkg/gui/presentation/stash_entries.go b/pkg/gui/presentation/stash_entries.go
new file mode 100644
index 000000000..8598b5e5f
--- /dev/null
+++ b/pkg/gui/presentation/stash_entries.go
@@ -0,0 +1,20 @@
+package presentation
+
+import (
+ "github.com/jesseduffield/lazygit/pkg/commands"
+)
+
+func GetStashEntryListDisplayStrings(stashEntries []*commands.StashEntry) [][]string {
+ lines := make([][]string, len(stashEntries))
+
+ for i := range stashEntries {
+ lines[i] = getStashEntryDisplayStrings(stashEntries[i])
+ }
+
+ return lines
+}
+
+// getStashEntryDisplayStrings returns the display string of branch
+func getStashEntryDisplayStrings(s *commands.StashEntry) []string {
+ return []string{s.DisplayString}
+}
diff --git a/pkg/gui/presentation/tags.go b/pkg/gui/presentation/tags.go
new file mode 100644
index 000000000..13f2b8b59
--- /dev/null
+++ b/pkg/gui/presentation/tags.go
@@ -0,0 +1,20 @@
+package presentation
+
+import (
+ "github.com/jesseduffield/lazygit/pkg/commands"
+)
+
+func GetTagListDisplayStrings(tags []*commands.Tag) [][]string {
+ lines := make([][]string, len(tags))
+
+ for i := range tags {
+ lines[i] = getTagDisplayStrings(tags[i])
+ }
+
+ return lines
+}
+
+// getTagDisplayStrings returns the display string of branch
+func getTagDisplayStrings(t *commands.Tag) []string {
+ return []string{t.Name}
+}
diff --git a/pkg/gui/reflog_panel.go b/pkg/gui/reflog_panel.go
index fc4ff98c7..37144d8c6 100644
--- a/pkg/gui/reflog_panel.go
+++ b/