Skip to content

Commit f0dbca4

Browse files
committed
Log startup blinks on slow streams
Relates to: #464
1 parent a9ca302 commit f0dbca4

3 files changed

Lines changed: 38 additions & 6 deletions

File tree

‎internal/pager.go‎

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,9 @@ func (p *Pager) StartPaging(screen twin.Screen, chromaStyle *chroma.Style, chrom
666666

667667
log.Info("Entering pager main loop...")
668668

669+
paintedWhileReading := false
670+
paintedAfter := time.Duration(0)
671+
669672
// Main loop
670673
spinner := ""
671674
for !p.quit {
@@ -696,23 +699,40 @@ func (p *Pager) StartPaging(screen twin.Screen, chromaStyle *chroma.Style, chrom
696699
p.DeInit = false // Makes ReprintAfterExit() be called on the way out
697700
p.quit = true
698701

699-
log.Info("Exiting because of --quit-if-one-screen, everything fit on one screen and we're done")
702+
if paintedWhileReading {
703+
log.Warnf("--quit-if-one-screen blinked: input was still arriving after %s so we painted rather than wait, all of it had arrived after %s",
704+
paintedAfter, time.Since(r.StartedAt))
705+
} else {
706+
log.Info("Exiting because of --quit-if-one-screen: everything fits on one screen")
707+
}
700708

701709
// Exit the main loop
702710
break
703711
}
704712

705-
// Highlighting can still grow the contents past one screen, so we
706-
// don't know yet whether we are staying. Painting now and quitting
707-
// right after is the blink of issue #425, so paint nothing and let
708-
// the event read below wait for highlighting instead: it signals
709-
// MaybeDone when it lands.
713+
// Two things can still flip canQuit from "yes" to "no":
714+
// highlighting and reading (we don't know the final count until
715+
// it's done). We hold the paint below for highlighting, since it's
716+
// fast and bounded, but not for reading: a slow or endless producer
717+
// would otherwise leave the screen blank forever. So when reading
718+
// is the only thing still pending, we paint immediately and risk
719+
// the blink from issue #464, instead of holding out the way #425's
720+
// fix does for highlighting.
710721
//
711722
// Somebody who is interacting gets painted for regardless, which
712723
// also means a reader that never finishes highlighting costs them a
713724
// keypress rather than the whole session.
714725
holdPaint := canQuit && !p.sawUserInput
715726
if !holdPaint {
727+
quitIfOneScreenApplies := p.QuitIfOneScreen && !p.isShowingHelp && len(p.readers) == 1
728+
stillReading := !r.ReadingDone.Load()
729+
if quitIfOneScreenApplies && stillReading && !paintedWhileReading {
730+
// Remembered so that if this does turn into the #464
731+
// blink, the warning above can say how early we painted.
732+
paintedWhileReading = true
733+
paintedAfter = time.Since(r.StartedAt)
734+
}
735+
716736
p.redraw(spinner)
717737
}
718738
}

‎internal/reader/constructors.go‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"runtime/debug"
1010
"strings"
1111
"sync/atomic"
12+
"time"
1213

1314
"github.com/alecthomas/chroma/v2"
1415
"github.com/alecthomas/chroma/v2/lexers"
@@ -136,6 +137,8 @@ func newReaderFromStream(reader io.Reader, originalFileName *string, formatter c
136137
FileName: originalFileName,
137138
DisplayName: displayFileName,
138139

140+
StartedAt: time.Now(),
141+
139142
streamCloser: streamCloser,
140143

141144
pauseAfterLines: pauseAfterLines,

‎internal/reader/reader.go‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,15 @@ type ReaderImpl struct {
116116

117117
Err error
118118

119+
// When we started reading this stream, once its first bytes had already
120+
// arrived. Nothing paints before that point (see AwaitFirstByte(), which
121+
// blocks pager startup on exactly this), so time spent waiting for a slow
122+
// producer's first byte can't cause a --quit-if-one-screen blink and is
123+
// correctly excluded here. Used for reporting how far into the read we were
124+
// when something happened, alongside the "Stream read in" duration logged
125+
// once ReadingDone.
126+
StartedAt time.Time
127+
119128
// Stream has been completely read. May not be highlighted yet.
120129
ReadingDone *atomic.Bool
121130

0 commit comments

Comments
 (0)