summaryrefslogtreecommitdiff
path: root/src/Pipe.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-27 23:42:53 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:14 -0300
commit9584b0682b45f17aaa42157540947904d867777a (patch)
treefaac80b84c02e9611e9df9ff0e210c1d1c895a84 /src/Pipe.zig
parent95a3a1bb822e583988bfe0f312d0ef219b27a454 (diff)
downloadpardes-9584b0682b45f17aaa42157540947904d867777a.tar.gz
pardes-9584b0682b45f17aaa42157540947904d867777a.zip
Give prompts their own line to type into instead of the tag's tail
A search, pipe or Save prompt wrote its marker and answer onto the end of the tag, so the tag's cursor, its selection, its 9P writes and a prompt abandoned by a click all shared one buffer: the abandoned text stayed in the tag and a 9P write landed inside the prompt. The answer is now its own Text on the pane, typed in insert mode and shown on the notice band where it was already drawn, and the tag never holds any of it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/Pipe.zig')
-rw-r--r--src/Pipe.zig19
1 files changed, 9 insertions, 10 deletions
diff --git a/src/Pipe.zig b/src/Pipe.zig
index c2b49f31..3e6752a8 100644
--- a/src/Pipe.zig
+++ b/src/Pipe.zig
@@ -73,13 +73,12 @@ pub fn submitPipe(p: *Pardes, id: usize) void {
const pane = p.panes[id] orelse return;
const f = pane.file orelse return;
if (!panes.Output.fileTraits(f.output).saves) return;
- const prompt = switch (pane.prompt) {
+ const how = switch (pane.prompt) {
.pipe => |pipe| pipe,
else => return,
};
- const tail = pane.tagSlice();
- const armed = tail[@min(prompt.at, tail.len)..];
- const marker = pipeMarker(prompt.how);
+ const armed = pane.promptText() orelse return;
+ const marker = pipeMarker(how);
if (!std.mem.startsWith(u8, armed, marker)) return;
const command = armed[marker.len..];
if (command.len == 0) return;
@@ -87,11 +86,11 @@ pub fn submitPipe(p: *Pardes, id: usize) void {
var ranges: [panes.Text.max_selections]modal.Selection = undefined;
const got = pane.body.ranges(f.content, 0, &ranges);
// `!`/`A-!` take no stdin and run ONCE — see `PendingPipe.nranges`.
- const ninputs = if (prompt.how.pipes()) got.n else 1;
+ const ninputs = if (how.pipes()) got.n else 1;
const inputs = p.gpa.alloc(selection_pipe.Input, ninputs) catch return;
var made: usize = 0;
for (ranges[0..ninputs], 0..) |range, i| {
- const bytes = if (prompt.how.pipes()) bytes: {
+ const bytes = if (how.pipes()) bytes: {
const lo = @min(range.anchor, range.head);
const hi = @max(range.anchor, range.head);
if (hi > f.content.len) break;
@@ -131,7 +130,7 @@ pub fn submitPipe(p: *Pardes, id: usize) void {
.ranges = ranges,
.primary = @intCast(got.pri),
.explicit = (pane.body.vsel.active and pane.body.vsel.explicit) or pane.body.msel.active,
- .how = prompt.how,
+ .how = how,
.nranges = @intCast(got.n),
};
p.emit(.{ .pipe = .{ .id = p.pipe.seq } });
@@ -295,12 +294,12 @@ test "selection pipe prompt submits exact request and Escape cancels" {
pane.body.vsel = .{ .active = true, .row = 0, .col = 0, .explicit = true };
p.update(.{ .key = .{ .cp = '|' } });
- try std.testing.expect(pane.tag_edit and pane.prompt == .pipe);
- try std.testing.expect(std.mem.endsWith(u8, pane.tagSlice(), config.pipe_marker));
+ try std.testing.expect(!pane.tag_edit and pane.prompt == .pipe);
+ try std.testing.expectEqualStrings(config.pipe_marker, pane.promptText().?);
try std.testing.expect(nextPipeEffect(p) == null);
p.update(.{ .key = .{ .cp = 't', .text = "tr a-z A-Z" } });
p.update(.{ .key = .{ .cp = Key.enter } });
- try std.testing.expect(!pane.tag_edit and pane.prompt != .pipe);
+ try std.testing.expect(!pane.tag_edit and pane.prompt != .pipe and pane.input.own == null);
const id = nextPipeEffect(p) orelse return error.MissingPipeEffect;
const request = p.pipe.pipeRequest(id) orelse return error.MissingPipeRequest;
try std.testing.expectEqualStrings("tr a-z A-Z", request.command);