summaryrefslogtreecommitdiff
path: root/src/ninep
diff options
context:
space:
mode:
Diffstat (limited to 'src/ninep')
-rw-r--r--src/ninep/ctl.zig34
1 files changed, 34 insertions, 0 deletions
diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig
index e4e983a8..8b73e8f7 100644
--- a/src/ninep/ctl.zig
+++ b/src/ninep/ctl.zig
@@ -76,6 +76,9 @@ fn run(p: *Pardes, id: usize, exec: bool, text: []const u8) void {
const after = Serials.snapshot(p);
var created = false;
for (after.list[0..after.len]) |serial| if (std.mem.indexOfScalar(u32, before.list[0..before.len], serial) == null) {
+ // A look's hits buffer is how it found the text, not where: it
+ // answers the pane the hit is selected in.
+ if (!exec) if (p.paneBySerial(serial)) |made| if (p.panes[made].?.file) |f| if (f.output) |o| if (o.from == .search) continue;
noteResult(p, serial);
created = true;
};
@@ -739,6 +742,37 @@ test "a second lock is refused until the holder unlocks or closes, and binds nob
for (p.fs.opens) |o| try testing.expect(o.node == 0);
}
+test "a look takes acme's :addr and file:addr, and a miss changes nothing" {
+ const gpa = testing.allocator;
+ const p = try withFile(gpa, "foo x foo y\nbar\n");
+ defer p.deinit();
+ const serial = serialOf(p);
+ const look_node = Node.of(serial, .look);
+ const dot = Node.of(serial, .dot);
+ // :addr is an address in this pane, evaluated from its dot.
+ try testing.expectEqual(Status.ok, wr(p, look_node, ":/y/\n").reply.status);
+ try testing.expectEqualStrings(" 10 11 ", rd(p, dot, 0, 64).bytes);
+ try testing.expectEqual(Status.ok, wr(p, look_node, ":#4\n").reply.status);
+ try testing.expectEqualStrings(" 4 4 ", rd(p, dot, 0, 64).bytes);
+ try testing.expectEqual(Status.ok, wr(p, look_node, ":/foo/\n").reply.status); // from #4: the second foo
+ try testing.expectEqualStrings(" 6 9 ", rd(p, dot, 0, 64).bytes);
+ // file:addr names the pane's own file here.
+ var line: [256]u8 = undefined;
+ const path = p.panes[0].?.file.?.path;
+ try testing.expectEqual(Status.ok, wr(p, look_node, try std.fmt.bufPrint(&line, "{s}:/bar/\n", .{path})).reply.status);
+ try testing.expectEqualStrings(" 12 15 ", rd(p, dot, 0, 64).bytes);
+ // A miss: no buffer, the selection kept, and it says so.
+ const panes_before = p.panes.len - std.mem.count(?*pardes.Pane, &p.panes, &.{null});
+ try testing.expectEqual(Status.ok, wr(p, look_node, "zzqq\n").reply.status);
+ try testing.expectEqual(panes_before, p.panes.len - std.mem.count(?*pardes.Pane, &p.panes, &.{null}));
+ try testing.expectEqualStrings(" 12 15 ", rd(p, dot, 0, 64).bytes);
+ try testing.expectStringStartsWith(p.panes[0].?.msg[0..p.panes[0].?.msg_len], "Look: no match");
+ // A hit answers the pane the text is selected in, not its hits buffer.
+ try testing.expectEqual(Status.ok, wr(p, look_node, "foo\n").reply.status);
+ var own: [16]u8 = undefined;
+ try testing.expectEqualStrings(try std.fmt.bufPrint(&own, "{d}\n", .{serial}), rd(p, look_node, 0, 64).bytes);
+}
+
test "exec runs a builtin at the pane and records the pane it acted on" {
const gpa = testing.allocator;
const p = try withFile(gpa, "Msg fs-ran\n");