@@ -168,6 +168,9 @@ func (r *standardRenderer) flush() {
168
168
// Output buffer
169
169
buf := & bytes.Buffer {}
170
170
171
+ // Moving to the begining of the section, that we rendered.
172
+ buf .WriteString (ansi .CursorUp (r .linesRendered - 1 ) + ansi .CursorLeft (r .width ))
173
+
171
174
newLines := strings .Split (r .buf .String (), "\n " )
172
175
173
176
// If we know the output's height, we can use it to determine how many
@@ -179,64 +182,25 @@ func (r *standardRenderer) flush() {
179
182
}
180
183
181
184
numLinesThisFlush := len (newLines )
182
- oldLines := strings .Split (r .lastRender , "\n " )
183
- skipLines := make (map [int ]struct {})
184
185
flushQueuedMessages := len (r .queuedMessageLines ) > 0 && ! r .altScreenActive
185
186
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
-
227
187
if flushQueuedMessages {
228
- // Dump the lines we've queued up for printing
188
+ // Dump the lines we've queued up for printing.
229
189
for _ , line := range r .queuedMessageLines {
190
+
191
+ // Removing previousy rendered content at the end of line.
192
+ line = line + ansi .EraseLineRight
193
+
230
194
_ , _ = buf .WriteString (line )
231
195
_ , _ = buf .WriteString ("\r \n " )
232
196
}
233
- // clear the queued message lines
197
+ // Clear the queued message lines.
234
198
r .queuedMessageLines = []string {}
235
199
}
236
200
237
- // Paint new lines
201
+ // Paint new lines.
238
202
for i := 0 ; i < len (newLines ); i ++ {
239
- if _ , skip := skipLines [i ]; skip {
203
+ if _ , skip := r . ignoreLines [i ]; skip {
240
204
// Unless this is the last line, move the cursor down.
241
205
if i < len (newLines )- 1 {
242
206
buf .WriteString (ansi .CursorDown1 )
@@ -250,6 +214,9 @@ func (r *standardRenderer) flush() {
250
214
251
215
line := newLines [i ]
252
216
217
+ // Removing left over content from previous render at the end of the line.
218
+ line = line + ansi .EraseLineRight
219
+
253
220
// Truncate lines wider than the width of the window to avoid
254
221
// wrapping, which will mess up rendering. If we don't have the
255
222
// width of the window this will be ignored.
@@ -270,6 +237,9 @@ func (r *standardRenderer) flush() {
270
237
}
271
238
r .linesRendered = numLinesThisFlush
272
239
240
+ // Clearing left over content from last render (if our new frame contains less lines).
241
+ buf .WriteString (ansi .EraseDisplayRight )
242
+
273
243
// Make sure the cursor is at the start of the last line to keep rendering
274
244
// behavior consistent.
275
245
if r .altScreenActive {
0 commit comments