DoxigAlpha

start

Initializes a global Progress instance.

Asserts there is only one global Progress instance.

Call Node.end when done.

Function parameters

Parameters

#

Type definitions in this namespace

Types

#
Node
Represents one unit of progress.

Initializes a global Progress instance.

Functions

#
start
Initializes a global Progress instance.
lockStdErr
Allows the caller to freely write to stderr until `unlockStdErr` is called.
lockStderrWriter
Allows the caller to freely write to the returned `Writer`,

= switch (builtin.os.tag) { .wasi, .freestanding, .windows => false, else => true, }

Values

#
have_ipc
= switch (builtin.os.tag) { .wasi, .freestanding, .windows => false, else => true, }

Source

Implementation

#
pub fn start(options: Options) Node {
    // Ensure there is only 1 global Progress object.
    if (global_progress.node_end_index != 0) {
        debug_start_trace.dump();
        unreachable;
    }
    debug_start_trace.add("first initialized here");

    @memset(global_progress.node_parents, .unused);
    const root_node = Node.init(@enumFromInt(0), .none, options.root_name, options.estimated_total_items);
    global_progress.done = false;
    global_progress.node_end_index = 1;

    assert(options.draw_buffer.len >= 200);
    global_progress.draw_buffer = options.draw_buffer;
    global_progress.refresh_rate_ns = options.refresh_rate_ns;
    global_progress.initial_delay_ns = options.initial_delay_ns;

    if (noop_impl)
        return Node.none;

    if (std.process.parseEnvVarInt("ZIG_PROGRESS", u31, 10)) |ipc_fd| {
        global_progress.update_thread = std.Thread.spawn(.{}, ipcThreadRun, .{
            @as(posix.fd_t, switch (@typeInfo(posix.fd_t)) {
                .int => ipc_fd,
                .pointer => @ptrFromInt(ipc_fd),
                else => @compileError("unsupported fd_t of " ++ @typeName(posix.fd_t)),
            }),
        }) catch |err| {
            std.log.warn("failed to spawn IPC thread for communicating progress to parent: {s}", .{@errorName(err)});
            return Node.none;
        };
    } else |env_err| switch (env_err) {
        error.EnvironmentVariableNotFound => {
            if (options.disable_printing) {
                return Node.none;
            }
            const stderr: std.fs.File = .stderr();
            global_progress.terminal = stderr;
            if (stderr.getOrEnableAnsiEscapeSupport()) {
                global_progress.terminal_mode = .ansi_escape_codes;
            } else if (is_windows and stderr.isTty()) {
                global_progress.terminal_mode = TerminalMode{ .windows_api = .{
                    .code_page = windows.kernel32.GetConsoleOutputCP(),
                } };
            }

            if (global_progress.terminal_mode == .off) {
                return Node.none;
            }

            if (have_sigwinch) {
                const act: posix.Sigaction = .{
                    .handler = .{ .sigaction = handleSigWinch },
                    .mask = posix.sigemptyset(),
                    .flags = (posix.SA.SIGINFO | posix.SA.RESTART),
                };
                posix.sigaction(posix.SIG.WINCH, &act, null);
            }

            if (switch (global_progress.terminal_mode) {
                .off => unreachable, // handled a few lines above
                .ansi_escape_codes => std.Thread.spawn(.{}, updateThreadRun, .{}),
                .windows_api => if (is_windows) std.Thread.spawn(.{}, windowsApiUpdateThreadRun, .{}) else unreachable,
            }) |thread| {
                global_progress.update_thread = thread;
            } else |err| {
                std.log.warn("unable to spawn thread for printing progress to terminal: {s}", .{@errorName(err)});
                return Node.none;
            }
        },
        else => |e| {
            std.log.warn("invalid ZIG_PROGRESS file descriptor integer: {s}", .{@errorName(e)});
            return Node.none;
        },
    }

    return root_node;
}