Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use synchronized update mode to simplify and enhance rendering #3713

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
CHANGELOG
=========

0.50.0
------
- Eliminated any flickering of the screen and simplified the code using [synchronized update mode](https://gist.github.com/christianparpart/d8a62cc1ab659194337d73e399004036)
- TODO: Not all terminals support this mode. We can detect if the current terminal supports this. But it means we can't simplify the code using the mode.

0.49.0
------
- Ingestion performance improved by around 40% (more or less depending on options)
Expand Down
39 changes: 9 additions & 30 deletions src/terminal.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,6 @@ type previewed struct {
offset int
filled bool
image bool
wipe bool
wireframe bool
}

Expand All @@ -145,8 +144,6 @@ type itemLine struct {
selected bool
label string
queryLen int
width int
bar bool
result Result
}

Expand Down Expand Up @@ -768,7 +765,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal {
initialPreviewOpts: opts.Preview,
previewOpts: opts.Preview,
previewer: previewer{0, []string{}, 0, false, true, disabledState, "", []bool{}},
previewed: previewed{0, 0, 0, false, false, false, false},
previewed: previewed{0, 0, 0, false, false, false},
previewBox: previewBox,
eventBox: eventBox,
mutex: sync.Mutex{},
Expand Down Expand Up @@ -1836,12 +1833,11 @@ func (t *Terminal) printItem(result Result, line int, i int, current bool, bar b

// Avoid unnecessary redraw
newLine := itemLine{offset: line, current: current, selected: selected, label: label,
result: result, queryLen: len(t.input), width: 0, bar: bar}
result: result, queryLen: len(t.input)}
prevLine := t.prevLines[i]
forceRedraw := prevLine.offset != newLine.offset
printBar := func() {
if len(t.scrollbar) > 0 && (bar != prevLine.bar || forceRedraw) {
t.prevLines[i].bar = bar
if len(t.scrollbar) > 0 {
t.move(line, t.window.Width()-1, true)
if bar {
t.window.CPrint(tui.ColScrollbar, t.scrollbar)
Expand All @@ -1859,7 +1855,7 @@ func (t *Terminal) printItem(result Result, line int, i int, current bool, bar b
return
}

t.move(line, 0, forceRedraw)
t.move(line, 0, true)
if current {
if len(label) == 0 {
t.window.CPrint(tui.ColCurrentCursorEmpty, t.pointerEmpty)
Expand All @@ -1871,7 +1867,7 @@ func (t *Terminal) printItem(result Result, line int, i int, current bool, bar b
} else {
t.window.CPrint(tui.ColCurrentSelectedEmpty, t.markerEmpty)
}
newLine.width = t.printHighlighted(result, tui.ColCurrent, tui.ColCurrentMatch, true, true)
t.printHighlighted(result, tui.ColCurrent, tui.ColCurrentMatch, true, true)
} else {
if len(label) == 0 {
t.window.CPrint(tui.ColCursorEmpty, t.pointerEmpty)
Expand All @@ -1883,11 +1879,7 @@ func (t *Terminal) printItem(result Result, line int, i int, current bool, bar b
} else {
t.window.Print(t.markerEmpty)
}
newLine.width = t.printHighlighted(result, tui.ColNormal, tui.ColMatch, false, true)
}
fillSpaces := prevLine.width - newLine.width
if fillSpaces > 0 {
t.window.Print(strings.Repeat(" ", fillSpaces))
t.printHighlighted(result, tui.ColNormal, tui.ColMatch, false, true)
}
printBar()
t.prevLines[i] = newLine
Expand Down Expand Up @@ -1931,7 +1923,7 @@ func (t *Terminal) overflow(runes []rune, max int) bool {
return t.displayWidthWithLimit(runes, 0, max) > max
}

func (t *Terminal) printHighlighted(result Result, colBase tui.ColorPair, colMatch tui.ColorPair, current bool, match bool) int {
func (t *Terminal) printHighlighted(result Result, colBase tui.ColorPair, colMatch tui.ColorPair, current bool, match bool) {
item := result.item

// Overflow
Expand Down Expand Up @@ -2009,11 +2001,9 @@ func (t *Terminal) printHighlighted(result Result, colBase tui.ColorPair, colMat
offsets[idx].offset[1] = util.Min32(offset.offset[1], int32(maxWidth))
}
}
displayWidth = t.displayWidthWithLimit(text, 0, displayWidth)
}

t.printColoredString(t.window, text, offsets, colBase)
return displayWidth
}

func (t *Terminal) printColoredString(window tui.Window, text []rune, offsets []colorOffset, colBase tui.ColorPair) {
Expand Down Expand Up @@ -2072,21 +2062,11 @@ func (t *Terminal) renderPreviewSpinner() {
}

func (t *Terminal) renderPreviewArea(unchanged bool) {
if t.previewed.wipe && t.previewed.version != t.previewer.version {
t.previewed.wipe = false
t.pwindow.Erase()
} else if unchanged {
if unchanged {
t.pwindow.MoveAndClear(0, 0) // Clear scroll offset display
} else {
t.previewed.filled = false
// We don't erase the window here to avoid flickering during scroll.
// However, tcell renderer uses double-buffering technique and there's no
// flickering. So we just erase the window and make the rest of the code
// simpler.
if !t.pwindow.EraseMaybe() {
t.pwindow.DrawBorder()
t.pwindow.Move(0, 0)
}
t.pwindow.Erase()
}

height := t.pwindow.Height()
Expand Down Expand Up @@ -2173,7 +2153,6 @@ Loop:
isItermImage := strings.HasPrefix(passThrough, "\x1b]1337;")
isImage := isSixel || isItermImage
if isImage {
t.previewed.wipe = true
// NOTE: We don't have a good way to get the height of an iTerm image,
// so we assume that it requires the full height of the preview
// window.
Expand Down
6 changes: 1 addition & 5 deletions src/tui/light.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func (r *LightRenderer) csi(code string) string {

func (r *LightRenderer) flush() {
if r.queued.Len() > 0 {
fmt.Fprint(os.Stderr, "\x1b[?25l"+r.queued.String()+"\x1b[?25h")
fmt.Fprint(os.Stderr, "\x1b[?2026h"+r.queued.String()+"\x1b[?2026l")
r.queued.Reset()
}
}
Expand Down Expand Up @@ -1128,7 +1128,3 @@ func (w *LightWindow) Erase() {
w.FinishFill()
w.Move(0, 0)
}

func (w *LightWindow) EraseMaybe() bool {
return false
}
5 changes: 0 additions & 5 deletions src/tui/tcell.go
Original file line number Diff line number Diff line change
Expand Up @@ -565,11 +565,6 @@ func (w *TcellWindow) Erase() {
w.drawBorder(false)
}

func (w *TcellWindow) EraseMaybe() bool {
w.Erase()
return true
}

func (w *TcellWindow) Enclose(y int, x int) bool {
return x >= w.left && x < (w.left+w.width) &&
y >= w.top && y < (w.top+w.height)
Expand Down
1 change: 0 additions & 1 deletion src/tui/tui.go
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,6 @@ type Window interface {
Fill(text string) FillReturn
CFill(fg Color, bg Color, attr Attr, text string) FillReturn
Erase()
EraseMaybe() bool
}

type FullscreenRenderer struct {
Expand Down