From 1c3842f136b9f98fae784559ec12d66d629c5909 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Mon, 28 Sep 2026 11:22:53 -0300 Subject: Exit quits and Kill stops commands, as in acme Kill quit the editor, which in acme is Exit; acme's Kill stops the commands it started. Exit now quits as acme's does (exec.c, rowclean): it refuses once, naming each pane with unsaved text, and quits when asked again with nothing edited since (a small scratch is not asked about). Kill, bare or with names, stops the commands pardes typed into a terminal (an exec, a middle click, a pty/run) while their shell's marks say they run, by SIGTERM to the terminal's foreground job, never to the shell (acme posts the kill note, which terminates). Both are session builtins; the topbar's Kill becomes Exit, same width, and every golden's topbar row changed by exactly that word (checked line by line); the builtins script scrolls one more row for the index's new line. Co-Authored-By: Claude Opus 5.5 --- src/Terminal.zig | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'src/Terminal.zig') diff --git a/src/Terminal.zig b/src/Terminal.zig index 0bec3ce8..cd292e5f 100644 --- a/src/Terminal.zig +++ b/src/Terminal.zig @@ -214,6 +214,29 @@ pub fn armShellSpawn(pane: *Pane) void { pane.pending_command.wait = .spawn; } +/// Remembers a line pardes types into this terminal as the command it +/// started, for Kill: it runs from the shell's next C mark to its D. +/// ponytail: of several lines queued for a shell not up yet, only the last +/// is remembered, as the first of them. +pub fn noteCommand(pane: *Pane, line: []const u8) void { + if (comptime !enabled) return; + const state = pane.terminal orelse return; + const word = std.mem.trim(u8, line, " \t")[0 .. std.mem.indexOfAny(u8, std.mem.trim(u8, line, " \t"), " \t") orelse std.mem.trim(u8, line, " \t").len]; + var sent: @typeInfo(@FieldType(Pane, "sent_command")).optional.child = .{ .seq = state.stream.handler.started +% 1 }; + sent.len = @intCast(@min(word.len, sent.word.len)); + @memcpy(sent.word[0..sent.len], word[0..sent.len]); + pane.sent_command = sent; +} + +/// Whether the command pardes last typed here is running now. +pub fn commandRunning(pane: *const Pane) bool { + if (comptime !enabled) return false; + const state = pane.terminal orelse return false; + const sent = pane.sent_command orelse return false; + const marks = &state.stream.handler; + return marks.phase == .running and marks.started == sent.seq; +} + pub fn queuePendingCommand(pane: *Pane, command: []const u8) !bool { if (pane.pending_command.wait == .none) return false; const old_len = pane.pending_command.bytes.len; -- cgit v1.3