summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/fs.md4
-rw-r--r--src/ninep/pane.zig16
2 files changed, 19 insertions, 1 deletions
diff --git a/docs/fs.md b/docs/fs.md
index fdcbdaf0..700ec97b 100644
--- a/docs/fs.md
+++ b/docs/fs.md
@@ -740,7 +740,9 @@ address at all, where acme
keeps the old one: until a good address is written, `addr` reads empty
(as an unset `limit` does), and reading, writing or truncating `data` and
`xdata` fail with `no address: the last one written to addr failed`, so a script that
-missed its target cannot then write at the last one.
+missed its target cannot then write at the last one; so does an address
+written to `addr` that goes from the current one (`.`, `+1`, `-/re/`), which
+there is none of, until an address that stands alone (`2`, `#0`, `/re/`) is.
The three flag files `dirty`, `mark` and `scroll` read `0` or `1` and take
`0` or `1`: whether the buffer differs from its file, whether a write pushes
diff --git a/src/ninep/pane.zig b/src/ninep/pane.zig
index 311a2429..f90a83d8 100644
--- a/src/ninep/pane.zig
+++ b/src/ninep/pane.zig
@@ -584,6 +584,10 @@ fn writeRange(req: Req, pane: *Pane, file: PaneFile) Reply {
const text = bodyOf(pane);
clampAddr(pf, text.len);
const expr = std.mem.trimEnd(u8, req.data, "\n");
+ // One that goes from the address (`.`, `+`, `-`) has none to go from
+ // after a failed one: said, rather than going from the one before it.
+ if (file == .addr and pf.addr_failed and expr.len > 0 and std.mem.indexOfScalar(u8, ".+-", expr[0]) != null)
+ return tree.failText(req.tag, E.INVAL, e_addr_failed);
var a: addressing.Addr = .{ .text = text, .lim = pf.limit, .expr = expr };
var r = if (pairOf(expr)) |pair|
State.Range{ .q0 = @min(pair.q0, clip(text.len)), .q1 = @min(pair.q1, clip(text.len)) }
@@ -1107,6 +1111,18 @@ test "two opens writing one body are two undo steps, however their writes interl
_ = call(p, .{ .tag = 3, .op = .release, .node = body, .handle = b, .opened = true });
}
+test "after a failed address, one that goes from it says there is none" {
+ const p = try withFile(testing.allocator, "one\ntwo\n");
+ defer p.deinit();
+ const addr = Node.of(serialOf(p), .addr);
+ try testing.expectEqual(Status.err, wr(p, addr, "/nomatch/").reply.status);
+ try testing.expectEqualStrings(e_addr_failed, wr(p, addr, ".+1").reply.ename);
+ try testing.expectEqualStrings(e_addr_failed, wr(p, addr, "+1").reply.ename);
+ // An absolute one sets it again, and then `.` works.
+ try testing.expectEqual(Status.ok, wr(p, addr, "2").reply.status);
+ try testing.expectEqual(Status.ok, wr(p, addr, ".").reply.status);
+}
+
test "a name cut across writes is one name, applied once at its newline or its close" {
const p = try withFile(testing.allocator, "x\n");
defer p.deinit();