diff options
Diffstat (limited to 'src/ninep/pane.zig')
| -rw-r--r-- | src/ninep/pane.zig | 29 |
1 files changed, 25 insertions, 4 deletions
diff --git a/src/ninep/pane.zig b/src/ninep/pane.zig index 852a9ec0..9aada3ee 100644 --- a/src/ninep/pane.zig +++ b/src/ninep/pane.zig @@ -48,6 +48,11 @@ pub const State = struct { /// follows sets it or, refused, leaves it as it was; with none, the /// open's release empties it (tree.zig releaseHandle). dot_truncated: bool = false, + /// The open whose writes to `sel` are being kept together (0: none) and + /// the text they have made so far: the next write of that open goes at + /// its end, as acme's wrselrange does. + wrsel_by: u32 = 0, + wrsel: Range = .{}, /// Opens of `event`, which hold the pane scripted. readers: u16 = 0, /// One of `readers` reads `event`; a second reading open is refused. @@ -787,12 +792,20 @@ fn writeData(p: *Pardes, req: Req, pane: *Pane) Reply { fn writeSel(p: *Pardes, req: Req, pane: *Pane) Reply { if (fileOf(pane) == null) return tree.failText(req.tag, E.INVAL, e_no_text); - const d = dotOf(pane); + const pf = &pane.fs; + // The same open's next write follows its last; any other replaces dot. + const going_on = req.handle != 0 and pf.wrsel_by == req.handle; + const d = if (going_on) State.Range{ .q0 = pf.wrsel.q1, .q1 = pf.wrsel.q1 } else dotOf(pane); const q0: usize = d.q0; const q1: usize = @max(q0, @as(usize, d.q1)); const take = spliceBody(p, pane, q0, q1, req.data) orelse return Reply.fail(req.tag, E.NOMEM); - setDot(pane, .{ .q0 = clip(q0 + take), .q1 = clip(q0 + take) }); + // What was written is selected, as acme's wrsel leaves it: `cat sel` + // reads it back. + const start = if (going_on) pf.wrsel.q0 else clip(q0); + pf.wrsel = .{ .q0 = start, .q1 = clip(q0 + take) }; + pf.wrsel_by = req.handle; + setDot(pane, pf.wrsel); return .{ .tag = req.tag, .written = @intCast(take) }; } @@ -1265,9 +1278,17 @@ test "sel reads the selection and writing sel replaces it" { try testing.expectEqual(Status.ok, wr(p, sel, "ONE").reply.status); try testing.expectEqualStrings("ONE\ntwo\n", p.panes[0].?.file.?.content); + // What was written is selected, as acme's wrsel leaves it. + try testing.expectEqualStrings("ONE", rd(p, sel, 0, 100).bytes); + // A write of another open replaces it; one open's writes run on. _ = wr(p, sel, "!"); - try testing.expectEqualStrings("ONE!\ntwo\n", p.panes[0].?.file.?.content); - try testing.expectEqual(@as(u64, 0), call(p, .{ .tag = 2, .op = .getattr, .node = sel }).reply.attr.size); + try testing.expectEqualStrings("!\ntwo\n", p.panes[0].?.file.?.content); + const hs = call(p, .{ .tag = 3, .op = .open, .node = sel, .omode = 1 }).reply.handle; + _ = call(p, .{ .tag = 4, .op = .write, .node = sel, .handle = hs, .data = "a" }); + _ = call(p, .{ .tag = 5, .op = .write, .node = sel, .handle = hs, .data = "b" }); + _ = call(p, .{ .tag = 6, .op = .release, .node = sel, .handle = hs, .opened = true }); + try testing.expectEqualStrings("ab\ntwo\n", p.panes[0].?.file.?.content); + try testing.expectEqualStrings("ab", rd(p, sel, 0, 100).bytes); } test "the flag files read and write the state acme kept behind ctl verbs" { |
