mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-01-04 03:48:07 +02:00
mouse support
This commit is contained in:
parent
afbc028ad6
commit
8c0ea8f45f
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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")
|
||||
}
|
||||
|
@ -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',
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -160,7 +160,8 @@ func renderDisplayableList(items []Displayable, isFocused bool) (string, error)
|
||||
return strings.Join(paddedDisplayStrings, "\n"), nil
|
||||
}
|
||||
|
||||
func decolorise(str string) string {
|
||||
// Decolorise strips a string of color
|
||||
func Decolorise(str string) string {
|
||||
re := regexp.MustCompile(`\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]`)
|
||||
return re.ReplaceAllString(str, "")
|
||||
}
|
||||
@ -172,7 +173,7 @@ func getPadWidths(stringArrays [][]string) []int {
|
||||
padWidths := make([]int, len(stringArrays[0])-1)
|
||||
for i := range padWidths {
|
||||
for _, strings := range stringArrays {
|
||||
uncoloredString := decolorise(strings[i])
|
||||
uncoloredString := Decolorise(strings[i])
|
||||
if len(uncoloredString) > padWidths[i] {
|
||||
padWidths[i] = len(uncoloredString)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user