1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-03-21 21:47:32 +02:00

paging keybindings for line by line panel

support searching in line by line panel

move mutexes into their own struct

add line by line panel mutex

apply LBL panel mutex

bump gocui to prevent crashing when search item count decreases
This commit is contained in:
Jesse Duffield 2020-10-02 07:56:14 +10:00
parent 40c5cd4b4b
commit 2e05ac0c90
14 changed files with 292 additions and 165 deletions

@ -15,7 +15,7 @@ func (gui *Gui) getSelectedCommitFile() *models.CommitFile {
}
func (gui *Gui) handleCommitFileSelect() error {
gui.handleEscapeLineByLinePanel()
gui.escapeLineByLinePanel()
commitFile := gui.getSelectedCommitFile()
if commitFile == nil {

@ -31,7 +31,7 @@ func (gui *Gui) handleCommitSelect() error {
}()
}
gui.handleEscapeLineByLinePanel()
gui.escapeLineByLinePanel()
var task updateTask
commit := gui.getSelectedLocalCommit()
@ -110,8 +110,8 @@ func (gui *Gui) refreshCommits() error {
}
func (gui *Gui) refreshCommitsWithLimit() error {
gui.State.BranchCommitsMutex.Lock()
defer gui.State.BranchCommitsMutex.Unlock()
gui.State.Mutexes.BranchCommitsMutex.Lock()
defer gui.State.Mutexes.BranchCommitsMutex.Unlock()
builder := commands.NewCommitListBuilder(gui.Log, gui.GitCommand, gui.OSCommand, gui.Tr)
@ -132,8 +132,8 @@ func (gui *Gui) refreshCommitsWithLimit() error {
}
func (gui *Gui) refreshRebaseCommits() error {
gui.State.BranchCommitsMutex.Lock()
defer gui.State.BranchCommitsMutex.Unlock()
gui.State.Mutexes.BranchCommitsMutex.Lock()
defer gui.State.Mutexes.BranchCommitsMutex.Unlock()
builder := commands.NewCommitListBuilder(gui.Log, gui.GitCommand, gui.OSCommand, gui.Tr)

@ -81,11 +81,11 @@ func (gui *Gui) selectFile(alreadySelected bool) error {
}
func (gui *Gui) refreshFilesAndSubmodules() error {
gui.State.RefreshingFilesMutex.Lock()
gui.State.Mutexes.RefreshingFilesMutex.Lock()
gui.State.IsRefreshingFiles = true
defer func() {
gui.State.IsRefreshingFiles = false
gui.State.RefreshingFilesMutex.Unlock()
gui.State.Mutexes.RefreshingFilesMutex.Unlock()
}()
selectedFile := gui.getSelectedFile()
@ -517,8 +517,8 @@ func (gui *Gui) pullFiles(opts PullFilesOptions) error {
}
func (gui *Gui) pullWithMode(mode string, opts PullFilesOptions) error {
gui.State.FetchMutex.Lock()
defer gui.State.FetchMutex.Unlock()
gui.State.Mutexes.FetchMutex.Lock()
defer gui.State.Mutexes.FetchMutex.Unlock()
err := gui.GitCommand.Fetch(
commands.FetchOptions{

@ -164,8 +164,8 @@ func (gui *Gui) handleInfoClick(g *gocui.Gui, v *gocui.View) error {
}
func (gui *Gui) fetch(canPromptForCredentials bool) (err error) {
gui.State.FetchMutex.Lock()
defer gui.State.FetchMutex.Unlock()
gui.State.Mutexes.FetchMutex.Lock()
defer gui.State.Mutexes.FetchMutex.Unlock()
fetchOpts := commands.FetchOptions{}
if canPromptForCredentials {

@ -285,6 +285,14 @@ type Modes struct {
Diffing Diffing
}
type guiStateMutexes struct {
RefreshingFilesMutex sync.Mutex
RefreshingStatusMutex sync.Mutex
FetchMutex sync.Mutex
BranchCommitsMutex sync.Mutex
LineByLinePanelMutex sync.Mutex
}
type guiState struct {
Files []*models.File
Submodules []*models.SubmoduleConfig
@ -310,10 +318,7 @@ type guiState struct {
SplitMainPanel bool
RetainOriginalDir bool
IsRefreshingFiles bool
RefreshingFilesMutex sync.Mutex
RefreshingStatusMutex sync.Mutex
FetchMutex sync.Mutex
BranchCommitsMutex sync.Mutex
Mutexes guiStateMutexes
Searching searchingState
ScreenMode int
SideView *gocui.View

@ -1147,14 +1147,14 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
ViewName: "main",
Contexts: []string{MAIN_PATCH_BUILDING_CONTEXT_KEY, MAIN_STAGING_CONTEXT_KEY},
Key: gui.getKey(config.Universal.PrevItem),
Handler: gui.handleSelectPrevLine,
Handler: gui.wrappedHandler(gui.handleSelectPrevLine),
Description: gui.Tr.PrevLine,
},
{
ViewName: "main",
Contexts: []string{MAIN_PATCH_BUILDING_CONTEXT_KEY, MAIN_STAGING_CONTEXT_KEY},
Key: gui.getKey(config.Universal.NextItem),
Handler: gui.handleSelectNextLine,
Handler: gui.wrappedHandler(gui.handleSelectNextLine),
Description: gui.Tr.NextLine,
},
{
@ -1162,56 +1162,56 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
Contexts: []string{MAIN_PATCH_BUILDING_CONTEXT_KEY, MAIN_STAGING_CONTEXT_KEY},
Key: gui.getKey(config.Universal.PrevItemAlt),
Modifier: gocui.ModNone,
Handler: gui.handleSelectPrevLine,
Handler: gui.wrappedHandler(gui.handleSelectPrevLine),
},
{
ViewName: "main",
Contexts: []string{MAIN_PATCH_BUILDING_CONTEXT_KEY, MAIN_STAGING_CONTEXT_KEY},
Key: gui.getKey(config.Universal.NextItemAlt),
Modifier: gocui.ModNone,
Handler: gui.handleSelectNextLine,
Handler: gui.wrappedHandler(gui.handleSelectNextLine),
},
{
ViewName: "main",
Contexts: []string{MAIN_PATCH_BUILDING_CONTEXT_KEY, MAIN_STAGING_CONTEXT_KEY},
Key: gocui.MouseWheelUp,
Modifier: gocui.ModNone,
Handler: gui.handleSelectPrevLine,
Handler: gui.wrappedHandler(gui.handleSelectPrevLine),
},
{
ViewName: "main",
Contexts: []string{MAIN_PATCH_BUILDING_CONTEXT_KEY, MAIN_STAGING_CONTEXT_KEY},
Key: gocui.MouseWheelDown,
Modifier: gocui.ModNone,
Handler: gui.handleSelectNextLine,
Handler: gui.wrappedHandler(gui.handleSelectNextLine),
},
{
ViewName: "main",
Contexts: []string{MAIN_PATCH_BUILDING_CONTEXT_KEY, MAIN_STAGING_CONTEXT_KEY},
Key: gui.getKey(config.Universal.PrevBlock),
Handler: gui.handleSelectPrevHunk,
Handler: gui.wrappedHandler(gui.handleSelectPrevHunk),
Description: gui.Tr.PrevHunk,
},
{
ViewName: "main",
Contexts: []string{MAIN_PATCH_BUILDING_CONTEXT_KEY, MAIN_STAGING_CONTEXT_KEY},
Key: gui.getKey(config.Universal.NextBlock),
Handler: gui.handleSelectNextHunk,
Description: gui.Tr.NextHunk,
},
{
ViewName: "main",
Contexts: []string{MAIN_PATCH_BUILDING_CONTEXT_KEY, MAIN_STAGING_CONTEXT_KEY},
Key: gui.getKey(config.Universal.PrevBlockAlt),
Modifier: gocui.ModNone,
Handler: gui.handleSelectPrevHunk,
Handler: gui.wrappedHandler(gui.handleSelectPrevHunk),
},
{
ViewName: "main",
Contexts: []string{MAIN_PATCH_BUILDING_CONTEXT_KEY, MAIN_STAGING_CONTEXT_KEY},
Key: gui.getKey(config.Universal.NextBlock),
Handler: gui.wrappedHandler(gui.handleSelectNextHunk),
Description: gui.Tr.NextHunk,
},
{
ViewName: "main",
Contexts: []string{MAIN_PATCH_BUILDING_CONTEXT_KEY, MAIN_STAGING_CONTEXT_KEY},
Key: gui.getKey(config.Universal.NextBlockAlt),
Modifier: gocui.ModNone,
Handler: gui.handleSelectNextHunk,
Handler: gui.wrappedHandler(gui.handleSelectNextHunk),
},
{
ViewName: "main",
@ -1227,6 +1227,50 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
Handler: gui.handleFileOpen,
Description: gui.Tr.LcOpenFile,
},
{
ViewName: "main",
Contexts: []string{MAIN_PATCH_BUILDING_CONTEXT_KEY, MAIN_STAGING_CONTEXT_KEY},
Key: gui.getKey(config.Universal.NextPage),
Modifier: gocui.ModNone,
Handler: gui.wrappedHandler(gui.handleLineByLineNextPage),
Description: gui.Tr.LcNextPage,
Tag: "navigation",
},
{
ViewName: "main",
Contexts: []string{MAIN_PATCH_BUILDING_CONTEXT_KEY, MAIN_STAGING_CONTEXT_KEY},
Key: gui.getKey(config.Universal.PrevPage),
Modifier: gocui.ModNone,
Handler: gui.wrappedHandler(gui.handleLineByLinePrevPage),
Description: gui.Tr.LcPrevPage,
Tag: "navigation",
},
{
ViewName: "main",
Contexts: []string{MAIN_PATCH_BUILDING_CONTEXT_KEY, MAIN_STAGING_CONTEXT_KEY},
Key: gui.getKey(config.Universal.GotoTop),
Modifier: gocui.ModNone,
Handler: gui.wrappedHandler(gui.handleLineByLineGotoTop),
Description: gui.Tr.LcGotoTop,
Tag: "navigation",
},
{
ViewName: "main",
Contexts: []string{MAIN_PATCH_BUILDING_CONTEXT_KEY, MAIN_STAGING_CONTEXT_KEY},
Key: gui.getKey(config.Universal.GotoBottom),
Modifier: gocui.ModNone,
Handler: gui.wrappedHandler(gui.handleLineByLineGotoBottom),
Description: gui.Tr.LcGotoBottom,
Tag: "navigation",
},
{
ViewName: "main",
Contexts: []string{MAIN_PATCH_BUILDING_CONTEXT_KEY, MAIN_STAGING_CONTEXT_KEY},
Key: gui.getKey(config.Universal.StartSearch),
Handler: gui.handleOpenSearch,
Description: gui.Tr.LcStartSearch,
Tag: "navigation",
},
{
ViewName: "main",
Contexts: []string{MAIN_PATCH_BUILDING_CONTEXT_KEY},
@ -1238,7 +1282,7 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
ViewName: "main",
Contexts: []string{MAIN_PATCH_BUILDING_CONTEXT_KEY, MAIN_STAGING_CONTEXT_KEY},
Key: gui.getKey(config.Main.ToggleDragSelect),
Handler: gui.handleToggleSelectRange,
Handler: gui.wrappedHandler(gui.handleToggleSelectRange),
Description: gui.Tr.ToggleDragSelect,
},
// Alias 'V' -> 'v'
@ -1246,14 +1290,14 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
ViewName: "main",
Contexts: []string{MAIN_PATCH_BUILDING_CONTEXT_KEY, MAIN_STAGING_CONTEXT_KEY},
Key: gui.getKey(config.Main.ToggleDragSelectAlt),
Handler: gui.handleToggleSelectRange,
Handler: gui.wrappedHandler(gui.handleToggleSelectRange),
Description: gui.Tr.ToggleDragSelect,
},
{
ViewName: "main",
Contexts: []string{MAIN_PATCH_BUILDING_CONTEXT_KEY, MAIN_STAGING_CONTEXT_KEY},
Key: gui.getKey(config.Main.ToggleSelectHunk),
Handler: gui.handleToggleSelectHunk,
Handler: gui.wrappedHandler(gui.handleToggleSelectHunk),
Description: gui.Tr.ToggleSelectHunk,
},
{
@ -1261,7 +1305,7 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
Contexts: []string{MAIN_PATCH_BUILDING_CONTEXT_KEY, MAIN_STAGING_CONTEXT_KEY},
Key: gocui.MouseLeft,
Modifier: gocui.ModNone,
Handler: gui.handleMouseDown,
Handler: gui.handleLBLMouseDown,
},
{
ViewName: "main",

@ -317,6 +317,8 @@ func (gui *Gui) layout(g *gocui.Gui) error {
listContextState.view.SetOnSelectItem(gui.onSelectItemWrapper(listContextState.listContext.onSearchSelect))
}
gui.getMainView().SetOnSelectItem(gui.onSelectItemWrapper(gui.handlelineByLineNavigateTo))
mainViewWidth, mainViewHeight := gui.getMainView().Size()
if mainViewWidth != gui.State.PrevMainWidth || mainViewHeight != gui.State.PrevMainHeight {
gui.State.PrevMainWidth = mainViewWidth

@ -25,6 +25,9 @@ const (
// returns whether the patch is empty so caller can escape if necessary
// both diffs should be non-coloured because we'll parse them and colour them here
func (gui *Gui) refreshLineByLinePanel(diff string, secondaryDiff string, secondaryFocused bool, selectedLineIdx int) (bool, error) {
gui.State.Mutexes.LineByLinePanelMutex.Lock()
defer gui.State.Mutexes.LineByLinePanelMutex.Unlock()
state := gui.State.Panels.LineByLine
patchParser, err := patch.NewPatchParser(gui.Log, diff)
@ -98,26 +101,32 @@ func (gui *Gui) refreshLineByLinePanel(diff string, secondaryDiff string, second
return false, nil
}
func (gui *Gui) handleSelectPrevLine(g *gocui.Gui, v *gocui.View) error {
return gui.handleCycleLine(-1)
func (gui *Gui) handleSelectPrevLine() error {
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error {
return gui.LBLCycleLine(-1)
})
}
func (gui *Gui) handleSelectNextLine(g *gocui.Gui, v *gocui.View) error {
return gui.handleCycleLine(+1)
func (gui *Gui) handleSelectNextLine() error {
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error {
return gui.LBLCycleLine(+1)
})
}
func (gui *Gui) handleSelectPrevHunk(g *gocui.Gui, v *gocui.View) error {
state := gui.State.Panels.LineByLine
func (gui *Gui) handleSelectPrevHunk() error {
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error {
newHunk := state.PatchParser.GetHunkContainingLine(state.SelectedLineIdx, -1)
return gui.selectNewHunk(newHunk)
})
}
func (gui *Gui) handleSelectNextHunk(g *gocui.Gui, v *gocui.View) error {
state := gui.State.Panels.LineByLine
func (gui *Gui) handleSelectNextHunk() error {
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error {
newHunk := state.PatchParser.GetHunkContainingLine(state.SelectedLineIdx, 1)
return gui.selectNewHunk(newHunk)
})
}
func (gui *Gui) selectNewHunk(newHunk *patch.PatchHunk) error {
@ -136,7 +145,7 @@ func (gui *Gui) selectNewHunk(newHunk *patch.PatchHunk) error {
return gui.focusSelection(true)
}
func (gui *Gui) handleCycleLine(change int) error {
func (gui *Gui) LBLCycleLine(change int) error {
state := gui.State.Panels.LineByLine
if state.SelectMode == HUNK {
@ -144,10 +153,10 @@ func (gui *Gui) handleCycleLine(change int) error {
return gui.selectNewHunk(newHunk)
}
return gui.handleSelectNewLine(state.SelectedLineIdx + change)
return gui.LBLSelectLine(state.SelectedLineIdx + change)
}
func (gui *Gui) handleSelectNewLine(newSelectedLineIdx int) error {
func (gui *Gui) LBLSelectLine(newSelectedLineIdx int) error {
state := gui.State.Panels.LineByLine
if newSelectedLineIdx < 0 {
@ -176,9 +185,8 @@ func (gui *Gui) handleSelectNewLine(newSelectedLineIdx int) error {
return gui.focusSelection(false)
}
func (gui *Gui) handleMouseDown(g *gocui.Gui, v *gocui.View) error {
state := gui.State.Panels.LineByLine
func (gui *Gui) handleLBLMouseDown(g *gocui.Gui, v *gocui.View) error {
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error {
if gui.popupPanelFocused() {
return nil
}
@ -189,39 +197,42 @@ func (gui *Gui) handleMouseDown(g *gocui.Gui, v *gocui.View) error {
state.SelectMode = RANGE
return gui.handleSelectNewLine(newSelectedLineIdx)
return gui.LBLSelectLine(newSelectedLineIdx)
})
}
func (gui *Gui) handleMouseDrag(g *gocui.Gui, v *gocui.View) error {
return gui.withLBLActiveCheck(func(*lineByLinePanelState) error {
if gui.popupPanelFocused() {
return nil
}
return gui.handleSelectNewLine(v.SelectedLineIdx())
return gui.LBLSelectLine(v.SelectedLineIdx())
})
}
func (gui *Gui) handleMouseScrollUp(g *gocui.Gui, v *gocui.View) error {
state := gui.State.Panels.LineByLine
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error {
if gui.popupPanelFocused() {
return nil
}
state.SelectMode = LINE
return gui.handleCycleLine(-1)
return gui.LBLCycleLine(-1)
})
}
func (gui *Gui) handleMouseScrollDown(g *gocui.Gui, v *gocui.View) error {
state := gui.State.Panels.LineByLine
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error {
if gui.popupPanelFocused() {
return nil
}
state.SelectMode = LINE
return gui.handleCycleLine(1)
return gui.LBLCycleLine(1)
})
}
func (gui *Gui) getSelectedCommitFileName() string {
@ -297,8 +308,8 @@ func (gui *Gui) focusSelection(includeCurrentHunk bool) error {
return nil
}
func (gui *Gui) handleToggleSelectRange(g *gocui.Gui, v *gocui.View) error {
state := gui.State.Panels.LineByLine
func (gui *Gui) handleToggleSelectRange() error {
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error {
if state.SelectMode == RANGE {
state.SelectMode = LINE
} else {
@ -307,11 +318,11 @@ func (gui *Gui) handleToggleSelectRange(g *gocui.Gui, v *gocui.View) error {
state.FirstLineIdx, state.LastLineIdx = state.SelectedLineIdx, state.SelectedLineIdx
return gui.refreshMainViewForLineByLine()
})
}
func (gui *Gui) handleToggleSelectHunk(g *gocui.Gui, v *gocui.View) error {
state := gui.State.Panels.LineByLine
func (gui *Gui) handleToggleSelectHunk() error {
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error {
if state.SelectMode == HUNK {
state.SelectMode = LINE
state.FirstLineIdx, state.LastLineIdx = state.SelectedLineIdx, state.SelectedLineIdx
@ -326,13 +337,18 @@ func (gui *Gui) handleToggleSelectHunk(g *gocui.Gui, v *gocui.View) error {
}
return gui.focusSelection(state.SelectMode == HUNK)
})
}
func (gui *Gui) handleEscapeLineByLinePanel() {
func (gui *Gui) escapeLineByLinePanel() {
gui.withLBLActiveCheck(func(*lineByLinePanelState) error {
gui.State.Panels.LineByLine = nil
return nil
})
}
func (gui *Gui) handleOpenFileAtLine() error {
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error {
// again, would be good to use inheritance here (or maybe even composition)
var filename string
switch gui.State.MainContext {
@ -348,7 +364,6 @@ func (gui *Gui) handleOpenFileAtLine() error {
return errors.Errorf("unknown main context: %s", gui.State.MainContext)
}
state := gui.State.Panels.LineByLine
// need to look at current index, then work out what my hunk's header information is, and see how far my line is away from the hunk header
selectedHunk := state.PatchParser.GetHunkContainingLine(state.SelectedLineIdx, 0)
lineNumber := selectedHunk.LineNumberOfLine(state.SelectedLineIdx)
@ -358,4 +373,58 @@ func (gui *Gui) handleOpenFileAtLine() error {
}
return nil
})
}
func (gui *Gui) handleLineByLineNextPage() error {
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error {
newSelectedLineIdx := state.SelectedLineIdx + gui.pageDelta(gui.getMainView())
return gui.lineByLineNavigateTo(newSelectedLineIdx)
})
}
func (gui *Gui) handleLineByLinePrevPage() error {
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error {
newSelectedLineIdx := state.SelectedLineIdx - gui.pageDelta(gui.getMainView())
return gui.lineByLineNavigateTo(newSelectedLineIdx)
})
}
func (gui *Gui) handleLineByLineGotoBottom() error {
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error {
newSelectedLineIdx := len(state.PatchParser.PatchLines) - 1
return gui.lineByLineNavigateTo(newSelectedLineIdx)
})
}
func (gui *Gui) handleLineByLineGotoTop() error {
return gui.lineByLineNavigateTo(0)
}
func (gui *Gui) handlelineByLineNavigateTo(selectedLineIdx int) error {
return gui.withLBLActiveCheck(func(state *lineByLinePanelState) error {
return gui.lineByLineNavigateTo(selectedLineIdx)
})
}
func (gui *Gui) lineByLineNavigateTo(selectedLineIdx int) error {
state := gui.State.Panels.LineByLine
state.SelectMode = LINE
return gui.LBLSelectLine(selectedLineIdx)
}
func (gui *Gui) withLBLActiveCheck(f func(*lineByLinePanelState) error) error {
gui.State.Mutexes.LineByLinePanelMutex.Lock()
defer gui.State.Mutexes.LineByLinePanelMutex.Unlock()
state := gui.State.Panels.LineByLine
if state == nil {
return nil
}
return f(state)
}

@ -186,11 +186,8 @@ func (lc *ListContext) handleNextPage(g *gocui.Gui, v *gocui.View) error {
if err != nil {
return nil
}
_, height := view.Size()
delta := height - 1
if delta == 0 {
delta = 1
}
delta := lc.Gui.pageDelta(view)
return lc.handleLineChange(delta)
}
@ -207,11 +204,9 @@ func (lc *ListContext) handlePrevPage(g *gocui.Gui, v *gocui.View) error {
if err != nil {
return nil
}
_, height := view.Size()
delta := height - 1
if delta == 0 {
delta = 1
}
delta := lc.Gui.pageDelta(view)
return lc.handleLineChange(-delta)
}

@ -92,7 +92,7 @@ func (gui *Gui) handleToggleSelectionForPatch(g *gocui.Gui, v *gocui.View) error
}
func (gui *Gui) handleEscapePatchBuildingPanel() error {
gui.handleEscapeLineByLinePanel()
gui.escapeLineByLinePanel()
if gui.GitCommand.PatchManager.IsEmpty() {
gui.GitCommand.PatchManager.Reset()

@ -158,8 +158,8 @@ func (gui *Gui) handleFetchRemote(g *gocui.Gui, v *gocui.View) error {
}
return gui.WithWaitingStatus(gui.Tr.FetchingRemoteStatus, func() error {
gui.State.FetchMutex.Lock()
defer gui.State.FetchMutex.Unlock()
gui.State.Mutexes.FetchMutex.Lock()
defer gui.State.Mutexes.FetchMutex.Unlock()
// TODO: test this
err := gui.GitCommand.FetchRemote(remote.Name, gui.promptUserForCredential)

@ -84,7 +84,7 @@ func (gui *Gui) handleTogglePanel(g *gocui.Gui, v *gocui.View) error {
}
func (gui *Gui) handleStagingEscape() error {
gui.handleEscapeLineByLinePanel()
gui.escapeLineByLinePanel()
return gui.switchContext(gui.Contexts.Files.Context)
}

@ -12,8 +12,8 @@ import (
// never call this on its own, it should only be called from within refreshCommits()
func (gui *Gui) refreshStatus() {
gui.State.RefreshingStatusMutex.Lock()
defer gui.State.RefreshingStatusMutex.Unlock()
gui.State.Mutexes.RefreshingStatusMutex.Lock()
defer gui.State.Mutexes.RefreshingStatusMutex.Unlock()
currentBranch := gui.currentBranch()
if currentBranch == nil {

@ -433,3 +433,15 @@ func (gui *Gui) handlePrevTab(g *gocui.Gui, v *gocui.View) error {
utils.ModuloWithWrap(v.TabIndex-1, len(v.Tabs)),
)
}
// this is the distance we will move the cursor when paging up or down in a view
func (gui *Gui) pageDelta(view *gocui.View) int {
_, height := view.Size()
delta := height - 1
if delta == 0 {
return 1
}
return delta
}