Skip to content

Commit 0cef3c7

Browse files
LeperGnomemeowgorithm
authored andcommitted
feat(render): remove flickering
1 parent 129d5eb commit 0cef3c7

File tree

1 file changed

+17
-47
lines changed

1 file changed

+17
-47
lines changed

standard_renderer.go

+17-47
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,9 @@ func (r *standardRenderer) flush() {
168168
// Output buffer
169169
buf := &bytes.Buffer{}
170170

171+
// Moving to the begining of the section, that we rendered.
172+
buf.WriteString(ansi.CursorUp(r.linesRendered-1) + ansi.CursorLeft(r.width))
173+
171174
newLines := strings.Split(r.buf.String(), "\n")
172175

173176
// If we know the output's height, we can use it to determine how many
@@ -179,64 +182,25 @@ func (r *standardRenderer) flush() {
179182
}
180183

181184
numLinesThisFlush := len(newLines)
182-
oldLines := strings.Split(r.lastRender, "\n")
183-
skipLines := make(map[int]struct{})
184185
flushQueuedMessages := len(r.queuedMessageLines) > 0 && !r.altScreenActive
185186

186-
// Clear any lines we painted in the last render.
187-
if r.linesRendered > 0 {
188-
for i := r.linesRendered - 1; i > 0; i-- {
189-
// if we are clearing queued messages, we want to clear all lines, since
190-
// printing messages allows for native terminal word-wrap, we
191-
// don't have control over the queued lines
192-
if flushQueuedMessages {
193-
buf.WriteString(ansi.EraseEntireLine)
194-
} else if (len(newLines) <= len(oldLines)) && (len(newLines) > i && len(oldLines) > i) && (newLines[i] == oldLines[i]) {
195-
// If the number of lines we want to render hasn't increased and
196-
// new line is the same as the old line we can skip rendering for
197-
// this line as a performance optimization.
198-
skipLines[i] = struct{}{}
199-
} else if _, exists := r.ignoreLines[i]; !exists {
200-
buf.WriteString(ansi.EraseEntireLine)
201-
}
202-
203-
buf.WriteString(ansi.CursorUp1)
204-
}
205-
206-
if _, exists := r.ignoreLines[0]; !exists {
207-
// We need to return to the start of the line here to properly
208-
// erase it. Going back the entire width of the terminal will
209-
// usually be farther than we need to go, but terminal emulators
210-
// will stop the cursor at the start of the line as a rule.
211-
//
212-
// We use this sequence in particular because it's part of the ANSI
213-
// standard (whereas others are proprietary to, say, VT100/VT52).
214-
// If cursor previous line (ESC[ + <n> + F) were better supported
215-
// we could use that above to eliminate this step.
216-
buf.WriteString(ansi.CursorLeft(r.width))
217-
buf.WriteString(ansi.EraseEntireLine)
218-
}
219-
}
220-
221-
// Merge the set of lines we're skipping as a rendering optimization with
222-
// the set of lines we've explicitly asked the renderer to ignore.
223-
for k, v := range r.ignoreLines {
224-
skipLines[k] = v
225-
}
226-
227187
if flushQueuedMessages {
228-
// Dump the lines we've queued up for printing
188+
// Dump the lines we've queued up for printing.
229189
for _, line := range r.queuedMessageLines {
190+
191+
// Removing previousy rendered content at the end of line.
192+
line = line + ansi.EraseLineRight
193+
230194
_, _ = buf.WriteString(line)
231195
_, _ = buf.WriteString("\r\n")
232196
}
233-
// clear the queued message lines
197+
// Clear the queued message lines.
234198
r.queuedMessageLines = []string{}
235199
}
236200

237-
// Paint new lines
201+
// Paint new lines.
238202
for i := 0; i < len(newLines); i++ {
239-
if _, skip := skipLines[i]; skip {
203+
if _, skip := r.ignoreLines[i]; skip {
240204
// Unless this is the last line, move the cursor down.
241205
if i < len(newLines)-1 {
242206
buf.WriteString(ansi.CursorDown1)
@@ -250,6 +214,9 @@ func (r *standardRenderer) flush() {
250214

251215
line := newLines[i]
252216

217+
// Removing left over content from previous render at the end of the line.
218+
line = line + ansi.EraseLineRight
219+
253220
// Truncate lines wider than the width of the window to avoid
254221
// wrapping, which will mess up rendering. If we don't have the
255222
// width of the window this will be ignored.
@@ -270,6 +237,9 @@ func (r *standardRenderer) flush() {
270237
}
271238
r.linesRendered = numLinesThisFlush
272239

240+
// Clearing left over content from last render (if our new frame contains less lines).
241+
buf.WriteString(ansi.EraseDisplayRight)
242+
273243
// Make sure the cursor is at the start of the last line to keep rendering
274244
// behavior consistent.
275245
if r.altScreenActive {

0 commit comments

Comments
 (0)