From 6c53afbc957bfd616cd32b64fd07fec4b4bcc68a Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Tue, 29 Sep 2026 06:22:15 -0300 Subject: A long msg record is cut between words with an ellipsis, as an err record is A Msg past 256 bytes was cut mid-word and silently: nothing told a reader of /log that the line went on. Co-Authored-By: Claude Opus 5.5 --- src/ninep/events.zig | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) (limited to 'src/ninep') diff --git a/src/ninep/events.zig b/src/ninep/events.zig index dd29b207..2b7c1c1d 100644 --- a/src/ninep/events.zig +++ b/src/ninep/events.zig @@ -149,16 +149,20 @@ pub fn noteLog(p: *Pardes, kind: LogKind, pane: *Pane) void { } /// Records `msg ` for what the editor said, `-` for no pane. -pub fn noteMessage(p: *Pardes, serial: u32, text: []const u8) void { +/// Text past LoggedMessage.cap bytes is cut between words with an ellipsis, +/// as an err record's reason is. +pub fn noteMessage(p: *Pardes, serial: u32, said: []const u8) void { var buf: [pardes.Messages.LoggedMessage.cap + 32]u8 = undefined; + const kept = pardes.Messages.clip(said, pardes.Messages.LoggedMessage.cap); + const cut = if (kept.len < said.len) "…" else ""; // A builtin's own word for what it did stands in for its Verbose // announcement just before (`Undo` then `Undo: nothing to undo`), so // that 1000 Undos with nothing left are one line, counted, as err's are. - dropAnnouncement(p, serial, text); + dropAnnouncement(p, serial, kept); pushCounting(p, (if (serial == 0) - std.fmt.bufPrint(&buf, "msg - {s}\n", .{text}) + std.fmt.bufPrint(&buf, "msg - {s}{s}\n", .{ kept, cut }) else - std.fmt.bufPrint(&buf, "msg {d} {s}\n", .{ serial, text })) catch return); + std.fmt.bufPrint(&buf, "msg {d} {s}{s}\n", .{ serial, kept, cut })) catch return); } /// Records `err : ` for a write or truncation that was @@ -1179,6 +1183,21 @@ test "follow new skips what the log held and waits for what comes after" { _ = call(p, .{ .tag = 5, .op = .release, .node = log, .handle = h }); } +test "a long msg record is cut between words at its cap, with an ellipsis" { + const p = try withFile(testing.allocator, "x\n"); + defer p.deinit(); + const long = "word " ** 60; // 300 bytes + _ = wr(p, Node.of(serialOf(p), .ctl), "Msg " ++ long ++ "\n"); + const log = @intFromEnum(tree.TopFile.log); + const h = call(p, .{ .tag = 1, .op = .open, .node = log }).reply.handle; + const text = call(p, .{ .tag = 2, .op = .read, .node = log, .handle = h, .size = 1 << 16 }).bytes; + const at = std.mem.lastIndexOf(u8, text, "msg ").?; + const record = text[at .. std.mem.indexOfScalarPos(u8, text, at, '\n').? + 1]; + try testing.expect(std.mem.endsWith(u8, record, " word…\n")); + try testing.expect(record.len <= "msg 1 ".len + pardes.Messages.LoggedMessage.cap + "…\n".len); + _ = call(p, .{ .tag = 3, .op = .release, .node = log, .handle = h }); +} + test "a long err record is cut between words, with an ellipsis" { const p = try withFile(testing.allocator, "x\n"); defer p.deinit(); -- cgit v1.3