diff --git a/packages/native/src/lib.zig b/packages/native/src/lib.zig index f6987cd1e..3ec9bc5ca 100644 --- a/packages/native/src/lib.zig +++ b/packages/native/src/lib.zig @@ -4,19 +4,58 @@ const build_options = @import("build_options"); const Allocator = std.mem.Allocator; pub const std_options: std.Options = .{ - .logFn = discardStdLog, + .log_level = .debug, + .logFn = handleStdLog, }; -fn discardStdLog( +fn handleStdLog( comptime message_level: std.log.Level, comptime scope: @EnumLiteral(), comptime format: []const u8, args: anytype, ) void { - _ = message_level; - _ = scope; - _ = format; - _ = args; + const ghostty_scope = switch (scope) { + .parser, + .stream, + .stream_terminal, + .screen, + .terminal, + .terminal_mem, + .terminal_apc, + .terminal_dcs, + .osc, + .osc_color, + .osc_iterm2, + .kitty_gfx, + .key_encode, + .mouse_encode, + .render_state_c, + => true, + else => false, + }; + if (!ghostty_scope) return; + const configured = ghosttyLogLevel() orelse return; + if (@intFromEnum(message_level) > @intFromEnum(configured)) return; + + const level: logger.LogLevel = switch (message_level) { + .err => .err, + .warn => .warn, + .info => .info, + .debug => .debug, + }; + logger.logMessage(level, "(" ++ @tagName(scope) ++ ") " ++ format, args); +} + +fn ghosttyLogLevel() ?std.log.Level { + const Environment = struct { + extern "c" fn getenv(name: [*:0]const u8) ?[*:0]const u8; + }; + const value = std.mem.span(Environment.getenv("OTUI_GHOSTTY_LOG_LEVEL") orelse return null); + if (std.ascii.eqlIgnoreCase(value, "error") or std.ascii.eqlIgnoreCase(value, "err")) return .err; + if (std.ascii.eqlIgnoreCase(value, "warning") or std.ascii.eqlIgnoreCase(value, "warn")) return .warn; + if (std.ascii.eqlIgnoreCase(value, "info")) return .info; + if (std.ascii.eqlIgnoreCase(value, "debug")) return .debug; + return null; } var io_threaded: std.Io.Threaded = .init_single_threaded; diff --git a/packages/web/src/content/docs/reference/env-vars.mdx b/packages/web/src/content/docs/reference/env-vars.mdx index 6e72e95dc..c983f0352 100644 --- a/packages/web/src/content/docs/reference/env-vars.mdx +++ b/packages/web/src/content/docs/reference/env-vars.mdx @@ -112,16 +112,21 @@ Tree-sitter worker started. An explicit client `workerPath` option takes precede ## Security-sensitive diagnostics -| Variable | Type | Default | Read time | Purpose | -| ---------------- | --------- | ------- | ----------------- | ----------------------------------------- | -| `OTUI_DEBUG` | `boolean` | `false` | Renderer creation | Retain raw input sequences for debugging | -| `OTUI_STDIN_LOG` | `string` | `""` | Renderer creation | Write the raw stdin byte stream to a file | +| Variable | Type | Default | Read time | Purpose | +| ------------------------ | --------- | ------- | --------------------- | ------------------------------------------------------------- | +| `OTUI_DEBUG` | `boolean` | `false` | Renderer creation | Retain raw input sequences for debugging | +| `OTUI_STDIN_LOG` | `string` | `""` | Renderer creation | Write the raw stdin byte stream to a file | +| `OTUI_GHOSTTY_LOG_LEVEL` | `string` | `""` | Native initialization | Forward scoped Ghostty logs through the normal OpenTUI logger | `OTUI_STDIN_LOG=/tmp/opentui-stdin.bin` records stdin before parsing. The renderer truncates the file when it starts and writes to it synchronously. The binary data can contain passwords and other sensitive input. Use this option only for short debugging sessions, and protect the recorded file. Treat `OTUI_DEBUG` input captures and `OTUI_DUMP_CAPTURES` output as sensitive data too. +`OTUI_GHOSTTY_LOG_LEVEL` accepts `error`, `warn`, `info`, or `debug` (`err` and `warning` are aliases). The selected level +includes all more severe messages. Unset or invalid values disable Ghostty logs. Standard-library logs outside the +recognized Ghostty scopes are always discarded. + ## Remote sessions A renderer with `remote: true` forwards no local environment keys to native terminal detection by default. Add only