std.Progress: fix suffix printing

Previously, `suffix` was copied to `output_buffer` at position
`max_end`, thereby writing into reserved space after `max_end`.
This only worked because `suffix` was not larger than
`bytes_needed_for_esc_codes_at_end` (otherwise there'd be a potential
buffer overrun) and no escape codes at end are actually written.

Since 2d5b2bf1c986d037ef965bf8c9b4d8dfd5967478, escape codes are no
longer written to the end of the buffer. They are now written
exclusively to the front of the buffer.
This allows removing `bytes_needed_for_esc_codes_at_end` and
simplifying the suffix printing logic.

This also fixes the bug that the ellipse suffix was not printed in
Windows terminals because `end.* > max_end` was never true.
This commit is contained in:
erikarvstedt 2022-02-14 11:14:50 +01:00 committed by GitHub
parent 9ca3c897ec
commit 8ed792b640
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -312,16 +312,10 @@ fn bufWrite(self: *Progress, end: *usize, comptime format: []const u8, args: any
error.NoSpaceLeft => {
self.columns_written += self.output_buffer.len - end.*;
end.* = self.output_buffer.len;
const suffix = "... ";
std.mem.copy(u8, self.output_buffer[self.output_buffer.len - suffix.len ..], suffix);
},
}
const bytes_needed_for_esc_codes_at_end: u8 = if (self.is_windows_terminal) 0 else 11;
const max_end = self.output_buffer.len - bytes_needed_for_esc_codes_at_end;
if (end.* > max_end) {
const suffix = "... ";
self.columns_written = self.columns_written - (end.* - max_end) + suffix.len;
std.mem.copy(u8, self.output_buffer[max_end..], suffix);
end.* = max_end + suffix.len;
}
}
test "basic functionality" {
@ -335,6 +329,8 @@ test "basic functionality" {
const root_node = progress.start("", 100);
defer root_node.end();
const speed_factor = std.time.ns_per_ms;
const sub_task_names = [_][]const u8{
"reticulating splines",
"adjusting shoes",
@ -350,24 +346,24 @@ test "basic functionality" {
next_sub_task = (next_sub_task + 1) % sub_task_names.len;
node.completeOne();
std.time.sleep(5 * std.time.ns_per_ms);
std.time.sleep(5 * speed_factor);
node.completeOne();
node.completeOne();
std.time.sleep(5 * std.time.ns_per_ms);
std.time.sleep(5 * speed_factor);
node.completeOne();
node.completeOne();
std.time.sleep(5 * std.time.ns_per_ms);
std.time.sleep(5 * speed_factor);
node.end();
std.time.sleep(5 * std.time.ns_per_ms);
std.time.sleep(5 * speed_factor);
}
{
var node = root_node.start("this is a really long name designed to activate the truncation code. let's find out if it works", 0);
node.activate();
std.time.sleep(10 * std.time.ns_per_ms);
std.time.sleep(10 * speed_factor);
progress.refresh();
std.time.sleep(10 * std.time.ns_per_ms);
std.time.sleep(10 * speed_factor);
node.end();
}
}