feature. See also
. The project being documented here (as the example) is the Zig library itself.
Progress.computeRedraw
fn computeRedraw(io: Io, serialized_buffer: *Serialized.Buffer) !struct
File
Code
fn computeRedraw(io: Io, serialized_buffer: *Serialized.Buffer) !struct { []u8, usize } {
if (global_progress.rows == 0 or global_progress.cols == 0) return error.WindowTooSmall;
const serialized = try serialize(io, serialized_buffer);
// children lists which do not exist in the canonical data. These are
// needed for tree traversal below.
var children_buffer: [node_storage_buffer_len]Children = undefined;
const children = children_buffer[0..serialized.parents.len];
@memset(children, .{ .child = .none, .sibling = .none });
for (serialized.parents, 0..) |parent, child_index_usize| {
const child_index: Node.Index = @fromBackingInt(@intCast(child_index_usize));
assert(parent != .unused);
const parent_index = parent.unwrap() orelse continue;
const children_node = &children[@backingInt(parent_index)];
if (children_node.child.unwrap()) |existing_child_index| {
const existing_child = &children[@backingInt(existing_child_index)];
children[@backingInt(child_index)].sibling = existing_child.sibling;
existing_child.sibling = child_index.toOptional();
} else {
children_node.child = child_index.toOptional();
}
}
// erase to end of screen, write, move cursor to beginning of line, move cursor up N lines
// This keeps the cursor at the beginning so that unlocked stderr writes
// don't get eaten by the clear.
var i: usize = 0;
const buf = global_progress.draw_buffer;
if (global_progress.terminal_mode == .ansi_escape_codes) {
buf[i..][0..start_sync.len].* = start_sync.*;
i += start_sync.len;
}
switch (global_progress.terminal_mode) {
.off => unreachable,
.ansi_escape_codes => {
buf[i..][0..clear.len].* = clear.*;
i += clear.len;
},
.windows_api => {},
}
const root_node_index: Node.Index = @fromBackingInt(@intCast(0));
i, const nl_n = computeNode(buf, i, 0, serialized, children, root_node_index);
if (global_progress.terminal_mode == .ansi_escape_codes) {
{
const root_storage = &serialized.storage[0];
const storage = if (root_storage.name[0] != 0 or children[0].child == .none) root_storage else &serialized.storage[@backingInt(children[0].child)];
const estimated_total = storage.estimated_total_count;
const completed_items = storage.completed_count;
const status = @atomicLoad(Status, &global_progress.status, .monotonic);
switch (status) {
.working => {
if (estimated_total == 0) {
buf[i..][0..progress_pulsing.len].* = progress_pulsing.*;
i += progress_pulsing.len;
} else {
const percent = completed_items * 100 / estimated_total;
if (std.fmt.bufPrint(buf[i..], @"progress_normal {d}", .{percent})) |b| {
i += b.len;
} else |_| {}
}
},
.success => {
buf[i..][0..progress_remove.len].* = progress_remove.*;
i += progress_remove.len;
},
.failure => {
buf[i..][0..progress_error_100.len].* = progress_error_100.*;
i += progress_error_100.len;
},
.failure_working => {
if (estimated_total == 0) {
buf[i..][0..progress_pulsing_error.len].* = progress_pulsing_error.*;
i += progress_pulsing_error.len;
} else {
const percent = completed_items * 100 / estimated_total;
if (std.fmt.bufPrint(buf[i..], @"progress_error {d}", .{percent})) |b| {
i += b.len;
} else |_| {}
}
},
}
}
if (nl_n > 0) {
buf[i] = '\r';
i += 1;
for (0..nl_n) |_| {
buf[i..][0..up_one_line.len].* = up_one_line.*;
i += up_one_line.len;
}
}
buf[i..][0..finish_sync.len].* = finish_sync.*;
i += finish_sync.len;
}
return .{ buf[0..i], nl_n };
}