summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Terminal.zig16
-rw-r--r--src/ninep/ctl.zig3
-rw-r--r--src/ninep/pty.zig29
-rw-r--r--src/pardes.zig3
4 files changed, 50 insertions, 1 deletions
diff --git a/src/Terminal.zig b/src/Terminal.zig
index 16d5af26..0bec3ce8 100644
--- a/src/Terminal.zig
+++ b/src/Terminal.zig
@@ -368,6 +368,22 @@ pub fn screenTextAlloc(pane: *Pane, gpa: std.mem.Allocator) ![]const u8 {
return state.vt.screens.active.dumpStringAlloc(gpa, .{ .screen = .{} });
}
+/// How long `screenTextAlloc` would be, counted without keeping it: the
+/// length a terminal's body reads as, which its ctl line reports.
+pub fn screenTextLen(pane: *Pane) usize {
+ if (comptime !enabled) return 0;
+ const state = pane.terminal orelse return 0;
+ const screen = state.vt.screens.active;
+ var buf: [256]u8 = undefined;
+ var counting: std.Io.Writer.Discarding = .init(&buf);
+ screen.dumpString(&counting.writer, .{
+ .tl = screen.pages.getTopLeft(.screen),
+ .br = screen.pages.getBottomRight(.screen) orelse return 0,
+ .unwrap = false,
+ }) catch return 0;
+ return @intCast(counting.fullCount());
+}
+
/// Release the emulator's heap. The Pane allocation itself is the core's.
pub fn deinitEmulator(pane: *Pane, gpa: std.mem.Allocator) void {
if (comptime !enabled) return;
diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig
index 5fe04f5c..c1f78bab 100644
--- a/src/ninep/ctl.zig
+++ b/src/ninep/ctl.zig
@@ -156,7 +156,8 @@ pub fn paneText(p: *Pardes, pane: *Pane, buf: []u8) []const u8 {
w.print("{d:>11} {d:>11} {d:>11} {d:>11} {d:>11} {d:>11} ", .{
pane.serial,
pane_files.tagOf(p, pane).len,
- pane_files.bodyOf(pane).len,
+ // A terminal's body is its history, read whole on an open's first read.
+ if (pane.isTerminal()) panes.Terminal.screenTextLen(pane) else pane_files.bodyOf(pane).len,
@as(u32, 0),
@intFromBool(pane_files.dirtyOf(pane)),
pane.cols,
diff --git a/src/ninep/pty.zig b/src/ninep/pty.zig
index 0a55df94..50d14624 100644
--- a/src/ninep/pty.zig
+++ b/src/ninep/pty.zig
@@ -849,6 +849,35 @@ test "a run's answer says cut when its output's start is gone, and reads a bound
try testing.expectEqualStrings("error out of memory\n", sh.answered(p, node, h, into));
}
+test "a terminal's ctl counts its body, and a new directory is a rename in the log" {
+ const gpa = testing.allocator;
+ const p = try withTerm(gpa);
+ defer p.deinit();
+ const serial = serialOf(p);
+ p.update(.{ .output = .{ .pane = 0, .bytes = "some history\r\nmore" } });
+ while (p.nextEffect()) |_| {}
+ const opened = call(p, .{ .tag = 1, .op = .open, .node = Node.of(serial, .body) });
+ const body_len = call(p, .{ .tag = 2, .op = .read, .node = Node.of(serial, .body), .handle = opened.reply.handle, .size = 1 << 16 }).bytes.len;
+ _ = call(p, .{ .tag = 3, .op = .release, .node = Node.of(serial, .body), .handle = opened.reply.handle });
+ try testing.expect(body_len > 0);
+ var fields = std.mem.tokenizeScalar(u8, rd(p, Node.of(serial, .ctl), 0, 4096).bytes, ' ');
+ _ = fields.next();
+ _ = fields.next();
+ try testing.expectEqual(body_len, try std.fmt.parseInt(usize, fields.next().?, 10));
+
+ const log = @intFromEnum(tree.TopFile.log);
+ const f = call(p, .{ .tag = 4, .op = .open, .node = log }).reply.handle;
+ const frozen = call(p, .{ .tag = 5, .op = .read, .node = log, .handle = f, .size = 1 << 16 }).bytes.len;
+ _ = call(p, .{ .tag = 6, .op = .write, .node = log, .handle = f, .data = "follow" });
+ p.setCwd(0, "/somewhere/else");
+ var want: [64]u8 = undefined;
+ try testing.expectEqualStrings(
+ try std.fmt.bufPrint(&want, "rename {d} /somewhere/else\n", .{serial}),
+ call(p, .{ .tag = 7, .op = .read, .node = log, .handle = f, .off = frozen, .size = 4096 }).bytes,
+ );
+ _ = call(p, .{ .tag = 8, .op = .release, .node = log, .handle = f });
+}
+
test "closing a terminal pane asks its shell to hang up the pty" {
const p = try withTerm(testing.allocator);
defer p.deinit();
diff --git a/src/pardes.zig b/src/pardes.zig
index 405e7839..084b2216 100644
--- a/src/pardes.zig
+++ b/src/pardes.zig
@@ -4298,6 +4298,9 @@ pub const Pardes = struct {
if (std.mem.eql(u8, cur, cwd)) return;
pane.setOwnedCwd(cwd) catch |err| return p.reportError(id, "directory", err);
if (look.lookHoverPane(p) == id) look.cancelLookHover(p);
+ // A terminal is named by its directory, so /log hears it renamed; one
+ // not announced yet is announced under the new name.
+ if (pane.isTerminal() and !pane.fs.unannounced) ctlfs.events.noteLog(p, .rename, pane);
}
pub fn shellBin(p: *const Pardes) []const u8 {