mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-10-05 21:46:49 -04:00
Let an emptied main pane forget what it was showing
A pane that has been emptied is showing nothing, but it kept the scroll position it was left at and went on claiming the render it used to show, so the next render into it — the same command's output, the file it was showing being selected again — counted as content the view already had, and was revealed partway down. So say what the empty pane is: at the top, and showing nothing that a render can be a re-render of. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
e2f0172cb6
commit
06e8cb85f9
+10
-1
@@ -162,10 +162,19 @@ func (gui *Gui) clampDiffSelectionToContent(view *gocui.View) {
|
||||
}
|
||||
|
||||
// clearMainView empties a pane that is being given nothing to show, selection and all.
|
||||
//
|
||||
// An emptied pane is showing nothing, so it also goes back to the top and stops
|
||||
// claiming the render it was showing: whatever it is given next is content the user
|
||||
// hasn't seen there, and is shown from the top like any other.
|
||||
func (gui *Gui) clearMainView(mainContext types.Context) {
|
||||
mainContext.GetView().Clear()
|
||||
view := mainContext.GetView()
|
||||
view.Clear()
|
||||
view.SetOrigin(0, 0)
|
||||
mainContext.SetHasSelectableContent(false)
|
||||
gui.State.ContextMgr.UpdateSelectionHighlights()
|
||||
if manager := gui.getViewBufferManagerForView(view); manager != nil {
|
||||
manager.ForgetRenderedContent()
|
||||
}
|
||||
}
|
||||
|
||||
// updateDiffSelectionVisibility works out whether a main pane holds anything for a
|
||||
|
||||
@@ -56,9 +56,6 @@ var PaneShownAgainStartsAtTheTop = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
t.Views().Secondary().
|
||||
IsVisible().
|
||||
Content(Contains("+LINE40")).
|
||||
/* EXPECTED:
|
||||
OriginY(0)
|
||||
ACTUAL: */
|
||||
OriginYAtLeast(1)
|
||||
},
|
||||
})
|
||||
|
||||
@@ -251,6 +251,17 @@ func (self *ViewBufferManager) GetTaskKey() string {
|
||||
return self.taskKey
|
||||
}
|
||||
|
||||
// ForgetRenderedContent records that the view no longer shows the render whose key it
|
||||
// is holding, because it has been emptied. The key says what the view is showing, and
|
||||
// the next task is compared against it to tell whether that task renders something
|
||||
// new. A view with nothing in it is showing nothing, so whatever comes next is new.
|
||||
func (self *ViewBufferManager) ForgetRenderedContent() {
|
||||
self.taskIDMutex.Lock()
|
||||
defer self.taskIDMutex.Unlock()
|
||||
|
||||
self.taskKey = ""
|
||||
}
|
||||
|
||||
func NewViewBufferManager(
|
||||
log *logrus.Entry,
|
||||
writer io.Writer,
|
||||
|
||||
@@ -610,6 +610,50 @@ func TestKeepScrollPositionForNextTask(t *testing.T) {
|
||||
assert.EqualValues(t, 0, beforeStartCount.Load())
|
||||
}
|
||||
|
||||
// A view that has been emptied is showing nothing, so the render it was showing is no
|
||||
// longer the one to compare the next task against: running the same command again is
|
||||
// putting content into the view that isn't there any more, and starts from the top.
|
||||
func TestForgetRenderedContent(t *testing.T) {
|
||||
resetOrigin, getResetOriginCallCount := getCounter()
|
||||
|
||||
manager := NewViewBufferManager(
|
||||
utils.NewDummyLog(),
|
||||
io.Discard,
|
||||
func() {}, // beforeStart
|
||||
func() {}, // refreshView
|
||||
func() {}, // onEndOfInput
|
||||
resetOrigin,
|
||||
func() {}, // beginRender
|
||||
func() {}, // swapInRender
|
||||
func() gocui.Task { return gocui.NewFakeTask() },
|
||||
// no UI thread in the test; run the view mutations inline
|
||||
func(f func()) error { f(); return nil },
|
||||
)
|
||||
|
||||
runTaskToCompletion := func(key string) {
|
||||
start := func() (Cmd, io.Reader) {
|
||||
// not actually starting this because it's not necessary
|
||||
return ExecCmd{Cmd: exec.Command("blah")}, &BlankLineReader{totalLinesToYield: 3}
|
||||
}
|
||||
done := make(chan struct{})
|
||||
_ = manager.NewTask(
|
||||
manager.NewCmdTask(start, "", LinesToRead{100, 50, nil}, func() { close(done) }), key)
|
||||
<-done
|
||||
}
|
||||
|
||||
runTaskToCompletion("cmd1")
|
||||
assert.Equal(t, 1, getResetOriginCallCount())
|
||||
|
||||
// Rendering the same command's output again leaves the view where it is, that being
|
||||
// what it already shows.
|
||||
runTaskToCompletion("cmd1")
|
||||
assert.Equal(t, 1, getResetOriginCallCount())
|
||||
|
||||
manager.ForgetRenderedContent()
|
||||
runTaskToCompletion("cmd1")
|
||||
assert.Equal(t, 2, getResetOriginCallCount(), "an emptied view is shown its content afresh")
|
||||
}
|
||||
|
||||
func TestNewCmdTaskRefresh(t *testing.T) {
|
||||
type scenario struct {
|
||||
name string
|
||||
|
||||
Reference in New Issue
Block a user