b1c9ad85
main: thread optional ScenarioState through runTerminal
a73x 2026-04-19 13:26
Signature change only — tick_ctx parameter is unused this commit beyond the loopShouldRun guard. Loop guard relaxed via loopShouldRun helper so scenario mode can exit on state.isDone(). Existing entry points pass null — no behavior change for the normal non-scenario path. Stub src/scenario_runtime.zig added so the import resolves; Task 3 replaces it with real TickIO callbacks. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
diff --git a/build.zig b/build.zig index 479c8c1..467df22 100644 --- a/build.zig +++ b/build.zig @@ -391,6 +391,17 @@ pub fn build(b: *std.Build) void { scenario_mod.addImport("png", png_mod); scenario_mod.addImport("imgdiff", imgdiff_lib_mod); // scenario_runtime stub module (Task 3 populates) const scenario_runtime_mod = b.createModule(.{ .root_source_file = b.path("src/scenario_runtime.zig"), .target = target, .optimize = optimize, }); scenario_runtime_mod.addImport("scenario", scenario_mod); exe_mod.addImport("scenario", scenario_mod); exe_mod.addImport("scenario_runtime", scenario_runtime_mod); const scenario_test_mod = b.createModule(.{ .root_source_file = b.path("src/scenario.zig"), .target = target, diff --git a/src/main.zig b/src/main.zig index 687c775..d69c6f0 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,6 +1,8 @@ const std = @import("std"); const vt = @import("vt"); const pty = @import("pty"); const scenario = @import("scenario"); const scenario_runtime = @import("scenario_runtime"); const wayland_client = @import("wayland-client"); const frame_loop_mod = @import("frame_loop"); const renderer = @import("renderer"); @@ -126,6 +128,16 @@ fn writeBenchJson(alloc: std.mem.Allocator, stats: FrameTimingStats, workload: ? try out.writeAll(json_bytes); } fn loopShouldRun(p: *pty.Pty, tick_ctx: ?*scenario_runtime.RunContext) bool { if (tick_ctx) |rc| { // Scenario mode — check state inside RunContext. Task 3 populates this field. if (rc.state) |s| { if (s.isDone()) return false; } } return p.isChildAlive(); } pub fn main() !void { var gpa: std.heap.DebugAllocator(.{}) = .init; defer _ = gpa.deinit(); @@ -167,10 +179,10 @@ pub fn main() !void { return capture.run(alloc, args[1..]); } return runTerminal(alloc); return runTerminal(alloc, null); } fn runTerminal(alloc: std.mem.Allocator) !void { fn runTerminal(alloc: std.mem.Allocator, tick_ctx: ?*scenario_runtime.RunContext) !void { // === font first, to know cell size === var font_lookup = try font.lookupConfiguredFont(alloc); defer font_lookup.deinit(alloc); @@ -341,7 +353,7 @@ fn runTerminal(alloc: std.mem.Allocator) !void { var blink_state: BlinkState = .{}; var previous_has_focus: bool = keyboard.has_focus; while (!window.should_close and p.isChildAlive()) { while (!window.should_close and loopShouldRun(&p, tick_ctx)) { const repeat_timeout_ms = remainingRepeatTimeoutMs(keyboard.nextRepeatDeadlineNs()); const blink_timeout_ms = remainingRepeatTimeoutMs(blink_state.next_deadline_ns); const timeout = computePollTimeoutMs(repeat_timeout_ms, blink_timeout_ms, render_pending); @@ -3527,5 +3539,5 @@ fn runHiddenFreezeRegression(alloc: std.mem.Allocator) !void { var buf: [1]u8 = undefined; _ = try stdin_file.read(&buf); return runTerminal(alloc); return runTerminal(alloc, null); } diff --git a/src/scenario_runtime.zig b/src/scenario_runtime.zig new file mode 100644 index 0000000..18de389 --- /dev/null +++ b/src/scenario_runtime.zig @@ -0,0 +1,5 @@ // src/scenario_runtime.zig (STUB — Task 3 replaces) const scenario = @import("scenario"); pub const RunContext = struct { state: ?*scenario.ScenarioState = null, };