From 8c0ea8f45fde1dfddd23198fcb06ae77468e3a3a Mon Sep 17 00:00:00 2001 From: Jesse Duffield Duffield Date: Mon, 25 Feb 2019 22:11:35 +1100 Subject: mouse support --- pkg/gui/branches_panel.go | 8 ++++++++ pkg/gui/commits_panel.go | 15 +++++++++++++++ pkg/gui/context.go | 3 ++- pkg/gui/files_panel.go | 32 ++++++++++++++++++++++++++++++++ pkg/gui/gui.go | 37 +++++++++++++++++++++++++++++-------- pkg/gui/keybindings.go | 43 ++++++++++++++++++++++++++++++++++++------- pkg/gui/merge_panel.go | 2 +- pkg/gui/stash_panel.go | 15 +++++++++++++++ pkg/gui/status_panel.go | 7 +++++++ pkg/gui/view_helpers.go | 21 +++++++++++++++++++-- 10 files changed, 164 insertions(+), 19 deletions(-) (limited to 'pkg/gui') diff --git a/pkg/gui/branches_panel.go b/pkg/gui/branches_panel.go index fdc35862f..5024e2b9d 100644 --- a/pkg/gui/branches_panel.go +++ b/pkg/gui/branches_panel.go @@ -84,6 +84,10 @@ func (gui *Gui) refreshBranches(g *gocui.Gui) error { } func (gui *Gui) handleBranchesNextLine(g *gocui.Gui, v *gocui.View) error { + if gui.popupPanelFocused() { + return nil + } + panelState := gui.State.Panels.Branches gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Branches), false) @@ -94,6 +98,10 @@ func (gui *Gui) handleBranchesNextLine(g *gocui.Gui, v *gocui.View) error { } func (gui *Gui) handleBranchesPrevLine(g *gocui.Gui, v *gocui.View) error { + if gui.popupPanelFocused() { + return nil + } + panelState := gui.State.Panels.Branches gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Branches), true) diff --git a/pkg/gui/commits_panel.go b/pkg/gui/commits_panel.go index 6b26d0ef3..7ca68767a 100644 --- a/pkg/gui/commits_panel.go +++ b/pkg/gui/commits_panel.go @@ -24,6 +24,13 @@ func (gui *Gui) getSelectedCommit(g *gocui.Gui) *commands.Commit { } func (gui *Gui) handleCommitSelect(g *gocui.Gui, v *gocui.View) error { + if gui.popupPanelFocused() { + return nil + } + + if _, err := gui.g.SetCurrentView(v.Name()); err != nil { + return err + } commit := gui.getSelectedCommit(g) if commit == nil { return gui.renderString(g, "main", gui.Tr.SLocalize("NoCommitsThisBranch")) @@ -73,6 +80,10 @@ func (gui *Gui) refreshCommits(g *gocui.Gui) error { } func (gui *Gui) handleCommitsNextLine(g *gocui.Gui, v *gocui.View) error { + if gui.popupPanelFocused() { + return nil + } + panelState := gui.State.Panels.Commits gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Commits), false) @@ -83,6 +94,10 @@ func (gui *Gui) handleCommitsNextLine(g *gocui.Gui, v *gocui.View) error { } func (gui *Gui) handleCommitsPrevLine(g *gocui.Gui, v *gocui.View) error { + if gui.popupPanelFocused() { + return nil + } + panelState := gui.State.Panels.Commits gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Commits), true) diff --git a/pkg/gui/context.go b/pkg/gui/context.go index 861ffc0be..b741132ea 100644 --- a/pkg/gui/context.go +++ b/pkg/gui/context.go @@ -15,6 +15,7 @@ func (gui *Gui) contextTitleMap() map[string]map[string]string { "main": { "staging": gui.Tr.SLocalize("StagingMainTitle"), "merging": gui.Tr.SLocalize("MergingMainTitle"), + "normal": "", }, } } @@ -56,7 +57,7 @@ func (gui *Gui) setInitialContexts() error { contextMap := gui.GetContextMap() initialContexts := map[string]string{ - "main": "merging", + "main": "normal", } for viewName, context := range initialContexts { diff --git a/pkg/gui/files_panel.go b/pkg/gui/files_panel.go index 4ed8ddb10..b1d1bcb5f 100644 --- a/pkg/gui/files_panel.go +++ b/pkg/gui/files_panel.go @@ -26,6 +26,30 @@ func (gui *Gui) getSelectedFile(g *gocui.Gui) (*commands.File, error) { return gui.State.Files[selectedLine], nil } +func (gui *Gui) handleFilesFocus(g *gocui.Gui, v *gocui.View) error { + if gui.popupPanelFocused() { + return nil + } + + cx, cy := v.Cursor() + _, oy := v.Origin() + + prevSelectedLine := gui.State.Panels.Files.SelectedLine + newSelectedLine := cy - oy + + if newSelectedLine > len(gui.State.Files)-1 || len(utils.Decolorise(gui.State.Files[newSelectedLine].DisplayString)) < cx { + return gui.handleFileSelect(gui.g, v, false) + } + + gui.State.Panels.Files.SelectedLine = newSelectedLine + + if prevSelectedLine == newSelectedLine && gui.currentViewName() == v.Name() { + return gui.handleFilePress(gui.g, v) + } else { + return gui.handleFileSelect(gui.g, v, true) + } +} + func (gui *Gui) handleFileSelect(g *gocui.Gui, v *gocui.View, alreadySelected bool) error { if _, err := gui.g.SetCurrentView(v.Name()); err != nil { return err @@ -87,6 +111,10 @@ func (gui *Gui) refreshFiles() error { } func (gui *Gui) handleFilesNextLine(g *gocui.Gui, v *gocui.View) error { + if gui.popupPanelFocused() { + return nil + } + panelState := gui.State.Panels.Files gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Files), false) @@ -94,6 +122,10 @@ func (gui *Gui) handleFilesNextLine(g *gocui.Gui, v *gocui.View) error { } func (gui *Gui) handleFilesPrevLine(g *gocui.Gui, v *gocui.View) error { + if gui.popupPanelFocused() { + return nil + } + panelState := gui.State.Panels.Files gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Files), true) diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index b4a55cc45..b3b219153 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -23,6 +23,7 @@ import ( "github.com/jesseduffield/lazygit/pkg/config" "github.com/jesseduffield/lazygit/pkg/i18n" "github.com/jesseduffield/lazygit/pkg/updates" + "github.com/jesseduffield/lazygit/pkg/utils" "github.com/sirupsen/logrus" ) @@ -274,13 +275,14 @@ func (gui *Gui) onFocus(v *gocui.View) error { func (gui *Gui) layout(g *gocui.Gui) error { g.Highlight = true width, height := g.Size() - version := gui.Config.GetVersion() + donate := color.New(color.FgMagenta, color.Underline).Sprint(gui.Tr.SLocalize("Donate")) + version := donate + " " + gui.Config.GetVersion() leftSideWidth := width / 3 statusFilesBoundary := 2 filesBranchesBoundary := 2 * height / 5 // height - 20 commitsBranchesBoundary := 3 * height / 5 // height - 10 commitsStashBoundary := height - 5 // height - 5 - optionsVersionBoundary := width - max(len(version), 1) + optionsVersionBoundary := width - max(len(utils.Decolorise(version)), 1) minimumHeight := 16 minimumWidth := 10 @@ -355,20 +357,22 @@ func (gui *Gui) layout(g *gocui.Gui) error { branchesView.FgColor = gocui.ColorWhite } - if v, err := g.SetView("commits", 0, commitsBranchesBoundary+panelSpacing, leftSideWidth, commitsStashBoundary, gocui.TOP|gocui.BOTTOM); err != nil { + commitsView, err := g.SetView("commits", 0, commitsBranchesBoundary+panelSpacing, leftSideWidth, commitsStashBoundary, gocui.TOP|gocui.BOTTOM) + if err != nil { if err.Error() != "unknown view" { return err } - v.Title = gui.Tr.SLocalize("CommitsTitle") - v.FgColor = gocui.ColorWhite + commitsView.Title = gui.Tr.SLocalize("CommitsTitle") + commitsView.FgColor = gocui.ColorWhite } - if v, err := g.SetView("stash", 0, commitsStashBoundary+panelSpacing, leftSideWidth, optionsTop, gocui.TOP|gocui.RIGHT); err != nil { + stashView, err := g.SetView("stash", 0, commitsStashBoundary+panelSpacing, leftSideWidth, optionsTop, gocui.TOP|gocui.RIGHT) + if err != nil { if err.Error() != "unknown view" { return err } - v.Title = gui.Tr.SLocalize("StashTitle") - v.FgColor = gocui.ColorWhite + stashView.Title = gui.Tr.SLocalize("StashTitle") + stashView.FgColor = gocui.ColorWhite } if v, err := g.SetView("options", appStatusOptionsBoundary-1, optionsTop, optionsVersionBoundary-1, optionsTop+2, 0); err != nil { @@ -465,6 +469,13 @@ func (gui *Gui) layout(g *gocui.Gui) error { listViews := map[*gocui.View]int{ filesView: gui.State.Panels.Files.SelectedLine, branchesView: gui.State.Panels.Branches.SelectedLine, + commitsView: gui.State.Panels.Commits.SelectedLine, + stashView: gui.State.Panels.Stash.SelectedLine, + } + + // menu view might not exist so we check to be safe + if menuView, err := gui.g.View("menu"); err == nil { + listViews[menuView] = gui.State.Panels.Menu.SelectedLine } for view, selectedLine := range listViews { // check if the selected line is now out of view and if so refocus it @@ -543,6 +554,8 @@ func (gui *Gui) Run() error { } defer g.Close() + g.Mouse = true + gui.g = g // TODO: always use gui.g rather than passing g around everywhere if err := gui.SetColorScheme(); err != nil { @@ -622,3 +635,11 @@ func (gui *Gui) quit(g *gocui.Gui, v *gocui.View) error { } return gocui.ErrQuit } + +func (gui *Gui) handleDonate(g *gocui.Gui, v *gocui.View) error { + cx, _ := v.Cursor() + if cx > len(gui.Tr.SLocalize("Donate")) { + return nil + } + return gui.OSCommand.OpenLink("https://donorbox.org/lazygit") +} diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go index 3c5862569..3e0e3b1d1 100644 --- a/pkg/gui/keybindings.go +++ b/pkg/gui/keybindings.go @@ -400,7 +400,6 @@ func (gui *Gui) GetInitialKeybindings() []*Binding { Handler: gui.handleStashApply, Description: gui.Tr.SLocalize("apply"), }, { - ViewName: "stash", Key: 'g', Modifier: gocui.ModNone, @@ -442,6 +441,11 @@ func (gui *Gui) GetInitialKeybindings() []*Binding { Key: 'q', Modifier: gocui.ModNone, Handler: gui.handleMenuClose, + }, { + ViewName: "version", + Key: gocui.MouseLeft, + Modifier: gocui.ModNone, + Handler: gui.handleDonate, }, } @@ -458,20 +462,25 @@ func (gui *Gui) GetInitialKeybindings() []*Binding { listPanelMap := map[string]struct { prevLine func(*gocui.Gui, *gocui.View) error nextLine func(*gocui.Gui, *gocui.View) error + focus func(*gocui.Gui, *gocui.View) error }{ - "menu": {prevLine: gui.handleMenuPrevLine, nextLine: gui.handleMenuNextLine}, - "files": {prevLine: gui.handleFilesPrevLine, nextLine: gui.handleFilesNextLine}, - "branches": {prevLine: gui.handleBranchesPrevLine, nextLine: gui.handleBranchesNextLine}, - "commits": {prevLine: gui.handleCommitsPrevLine, nextLine: gui.handleCommitsNextLine}, - "stash": {prevLine: gui.handleStashPrevLine, nextLine: gui.handleStashNextLine}, + "menu": {prevLine: gui.handleMenuPrevLine, nextLine: gui.handleMenuNextLine, focus: gui.handleMenuSelect}, + "files": {prevLine: gui.handleFilesPrevLine, nextLine: gui.handleFilesNextLine, focus: gui.handleFilesFocus}, + "branches": {prevLine: gui.handleBranchesPrevLine, nextLine: gui.handleBranchesNextLine, focus: gui.handleBranchSelect}, + "commits": {prevLine: gui.handleCommitsPrevLine, nextLine: gui.handleCommitsNextLine, focus: gui.handleCommitSelect}, + "stash": {prevLine: gui.handleStashPrevLine, nextLine: gui.handleStashNextLine, focus: gui.handleStashEntrySelect}, + "status": {focus: gui.handleStatusSelect}, } for viewName, functions := range listPanelMap { bindings = append(bindings, []*Binding{ {ViewName: viewName, Key: 'k', Modifier: gocui.ModNone, Handler: functions.prevLine}, {ViewName: viewName, Key: gocui.KeyArrowUp, Modifier: gocui.ModNone, Handler: functions.prevLine}, + {ViewName: viewName, Key: gocui.MouseWheelUp, Modifier: gocui.ModNone, Handler: functions.prevLine}, {ViewName: viewName, Key: 'j', Modifier: gocui.ModNone, Handler: functions.nextLine}, {ViewName: viewName, Key: gocui.KeyArrowDown, Modifier: gocui.ModNone, Handler: functions.nextLine}, + {ViewName: viewName, Key: gocui.MouseWheelDown, Modifier: gocui.ModNone, Handler: functions.nextLine}, + {ViewName: viewName, Key: gocui.MouseLeft, Modifier: gocui.ModNone, Handler: functions.focus}, }...) } @@ -481,7 +490,7 @@ func (gui *Gui) GetInitialKeybindings() []*Binding { // GetCurrentKeybindings gets the list of keybindings given the current context func (gui *Gui) GetCurrentKeybindings() []*Binding { bindings := gui.GetInitialKeybindings() - viewName := gui.currentViewName(gui.g) + viewName := gui.currentViewName() currentContext := gui.State.Contexts[viewName] contextBindings := gui.GetContextMap()[viewName][currentContext] @@ -559,6 +568,16 @@ func (gui *Gui) GetContextMap() map[string]map[string][]*Binding { Key: gocui.MouseWheelDown, Modifier: gocui.ModNone, Handler: gui.handleStagingNextLine, + }, { + ViewName: "main", + Key: gocui.KeyArrowLeft, + Modifier: gocui.ModNone, + Handler: gui.handleStagingPrevLine, + }, { + ViewName: "main", + Key: gocui.MouseWheelDown, + Modifier: gocui.ModNone, + Handler: gui.handleStagingNextLine, }, { ViewName: "main", Key: gocui.KeyArrowLeft, @@ -640,6 +659,16 @@ func (gui *Gui) GetContextMap() map[string]map[string][]*Binding { Modifier: gocui.ModNone, Handler: gui.handleSelectBottom, Description: gui.Tr.SLocalize("SelectBottom"), + }, { + ViewName: "main", + Key: gocui.MouseWheelUp, + Modifier: gocui.ModNone, + Handler: gui.handleSelectTop, + }, { + ViewName: "main", + Key: gocui.MouseWheelDown, + Modifier: gocui.ModNone, + Handler: gui.handleSelectBottom, }, { ViewName: "main", Key: 'h', diff --git a/pkg/gui/merge_panel.go b/pkg/gui/merge_panel.go index efb6c5544..0d10ed4d7 100644 --- a/pkg/gui/merge_panel.go +++ b/pkg/gui/merge_panel.go @@ -205,7 +205,7 @@ func (gui *Gui) refreshMergePanel() error { panelState.ConflictIndex = len(panelState.Conflicts) - 1 } - hasFocus := gui.currentViewName(gui.g) == "main" + hasFocus := gui.currentViewName() == "main" content, err := gui.coloredConflictFile(cat, panelState.Conflicts, panelState.ConflictIndex, panelState.ConflictTop, hasFocus) if err != nil { return err diff --git a/pkg/gui/stash_panel.go b/pkg/gui/stash_panel.go index ed2f71401..05844f0ac 100644 --- a/pkg/gui/stash_panel.go +++ b/pkg/gui/stash_panel.go @@ -20,6 +20,13 @@ func (gui *Gui) getSelectedStashEntry(v *gocui.View) *commands.StashEntry { } func (gui *Gui) handleStashEntrySelect(g *gocui.Gui, v *gocui.View) error { + if gui.popupPanelFocused() { + return nil + } + + if _, err := gui.g.SetCurrentView(v.Name()); err != nil { + return err + } stashEntry := gui.getSelectedStashEntry(v) if stashEntry == nil { return gui.renderString(g, "main", gui.Tr.SLocalize("NoStashEntries")) @@ -60,6 +67,10 @@ func (gui *Gui) refreshStashEntries(g *gocui.Gui) error { } func (gui *Gui) handleStashNextLine(g *gocui.Gui, v *gocui.View) error { + if gui.popupPanelFocused() { + return nil + } + panelState := gui.State.Panels.Stash gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.StashEntries), false) @@ -70,6 +81,10 @@ func (gui *Gui) handleStashNextLine(g *gocui.Gui, v *gocui.View) error { } func (gui *Gui) handleStashPrevLine(g *gocui.Gui, v *gocui.View) error { + if gui.popupPanelFocused() { + return nil + } + panelState := gui.State.Panels.Stash gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.StashEntries), true) diff --git a/pkg/gui/status_panel.go b/pkg/gui/status_panel.go index 9853760e7..8c03c30de 100644 --- a/pkg/gui/status_panel.go +++ b/pkg/gui/status_panel.go @@ -48,6 +48,13 @@ func (gui *Gui) handleCheckForUpdate(g *gocui.Gui, v *gocui.View) error { } func (gui *Gui) handleStatusSelect(g *gocui.Gui, v *gocui.View) error { + if gui.popupPanelFocused() { + return nil + } + + if _, err := gui.g.SetCurrentView(v.Name()); err != nil { + return err + } magenta := color.New(color.FgMagenta) dashboardString := strings.Join( diff --git a/pkg/gui/view_helpers.go b/pkg/gui/view_helpers.go index 53cf80de5..dcb58c7de 100644 --- a/pkg/gui/view_helpers.go +++ b/pkg/gui/view_helpers.go @@ -287,8 +287,8 @@ func (gui *Gui) trimmedContent(v *gocui.View) string { return strings.TrimSpace(v.Buffer()) } -func (gui *Gui) currentViewName(g *gocui.Gui) string { - currentView := g.CurrentView() +func (gui *Gui) currentViewName() string { + currentView := gui.g.CurrentView() return currentView.Name() } @@ -380,3 +380,20 @@ func (gui *Gui) renderPanelOptions() error { } return gui.renderGlobalOptions() } + +func (gui *Gui) handleFocusView(g *gocui.Gui, v *gocui.View) error { + _, err := gui.g.SetCurrentView(v.Name()) + return err +} + +func (gui *Gui) popupPanelFocused() bool { + viewNames := []string{"commitMessage", + "credentials", + "menu"} + for _, viewName := range viewNames { + if gui.currentViewName() == viewName { + return true + } + } + return false +} -- cgit v1.2.3