authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-05-22 22:01:15-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-05-27 20:56:48-07:00
log66c3b6ac65fad662c121073500c3cf3b7c9fcb60
treec8d40c8dc08e148b60c3bdf6119f12f4fed6fe8f
parenta3c9511ab9d56d4c06c612536a27b84d67ae415c

fix terminal repainting

the clear, save, restore thing doesn't work when the terminal is at the bottom

1 files changed, 23 insertions(+), 7 deletions(-)

lib/std/Progress.zig+23-7
......@@ -35,6 +35,9 @@ initial_delay_ns: u64,
3535
3636rows: u16,
3737cols: u16,
38/// Needed because terminal escape codes require one to take scrolling into
39/// account.
40newline_count: u16,
3841
3942/// Accessed only by the update thread.
4043draw_buffer: []u8,
......@@ -240,6 +243,7 @@ var global_progress: Progress = .{
240243 .initial_delay_ns = undefined,
241244 .rows = 0,
242245 .cols = 0,
246 .newline_count = 0,
243247 .draw_buffer = undefined,
244248 .done = false,
245249
......@@ -346,6 +350,7 @@ fn updateThreadRun() void {
346350}
347351
348352const start_sync = "\x1b[?2026h";
353const up_one_line = "\x1bM";
349354const clear = "\x1b[J";
350355const save = "\x1b7";
351356const restore = "\x1b8";
......@@ -431,22 +436,32 @@ fn computeRedraw() []u8 {
431436 }
432437
433438 // The strategy is: keep the cursor at the beginning, and then with every redraw:
434 // erase, save, write, restore
439 // erase to end of screen, write, move cursor to beginning of line, move cursor up N lines
435440
436441 var i: usize = 0;
437442 const buf = global_progress.draw_buffer;
438443
439 const prefix = start_sync ++ clear ++ save;
440 const suffix = restore ++ finish_sync;
444 buf[i..][0..start_sync.len].* = start_sync.*;
445 i += start_sync.len;
441446
442 buf[0..prefix.len].* = prefix.*;
443 i = prefix.len;
447 buf[0..clear.len].* = clear.*;
448 i = clear.len;
444449
445450 const root_node_index: Node.Index = @enumFromInt(0);
446451 i = computeNode(buf, i, serialized_node_storage, serialized_node_parents, children, root_node_index);
447452
448 buf[i..][0..suffix.len].* = suffix.*;
449 i += suffix.len;
453 if (buf[i - 1] == '\n') {
454 buf[i - 1] = '\r';
455 const prev_nl_n = global_progress.newline_count - 1;
456 global_progress.newline_count = 0;
457 for (0..prev_nl_n) |_| {
458 buf[i..][0..up_one_line.len].* = up_one_line.*;
459 i += up_one_line.len;
460 }
461 }
462
463 buf[i..][0..finish_sync.len].* = finish_sync.*;
464 i += finish_sync.len;
450465
451466 return buf[0..i];
452467}
......@@ -514,6 +529,7 @@ fn computeNode(
514529 i = @min(global_progress.cols + start_i, i);
515530 buf[i] = '\n';
516531 i += 1;
532 global_progress.newline_count += 1;
517533
518534 if (children[@intFromEnum(node_index)].child.unwrap()) |child| {
519535 i = computeNode(buf, i, serialized_node_storage, serialized_node_parents, children, child);