mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-14 15:56:13 +03:00
terminal: handle consecutive .input's in clearPrompt
Our semantic prompts are row-based, so the last prompt marker set on a row "wins". In the case of at least our bash shell integration, this means that consecutive prompt lines will all be marked as .input (OSC 133;B -- end-of-prompt, start of input). Previously, clearPrompt() identified the current prompt's "area" by searching upward from the current row until it encounters a .prompt marker or some command output. In the bash case, .prompt is never the dominant ("last") marker, so clearPrompt() would aggressively clear all immediately preceding consecutive prompts. With this change, we'll stop searching upwards when we encounter some command output, a .prompt marker, _or another .input marker_. That last case prevents clearPrompt() from unintentionally clearing earlier prompt lines. There may be improvements we can make to the way that our bash shell integration emits semantic prompt markers, but I think this logic is generally sound for all cases, and it specifically improves the current bash prompt-clearing experience.
This commit is contained in:

committed by
Mitchell Hashimoto

parent
56f285cbc2
commit
82756f8b4c
@ -1315,8 +1315,13 @@ pub fn clearPrompt(self: *Screen) void {
|
|||||||
switch (row.semantic_prompt) {
|
switch (row.semantic_prompt) {
|
||||||
// We are at a prompt but we're not at the start of the prompt.
|
// We are at a prompt but we're not at the start of the prompt.
|
||||||
// We mark our found value and continue because the prompt
|
// We mark our found value and continue because the prompt
|
||||||
// may be multi-line.
|
// may be multi-line, unless this is the second time we've
|
||||||
.input => found = p,
|
// seen an .input marker, in which case we've run into an
|
||||||
|
// earlier prompt.
|
||||||
|
.input => {
|
||||||
|
if (found != null) break;
|
||||||
|
found = p;
|
||||||
|
},
|
||||||
|
|
||||||
// If we find the prompt then we're done. We are also done
|
// If we find the prompt then we're done. We are also done
|
||||||
// if we find any prompt continuation, because the shells
|
// if we find any prompt continuation, because the shells
|
||||||
@ -3565,6 +3570,32 @@ test "Screen: clearPrompt continuation" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "Screen: clearPrompt consecutive prompts" {
|
||||||
|
const testing = std.testing;
|
||||||
|
const alloc = testing.allocator;
|
||||||
|
|
||||||
|
var s = try init(alloc, 5, 3, 0);
|
||||||
|
defer s.deinit();
|
||||||
|
const str = "1ABCD\n2EFGH\n3IJKL";
|
||||||
|
try s.testWriteString(str);
|
||||||
|
|
||||||
|
// Set both rows to be prompts
|
||||||
|
{
|
||||||
|
s.cursorAbsolute(0, 1);
|
||||||
|
s.cursor.page_row.semantic_prompt = .input;
|
||||||
|
s.cursorAbsolute(0, 2);
|
||||||
|
s.cursor.page_row.semantic_prompt = .input;
|
||||||
|
}
|
||||||
|
|
||||||
|
s.clearPrompt();
|
||||||
|
|
||||||
|
{
|
||||||
|
const contents = try s.dumpStringAlloc(alloc, .{ .screen = .{} });
|
||||||
|
defer alloc.free(contents);
|
||||||
|
try testing.expectEqualStrings("1ABCD\n2EFGH", contents);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
test "Screen: clearPrompt no prompt" {
|
test "Screen: clearPrompt no prompt" {
|
||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
const alloc = testing.allocator;
|
const alloc = testing.allocator;
|
||||||
|
Reference in New Issue
Block a user