summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dump.zig9
-rw-r--r--src/main.zig30
-rw-r--r--test/hxdiff.zig6
-rw-r--r--test/snapshot.zig8
-rw-r--r--test/snapshots/logquiet.golden31
-rw-r--r--test/snapshots/logquiet.snap16
6 files changed, 91 insertions, 9 deletions
diff --git a/src/dump.zig b/src/dump.zig
index 06b9cec6..51221197 100644
--- a/src/dump.zig
+++ b/src/dump.zig
@@ -1,6 +1,11 @@
const std = @import("std");
const builtin = @import("builtin");
+// scoped, not bare std.log: main.zig's logFn drops the unscoped .default scope
+// wholesale (ghostty and uucode log there too), and a corrupt dump's parse
+// diagnostic is the only thing that says WHICH field went bad.
+const log = std.log.scoped(.dump);
+
/// Where the next dump goes. $PARDES_DUMP wins verbatim (the snapshot harness
/// pins it for deterministic goldens); else $XDG_DATA_HOME|~/.local/share
/// /pardes/pardes-<utc>.zon — timestamped so dumps never overwrite each other.
@@ -148,7 +153,7 @@ pub fn readZon(gpa: std.mem.Allocator, bytes: []const u8, label: []const u8) !St
pub fn readZonZ(gpa: std.mem.Allocator, source: [:0]const u8, label: []const u8) !State {
if (builtin.os.tag == .emscripten) {
const state = std.zon.parse.fromSliceAlloc(State, gpa, source, null, .{}) catch |err| {
- std.log.err("parse dump {s}: {s}", .{ label, @errorName(err) });
+ log.err("parse dump {s}: {s}", .{ label, @errorName(err) });
return err;
};
errdefer std.zon.parse.free(gpa, state);
@@ -159,7 +164,7 @@ pub fn readZonZ(gpa: std.mem.Allocator, source: [:0]const u8, label: []const u8)
var diag: std.zon.parse.Diagnostics = .{};
defer diag.deinit(gpa);
const state = std.zon.parse.fromSliceAlloc(State, gpa, source, &diag, .{}) catch |err| {
- std.log.err("parse dump {s}: {f}", .{ label, diag });
+ log.err("parse dump {s}: {f}", .{ label, diag });
return err;
};
errdefer std.zon.parse.free(gpa, state);
diff --git a/src/main.zig b/src/main.zig
index 47121691..61c0049e 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -18,13 +18,29 @@ pub const std_options_debug_io: std.Io = if (is_emscripten)
else
std_options_debug_threaded_io.?.io();
-// ghostty-vt's stream logs every mode it doesn't implement, and in the tty
-// shell stderr IS the screen — the warning scribbles over the grid. macOS
-// bash/readline sends one such mode (1034, meta-key) on every startup, so
-// keep the stream scope to errors; linux shells just never tripped it.
-pub const std_options: std.Options = .{
- .log_scope_levels = &.{.{ .scope = .stream, .level = .err }},
-};
+// Every std.log call in the process — ours and every dependency's — funnels
+// through this one function. ghostty-vt narrates whatever it does not
+// implement in the bytes a child writes to its pty (`debug(stream)`,
+// `warning(stream): ignoring unimplemented CSI p`, `debug(kitty_gfx)`; opening
+// yazi is worth several lines before it has drawn anything), and in the tty
+// shell stderr IS the screen — those land on top of the rendered grid, and in
+// the gui/web shells on the console. So drop the libraries at every level: an
+// `err` painted over the UI is no better than a debug one. Only pardes' own
+// scopes get through, because their messages carry detail the error returns
+// don't (gui's SDL_GetError strings, dump's zon parse diagnostic) — .default
+// is NOT one of them, ghostty and uucode both log unscoped. Set PARDES_LOG to
+// get the real logger back: `PARDES_LOG=1 pardes 2>/tmp/pardes.log`.
+pub const std_options: std.Options = .{ .logFn = logFn };
+
+fn logFn(
+ comptime level: std.log.Level,
+ comptime scope: @EnumLiteral(),
+ comptime format: []const u8,
+ args: anytype,
+) void {
+ if (scope != .gui and scope != .dump and std.c.getenv("PARDES_LOG") == null) return;
+ std.log.defaultLog(level, scope, format, args);
+}
// A panic must restore the terminal (cooked mode, main screen, mouse off)
// before the trace prints, or it lands garbled in a raw alt screen. recover()
diff --git a/test/hxdiff.zig b/test/hxdiff.zig
index dc901263..b04cc0b5 100644
--- a/test/hxdiff.zig
+++ b/test/hxdiff.zig
@@ -49,6 +49,12 @@ const std = @import("std");
const libc = std.c;
const pardes = @import("pardes");
+// Its own root, so src/main.zig's logFn does not apply here: the core it
+// drives feeds every case's text through ghostty-vt, which narrates each
+// sequence it does not implement. Cut the libraries back to errors; the
+// per-case report goes through std.debug, so a mismatch stays loud.
+pub const std_options: std.Options = .{ .log_level = .err };
+
const gpa = std.heap.page_allocator;
pub fn main(init: std.process.Init) !void {
diff --git a/test/snapshot.zig b/test/snapshot.zig
index 54ba0271..5417530d 100644
--- a/test/snapshot.zig
+++ b/test/snapshot.zig
@@ -32,6 +32,14 @@ const libc = std.c;
const ghostty_vt = @import("ghostty-vt");
const eh = @import("e2e_harness.zig");
+// This harness parses the app's output with its OWN ghostty-vt, which narrates
+// every sequence it does not implement — vaxis's startup capability probes
+// alone cost four `debug(stream)`/`warning(stream)`/`debug(kitty_gfx)` lines
+// per script, burying the PASS/FAIL report under 200 lines of chatter. Cut the
+// libraries back to errors; the report itself goes through std.debug, so a
+// failure stays loud either way.
+pub const std_options: std.Options = .{ .log_level = .err };
+
extern "c" fn setenv(name: [*:0]const u8, value: [*:0]const u8, overwrite: c_int) c_int;
extern "c" fn execvp(file: [*:0]const u8, argv: [*:null]const ?[*:0]const u8) c_int;
diff --git a/test/snapshots/logquiet.golden b/test/snapshots/logquiet.golden
new file mode 100644
index 00000000..86b1567a
--- /dev/null
+++ b/test/snapshots/logquiet.golden
@@ -0,0 +1,31 @@
+== snap quiet grid=100x30 cursor=62,4
+|Kill Newcol Tutor Debug Colors NextColor Crt Dump
+| TTY /tmp/pardes-snap/logquiet/cwd Del
+| $ ls
+| $ printf '\033_Ga=q,i=1,s=1,v=1,f=24,t=d;AAAA\033\\\033[>0p'
+| $ '\033_Ga=q,i=1,s=1,v=1,f=24,t=d;AAAA\033\\\033[>0p'Gi=1;OK
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
+|
diff --git a/test/snapshots/logquiet.snap b/test/snapshots/logquiet.snap
new file mode 100644
index 00000000..02d52495
--- /dev/null
+++ b/test/snapshots/logquiet.snap
@@ -0,0 +1,16 @@
+# ghostty-vt narrates every sequence it does not implement through std.log,
+# and a pardes child's stderr is this pty — so a library log line lands on the
+# rendered grid, exactly where it does on a real user's terminal. The two
+# sequences below are the cheapest ones that trip it: a kitty graphics query
+# (`debug(kitty_gfx): executing kitty graphics command`) and a private CSI p
+# (`warning(stream): ignoring unimplemented CSI p with intermediates: >`).
+# The golden is the assertion that neither reaches the screen.
+start 30 100 -n 1
+wait 8000 Kill Newcol
+stable 700 20000
+key c-b
+stable 600 8000
+text printf '\033_Ga=q,i=1,s=1,v=1,f=24,t=d;AAAA\033\\\033[>0p'
+key enter
+stable 700 20000
+snap quiet