diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-27 22:46:26 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-10-01 00:12:14 -0300 |
| commit | 71a9f04342493325c10b1b9bc122a88d41143782 (patch) | |
| tree | c9b1f27a84404a8332c4066a56d922a031eec194 /src | |
| parent | d126715cd20a39dbc10870318968546f5e371b97 (diff) | |
| download | pardes-71a9f04342493325c10b1b9bc122a88d41143782.tar.gz pardes-71a9f04342493325c10b1b9bc122a88d41143782.zip | |
Give the pipe its own fields in Pipe
Not a pure move: state moves. Pardes's `pipe_seq` and `pipe_wait` become
Pipe.zig's own fields `seq` and `wait`, and Pardes embeds one as
`pipe: Pipe = .{}`. pipeRequest reads only the request in flight, so it now
takes `pipe: *const Pipe` and the four shells call
`core.pipe.pipeRequest(id)` (their Pipe imports go away again); the other
pipe functions still need the panes and keep `p: *Pardes`, writing
`p.pipe.seq/wait`. Field reads in dump.zig, the shells' tests and two test
files follow (`core.pipe_wait` becomes `core.pipe.wait`). No behaviour
change.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src')
| -rw-r--r-- | src/Pipe.zig | 32 | ||||
| -rw-r--r-- | src/detached/client.zig | 2 | ||||
| -rw-r--r-- | src/detached/server.zig | 7 | ||||
| -rw-r--r-- | src/dump.zig | 2 | ||||
| -rw-r--r-- | src/gui/gui.zig | 7 | ||||
| -rw-r--r-- | src/macos.zig | 11 | ||||
| -rw-r--r-- | src/pardes.zig | 5 | ||||
| -rw-r--r-- | src/tty/tty.zig | 7 |
8 files changed, 37 insertions, 36 deletions
diff --git a/src/Pipe.zig b/src/Pipe.zig index 0fde654a..c01098ff 100644 --- a/src/Pipe.zig +++ b/src/Pipe.zig @@ -11,6 +11,12 @@ const edit = @import("edit.zig"); const Pane = panes.Pane; const Key = pardes.Key; const Pardes = pardes.Pardes; +const Pipe = @This(); + +/// Bumped for every request, so a late answer to an older one is ignored. +seq: u32 = 0, +/// The request in flight, and what it needs to apply its answer. +wait: ?PendingPipe = null, fn nextPipeEffect(p: *Pardes) ?u32 { while (p.nextEffect()) |effect| switch (effect) { @@ -112,10 +118,10 @@ pub fn submitPipe(p: *Pardes, id: usize) void { return; }; - p.pipe_seq +%= 1; - if (p.pipe_wait) |*old| old.deinit(p.gpa); - p.pipe_wait = .{ - .id = p.pipe_seq, + p.pipe.seq +%= 1; + if (p.pipe.wait) |*old| old.deinit(p.gpa); + p.pipe.wait = .{ + .id = p.pipe.seq, .pane = id, .serial = pane.serial, .revision = f.revision, @@ -128,13 +134,13 @@ pub fn submitPipe(p: *Pardes, id: usize) void { .how = prompt.how, .nranges = @intCast(got.n), }; - p.emit(.{ .pipe = .{ .id = p.pipe_seq } }); + p.emit(.{ .pipe = .{ .id = p.pipe.seq } }); } /// Frontends call this while draining a .pipe effect, then immediately /// copy the borrowed view into a worker-owned selection_pipe.Job. -pub fn pipeRequest(p: *const Pardes, id: u32) ?selection_pipe.Request { - if (p.pipe_wait) |*wait| { +pub fn pipeRequest(pipe: *const Pipe, id: u32) ?selection_pipe.Request { + if (pipe.wait) |*wait| { if (wait.id == id) return wait.request(); } return null; @@ -215,9 +221,9 @@ pub fn pipeResponse( ) void { // A SUPERSEDED OR UNKNOWN id is the one silence worth keeping: it is // the answer to a question nobody is still asking. - if (p.pipe_wait == null or p.pipe_wait.?.id != id) return; - var wait = p.pipe_wait.?; - p.pipe_wait = null; + if (p.pipe.wait == null or p.pipe.wait.?.id != id) return; + var wait = p.pipe.wait.?; + p.pipe.wait = null; defer wait.deinit(p.gpa); if (!success or outputs.len != wait.inputs.len) return pipeFailed(p, &wait, failure); @@ -296,7 +302,7 @@ test "selection pipe prompt submits exact request and Escape cancels" { p.update(.{ .key = .{ .cp = Key.enter } }); try std.testing.expect(!pane.tag_edit and pane.prompt != .pipe); const id = nextPipeEffect(p) orelse return error.MissingPipeEffect; - const request = pipeRequest(p, id) orelse return error.MissingPipeRequest; + const request = p.pipe.pipeRequest(id) orelse return error.MissingPipeRequest; try std.testing.expectEqualStrings("tr a-z A-Z", request.command); try std.testing.expectEqualStrings("/", request.cwd); try std.testing.expectEqual(@as(usize, 1), request.inputs.len); @@ -327,7 +333,7 @@ test "selection pipe replaces all ranges atomically and undo restores them" { p.update(.{ .key = .{ .cp = 'c', .text = "cat" } }); p.update(.{ .key = .{ .cp = Key.enter } }); const id = nextPipeEffect(p) orelse return error.MissingPipeEffect; - const request = pipeRequest(p, id) orelse return error.MissingPipeRequest; + const request = p.pipe.pipeRequest(id) orelse return error.MissingPipeRequest; try std.testing.expectEqual(@as(usize, 2), request.inputs.len); try std.testing.expectEqualSlices(u8, "aa", request.inputs[0].bytes); try std.testing.expectEqualSlices(u8, "cc", request.inputs[1].bytes); @@ -399,7 +405,7 @@ test "a command with no stdin runs once and every cursor gets that one answer" { for ("date") |c| p.update(.{ .key = .{ .cp = c, .text = &.{c} } }); p.update(.{ .key = .{ .cp = Key.enter } }); const id = nextPipeEffect(p) orelse return error.MissingPipeEffect; - const request = pipeRequest(p, id) orelse return error.MissingPipeRequest; + const request = p.pipe.pipeRequest(id) orelse return error.MissingPipeRequest; try std.testing.expectEqual(@as(usize, 1), request.inputs.len); try std.testing.expectEqualSlices(u8, "", request.inputs[0].bytes); diff --git a/src/detached/client.zig b/src/detached/client.zig index 7cee790a..6476d521 100644 --- a/src/detached/client.zig +++ b/src/detached/client.zig @@ -884,7 +884,7 @@ test "detached selection pipe runs off the loop and returns through the attached while (try client.next()) |_| {} if (std.mem.eql(u8, pane.file.?.content, "ONE\ntwo\n")) break; } else return error.PipeDidNotComplete; - try testing.expect(h.core.pipe_wait == null); + try testing.expect(h.core.pipe.wait == null); try testing.expectEqual(@as(usize, 0), h.session.pipe_tasks.len); try h.pumpUntilShowsCore(&client); } diff --git a/src/detached/server.zig b/src/detached/server.zig index 9b23f8d6..2b9c9247 100644 --- a/src/detached/server.zig +++ b/src/detached/server.zig @@ -9,7 +9,6 @@ const wire = @import("wire.zig"); const host_io = @import("../host_io.zig"); const selection_pipe = @import("../selection_pipe.zig"); -const Pipe = @import("../Pipe.zig"); const file_watch = @import("../file_watch.zig"); @@ -412,7 +411,7 @@ pub const Session = struct { s.core.update(.{ .pipe_resp = .{ .id = id, .success = false, .outputs = &.{} } }); return; } - const request = Pipe.pipeRequest(s.core, id) orelse return; + const request = s.core.pipe.pipeRequest(id) orelse return; const job = selection_pipe.Job.copy(s.worker_gpa, request) catch |err| { s.core.update(.{ .pipe_resp = .{ .id = id, .success = false, .outputs = &.{} } }); return s.core.reportError(s.core.active, "pipe", err); @@ -1257,9 +1256,9 @@ test "detached worker setup failure completes requests without changing document s.core.update(.{ .key = .{ .cp = '|' } }); s.core.update(.{ .key = .{ .cp = 't', .text = "tr a-z A-Z" } }); s.core.update(.{ .key = .{ .cp = pardes.Key.enter } }); - try std.testing.expect(s.core.pipe_wait != null); + try std.testing.expect(s.core.pipe.wait != null); while (s.core.nextEffect()) |effect| s.core.perform(effect); - try std.testing.expect(s.core.pipe_wait == null); + try std.testing.expect(s.core.pipe.wait == null); try std.testing.expectEqual(@as(usize, 0), s.pipe_tasks.len); try std.testing.expectEqualStrings("one\n", pane.file.?.content); try std.testing.expect(failing.has_induced_failure); diff --git a/src/dump.zig b/src/dump.zig index 0ce2d10e..46cf6001 100644 --- a/src/dump.zig +++ b/src/dump.zig @@ -701,7 +701,7 @@ fn initDump(gpa: std.mem.Allocator, opts: Options, zon_bytes: []const u8, previo if (previous) |old| { p.next_serial = old.next_serial; p.lsp_seq = old.lsp_seq; - p.pipe_seq = old.pipe_seq; + p.pipe.seq = old.pipe.seq; p.cell_pixels = old.cell_pixels; p.row_metrics = old.row_metrics; p.native_images = old.native_images; diff --git a/src/gui/gui.zig b/src/gui/gui.zig index ef94d5b3..a11b22c7 100644 --- a/src/gui/gui.zig +++ b/src/gui/gui.zig @@ -16,7 +16,6 @@ const crt = @import("crt.zig"); const pet = @import("pet.zig"); const fonts = @import("../fonts.zig"); // the Font builtin's half of the seam const selection_pipe = @import("../selection_pipe.zig"); -const Pipe = @import("../Pipe.zig"); const c_heap = @import("c_heap"); const ninep_io = @import("../9p_io.zig"); @@ -1704,7 +1703,7 @@ fn spawnPipe( core.update(.{ .pipe_resp = .{ .id = id, .success = false, .outputs = &.{} } }); return; } - const view = Pipe.pipeRequest(core, id) orelse return; + const view = core.pipe.pipeRequest(id) orelse return; const job = selection_pipe.Job.copy(gpa, view) catch |err| { core.update(.{ .pipe_resp = .{ .id = id, .success = false, .outputs = &.{} } }); return core.reportError(core.active, "pipe", err); @@ -1768,9 +1767,9 @@ test "GUI worker setup failures finish matching LSP and pipe requests" { core.update(.{ .key = .{ .cp = '|' } }); core.update(.{ .key = .{ .cp = 't', .text = "tr a-z A-Z" } }); core.update(.{ .key = .{ .cp = pardes.Key.enter } }); - const pipe_id = core.pipe_wait.?.id; + const pipe_id = core.pipe.wait.?.id; spawnPipe(core, failing_io, failing.allocator(), &queue, &tasks, pipe_id); - try std.testing.expect(core.pipe_wait == null); + try std.testing.expect(core.pipe.wait == null); try std.testing.expectEqualStrings("abc", pane.file.?.content); try std.testing.expectEqual(@as(usize, 0), workers.active.load(.monotonic)); try std.testing.expectEqual(@as(usize, 0), tasks.len); diff --git a/src/macos.zig b/src/macos.zig index dc5b79d0..ccbb5dd5 100644 --- a/src/macos.zig +++ b/src/macos.zig @@ -18,7 +18,6 @@ const host_io = @import("host_io.zig"); const fonts = @import("fonts.zig"); // the shared fallback preference order const tracy = @import("tracy.zig"); // no-op unless -Dtracy names a checkout const selection_pipe = @import("selection_pipe.zig"); // Job, runJob and Tasks -const Pipe = @import("Pipe.zig"); const crash = @import("crash.zig"); pub const panic = std.debug.FullPanic(struct { @@ -344,9 +343,9 @@ test "mac worker setup failures finish matching LSP and pipe requests" { core.update(.{ .key = .{ .cp = '|' } }); core.update(.{ .key = .{ .cp = 't', .text = "tr a-z A-Z" } }); core.update(.{ .key = .{ .cp = pardes.Key.enter } }); - const pipe_id = core.pipe_wait.?.id; + const pipe_id = core.pipe.wait.?.id; pipeRequest(&st, pipe_id); - try std.testing.expect(core.pipe_wait == null); + try std.testing.expect(core.pipe.wait == null); try std.testing.expectEqualStrings("abc", pane.file.?.content); try std.testing.expect(st.lsp_task == null); try std.testing.expectEqual(@as(usize, 0), st.pipe_tasks.len); @@ -1471,7 +1470,7 @@ test "mac Restore keeps host state and rejects callbacks from the old core" { st.core.update(.{ .key = .{ .cp = '|' } }); st.core.update(.{ .key = .{ .cp = 't', .text = "tr a-z A-Z" } }); st.core.update(.{ .key = .{ .cp = pardes.Key.enter } }); - const pipe_id = st.core.pipe_wait.?.id; + const pipe_id = st.core.pipe.wait.?.id; try std.testing.expect(st.pipe_tasks.add(.{ .id = pipe_id, .future = .{ .any_future = null, .result = {} } })); const output = try gpa.dupe(u8, "FRESH"); const outputs = gpa.dupe([]u8, &.{output}) catch |err| { @@ -1480,7 +1479,7 @@ test "mac Restore keeps host state and rejects callbacks from the old core" { }; st.inbox.push(gpa, std.testing.io, .{ .pipe = .{ .id = pipe_id, .success = true, .outputs = outputs } }); try std.testing.expect(drainInbox(&st)); - try std.testing.expect(st.core.pipe_wait == null); + try std.testing.expect(st.core.pipe.wait == null); try std.testing.expectEqual(@as(usize, 0), st.pipe_tasks.len); try std.testing.expectEqualStrings("FRESH body\n", pane.file.?.content); } @@ -2352,7 +2351,7 @@ fn pipeRequest(ctx: ?*anyopaque, id: u32) void { st.core.update(.{ .pipe_resp = .{ .id = id, .success = false, .outputs = &.{} } }); return; } - const view = Pipe.pipeRequest(st.core, id) orelse return; + const view = st.core.pipe.pipeRequest(id) orelse return; const job = selection_pipe.Job.copy(st.gpa, view) catch |err| { st.core.update(.{ .pipe_resp = .{ .id = id, .success = false, .outputs = &.{} } }); return st.core.reportError(st.core.active, "pipe", err); diff --git a/src/pardes.zig b/src/pardes.zig index 00439a36..97860cfe 100644 --- a/src/pardes.zig +++ b/src/pardes.zig @@ -3746,8 +3746,7 @@ pub const Pardes = struct { col: i32 = 0, } = null, - pipe_seq: u32 = 0, - pipe_wait: ?Pipe.PendingPipe = null, + pipe: Pipe = .{}, fs: filesystem.Namespace = .{}, boot: Boot = .shell, @@ -3958,7 +3957,7 @@ pub const Pardes = struct { if (p.last_dump) |d| gpa.free(d); if (p.custom_theme) |theme_value| std.zon.parse.free(gpa, theme_value); if (p.chord_arg) |a| gpa.free(a); - if (p.pipe_wait) |*wait| wait.deinit(gpa); + if (p.pipe.wait) |*wait| wait.deinit(gpa); p.locations_cache.deinit(p.tree_sitter_gpa); p.fs.deinit(gpa); p.shell_rows.reset(gpa); diff --git a/src/tty/tty.zig b/src/tty/tty.zig index 24403ba8..e3378f5b 100644 --- a/src/tty/tty.zig +++ b/src/tty/tty.zig @@ -11,7 +11,6 @@ const look = @import("../look.zig"); const message = pardes.Messages.Message; const file_watch = @import("../file_watch.zig"); const selection_pipe = @import("../selection_pipe.zig"); -const Pipe = @import("../Pipe.zig"); const ninep_io = @import("../9p_io.zig"); const panel_compositor = @import("panel_compositor.zig"); const detached_client = @import("../detached/client.zig"); @@ -1326,7 +1325,7 @@ const Shell = struct { s.core.update(.{ .pipe_resp = .{ .id = id, .success = false, .outputs = &.{} } }); return; } - const view = Pipe.pipeRequest(s.core, id) orelse return; + const view = s.core.pipe.pipeRequest(id) orelse return; const job = selection_pipe.Job.copy(s.gpa, view) catch |err| { s.core.update(.{ .pipe_resp = .{ .id = id, .success = false, .outputs = &.{} } }); return s.core.reportError(s.core.active, "pipe", err); @@ -1424,9 +1423,9 @@ test "TTY worker setup failures finish matching LSP and pipe requests" { core.update(.{ .key = .{ .cp = '|' } }); core.update(.{ .key = .{ .cp = 't', .text = "tr a-z A-Z" } }); core.update(.{ .key = .{ .cp = pardes.Key.enter } }); - const pipe_id = core.pipe_wait.?.id; + const pipe_id = core.pipe.wait.?.id; Shell.pipe(&shell, pipe_id); - try std.testing.expect(core.pipe_wait == null); + try std.testing.expect(core.pipe.wait == null); try std.testing.expectEqualStrings("abc", pane.file.?.content); try std.testing.expect(shell.lsp_task == null); try std.testing.expectEqual(@as(usize, 0), shell.pipe_tasks.len); |
