summaryrefslogtreecommitdiff
path: root/src/pardes.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/pardes.zig')
-rw-r--r--src/pardes.zig32
1 files changed, 30 insertions, 2 deletions
diff --git a/src/pardes.zig b/src/pardes.zig
index 55461c5d..111e2853 100644
--- a/src/pardes.zig
+++ b/src/pardes.zig
@@ -3809,12 +3809,27 @@ pub const AttachRequest = struct { pane: u8, name: []const u8 };
/// freed the moment `off` reaches the end or the pane goes away.
pub const PendingWrite = struct { bytes: []u8, off: usize = 0 };
+/// WHAT `pty/ctl`'s `sig` VERB CAN SEND. Named rather than numeric because the
+/// core is freestanding: it has no `SIGINT` to name and a number written here
+/// would be one platform's number travelling to a host that may not share it.
+/// Five, and deliberately not the whole of signal(7): these are the ones a
+/// human at a terminal already has a key or a `kill` for, and every one of
+/// them means something to a program on a tty. `sig USR1` at a shell is a
+/// message to a daemon, not a terminal operation, and nothing asked for it.
+pub const PtySignal = enum(u8) { int, term, hup, quit, kill };
+
/// IO the core wants done. Payloads are inline (fixed buffers): effects are
/// queued values with no lifetime ties back into the core.
pub const Effect = union(enum) {
spawn: struct { pane: u8, cwd: Buf(256) },
write: struct { pane: u8, bytes: Buf(64) },
resize_pty: struct { pane: u8, cols: u16, rows: u16 },
+ /// Deliver a signal to whatever is on this pane's tty — `pty/ctl`'s
+ /// `sig INT`, i.e. the ^C a script cannot type because ^C is not a byte
+ /// the pty would interpret on its own. The only genuinely new capability
+ /// the `pty/` directory added: `spawn` and `resize_pty` above were already
+ /// here, so `exec` and `winsize` are those two acquiring a name.
+ signal_pty: struct { pane: u8, sig: PtySignal },
open_link: Buf(256),
/// write this pane's file content to its path; the shell reads both off
/// the core (content is unbounded, effects are fixed-size values)
@@ -6805,8 +6820,11 @@ pub const Pardes = struct {
}
/// Has a program taken this pane's tty? A host that cannot tell says no,
- /// which is how pardes behaved before the probe existed.
- fn hostTtyTaken(p: *const Pardes, id: usize) bool {
+ /// which is how pardes behaved before the probe existed. Public because
+ /// `pty/status` reports it: it is the one field of that file the core does
+ /// not own itself, and asking here rather than reaching for the vtable in
+ /// acmefs keeps the null-method default in one place.
+ pub fn hostTtyTaken(p: *const Pardes, id: usize) bool {
const f = p.host.vtable.pull_tty_taken orelse return false;
return f(p.host.ctx, @intCast(id));
}
@@ -6857,6 +6875,10 @@ pub const Pardes = struct {
// screen, and the bytes are dropped rather than transcribed.
.write => |w| if (v.push_pty_write) |f| f(p.host.ctx, w.pane, w.bytes.slice()),
.resize_pty => |r| if (v.push_pty_resize) |f| f(p.host.ctx, r.pane, r.cols, r.rows),
+ // A host with no signal method has no child to signal: the
+ // fallback host's ptys are silent (see `.write` above), so there
+ // is nothing to record and nothing to lie about.
+ .signal_pty => |s| if (v.push_pty_signal) |f| f(p.host.ctx, s.pane, s.sig),
.open_link => |u| if (v.push_open_link) |f|
f(p.host.ctx, u.slice())
else
@@ -7081,6 +7103,12 @@ pub const Pardes = struct {
},
.output => |o| {
const pane = p.panes[o.pane] orelse return;
+ // The RAW bytes, before the emulator eats them. `pty/data`'s
+ // read is the only thing that wants them — the grid is a
+ // rendering and cannot be un-rendered — and this is one load
+ // and one branch on a pane nobody is reading. See
+ // `acmefs.notePtyOutput`.
+ acmefs.notePtyOutput(p, o.pane, o.bytes);
term_pane.feedOutput(p, pane, o.bytes);
},
.eof => |e| p.removePane(e.pane),