diff options
Diffstat (limited to 'src/ninep/pane.zig')
| -rw-r--r-- | src/ninep/pane.zig | 34 |
1 files changed, 29 insertions, 5 deletions
diff --git a/src/ninep/pane.zig b/src/ninep/pane.zig index 0a511118..d2b2a791 100644 --- a/src/ninep/pane.zig +++ b/src/ninep/pane.zig @@ -194,6 +194,20 @@ pub fn spliceBody(p: *Pardes, pane: *Pane, q0: usize, q1: usize, bytes: []const return take; } +test "a terminal's body stats as long as it reads" { + const gpa = testing.allocator; + const p = try pardes.Pardes.init(gpa, .{ .tty_only = true, .cols = 80, .rows = 24 }); + defer p.deinit(); + while (p.nextEffect()) |_| {} + const pane = p.panes[0].?; + try testing.expect(pane.isTerminal()); + p.update(.{ .output = .{ .pane = 0, .bytes = "$ ls\r\nalpha beta\r\n$ " } }); + const body = Node.of(pane.serial, .body); + const whole = rd(p, body, 0, 1 << 16); + try testing.expect(whole.bytes.len > 0); + try testing.expectEqual(@as(u64, whole.bytes.len), call(p, .{ .tag = 1, .op = .getattr, .node = body }).reply.attr.size); +} + // ---- what stat reports ---- /// A range file's text: acme's addr format, two right-aligned offsets, so @@ -204,7 +218,9 @@ pub fn fileSize(p: *Pardes, id: usize, f: PaneFile) u64 { const pane = p.panes[id] orelse return 0; const pf = &pane.fs; return switch (f) { - .body, .data, .xdata => bodyOf(pane).len, + // A terminal's body reads its screen and history, as text. + .body => if (pane.file == null and pane.isTerminal()) panes.Terminal.screenTextLen(pane) else bodyOf(pane).len, + .data, .xdata => bodyOf(pane).len, .tag => tagOf(p, pane).len, .name => nameOf(pane).len + 1, .ctl => ctl: { @@ -453,16 +469,22 @@ 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 /// that does not evaluate says why: `bad address syntax`, `no match for -/// regexp`, `address out of range`, `bad regular expression`. +/// regexp`, `address out of range`, `bad regular expression`, `addresses +/// out of order`. fn writeRange(req: Req, pane: *Pane, file: PaneFile) Reply { const pf = &pane.fs; const text = bodyOf(pane); clampAddr(pf, text.len); const expr = std.mem.trimEnd(u8, req.data, "\n"); var a: addressing.Addr = .{ .text = text, .lim = pf.limit, .expr = expr }; - const r = if (pairOf(expr)) |pair| + var r = if (pairOf(expr)) |pair| State.Range{ .q0 = @min(pair.q0, clip(text.len)), .q1 = @min(pair.q1, clip(text.len)) } else if (a.address(pf.addr)) |found| (if (a.i < expr.len) null else found) else null; + // sam's check, which acme leaves out: `#100,#50` names no range. + if (r) |found| if (found.q0 > found.q1) { + a.err = addressing.e_order; + r = null; + }; const range = r orelse { if (file == .addr) pf.addr_failed = true; return tree.failText(req.tag, E.INVAL, a.err); @@ -485,7 +507,7 @@ fn writeRange(req: Req, pane: *Pane, file: PaneFile) Reply { fn writeFlag(p: *Pardes, req: Req, pane: *Pane, file: PaneFile) Reply { const word = std.mem.trim(u8, req.data, " \t\r\n"); - if (!std.mem.eql(u8, word, "1") and !std.mem.eql(u8, word, "0")) return Reply.fail(req.tag, E.INVAL); + if (!std.mem.eql(u8, word, "1") and !std.mem.eql(u8, word, "0")) return tree.failText(req.tag, E.INVAL, "takes 1 or 0"); const on = word[0] == '1'; const pf = &pane.fs; switch (file) { @@ -851,8 +873,10 @@ test "the flag files read and write the state acme kept behind ctl verbs" { for ([_]u64{ dirty, mark, scroll }) |node| { try testing.expectEqual(@as(u64, 2), call(p, .{ .tag = 1, .op = .getattr, .node = node }).reply.attr.size); - for ([_][]const u8{ "", "yes", "2", "0 1", "true" }) |bad| + for ([_][]const u8{ "", "yes", "2", "0 1", "true" }) |bad| { try testing.expectEqual(E.INVAL, wr(p, node, bad).errno()); + try testing.expectEqualStrings("takes 1 or 0", wr(p, node, bad).reply.ename); + } } try testing.expectEqualStrings("0\n", rd(p, dirty, 0, 8).bytes); |
