summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-10-01 02:52:43 -0300
committerGabriel Schneider <[email protected]>2026-10-01 02:52:43 -0300
commit0f5773256072b08a1ec294fa63822f63eb6a429b (patch)
treef1aa96433911abe340cd141fe87a7fde27ed7e8f
parent083167d5b6bc403395f18ddb5e07a2743bb2632f (diff)
downloadpardes-0f5773256072b08a1ec294fa63822f63eb6a429b.tar.gz
pardes-0f5773256072b08a1ec294fa63822f63eb6a429b.zip
addr, dot and limit on a pane with no text, a terminal, an image or a PDF, are refused alike: "this pane has no text to address"
A terminal took an addr write and evaluated it over nothing, saying "bad address syntax" or "address out of range" by the expression, while dot refused it as no text at all. A range file of a pane with no text now refuses every write the same way, before the expression is read. Co-Authored-By: Claude Opus 5.5 <[email protected]>
-rw-r--r--src/ninep/ctl.zig20
-rw-r--r--src/ninep/pane.zig10
2 files changed, 18 insertions, 12 deletions
diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig
index 5d08a77f..42b88b91 100644
--- a/src/ninep/ctl.zig
+++ b/src/ninep/ctl.zig
@@ -3234,19 +3234,23 @@ test "a tag write refuses NUL and the other control characters" {
}
}
-test "a malformed address is bad address syntax, on a terminal as on a text" {
+test "a malformed address is bad address syntax; on a pane with no text any address is refused as nothing to address" {
const p = try th.withTerm(testing.allocator);
defer p.deinit();
const t = try withFile(testing.allocator, "one\n");
defer t.deinit();
- for ([_]*pardes.Pardes{ p, t }) |q| {
- for ([_][]const u8{ "1x", "/(/", ",,x" }) |expr| {
- const refused = wr(q, Node.of(serialOf(q), .addr), expr);
- try testing.expectEqual(E.INVAL, refused.errno());
- try testing.expect(refused.reply.ename.len > 0);
- }
- try testing.expectEqualStrings("bad address syntax", wr(q, Node.of(serialOf(q), .addr), "1x").reply.ename);
+ for ([_][]const u8{ "1x", "/(/", ",,x" }) |expr| {
+ const refused = wr(t, Node.of(serialOf(t), .addr), expr);
+ try testing.expectEqual(E.INVAL, refused.errno());
+ try testing.expect(refused.reply.ename.len > 0);
}
+ try testing.expectEqualStrings("bad address syntax", wr(t, Node.of(serialOf(t), .addr), "1x").reply.ename);
+ // A terminal (as an image or a PDF): addr, dot and limit alike.
+ for ([_]tree.PaneFile{ .addr, .dot, .limit }) |file| for ([_][]const u8{ "1", "1x" }) |expr| {
+ const refused = wr(p, Node.of(serialOf(p), file), expr);
+ try testing.expectEqual(E.INVAL, refused.errno());
+ try testing.expectEqualStrings("this pane has no text to address", refused.reply.ename);
+ };
}
test "a bad event record says what is wrong with it" {
diff --git a/src/ninep/pane.zig b/src/ninep/pane.zig
index 9aada3ee..47fdd755 100644
--- a/src/ninep/pane.zig
+++ b/src/ninep/pane.zig
@@ -819,6 +819,8 @@ fn pairOf(text: []const u8) ?State.Range {
return .{ .q0 = q0, .q1 = q1 };
}
+pub const e_no_text_address = "this pane has no text to address";
+
pub const e_addr_failed = "no address: the last one written to addr failed";
/// A range file takes an address expression, or that pair of offsets. One
@@ -826,6 +828,9 @@ pub const e_addr_failed = "no address: the last one written to addr failed";
/// regexp`, `address out of range`, `bad regular expression`, `addresses
/// out of order`.
fn writeRange(req: Req, pane: *Pane, file: PaneFile) Reply {
+ // A terminal, an image or a PDF has no text an address names: refused
+ // alike for addr, dot and limit, before the expression is read.
+ if (fileOf(pane) == null) return tree.failText(req.tag, E.INVAL, e_no_text_address);
const pf = &pane.fs;
const text = bodyOf(pane);
clampAddr(pf, text.len);
@@ -868,10 +873,7 @@ fn writeRange(req: Req, pane: *Pane, file: PaneFile) Reply {
},
.limit => pf.limit = range,
// Setting dot scrolls to it, which is the whole of acme's `show`.
- .dot => {
- if (fileOf(pane) == null) return tree.failText(req.tag, E.INVAL, e_no_text);
- setDot(pane, range);
- },
+ .dot => setDot(pane, range),
else => unreachable,
}
return .{ .tag = req.tag, .written = @intCast(req.data.len) };