diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Messages.zig | 2 | ||||
| -rw-r--r-- | src/ninep/events.zig | 27 |
2 files changed, 24 insertions, 5 deletions
diff --git a/src/Messages.zig b/src/Messages.zig index d8aeea0c..eb2fa5e2 100644 --- a/src/Messages.zig +++ b/src/Messages.zig @@ -413,7 +413,7 @@ fn logMessage(p: *Pardes, id: usize, text: []const u8) void { const serial: u32 = if (p.fs.session_write) 0 else if (id < MAX_PANES) if (p.panes[id]) |pane| pane.serial else 0 else 0; const kept = text[0..@min(text.len, LoggedMessage.cap)]; // /log hears every one (a failure of a ctl write as its err record). - if (!p.fs.unlogged) ctlfs.events.noteMessage(p, serial, kept); + if (!p.fs.unlogged) ctlfs.events.noteMessage(p, serial, text); if (p.messages.len > 0) { const last = &p.messages.log[(p.messages.head + limits.message_log - 1) % limits.message_log]; if (last.serial == serial and 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 <serial> <text>` 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 <serial|-> <file>: <why>` 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(); |
