summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Messages.zig2
-rw-r--r--src/ninep/events.zig27
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();