summaryrefslogtreecommitdiff
path: root/src/Pipe.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/Pipe.zig')
-rw-r--r--src/Pipe.zig63
1 files changed, 43 insertions, 20 deletions
diff --git a/src/Pipe.zig b/src/Pipe.zig
index 48e98b7b..6981c023 100644
--- a/src/Pipe.zig
+++ b/src/Pipe.zig
@@ -8,6 +8,7 @@ const panes = @import("panes.zig");
const config = @import("config.zig");
const selection_pipe = @import("selection_pipe.zig");
const edit = @import("edit.zig");
+const edit_cmd = @import("edit_cmd.zig");
const Pane = panes.Pane;
const Text = panes.Text;
const Key = pardes.Key;
@@ -18,6 +19,21 @@ const Pipe = @This();
seq: u32 = 0,
/// The request in flight, and what it needs to apply its answer.
wait: ?PendingPipe = null,
+/// An Edit waiting on its `<`, `|` and `>` commands, which share the ids.
+edit_run: ?*edit_cmd.Pending = null,
+/// What an Edit's `w` took, for the `edit_write` effect to write.
+writes: std.ArrayList(edit_cmd.Write) = .empty,
+
+pub fn deinit(pipe: *Pipe, gpa: std.mem.Allocator) void {
+ if (pipe.wait) |*wait| wait.deinit(gpa);
+ if (pipe.edit_run) |pending| {
+ pending.deinit(gpa);
+ // A 9P write waiting on it is answered (the core is going).
+ pardes.turn.editAnswered();
+ }
+ for (pipe.writes.items) |*w| w.deinit(gpa);
+ pipe.writes.deinit(gpa);
+}
fn nextPipeEffect(p: *Pardes) ?u32 {
while (p.nextEffect()) |effect| switch (effect) {
@@ -164,6 +180,7 @@ pub fn pipeRequest(pipe: *const Pipe, id: u32) ?selection_pipe.Request {
if (pipe.wait) |*wait| {
if (wait.id == id) return wait.request();
}
+ if (pipe.edit_run) |pending| if (pending.id == id) return pending.request;
return null;
}
@@ -172,26 +189,9 @@ fn pipeFailed(p: *Pardes, wait: *const PendingPipe, failure: ?selection_pipe.Fai
defer out.deinit();
const w = &out.writer;
w.print("| {s}\n\n", .{wait.command}) catch return;
- if (failure) |fail| {
- if (wait.inputs.len > 1)
- w.print("selection {d} of {d}: ", .{ fail.index + 1, wait.inputs.len }) catch return;
- switch (fail.kind) {
- .exit => w.print("exit status {d}\n", .{fail.code}) catch return,
- .signal => w.writeAll("killed by a signal\n") catch return,
- .timeout => w.print(
- "still running after {d} seconds, and stopped\n",
- .{selection_pipe.command_timeout_seconds},
- ) catch return,
- .too_large => w.writeAll("produced more output than a filter may return\n") catch return,
- .spawn => w.writeAll("could not be started\n") catch return,
- .io => w.writeAll("could not be read\n") catch return,
- }
- if (fail.stderr.len > 0) w.print("\n{s}", .{fail.stderr}) catch return;
- } else {
- // No diagnosis at all: nobody ran it. The detached daemon, the
- // browser and the board all leave `pipe` null on purpose.
- w.writeAll("this session cannot run filters\n") catch return;
- }
+ if (wait.inputs.len > 1) if (failure) |fail|
+ w.print("selection {d} of {d}: ", .{ fail.index + 1, wait.inputs.len }) catch return;
+ writeFailure(w, failure) catch return;
const content = out.toOwnedSlice() catch return;
const was = p.active;
panes.Output.openErrors(p, wait.pane, content) catch |err| {
@@ -203,6 +203,28 @@ fn pipeFailed(p: *Pardes, wait: *const PendingPipe, failure: ?selection_pipe.Fai
if (p.panes[was] != null) p.active = was;
}
+/// How a filter failed, a line, and the command's stderr after it: what
+/// +Errors says of a `|` and of an Edit's `< | >`.
+pub fn writeFailure(w: *std.Io.Writer, failure: ?selection_pipe.Failure) !void {
+ const fail = failure orelse {
+ // No diagnosis at all: nobody ran it. The detached daemon, the
+ // browser and the board all leave `pipe` null on purpose.
+ return w.writeAll("this session cannot run filters\n");
+ };
+ switch (fail.kind) {
+ .exit => try w.print("exit status {d}\n", .{fail.code}),
+ .signal => try w.writeAll("killed by a signal\n"),
+ .timeout => try w.print(
+ "still running after {d} seconds, and stopped\n",
+ .{selection_pipe.command_timeout_seconds},
+ ),
+ .too_large => try w.writeAll("produced more output than a filter may return\n"),
+ .spawn => try w.writeAll("could not be started\n"),
+ .io => try w.writeAll("could not be read\n"),
+ }
+ if (fail.stderr.len > 0) try w.print("\n{s}", .{fail.stderr});
+}
+
fn pipeCut(wait: *const PendingPipe, content: []const u8, i: usize) ?struct { lo: usize, hi: usize } {
const range = wait.ranges[i];
const lo = @min(range.anchor, range.head);
@@ -240,6 +262,7 @@ pub fn pipeResponse(
outputs: []const []const u8,
failure: ?selection_pipe.Failure,
) void {
+ if (p.pipe.edit_run) |pending| if (pending.id == id) return edit_cmd.finish(p, success, outputs, failure);
// 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;