summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ninep/pane.zig3
-rw-r--r--src/ninep/pty.zig31
-rw-r--r--src/pardes.zig1
3 files changed, 27 insertions, 8 deletions
diff --git a/src/ninep/pane.zig b/src/ninep/pane.zig
index 50fc220e..ad6a6a28 100644
--- a/src/ninep/pane.zig
+++ b/src/ninep/pane.zig
@@ -63,6 +63,9 @@ pub const State = struct {
lock: ?u32 = null,
/// The host started a shell it could not teach to mark its prompts.
unmarked: bool = false,
+ /// The pty's size as pty/ctl's winsize last set it, until the pane's own
+ /// grid resizes and gives the pty its size again.
+ winsize: ?[2]u16 = null,
/// Installed during this update; /log hears about it once the update ends
/// and the pane has its file, name and place.
unannounced: bool = false,
diff --git a/src/ninep/pty.zig b/src/ninep/pty.zig
index 7a5187fe..37132f90 100644
--- a/src/ninep/pty.zig
+++ b/src/ninep/pty.zig
@@ -60,6 +60,7 @@ fn verb(p: *Pardes, id: usize, line: []const u8, apply: bool) bool {
if (words.next() != null) return false;
if (!apply) return true;
p.emit(.{ .resize_pty = .{ .pane = @intCast(id), .cols = cols, .rows = rows } });
+ pane.fs.winsize = .{ cols, rows };
},
.sig => {
const which = signalNamed(words.next() orelse return false) orelse return false;
@@ -79,13 +80,20 @@ fn verb(p: *Pardes, id: usize, line: []const u8, apply: bool) bool {
/// ctl reads back its state in the words it takes, as a Plan 9 ctl does.
pub fn readCtl(p: *Pardes, req: Req, pane: *Pane) Reply {
- p.fs.stage(p.gpa).print(p.gpa, "winsize {d} {d}\n", .{ pane.cols, pane.rows }) catch
+ const size = winsize(pane);
+ p.fs.stage(p.gpa).print(p.gpa, "winsize {d} {d}\n", .{ size[0], size[1] }) catch
return Reply.fail(req.tag, E.NOMEM);
return tree.stagedReply(p, req);
}
-/// Three right-aligned fields: cols, rows and busy: whether a run written now
-/// would be told `busy` (a command runs, or text is typed at the prompt).
+/// The pty's size: what ctl's winsize set, else the pane's grid.
+fn winsize(pane: *const Pane) [2]u16 {
+ return pane.fs.winsize orelse .{ pane.cols, pane.rows };
+}
+
+/// Three right-aligned fields: the pty's cols and rows, and busy: whether a
+/// run written now would be told `busy` (a command runs, or text is typed at
+/// the prompt). A newline ends the line, as a Plan 9 status file's does.
pub const status_len: u64 = 36;
pub fn readStatus(p: *Pardes, req: Req, id: usize, pane: *Pane) Reply {
@@ -97,7 +105,8 @@ pub fn readStatus(p: *Pardes, req: Req, id: usize, pane: *Pane) Reply {
const busy = p.hostTtyTaken(id) or (!pane.fs.unmarked and (waitingRun(p, pane) != null or
(if (marks) |m| m.prompts > 0 and (m.phase != .input or !pardes.panes.Terminal.promptInputEmpty(pane)) else false)));
const out = p.fs.stage(p.gpa);
- out.print(p.gpa, "{d:>11} {d:>11} {d:>11} ", .{ pane.cols, pane.rows, @intFromBool(busy) }) catch {};
+ const size = winsize(pane);
+ out.print(p.gpa, "{d:>11} {d:>11} {d:>11}\n", .{ size[0], size[1], @intFromBool(busy) }) catch {};
return tree.stagedReply(p, req);
}
@@ -466,6 +475,12 @@ test "every pty/ctl verb, and every refusal" {
try testing.expectEqual(@as(u16, 44), ws.winsize.?.rows);
try testing.expectEqual(cols, pane.cols);
try testing.expectEqual(rows, pane.rows);
+ // ctl and status read back the pty's size, until the pane resizes.
+ try testing.expectEqualStrings("winsize 132 44\n", rd(p, ctl, 0, 64).bytes);
+ try testing.expect(std.mem.startsWith(u8, rd(p, Node.of(serialOf(p), .pty_status), 0, 64).bytes, " 132 44 "));
+ p.update(.{ .resize = .{ .cols = 76, .rows = 24 } });
+ try testing.expect(pane.cols != 132);
+ try testing.expectEqualStrings(try std.fmt.bufPrint(&said, "winsize {d} {d}\n", .{ pane.cols, pane.rows }), rd(p, ctl, 0, 64).bytes);
for ([_]struct { line: []const u8, want: pardes.PtySignal }{
.{ .line = "sig INT", .want = .int },
@@ -556,7 +571,7 @@ test "pty/status reports the grid and who holds the tty" {
const a = rd(p, status, 0, 256);
try testing.expectEqual(Status.ok, a.reply.status);
var want: [64]u8 = undefined;
- const whole = try std.fmt.bufPrint(&want, "{d:>11} {d:>11} {d:>11} ", .{ pane.cols, pane.rows, 0 });
+ const whole = try std.fmt.bufPrint(&want, "{d:>11} {d:>11} {d:>11}\n", .{ pane.cols, pane.rows, 0 });
try testing.expectEqualStrings(whole, a.bytes);
try testing.expectEqual(@as(usize, 3 * 12), a.bytes.len);
try testing.expectEqualStrings(whole[12..], rd(p, status, 12, 256).bytes);
@@ -565,7 +580,7 @@ test "pty/status reports the grid and who holds the tty" {
p.host = .{ .ctx = &probe, .vtable = &th.FakeTty.vtable };
const held = rd(p, status, 0, 256);
try testing.expectEqualStrings(
- try std.fmt.bufPrint(&want, "{d:>11} {d:>11} {d:>11} ", .{ pane.cols, pane.rows, 1 }),
+ try std.fmt.bufPrint(&want, "{d:>11} {d:>11} {d:>11}\n", .{ pane.cols, pane.rows, 1 }),
held.bytes,
);
}
@@ -647,12 +662,12 @@ test "run answers how its command ended once the shell is back at a prompt" {
// Before its first prompt the shell cannot take a line yet: the line
// waits for it, and pty/status does not call the shell busy meanwhile.
const status = Node.of(serialOf(p), .pty_status);
- try testing.expect(std.mem.endsWith(u8, rd(p, status, 0, 64).bytes, " 0 "));
+ try testing.expect(std.mem.endsWith(u8, rd(p, status, 0, 64).bytes, " 0\n"));
const early = call(p, .{ .tag = 1, .op = .open, .node = node });
const waiting = call(p, .{ .tag = 2, .op = .write, .node = node, .handle = early.reply.handle, .data = "true\n" });
try testing.expectEqualStrings("", waiting.pty());
try testing.expectEqual(Status.again, call(p, .{ .tag = 3, .op = .read, .node = node, .handle = early.reply.handle, .size = 64 }).reply.status);
- try testing.expect(std.mem.endsWith(u8, rd(p, status, 0, 64).bytes, " 1 "));
+ try testing.expect(std.mem.endsWith(u8, rd(p, status, 0, 64).bytes, " 1\n"));
// A respawn before that prompt keeps it waiting for the new shell's.
p.acknowledgeShell(0, "/bin/sh", true);
try testing.expectEqual(Status.again, call(p, .{ .tag = 3, .op = .read, .node = node, .handle = early.reply.handle, .size = 64 }).reply.status);
diff --git a/src/pardes.zig b/src/pardes.zig
index 992311a2..a3436870 100644
--- a/src/pardes.zig
+++ b/src/pardes.zig
@@ -6186,6 +6186,7 @@ pub const Pardes = struct {
panes.Terminal.resizeGrid(pane, p.gpa, cols, rows);
p.shell_rows.markStale(pane); // reflow moved every row
p.emit(.{ .resize_pty = .{ .pane = @intCast(id), .cols = cols, .rows = rows } });
+ pane.fs.winsize = null;
}
pane.cols = cols;
pane.rows = rows;