std: rework TTY detection and printing

This commit sketches an idea for how to deal with detection of file
streams as being terminals.

When a File stream is a terminal, writes through the stream should have
their escapes stripped unless the programmer explicitly enables terminal
escapes. Furthermore, the programmer needs a convenient API for
intentionally outputting escapes into the stream. In particular it
should be possible to set colors that are silently discarded when the
stream is not a terminal.

This commit makes `Io.File.Writer` track the terminal mode in the
already-existing `mode` field, making it the appropriate place to
implement escape stripping.

`Io.lockStderrWriter` returns a `*Io.File.Writer` with terminal
detection already done by default. This is a higher-level application
layer stream for writing to stderr.

Meanwhile, `std.debug.lockStderrWriter` also returns a `*Io.File.Writer`
but a lower-level one that is hard-coded to use a static single-threaded
`std.Io.Threaded` instance. This is the same instance that is used for
collecting debug information and iterating the unwind info.
This commit is contained in:
Andrew Kelley 2025-12-09 22:10:12 -08:00
parent 78d262d96e
commit ffcbd48a12
10 changed files with 448 additions and 400 deletions

View file

@ -439,25 +439,25 @@ pub fn getEnvVarOwned(allocator: Allocator, key: []const u8) GetEnvVarOwnedError
}
/// On Windows, `key` must be valid WTF-8.
pub fn hasEnvVarConstant(comptime key: []const u8) bool {
pub inline fn hasEnvVarConstant(comptime key: []const u8) bool {
if (native_os == .windows) {
const key_w = comptime unicode.wtf8ToWtf16LeStringLiteral(key);
return getenvW(key_w) != null;
} else if (native_os == .wasi and !builtin.link_libc) {
@compileError("hasEnvVarConstant is not supported for WASI without libc");
return false;
} else {
return posix.getenv(key) != null;
}
}
/// On Windows, `key` must be valid WTF-8.
pub fn hasNonEmptyEnvVarConstant(comptime key: []const u8) bool {
pub inline fn hasNonEmptyEnvVarConstant(comptime key: []const u8) bool {
if (native_os == .windows) {
const key_w = comptime unicode.wtf8ToWtf16LeStringLiteral(key);
const value = getenvW(key_w) orelse return false;
return value.len != 0;
} else if (native_os == .wasi and !builtin.link_libc) {
@compileError("hasNonEmptyEnvVarConstant is not supported for WASI without libc");
return false;
} else {
const value = posix.getenv(key) orelse return false;
return value.len != 0;