From a630f5e83ef9efabca790770112dcea689384631 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Tue, 29 Sep 2026 08:14:42 -0300 Subject: A new terminal's greeting `ls` goes at its shell's first prompt or never The greeting waited for any moment the cursor sat at a prompt's input, so where the first prompt was missed (a resize still pending, a line written before it), `ls` was typed later into whatever ran then. It is now sent only while nothing has run (pardes's marks saw no command start) and nothing is typed at the prompt; past that it is dropped, never typed late. A prompt drawn again for a resize is still the first. Co-Authored-By: Claude Opus 5.5 --- src/Terminal.zig | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'src/Terminal.zig') diff --git a/src/Terminal.zig b/src/Terminal.zig index 4808298e..32595d25 100644 --- a/src/Terminal.zig +++ b/src/Terminal.zig @@ -1013,6 +1013,27 @@ pub fn onAlternateScreen(pane: *const Pane) bool { return state.vt.screens.active_key == .alternate; } +/// Whether a new terminal's greeting may be typed now: only at the shell's +/// first prompt (pardes's own marks: no command started; a prompt drawn +/// again for a resize is the same first prompt), with nothing +/// typed at it and no program on the alternate screen. Any later moment is `.never`, for good: something has run or +/// been typed first, and an `ls` then would go into it. A shell pardes +/// cannot mark has no first prompt to find, and is never greeted. +pub fn greeting(pane: *const Pane) enum { wait, now, never } { + if (comptime !enabled) return .never; + if (pane.fs.unmarked) return .never; + // Text typed into the edit buffer that stands in for the prompt row. + if (pane.ovl) |o| if (o.text.len > 0) return .never; + const state = pane.terminal orelse return .wait; + const marks = &state.stream.handler; + // (Not `declined`: bash's first prompt comes after a D of its own.) + if (marks.started > 0) return .never; + // At a prompt's input (ghostty's semantic marks, pardes's or the + // shell's own), before any command pardes's marks saw run. + if (!promptInputReady(pane)) return .wait; + return if (promptInputEmpty(pane)) .now else .never; +} + pub fn promptInputReady(pane: *const Pane) bool { if (comptime !enabled) return false; const state = pane.terminal orelse return false; -- cgit v1.3