1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-08-09 09:22:48 +03:00

standardise rendering of lists in panels

This commit is contained in:
Jesse Duffield
2018-09-17 21:02:30 +10:00
parent 3b765e5417
commit c00c834b35
15 changed files with 256 additions and 180 deletions

View File

@@ -7,6 +7,7 @@ import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands"
"github.com/jesseduffield/lazygit/pkg/git"
"github.com/jesseduffield/lazygit/pkg/utils"
)
func (gui *Gui) handleBranchPress(g *gocui.Gui, v *gocui.View) error {
@@ -109,7 +110,7 @@ func (gui *Gui) handleMerge(g *gocui.Gui, v *gocui.View) error {
return nil
}
func (gui *Gui) getSelectedBranch(v *gocui.View) commands.Branch {
func (gui *Gui) getSelectedBranch(v *gocui.View) *commands.Branch {
lineNumber := gui.getItemPosition(v)
return gui.State.Branches[lineNumber]
}
@@ -151,12 +152,15 @@ func (gui *Gui) refreshBranches(g *gocui.Gui) error {
return err
}
gui.State.Branches = builder.Build()
v.Clear()
displayStrings := make([]string, len(gui.State.Branches))
for i, branch := range gui.State.Branches {
displayStrings[i] = branch.GetDisplayString()
list, err := utils.RenderList(gui.State.Branches)
if err != nil {
return err
}
fmt.Fprint(v, strings.Join(displayStrings, "\n"))
fmt.Fprint(v, list)
gui.resetOrigin(v)
return gui.refreshStatus(g)
})

View File

@@ -3,26 +3,12 @@ package gui
import (
"errors"
"fmt"
"strings"
"github.com/fatih/color"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands"
"github.com/jesseduffield/lazygit/pkg/utils"
)
func (gui *Gui) renderCommit(commit commands.Commit) string {
red := color.New(color.FgRed)
yellow := color.New(color.FgYellow)
white := color.New(color.FgWhite)
shaColor := yellow
if commit.Pushed {
shaColor = red
}
return shaColor.Sprint(commit.Sha) + " " + white.Sprint(commit.Name)
}
func (gui *Gui) refreshCommits(g *gocui.Gui) error {
g.Update(func(*gocui.Gui) error {
gui.State.Commits = gui.GitCommand.GetCommits()
@@ -30,12 +16,14 @@ func (gui *Gui) refreshCommits(g *gocui.Gui) error {
if err != nil {
panic(err)
}
v.Clear()
displayStrings := make([]string, len(gui.State.Commits))
for i, commit := range gui.State.Commits {
displayStrings[i] = gui.renderCommit(commit)
list, err := utils.RenderList(gui.State.Commits)
if err != nil {
return err
}
fmt.Fprint(v, strings.Join(displayStrings, "\n"))
fmt.Fprint(v, list)
gui.refreshStatus(g)
if g.CurrentView().Name() == "commits" {
gui.handleCommitSelect(g, v)
@@ -106,7 +94,7 @@ func (gui *Gui) handleCommitSquashDown(g *gocui.Gui, v *gocui.View) error {
}
// TODO: move to files panel
func (gui *Gui) anyUnStagedChanges(files []commands.File) bool {
func (gui *Gui) anyUnStagedChanges(files []*commands.File) bool {
for _, file := range files {
if file.Tracked && file.HasUnstagedChanges {
return true
@@ -169,13 +157,13 @@ func (gui *Gui) handleRenameCommitEditor(g *gocui.Gui, v *gocui.View) error {
return nil
}
func (gui *Gui) getSelectedCommit(g *gocui.Gui) (commands.Commit, error) {
func (gui *Gui) getSelectedCommit(g *gocui.Gui) (*commands.Commit, error) {
v, err := g.View("commits")
if err != nil {
panic(err)
}
if len(gui.State.Commits) == 0 {
return commands.Commit{}, errors.New(gui.Tr.SLocalize("NoCommitsThisBranch"))
return &commands.Commit{}, errors.New(gui.Tr.SLocalize("NoCommitsThisBranch"))
}
lineNumber := gui.getItemPosition(v)
if lineNumber > len(gui.State.Commits)-1 {

View File

@@ -10,14 +10,14 @@ import (
"fmt"
"strings"
"github.com/fatih/color"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands"
"github.com/jesseduffield/lazygit/pkg/utils"
)
func (gui *Gui) stagedFiles() []commands.File {
func (gui *Gui) stagedFiles() []*commands.File {
files := gui.State.Files
result := make([]commands.File, 0)
result := make([]*commands.File, 0)
for _, file := range files {
if file.HasStagedChanges {
result = append(result, file)
@@ -26,9 +26,9 @@ func (gui *Gui) stagedFiles() []commands.File {
return result
}
func (gui *Gui) trackedFiles() []commands.File {
func (gui *Gui) trackedFiles() []*commands.File {
files := gui.State.Files
result := make([]commands.File, 0)
result := make([]*commands.File, 0)
for _, file := range files {
if file.Tracked {
result = append(result, file)
@@ -117,9 +117,9 @@ func (gui *Gui) handleAddPatch(g *gocui.Gui, v *gocui.View) error {
return gui.Errors.ErrSubProcess
}
func (gui *Gui) getSelectedFile(g *gocui.Gui) (commands.File, error) {
func (gui *Gui) getSelectedFile(g *gocui.Gui) (*commands.File, error) {
if len(gui.State.Files) == 0 {
return commands.File{}, gui.Errors.ErrNoFiles
return &commands.File{}, gui.Errors.ErrNoFiles
}
filesView, err := g.View("files")
if err != nil {
@@ -185,7 +185,7 @@ func (gui *Gui) handleFileSelect(g *gocui.Gui, v *gocui.View) error {
gui.renderString(g, "main", gui.Tr.SLocalize("NoChangedFiles"))
return gui.renderfilesOptions(g, nil)
}
gui.renderfilesOptions(g, &file)
gui.renderfilesOptions(g, file)
var content string
if file.HasMergeConflicts {
return gui.refreshMergePanel(g)
@@ -276,25 +276,6 @@ func (gui *Gui) updateHasMergeConflictStatus() error {
return nil
}
func (gui *Gui) renderFile(file 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 !file.Tracked && !file.HasStagedChanges {
return red.Sprint(file.DisplayString)
}
output := green.Sprint(file.DisplayString[0:1])
output += red.Sprint(file.DisplayString[1:3])
if file.HasUnstagedChanges {
output += red.Sprint(file.Name)
} else {
output += green.Sprint(file.Name)
}
return output
}
func (gui *Gui) catSelectedFile(g *gocui.Gui) (string, error) {
item, err := gui.getSelectedFile(g)
if err != nil {
@@ -321,13 +302,12 @@ func (gui *Gui) refreshFiles(g *gocui.Gui) error {
}
gui.refreshStateFiles()
displayStrings := make([]string, len(gui.State.Files))
for i, file := range gui.State.Files {
displayStrings[i] = gui.renderFile(file)
}
filesView.Clear()
fmt.Fprint(filesView, strings.Join(displayStrings, "\n"))
list, err := utils.RenderList(gui.State.Files)
if err != nil {
return err
}
fmt.Fprint(filesView, list)
gui.correctCursor(filesView)
if filesView == g.CurrentView() {

View File

@@ -71,10 +71,10 @@ type Gui struct {
}
type guiState struct {
Files []commands.File
Branches []commands.Branch
Commits []commands.Commit
StashEntries []commands.StashEntry
Files []*commands.File
Branches []*commands.Branch
Commits []*commands.Commit
StashEntries []*commands.StashEntry
PreviousView string
HasMergeConflicts bool
ConflictIndex int
@@ -83,17 +83,17 @@ type guiState struct {
EditHistory *stack.Stack
Platform commands.Platform
Updating bool
Keys []Binding
Keys []*Binding
}
// NewGui builds a new gui handler
func NewGui(log *logrus.Entry, gitCommand *commands.GitCommand, oSCommand *commands.OSCommand, tr *i18n.Localizer, config config.AppConfigurer, updater *updates.Updater) (*Gui, error) {
initialState := guiState{
Files: make([]commands.File, 0),
Files: make([]*commands.File, 0),
PreviousView: "files",
Commits: make([]commands.Commit, 0),
StashEntries: make([]commands.StashEntry, 0),
Commits: make([]*commands.Commit, 0),
StashEntries: make([]*commands.StashEntry, 0),
ConflictIndex: 0,
ConflictTop: true,
Conflicts: make([]commands.Conflict, 0),

View File

@@ -1,6 +1,8 @@
package gui
import "github.com/jesseduffield/gocui"
import (
"github.com/jesseduffield/gocui"
)
// Binding - a keybinding mapping a key and modifier to a handler. The keypress
// is only handled if the given view has focus, or handled globally if the view
@@ -14,8 +16,26 @@ type Binding struct {
Description string
}
func (gui *Gui) GetKeybindings() []Binding {
bindings := []Binding{
// GetDisplayStrings returns the display string of a file
func (b *Binding) GetDisplayStrings() []string {
return []string{b.GetKey(), b.Description}
}
func (b *Binding) GetKey() string {
r, ok := b.Key.(rune)
key := ""
if ok {
key = string(r)
} else if b.KeyReadable != "" {
key = b.KeyReadable
}
return key
}
func (gui *Gui) GetKeybindings() []*Binding {
bindings := []*Binding{
{
ViewName: "",
Key: 'q',
@@ -360,7 +380,7 @@ func (gui *Gui) GetKeybindings() []Binding {
// Would make these keybindings global but that interferes with editing
// input in the confirmation panel
for _, viewName := range []string{"status", "files", "branches", "commits", "stash", "menu"} {
bindings = append(bindings, []Binding{
bindings = append(bindings, []*Binding{
{ViewName: viewName, Key: gocui.KeyTab, Modifier: gocui.ModNone, Handler: gui.nextView},
{ViewName: viewName, Key: gocui.KeyArrowLeft, Modifier: gocui.ModNone, Handler: gui.previousView},
{ViewName: viewName, Key: gocui.KeyArrowRight, Modifier: gocui.ModNone, Handler: gui.nextView},

View File

@@ -49,50 +49,20 @@ func (gui *Gui) handleMenuClose(g *gocui.Gui, v *gocui.View) error {
return gui.returnFocus(g, v)
}
func (gui *Gui) GetKey(binding Binding) string {
r, ok := binding.Key.(rune)
key := ""
if ok {
key = string(r)
} else if binding.KeyReadable != "" {
key = binding.KeyReadable
}
return key
}
func (gui *Gui) GetMaxKeyLength(bindings []Binding) int {
max := 0
for _, binding := range bindings {
keyLength := len(gui.GetKey(binding))
if keyLength > max {
max = keyLength
}
}
return max
}
func (gui *Gui) handleMenu(g *gocui.Gui, v *gocui.View) error {
var (
contentGlobal, contentPanel []string
bindingsGlobal, bindingsPanel []Binding
bindingsGlobal, bindingsPanel []*Binding
)
// clear keys slice, so we don't have ghost elements
gui.State.Keys = gui.State.Keys[:0]
bindings := gui.GetKeybindings()
padWidth := gui.GetMaxKeyLength(bindings)
for _, binding := range bindings {
key := gui.GetKey(binding)
if key != "" && binding.Description != "" {
content := fmt.Sprintf("%s %s", utils.WithPadding(key, padWidth), binding.Description)
if binding.GetKey() != "" && binding.Description != "" {
switch binding.ViewName {
case "":
contentGlobal = append(contentGlobal, content)
bindingsGlobal = append(bindingsGlobal, binding)
case v.Name():
contentPanel = append(contentPanel, content)
bindingsPanel = append(bindingsPanel, binding)
}
}
@@ -100,24 +70,25 @@ func (gui *Gui) handleMenu(g *gocui.Gui, v *gocui.View) error {
// append dummy element to have a separator between
// panel and global keybindings
contentPanel = append(contentPanel, "")
bindingsPanel = append(bindingsPanel, Binding{})
content := append(contentPanel, contentGlobal...)
bindingsPanel = append(bindingsPanel, &Binding{})
gui.State.Keys = append(bindingsPanel, bindingsGlobal...)
contentJoined := strings.Join(content, "\n")
x0, y0, x1, y1 := gui.getConfirmationPanelDimensions(g, contentJoined)
list, err := utils.RenderList(gui.State.Keys)
if err != nil {
return err
}
x0, y0, x1, y1 := gui.getConfirmationPanelDimensions(g, list)
menuView, _ := g.SetView("menu", x0, y0, x1, y1, 0)
menuView.Title = strings.Title(gui.Tr.SLocalize("menu"))
menuView.FgColor = gocui.ColorWhite
menuView.Clear()
fmt.Fprint(menuView, list)
if err := gui.renderMenuOptions(g); err != nil {
return err
}
fmt.Fprint(menuView, contentJoined)
g.Update(func(g *gocui.Gui) error {
_, err := g.SetViewOnTop("menu")
if err != nil {

View File

@@ -2,10 +2,10 @@ package gui
import (
"fmt"
"strings"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands"
"github.com/jesseduffield/lazygit/pkg/utils"
)
func (gui *Gui) refreshStashEntries(g *gocui.Gui) error {
@@ -16,13 +16,12 @@ func (gui *Gui) refreshStashEntries(g *gocui.Gui) error {
}
gui.State.StashEntries = gui.GitCommand.GetStashEntries()
displayStrings := make([]string, len(gui.State.StashEntries))
for i, stashEntry := range gui.State.StashEntries {
displayStrings[i] = stashEntry.DisplayString
}
v.Clear()
fmt.Fprint(v, strings.Join(displayStrings, "\n"))
list, err := utils.RenderList(gui.State.StashEntries)
if err != nil {
return err
}
fmt.Fprint(v, list)
return gui.resetOrigin(v)
})
@@ -35,7 +34,7 @@ func (gui *Gui) getSelectedStashEntry(v *gocui.View) *commands.StashEntry {
}
stashView, _ := gui.g.View("stash")
lineNumber := gui.getItemPosition(stashView)
return &gui.State.StashEntries[lineNumber]
return gui.State.StashEntries[lineNumber]
}
func (gui *Gui) renderStashOptions(g *gocui.Gui) error {