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,...@@ -35,6 +35,9 @@ initial_delay_ns: u64,
3535
36rows: u16,36rows: u16,
37cols: u16,37cols: u16,
38/// Needed because terminal escape codes require one to take scrolling into
39/// account.
40newline_count: u16,
3841
39/// Accessed only by the update thread.42/// Accessed only by the update thread.
40draw_buffer: []u8,43draw_buffer: []u8,
...@@ -240,6 +243,7 @@ var global_progress: Progress = .{...@@ -240,6 +243,7 @@ var global_progress: Progress = .{
240 .initial_delay_ns = undefined,243 .initial_delay_ns = undefined,
241 .rows = 0,244 .rows = 0,
242 .cols = 0,245 .cols = 0,
246 .newline_count = 0,
243 .draw_buffer = undefined,247 .draw_buffer = undefined,
244 .done = false,248 .done = false,
245249
...@@ -346,6 +350,7 @@ fn updateThreadRun() void {...@@ -346,6 +350,7 @@ fn updateThreadRun() void {
346}350}
347351
348const start_sync = "\x1b[?2026h";352const start_sync = "\x1b[?2026h";
353const up_one_line = "\x1bM";
349const clear = "\x1b[J";354const clear = "\x1b[J";
350const save = "\x1b7";355const save = "\x1b7";
351const restore = "\x1b8";356const restore = "\x1b8";
...@@ -431,22 +436,32 @@ fn computeRedraw() []u8 {...@@ -431,22 +436,32 @@ fn computeRedraw() []u8 {
431 }436 }
432437
433 // The strategy is: keep the cursor at the beginning, and then with every redraw:438 // The strategy is: keep the cursor at the beginning, and then with every redraw:
434 // erase, save, write, restore439 // erase to end of screen, write, move cursor to beginning of line, move cursor up N lines
435440
436 var i: usize = 0;441 var i: usize = 0;
437 const buf = global_progress.draw_buffer;442 const buf = global_progress.draw_buffer;
438443
439 const prefix = start_sync ++ clear ++ save;444 buf[i..][0..start_sync.len].* = start_sync.*;
440 const suffix = restore ++ finish_sync;445 i += start_sync.len;
441446
442 buf[0..prefix.len].* = prefix.*;447 buf[0..clear.len].* = clear.*;
443 i = prefix.len;448 i = clear.len;
444449
445 const root_node_index: Node.Index = @enumFromInt(0);450 const root_node_index: Node.Index = @enumFromInt(0);
446 i = computeNode(buf, i, serialized_node_storage, serialized_node_parents, children, root_node_index);451 i = computeNode(buf, i, serialized_node_storage, serialized_node_parents, children, root_node_index);
447452
448 buf[i..][0..suffix.len].* = suffix.*;453 if (buf[i - 1] == '\n') {
449 i += suffix.len;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
451 return buf[0..i];466 return buf[0..i];
452}467}
...@@ -514,6 +529,7 @@ fn computeNode(...@@ -514,6 +529,7 @@ fn computeNode(
514 i = @min(global_progress.cols + start_i, i);529 i = @min(global_progress.cols + start_i, i);
515 buf[i] = '\n';530 buf[i] = '\n';
516 i += 1;531 i += 1;
532 global_progress.newline_count += 1;
517533
518 if (children[@intFromEnum(node_index)].child.unwrap()) |child| {534 if (children[@intFromEnum(node_index)].child.unwrap()) |child| {
519 i = computeNode(buf, i, serialized_node_storage, serialized_node_parents, children, child);535 i = computeNode(buf, i, serialized_node_storage, serialized_node_parents, children, child);