DoxigAlpha

clearWrittenWindowsApi

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

#
fn clearWrittenWindowsApi() error{Unexpected}!void {
    // This uses a 'marker' strategy. The idea is:
    // - Always write a marker (in this case U+25BA or ►) at the beginning of the progress
    // - Get the current cursor position (at the end of the progress)
    // - Subtract the number of lines written to get the expected start of the progress
    // - Check to see if the first character at the start of the progress is the marker
    // - If it's not the marker, keep checking the line before until we find it
    // - Clear the screen from that position down, and set the cursor position to the start
    //
    // This strategy works even if there is line wrapping, and can handle the window
    // being resized/scrolled arbitrarily.
    //
    // Notes:
    // - Ideally, the marker would be a zero-width character, but the Windows console
    //   doesn't seem to support rendering zero-width characters (they show up as a space)
    // - This same marker idea could technically be done with an attribute instead
    //   (https://learn.microsoft.com/en-us/windows/console/console-screen-buffers#character-attributes)
    //   but it must be a valid attribute and it actually needs to apply to the first
    //   character in order to be readable via ReadConsoleOutputAttribute. It doesn't seem
    //   like any of the available attributes are invisible/benign.
    if (!global_progress.need_clear) return;
    const handle = global_progress.terminal.handle;
    const screen_area = @as(windows.DWORD, global_progress.cols) * global_progress.rows;

    var console_info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined;
    if (windows.kernel32.GetConsoleScreenBufferInfo(handle, &console_info) == 0) {
        return error.Unexpected;
    }
    var num_chars_written: windows.DWORD = undefined;
    if (windows.kernel32.FillConsoleOutputCharacterW(handle, ' ', screen_area, console_info.dwCursorPosition, &num_chars_written) == 0) {
        return error.Unexpected;
    }
}