summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Duffield <jessedduffield@gmail.com>2021-10-17 19:01:02 +1100
committerJesse Duffield <jessedduffield@gmail.com>2021-10-17 19:45:57 +1100
commitd672b7342f12c64112cd6b59fb5e4286a7cb92b4 (patch)
tree4b4c51680b05217708ce7ca596b6a47ffc170838
parente7c27b6f4aef44a2391dd207e1321008b5d1dcff (diff)
stop resetting scroll all the time
-rw-r--r--pkg/gui/files_panel.go7
-rw-r--r--pkg/gui/list_context.go12
-rw-r--r--pkg/gui/list_context_config.go125
-rw-r--r--pkg/gui/main_panels.go18
-rw-r--r--pkg/gui/pty.go5
-rw-r--r--pkg/gui/tasks_adapter.go59
-rw-r--r--pkg/tasks/tasks.go43
7 files changed, 129 insertions, 140 deletions
diff --git a/pkg/gui/files_panel.go b/pkg/gui/files_panel.go
index 05b966e5d..708eae1f5 100644
--- a/pkg/gui/files_panel.go
+++ b/pkg/gui/files_panel.go
@@ -57,13 +57,6 @@ func (gui *Gui) selectFile(alreadySelected bool) error {
}
if !alreadySelected {
- // TODO: pull into update task interface
- if err := gui.resetOrigin(gui.Views.Main); err != nil {
- return err
- }
- if err := gui.resetOrigin(gui.Views.Secondary); err != nil {
- return err
- }
gui.takeOverMergeConflictScrolling()
}
diff --git a/pkg/gui/list_context.go b/pkg/gui/list_context.go
index dc9425d20..a8ed12372 100644
--- a/pkg/gui/list_context.go
+++ b/pkg/gui/list_context.go
@@ -11,8 +11,7 @@ type ListContext struct {
SelectedItem func() (ListItem, bool)
GetPanelState func() IListPanelState
- Gui *Gui
- ResetMainViewOriginOnFocus bool
+ Gui *Gui
*BasicContext
}
@@ -79,15 +78,6 @@ func (lc *ListContext) HandleFocus() error {
view.FocusPoint(0, lc.GetPanelState().GetSelectedLineIdx())
- if lc.ResetMainViewOriginOnFocus {
- if err := lc.Gui.resetOrigin(lc.Gui.Views.Main); err != nil {
- return err
- }
- if err := lc.Gui.resetOrigin(lc.Gui.Views.Secondary); err != nil {
- return err
- }
- }
-
if lc.Gui.State.Modes.Diffing.Active() {
return lc.Gui.renderDiff()
}
diff --git a/pkg/gui/list_context_config.go b/pkg/gui/list_context_config.go
index dab3c35e7..0d591531e 100644
--- a/pkg/gui/list_context_config.go
+++ b/pkg/gui/list_context_config.go
@@ -14,12 +14,11 @@ func (gui *Gui) menuListContext() *ListContext {
Kind: PERSISTENT_POPUP,
OnGetOptionsMap: gui.getMenuOptions,
},
- GetItemsLength: func() int { return gui.Views.Menu.LinesHeight() },
- GetPanelState: func() IListPanelState { return gui.State.Panels.Menu },
- OnFocus: gui.handleMenuSelect,
- OnClickSelectedItem: gui.onMenuPress,
- Gui: gui,
- ResetMainViewOriginOnFocus: false,
+ GetItemsLength: func() int { return gui.Views.Menu.LinesHeight() },
+ GetPanelState: func() IListPanelState { return gui.State.Panels.Menu },
+ OnFocus: gui.handleMenuSelect,
+ OnClickSelectedItem: gui.onMenuPress,
+ Gui: gui,
// no GetDisplayStrings field because we do a custom render on menu creation
}
@@ -33,12 +32,11 @@ func (gui *Gui) filesListContext() *ListContext {
Key: FILES_CONTEXT_KEY,
Kind: SIDE_CONTEXT,
},
- GetItemsLength: func() int { return gui.State.FileManager.GetItemsLength() },
- GetPanelState: func() IListPanelState { return gui.State.Panels.Files },
- OnFocus: gui.focusAndSelectFile,
- OnClickSelectedItem: gui.handleFilePress,
- Gui: gui,
- ResetMainViewOriginOnFocus: false,
+ GetItemsLength: func() int { return gui.State.FileManager.GetItemsLength() },
+ GetPanelState: func() IListPanelState { return gui.State.Panels.Files },
+ OnFocus: gui.focusAndSelectFile,
+ OnClickSelectedItem: gui.handleFilePress,
+ Gui: gui,
GetDisplayStrings: func() [][]string {
lines := gui.State.FileManager.Render(gui.State.Modes.Diffing.Ref, gui.State.Submodules)
mappedLines := make([][]string, len(lines))
@@ -63,11 +61,10 @@ func (gui *Gui) branchesListContext() *ListContext {
Key: LOCAL_BRANCHES_CONTEXT_KEY,
Kind: SIDE_CONTEXT,
},
- GetItemsLength: func() int { return len(gui.State.Branches) },
- GetPanelState: func() IListPanelState { return gui.State.Panels.Branches },
- OnFocus: gui.handleBranchSelect,
- Gui: gui,
- ResetMainViewOriginOnFocus: true,
+ GetItemsLength: func() int { return len(gui.State.Branches) },
+ GetPanelState: func() IListPanelState { return gui.State.Panels.Branches },
+ OnFocus: gui.handleBranchSelect,
+ Gui: gui,
GetDisplayStrings: func() [][]string {
return presentation.GetBranchListDisplayStrings(gui.State.Branches, gui.State.ScreenMode != SCREEN_NORMAL, gui.State.Modes.Diffing.Ref)
},
@@ -86,12 +83,11 @@ func (gui *Gui) remotesListContext() *ListContext {
Key: REMOTES_CONTEXT_KEY,
Kind: SIDE_CONTEXT,
},
- GetItemsLength: func() int { return len(gui.State.Remotes) },
- GetPanelState: func() IListPanelState { return gui.State.Panels.Remotes },
- OnFocus: gui.handleRemoteSelect,
- OnClickSelectedItem: gui.handleRemoteEnter,
- Gui: gui,
- ResetMainViewOriginOnFocus: true,
+ GetItemsLength: func() int { return len(gui.State.Remotes) },
+ GetPanelState: func() IListPanelState { return gui.State.Panels.Remotes },
+ OnFocus: gui.handleRemoteSelect,
+ OnClickSelectedItem: gui.handleRemoteEnter,
+ Gui: gui,
GetDisplayStrings: func() [][]string {
return presentation.GetRemoteListDisplayStrings(gui.State.Remotes, gui.State.Modes.Diffing.Ref)
},
@@ -110,11 +106,10 @@ func (gui *Gui) remoteBranchesListContext() *ListContext {
Key: REMOTE_BRANCHES_CONTEXT_KEY,
Kind: SIDE_CONTEXT,
},
- GetItemsLength: func() int { return len(gui.State.RemoteBranches) },
- GetPanelState: func() IListPanelState { return gui.State.Panels.RemoteBranches },
- OnFocus: gui.handleRemoteBranchSelect,
- Gui: gui,
- ResetMainViewOriginOnFocus: true,
+ GetItemsLength: func() int { return len(gui.State.RemoteBranches) },
+ GetPanelState: func() IListPanelState { return gui.State.Panels.RemoteBranches },
+ OnFocus: gui.handleRemoteBranchSelect,
+ Gui: gui,
GetDisplayStrings: func() [][]string {
return presentation.GetRemoteBranchListDisplayStrings(gui.State.RemoteBranches, gui.State.Modes.Diffing.Ref)
},
@@ -133,11 +128,10 @@ func (gui *Gui) tagsListContext() *ListContext {
Key: TAGS_CONTEXT_KEY,
Kind: SIDE_CONTEXT,
},
- GetItemsLength: func() int { return len(gui.State.Tags) },
- GetPanelState: func() IListPanelState { return gui.State.Panels.Tags },
- OnFocus: gui.handleTagSelect,
- Gui: gui,
- ResetMainViewOriginOnFocus: true,
+ GetItemsLength: func() int { return len(gui.State.Tags) },
+ GetPanelState: func() IListPanelState { return gui.State.Panels.Tags },
+ OnFocus: gui.handleTagSelect,
+ Gui: gui,
GetDisplayStrings: func() [][]string {
return presentation.GetTagListDisplayStrings(gui.State.Tags, gui.State.Modes.Diffing.Ref)
},
@@ -157,12 +151,11 @@ func (gui *Gui) branchCommitsListContext() *ListContext {
Key: BRANCH_COMMITS_CONTEXT_KEY,
Kind: SIDE_CONTEXT,
},
- GetItemsLength: func() int { return len(gui.State.Commits) },
- GetPanelState: func() IListPanelState { return gui.State.Panels.Commits },
- OnFocus: gui.handleCommitSelect,
- OnClickSelectedItem: gui.handleViewCommitFiles,
- Gui: gui,
- ResetMainViewOriginOnFocus: true,
+ GetItemsLength: func() int { return len(gui.State.Commits) },
+ GetPanelState: func() IListPanelState { return gui.State.Panels.Commits },
+ OnFocus: gui.handleCommitSelect,
+ OnClickSelectedItem: gui.handleViewCommitFiles,
+ Gui: gui,
GetDisplayStrings: func() [][]string {
return presentation.GetCommitListDisplayStrings(
gui.State.Commits,
@@ -188,11 +181,10 @@ func (gui *Gui) reflogCommitsListContext() *ListContext {
Key: REFLOG_COMMITS_CONTEXT_KEY,
Kind: SIDE_CONTEXT,
},
- GetItemsLength: func() int { return len(gui.State.FilteredReflogCommits) },
- GetPanelState: func() IListPanelState { return gui.State.Panels.ReflogCommits },
- OnFocus: gui.handleReflogCommitSelect,
- Gui: gui,
- ResetMainViewOriginOnFocus: true,
+ GetItemsLength: func() int { return len(gui.State.FilteredReflogCommits) },
+ GetPanelState: func() IListPanelState { return gui.State.Panels.ReflogCommits },
+ OnFocus: gui.handleReflogCommitSelect,
+ Gui: gui,
GetDisplayStrings: func() [][]string {
return presentation.GetReflogCommitListDisplayStrings(
gui.State.FilteredReflogCommits,
@@ -218,11 +210,10 @@ func (gui *Gui) subCommitsListContext() *ListContext {
Key: SUB_COMMITS_CONTEXT_KEY,
Kind: SIDE_CONTEXT,
},
- GetItemsLength: func() int { return len(gui.State.SubCommits) },
- GetPanelState: func() IListPanelState { return gui.State.Panels.SubCommits },
- OnFocus: gui.handleSubCommitSelect,
- Gui: gui,
- ResetMainViewOriginOnFocus: true,
+ GetItemsLength: func() int { return len(gui.State.SubCommits) },
+ GetPanelState: func() IListPanelState { return gui.State.Panels.SubCommits },
+ OnFocus: gui.handleSubCommitSelect,
+ Gui: gui,
GetDisplayStrings: func() [][]string {
return presentation.GetCommitListDisplayStrings(
gui.State.SubCommits,
@@ -247,11 +238,10 @@ func (gui *Gui) stashListContext() *ListContext {
Key: STASH_CONTEXT_KEY,
Kind: SIDE_CONTEXT,
},
- GetItemsLength: func() int { return len(gui.State.StashEntries) },
- GetPanelState: func() IListPanelState { return gui.State.Panels.Stash },
- OnFocus: gui.handleStashEntrySelect,
- Gui: gui,
- ResetMainViewOriginOnFocus: true,
+ GetItemsLength: func() int { return len(gui.State.StashEntries) },
+ GetPanelState: func() IListPanelState { return gui.State.Panels.Stash },
+ OnFocus: gui.handleStashEntrySelect,
+ Gui: gui,
GetDisplayStrings: func() [][]string {
return presentation.GetStashEntryListDisplayStrings(gui.State.StashEntries, gui.State.Modes.Diffing.Ref)
},
@@ -270,11 +260,10 @@ func (gui *Gui) commitFilesListContext() *ListContext {
Key: COMMIT_FILES_CONTEXT_KEY,
Kind: SIDE_CONTEXT,
},
- GetItemsLength: func() int { return gui.State.CommitFileManager.GetItemsLength() },
- GetPanelState: func() IListPanelState { return gui.State.Panels.CommitFiles },
- OnFocus: gui.handleCommitFileSelect,
- Gui: gui,
- ResetMainViewOriginOnFocus: true,
+ GetItemsLength: func() int { return gui.State.CommitFileManager.GetItemsLength() },
+ GetPanelState: func() IListPanelState { return gui.State.Panels.CommitFiles },
+ OnFocus: gui.handleCommitFileSelect,
+ Gui: gui,
GetDisplayStrings: func() [][]string {
if gui.State.CommitFileManager.GetItemsLength() == 0 {
return [][]string{{style.FgRed.Sprint("(none)")}}
@@ -303,11 +292,10 @@ func (gui *Gui) submodulesListContext() *ListContext {
Key: SUBMODULES_CONTEXT_KEY,
Kind: SIDE_CONTEXT,
},
- GetItemsLength: func() int { return len(gui.State.Submodules) },
- GetPanelState: func() IListPanelState { return gui.State.Panels.Submodules },
- OnFocus: gui.handleSubmoduleSelect,
- Gui: gui,
- ResetMainViewOriginOnFocus: true,
+ GetItemsLength: func() int { return len(gui.State.Submodules) },
+ GetPanelState: func() IListPanelState { return gui.State.Panels.Submodules },
+ OnFocus: gui.handleSubmoduleSelect,
+ Gui: gui,
GetDisplayStrings: func() [][]string {
return presentation.GetSubmoduleListDisplayStrings(gui.State.Submodules)
},
@@ -326,11 +314,10 @@ func (gui *Gui) suggestionsListContext() *ListContext {
Key: SUGGESTIONS_CONTEXT_KEY,
Kind: PERSISTENT_POPUP,
},
- GetItemsLength: func() int { return len(gui.State.Suggestions) },
- GetPanelState: func() IListPanelState { return gui.State.Panels.Suggestions },
- OnFocus: func() error { return nil },
- Gui: gui,
- ResetMainViewOriginOnFocus: false,
+ GetItemsLength: func() int { return len(gui.State.Suggestions) },
+ GetPanelState: func() IListPanelState { return gui.State.Panels.Suggestions },
+ OnFocus: func() error { return nil },
+ Gui: gui,
GetDisplayStrings: func() [][]string {
return presentation.GetSuggestionListDisplayStrings(gui.State.Suggestions)
},
diff --git a/pkg/gui/main_panels.go b/pkg/gui/main_panels.go
index 389a9d783..72af94b1d 100644
--- a/pkg/gui/main_panels.go
+++ b/pkg/gui/main_panels.go
@@ -29,7 +29,6 @@ type TaskKind int
const (
RENDER_STRING TaskKind = iota
RENDER_STRING_WITHOUT_SCROLL
- RUN_FUNCTION
RUN_COMMAND
RUN_PTY
)
@@ -97,19 +96,6 @@ func NewRunPtyTask(cmd *exec.Cmd) *runPtyTask {
// return &runPtyTask{cmd: cmd, prefix: prefix}
// }
-type runFunctionTask struct {
- f func(chan struct{}) error
-}
-
-func (t *runFunctionTask) GetKind() TaskKind {
- return RUN_FUNCTION
-}
-
-// currently unused
-// func (gui *Gui) createRunFunctionTask(f func(chan struct{}) error) *runFunctionTask {
-// return &runFunctionTask{f: f}
-// }
-
func (gui *Gui) runTaskForView(view *gocui.View, task updateTask) error {
switch task.GetKind() {
case RENDER_STRING:
@@ -120,10 +106,6 @@ func (gui *Gui) runTaskForView(view *gocui.View, task updateTask) error {
specificTask := task.(*renderStringWithoutScrollTask)
return gui.newStringTaskWithoutScroll(view, specificTask.str)
- case RUN_FUNCTION:
- specificTask := task.(*runFunctionTask)
- return gui.newTask(view, specificTask.f)
-
case RUN_COMMAND:
specificTask := task.(*runCommandTask)
return gui.newCmdTask(view, specificTask.cmd, specificTask.prefix)
diff --git a/pkg/gui/pty.go b/pkg/gui/pty.go
index f53904835..ff6892d73 100644
--- a/pkg/gui/pty.go
+++ b/pkg/gui/pty.go
@@ -5,6 +5,7 @@ package gui
import (
"os/exec"
+ "strings"
"github.com/creack/pty"
"github.com/jesseduffield/gocui"
@@ -40,6 +41,8 @@ func (gui *Gui) newPtyTask(view *gocui.View, cmd *exec.Cmd, prefix string) error
return gui.newCmdTask(view, cmd, prefix)
}
+ cmdStr := strings.Join(cmd.Args, " ")
+
cmd.Env = append(cmd.Env, "GIT_PAGER="+pager)
_, height := view.Size()
@@ -62,7 +65,7 @@ func (gui *Gui) newPtyTask(view *gocui.View, cmd *exec.Cmd, prefix string) error
return err
}
- if err := manager.NewTask(manager.NewCmdTask(ptmx, cmd, prefix, height+oy+10, onClose)); err != nil {
+ if err := manager.NewTask(manager.NewCmdTask(ptmx, cmd, prefix, height+oy+10, onClose), cmdStr); err != nil {
return err
}
diff --git a/pkg/gui/tasks_adapter.go b/pkg/gui/tasks_adapter.go
index 71cde5b00..8d1f289db 100644
--- a/pkg/gui/tasks_adapter.go
+++ b/pkg/gui/tasks_adapter.go
@@ -9,9 +9,10 @@ import (
)
func (gui *Gui) newCmdTask(view *gocui.View, cmd *exec.Cmd, prefix string) error {
+ cmdStr := strings.Join(cmd.Args, " ")
gui.Log.WithField(
"command",
- strings.Join(cmd.Args, " "),
+ cmdStr,
).Debug("RunCommand")
_, height := view.Size()
@@ -29,17 +30,7 @@ func (gui *Gui) newCmdTask(view *gocui.View, cmd *exec.Cmd, prefix string) error
return err
}
- if err := manager.NewTask(manager.NewCmdTask(r, cmd, prefix, height+oy+10, nil)); err != nil {
- return err
- }
-
- return nil
-}
-
-func (gui *Gui) newTask(view *gocui.View, f func(chan struct{}) error) error {
- manager := gui.getManager(view)
-
- if err := manager.NewTask(f); err != nil {
+ if err := manager.NewTask(manager.NewCmdTask(r, cmd, prefix, height+oy+10, nil), cmdStr); err != nil {
return err
}
@@ -47,29 +38,24 @@ func (gui *Gui) newTask(view *gocui.View, f func(chan struct{}) error) error {
}
func (gui *Gui) newStringTask(view *gocui.View, str string) error {
- manager := gui.getManager(view)
-
- f := func(stop chan struct{}) error {
- gui.renderString(view, str)
- return nil
- }
-
- if err := manager.NewTask(f); err != nil {
- return err
- }
-
- return nil
+ // using str so that if rendering the exact same thing we don't reset the origin
+ return gui.newStringTaskWithKey(view, str, str)
}
func (gui *Gui) newStringTaskWithoutScroll(view *gocui.View, str string) error {
+ // using empty key so that on subsequent calls we won't reset the view's origin
+ return gui.newStringTaskWithKey(view, str, "")
+}
+
+func (gui *Gui) newStringTaskWithKey(view *gocui.View, str string, key string) error {
manager := gui.getManager(view)
f := func(stop chan struct{}) error {
- gui.setViewContent(view, str)
+ gui.renderString(view, str)
return nil
}
- if err := manager.NewTask(f); err != nil {
+ if err := manager.NewTask(f, key); err != nil {
return err
}
@@ -97,8 +83,29 @@ func (gui *Gui) getManager(view *gocui.View) *tasks.ViewBufferManager {
})
},
func() {
+ // Need to check if the content of the view is well past the origin.
+ // It would be better to use .ViewLinesHeight here (given it considers
+ // wrapping) but when this function is called they haven't been written to yet.
+ linesHeight := view.LinesHeight()
+ _, height := view.Size()
+ _, originY := view.Origin()
+ if linesHeight < originY {
+ newOriginY := linesHeight - height
+ if newOriginY < 0 {
+ newOriginY = 0
+ }
+ err := view.SetOrigin(0, newOriginY)
+ if err != nil {
+ panic(err)
+ }
+
+ }
+
view.FlushStaleCells()
},
+ func() {
+ _ = view.SetOrigin(0, 0)
+ },
)
gui.viewBufferManagerMap[view.Name()] = manager
}
diff --git a/pkg/tasks/tasks.go b/pkg/tasks/tasks.go
index 8287b3927..ba86317ac 100644
--- a/pkg/tasks/tasks.go
+++ b/pkg/tasks/tasks.go
@@ -31,15 +31,36 @@ type ViewBufferManager struct {
Log *logrus.Entry
newTaskId int
readLines chan int
+ taskKey string
+ onNewKey func()
// beforeStart is the function that is called before starting a new task
- beforeStart func()
- refreshView func()
- flushStaleCells func()
+ beforeStart func()
+ refreshView func()
+ onEndOfInput func()
}
-func NewViewBufferManager(log *logrus.Entry, writer io.Writer, beforeStart func(), refreshView func(), flushStaleCells func()) *ViewBufferManager {
- return &ViewBufferManager{Log: log, writer: writer, beforeStart: beforeStart, refreshView: refreshView, flushStaleCells: flushStaleCells, readLines: make(chan int, 1024)}
+func (m *ViewBufferManager) GetTaskKey() string {
+ return m.taskKey
+}
+
+func NewViewBufferManager(
+ log *logrus.Entry,
+ writer io.Writer,
+ beforeStart func(),
+ refreshView func(),
+ onEndOfInput func(),
+ onNewKey func(),
+) *ViewBufferManager {
+ return &ViewBufferManager{
+ Log: log,
+ writer: writer,
+ beforeStart: beforeStart,
+ refreshView: refreshView,
+ onEndOfInput: onEndOfInput,
+ readLines: make(chan int, 1024),
+ onNewKey: onNewKey,
+ }
}
func (m *ViewBufferManager) ReadLines(n int) {
@@ -117,11 +138,11 @@ func (m *ViewBufferManager) NewCmdTask(r io.Reader, cmd *exec.Cmd, prefix string
if !ok {
// if we're here then there's nothing left to scan from the source
// so we're at the EOF and can flush the stale content
- m.flushStaleCells()
+ m.onEndOfInput()
m.refreshView()
break outer
}
- _, _ = m.writer.Write(append(scanner.Bytes(), []byte("\n")...))
+ _, _ = m.writer.Write(append(scanner.Bytes(), '\n'))
}
m.refreshView()
case <-stop:
@@ -179,11 +200,17 @@ func (t *ViewBufferManager) Close() {
// 1) command based, where the manager can be asked to read more lines, but the command can be killed
// 2) string based, where the manager can also be asked to read more lines
-func (m *ViewBufferManager) NewTask(f func(stop chan struct{}) error) error {
+func (m *ViewBufferManager) NewTask(f func(stop chan struct{}) error, key string) error {
go utils.Safe(func() {
m.taskIDMutex.Lock()
m.newTaskId++
taskID := m.newTaskId
+
+ if m.GetTaskKey() != key && m.onNewKey != nil {
+ m.onNewKey()
+ }
+ m.taskKey = key
+
m.taskIDMutex.Unlock()
m.waitingMutex.Lock()