mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-05-28 07:45:20 +00:00
surface: respect semantic prompt boundaries for links
Link detection currently expands the clicked location to a full line before running the configured regexes. When semantic prompt markers are present, this can cause prompt text and neighboring content to be matched together even though they are distinct semantic regions. Use semantic prompt boundaries when selecting the text to inspect for link matching. This keeps prompt text separate from the content beside it and avoids folding prompt text into double-click link/path selection. Add a regression test that models a prompt and command on the same line and verifies the prompt region and input region remain separate.
This commit is contained in:
@@ -4295,7 +4295,9 @@ fn linkAtPin(
|
||||
const line = screen.selectLine(.{
|
||||
.pin = mouse_pin,
|
||||
.whitespace = null,
|
||||
.semantic_prompt_boundary = false,
|
||||
// Respect semantic prompt boundaries so link/path matching doesn't
|
||||
// merge shell prompt content with the text beside it.
|
||||
.semantic_prompt_boundary = true,
|
||||
}) orelse return null;
|
||||
|
||||
var strmap: terminal.StringMap = undefined;
|
||||
@@ -6658,3 +6660,60 @@ test "Surface: rectangle selection logic" {
|
||||
true, //rectangle selection
|
||||
);
|
||||
}
|
||||
|
||||
test "Surface: link selection line respects prompt boundary" {
|
||||
const testing = std.testing;
|
||||
const alloc = testing.allocator;
|
||||
|
||||
var screen = try terminal.Screen.init(alloc, .{
|
||||
.cols = 20,
|
||||
.rows = 5,
|
||||
.max_scrollback = 0,
|
||||
});
|
||||
defer screen.deinit();
|
||||
|
||||
screen.cursorSetSemanticContent(.{ .prompt = .initial });
|
||||
try screen.testWriteString("/tmp $ ");
|
||||
screen.cursorSetSemanticContent(.{ .input = .clear_explicit });
|
||||
try screen.testWriteString("locale");
|
||||
|
||||
{
|
||||
var sel = screen.selectLine(.{
|
||||
.pin = screen.pages.pin(.{ .active = .{
|
||||
.x = 1,
|
||||
.y = 0,
|
||||
} }).?,
|
||||
.whitespace = null,
|
||||
.semantic_prompt_boundary = true,
|
||||
}).?;
|
||||
defer sel.deinit(&screen);
|
||||
|
||||
const contents = try screen.selectionString(alloc, .{
|
||||
.sel = sel,
|
||||
.trim = false,
|
||||
});
|
||||
defer alloc.free(contents);
|
||||
|
||||
try testing.expectEqualStrings("/tmp $ ", contents);
|
||||
}
|
||||
|
||||
{
|
||||
var sel = screen.selectLine(.{
|
||||
.pin = screen.pages.pin(.{ .active = .{
|
||||
.x = 8,
|
||||
.y = 0,
|
||||
} }).?,
|
||||
.whitespace = null,
|
||||
.semantic_prompt_boundary = true,
|
||||
}).?;
|
||||
defer sel.deinit(&screen);
|
||||
|
||||
const contents = try screen.selectionString(alloc, .{
|
||||
.sel = sel,
|
||||
.trim = false,
|
||||
});
|
||||
defer alloc.free(contents);
|
||||
|
||||
try testing.expectEqualStrings("locale", contents);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user