diff --git a/pkg/gui/controllers/view_selection_controller.go b/pkg/gui/controllers/view_selection_controller.go index e961e9979..638c46ba6 100644 --- a/pkg/gui/controllers/view_selection_controller.go +++ b/pkg/gui/controllers/view_selection_controller.go @@ -95,7 +95,15 @@ func (self *ViewSelectionController) handleGotoTop() error { } func (self *ViewSelectionController) handleGotoBottom() error { - v := self.Context().GetView() - self.handleLineChange(v.ViewLinesHeight()) + if manager := self.c.GetViewBufferManagerForView(self.context.GetView()); manager != nil { + manager.ReadToEnd(func() { + self.c.OnUIThread(func() error { + v := self.Context().GetView() + self.handleLineChange(v.ViewLinesHeight()) + return nil + }) + }) + } + return nil } diff --git a/pkg/tasks/tasks.go b/pkg/tasks/tasks.go index 6f6960d5f..e20e58045 100644 --- a/pkg/tasks/tasks.go +++ b/pkg/tasks/tasks.go @@ -70,6 +70,9 @@ type LinesToRead struct { // do an initial refresh. Only set for the initial read request; -1 for // subsequent requests. InitialRefreshAfter int + + // Function to call after reading the lines is done + Then func() } func (m *ViewBufferManager) GetTaskKey() string { @@ -105,6 +108,16 @@ func (self *ViewBufferManager) ReadLines(n int) { } } +func (self *ViewBufferManager) ReadToEnd(then func()) { + if self.readLines != nil { + go utils.Safe(func() { + self.readLines <- LinesToRead{Total: -1, InitialRefreshAfter: -1, Then: then} + }) + } else if then != nil { + then() + } +} + func (self *ViewBufferManager) NewCmdTask(start func() (*exec.Cmd, io.Reader), prefix string, linesToRead LinesToRead, onDoneFn func()) func(TaskOpts) error { return func(opts TaskOpts) error { var onDoneOnce sync.Once @@ -234,11 +247,17 @@ func (self *ViewBufferManager) NewCmdTask(start func() (*exec.Cmd, io.Reader), p case <-opts.Stop: break outer case linesToRead := <-self.readLines: - for i := 0; i < linesToRead.Total; i++ { + callThen := func() { + if linesToRead.Then != nil { + linesToRead.Then() + } + } + for i := 0; linesToRead.Total == -1 || i < linesToRead.Total; i++ { var ok bool var line []byte select { case <-opts.Stop: + callThen() break outer case line, ok = <-lineChan: break @@ -258,6 +277,7 @@ func (self *ViewBufferManager) NewCmdTask(start func() (*exec.Cmd, io.Reader), p // 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 self.onEndOfInput() + callThen() break outer } writeToView(append(line, '\n')) @@ -272,6 +292,7 @@ func (self *ViewBufferManager) NewCmdTask(start func() (*exec.Cmd, io.Reader), p } refreshViewIfStale() onFirstPageShown() + callThen() } } diff --git a/pkg/tasks/tasks_test.go b/pkg/tasks/tasks_test.go index 89056807f..72da6d83c 100644 --- a/pkg/tasks/tasks_test.go +++ b/pkg/tasks/tasks_test.go @@ -52,7 +52,7 @@ func TestNewCmdTaskInstantStop(t *testing.T) { return cmd, reader } - fn := manager.NewCmdTask(start, "prefix\n", LinesToRead{20, -1}, onDone) + fn := manager.NewCmdTask(start, "prefix\n", LinesToRead{20, -1, nil}, onDone) _ = fn(TaskOpts{Stop: stop, InitialContentLoaded: func() { task.Done() }}) @@ -115,7 +115,7 @@ func TestNewCmdTask(t *testing.T) { return cmd, reader } - fn := manager.NewCmdTask(start, "prefix\n", LinesToRead{20, -1}, onDone) + fn := manager.NewCmdTask(start, "prefix\n", LinesToRead{20, -1, nil}, onDone) wg := sync.WaitGroup{} wg.Add(1) go func() { @@ -184,37 +184,37 @@ func TestNewCmdTaskRefresh(t *testing.T) { { "total < initialRefreshAfter", 150, - LinesToRead{100, 120}, + LinesToRead{100, 120, nil}, []int{100}, }, { "total == initialRefreshAfter", 150, - LinesToRead{100, 100}, + LinesToRead{100, 100, nil}, []int{100}, }, { "total > initialRefreshAfter", 150, - LinesToRead{100, 50}, + LinesToRead{100, 50, nil}, []int{50, 100}, }, { "initialRefreshAfter == -1", 150, - LinesToRead{100, -1}, + LinesToRead{100, -1, nil}, []int{100}, }, { "totalTaskLines < initialRefreshAfter", 25, - LinesToRead{100, 50}, + LinesToRead{100, 50, nil}, []int{25}, }, { "totalTaskLines between total and initialRefreshAfter", 75, - LinesToRead{100, 50}, + LinesToRead{100, 50, nil}, []int{50, 75}, }, }