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 --- test/panes.zig | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/panes.zig b/test/panes.zig index 1ca33053..c1ae1666 100644 --- a/test/panes.zig +++ b/test/panes.zig @@ -3466,14 +3466,14 @@ const TerminalTests = struct { .write => return error.GreetedBeforePrompt, else => {}, }; - p.update(.{ .output = .{ .pane = 0, .bytes = "\x1b]133;A\x07prompt$ " } }); + p.update(.{ .output = .{ .pane = 0, .bytes = "\x1b]133;A;aid=pardes\x07prompt$ " } }); try std.testing.expect(!promptInputReady(pane)); while (p.nextEffect()) |effect| switch (effect) { .write => return error.GreetedDuringPrompt, else => {}, }; - p.update(.{ .output = .{ .pane = 0, .bytes = "\x1b]133;B\x07" } }); + p.update(.{ .output = .{ .pane = 0, .bytes = "\x1b]133;B;aid=pardes\x07" } }); try std.testing.expect(promptInputReady(pane)); var greeted = false; while (p.nextEffect()) |effect| switch (effect) { @@ -3484,6 +3484,30 @@ const TerminalTests = struct { try std.testing.expect(!pane.greet); } + test "the greeting is dropped, never typed later, once something ran or was typed first" { + if (pardes.platform == .web) return; + for ([_][]const u8{ + // A command ran before the first prompt was seen at rest. + "\x1b]133;A;aid=pardes\x07$ \x1b]133;B;aid=pardes\x07\x1b]133;C;aid=pardes\x07out\r\n\x1b]133;D;0;aid=pardes\x07\x1b]133;A;aid=pardes\x07$ \x1b]133;B;aid=pardes\x07", + // Someone typed at the first prompt. + "\x1b]133;A;aid=pardes\x07$ \x1b]133;B;aid=pardes\x07vim", + }) |output| { + const p = try Pardes.init(std.testing.allocator, .{ .cols = 80, .rows = 24 }); + defer p.deinit(); + const pane = p.panes[0].?; + while (p.nextEffect()) |_| {} + p.update(.{ .resize = .{ .cols = 80, .rows = 24 } }); + p.update(.{ .output = .{ .pane = 0, .bytes = output } }); + // and a later, quiet prompt changes nothing + p.update(.{ .output = .{ .pane = 0, .bytes = "\r\n\x1b]133;A;aid=pardes\x07$ \x1b]133;B;aid=pardes\x07" } }); + while (p.nextEffect()) |effect| switch (effect) { + .write => |write| if (std.mem.eql(u8, write.bytes.slice(), "ls\r")) return error.GreetedLate, + else => {}, + }; + try std.testing.expect(!pane.greet); + } + } + test "fresh-shell commands preserve order and wait for OSC 133 B" { if (pardes.platform == .web) return; const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true }); -- cgit v1.3