summaryrefslogtreecommitdiff
path: root/src/ninep/events.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-27 18:07:06 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:14 -0300
commit6f7beca8d27e2e00f7b90bb75015637a9aa4c950 (patch)
tree823e143a5e29aca8049c905213e40520f3354383 /src/ninep/events.zig
parentf4412d6dfdb1e2bd8549a7edba785ee242fd38f2 (diff)
downloadpardes-6f7beca8d27e2e00f7b90bb75015637a9aa4c950.tar.gz
pardes-6f7beca8d27e2e00f7b90bb75015637a9aa4c950.zip
Run a line at a terminal's prompt through pty/run and read how it ended
/pane/<n>/pty/run takes factotum's rpc shape: write one line on an open, read the answer on that same open. The answer is exit N once the command ended and the shell is back at a prompt; busy at once when a command runs, text is typed at the prompt, or the shell has not drawn its first prompt; error not run when the shell refused the line without running it (fish on a syntax error keeps it on the prompt, so it is taken back with Ctrl-U); error shell gone when the pane closes or its shell is replaced; error no prompt marks for a shell pardes could not instrument. The end comes from the shell's OSC 133 marks. ghostty parses D's exit status and drops it, so the stream now runs through a handler that wraps ghostty's and follows prompt -> input -> running -> done. The marks pardes injects into bash and fish carry aid=pardes and only those count, so fish 4's own marks (which doubled ours), a nested shell's, and a stray 133;D in printed output are ignored. Checked end to end against real bash and fish: false, exit 7, a syntax error, sleep, busy while running, and the pane closing mid-command. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/ninep/events.zig')
-rw-r--r--src/ninep/events.zig10
1 files changed, 6 insertions, 4 deletions
diff --git a/src/ninep/events.zig b/src/ninep/events.zig
index ebd1cd2c..fa0a4975 100644
--- a/src/ninep/events.zig
+++ b/src/ninep/events.zig
@@ -128,6 +128,7 @@ pub fn noteInstall(p: *Pardes, id: usize) void {
/// A pane leaving; one never announced leaves silently.
pub fn noteRetire(p: *Pardes, id: usize, pane: *Pane) void {
if (id >= MAX_PANES) return;
+ tree.pty.shellGone(p, id);
if (p.fs.panes[id].unannounced) {
p.fs.panes[id].unannounced = false;
return;
@@ -168,10 +169,11 @@ fn pushLog(p: *Pardes, record: []u8) void {
c.* = ' ';
};
// One record larger than the ring would push every other out and then
- // not fit itself; cut it to what fits instead.
- const fit = @min(record.len, p.fs.log.cap - 4);
- record[fit - 1] = '\n';
- p.fs.log.push(p.gpa, record[0..fit]);
+ // not fit itself; cut it to what fits instead, on a character boundary.
+ var end = @min(record.len, p.fs.log.cap - 4) - 1;
+ while (end > 0 and record[end] & 0xC0 == 0x80) end -= 1;
+ record[end] = '\n';
+ p.fs.log.push(p.gpa, record[0 .. end + 1]);
}
/// An open freezes the ring's text, so `cat log` answers what happened lately