summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-27 22:46:26 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:14 -0300
commit71a9f04342493325c10b1b9bc122a88d41143782 (patch)
treec9b1f27a84404a8332c4066a56d922a031eec194 /src
parentd126715cd20a39dbc10870318968546f5e371b97 (diff)
downloadpardes-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.zig32
-rw-r--r--src/detached/client.zig2
-rw-r--r--src/detached/server.zig7
-rw-r--r--src/dump.zig2
-rw-r--r--src/gui/gui.zig7
-rw-r--r--src/macos.zig11
-rw-r--r--src/pardes.zig5
-rw-r--r--src/tty/tty.zig7
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);