mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-06-06 20:04:25 +00:00
terminal: set semantic_prompt.click based on OSC133A options
This commit is contained in:
@@ -1087,9 +1087,11 @@ pub fn semanticPrompt(
|
||||
// "First do a fresh-line."
|
||||
try self.semanticPromptFreshLine();
|
||||
|
||||
const screen: *Screen = self.screens.active;
|
||||
|
||||
// "Subsequent text (until a OSC "133;B" or OSC "133;I" command)
|
||||
// is a prompt string (as if followed by OSC 133;P;k=i\007)."
|
||||
self.screens.active.cursorSetSemanticContent(.{
|
||||
screen.cursorSetSemanticContent(.{
|
||||
.prompt = cmd.readOption(.prompt_kind) orelse .initial,
|
||||
});
|
||||
|
||||
@@ -1100,6 +1102,24 @@ pub fn semanticPrompt(
|
||||
self.flags.shell_redraws_prompt = v;
|
||||
}
|
||||
|
||||
click: {
|
||||
// Handle click_events as a priority over cl. click_events
|
||||
// is another Kitty-specific extension that converts clicks
|
||||
// within a prompt area to SGR mouse events and defers to the
|
||||
// shell to handle them.
|
||||
if (cmd.readOption(.click_events)) |v| {
|
||||
if (v) {
|
||||
screen.semantic_prompt.click = .click_events;
|
||||
break :click;
|
||||
}
|
||||
}
|
||||
|
||||
// If click_events was not set or disabled, fallback to `cl`.
|
||||
if (cmd.readOption(.cl)) |v| {
|
||||
screen.semantic_prompt.click = .{ .cl = v };
|
||||
}
|
||||
}
|
||||
|
||||
// The "aid" and "cl" options are also valid for this
|
||||
// command but we don't yet handle these in any meaningful way.
|
||||
},
|
||||
@@ -11635,6 +11655,109 @@ test "Terminal: multiple newlines in prompt mode marks all rows" {
|
||||
}
|
||||
}
|
||||
|
||||
test "Terminal: OSC133A click_events=1 sets click to click_events" {
|
||||
const alloc = testing.allocator;
|
||||
var t = try init(alloc, .{ .cols = 10, .rows = 5 });
|
||||
defer t.deinit(alloc);
|
||||
|
||||
// Verify default state is none
|
||||
try testing.expectEqual(.none, t.screens.active.semantic_prompt.click);
|
||||
|
||||
// OSC 133;A with click_events=1
|
||||
try t.semanticPrompt(.{
|
||||
.action = .fresh_line_new_prompt,
|
||||
.options_unvalidated = "click_events=1",
|
||||
});
|
||||
|
||||
try testing.expectEqual(.click_events, t.screens.active.semantic_prompt.click);
|
||||
}
|
||||
|
||||
test "Terminal: OSC133A click_events=0 does not set click_events" {
|
||||
const alloc = testing.allocator;
|
||||
var t = try init(alloc, .{ .cols = 10, .rows = 5 });
|
||||
defer t.deinit(alloc);
|
||||
|
||||
// OSC 133;A with click_events=0
|
||||
try t.semanticPrompt(.{
|
||||
.action = .fresh_line_new_prompt,
|
||||
.options_unvalidated = "click_events=0",
|
||||
});
|
||||
|
||||
// Should remain none since click_events=0 doesn't activate anything
|
||||
try testing.expectEqual(.none, t.screens.active.semantic_prompt.click);
|
||||
}
|
||||
|
||||
test "Terminal: OSC133A cl option sets click to cl value" {
|
||||
const alloc = testing.allocator;
|
||||
var t = try init(alloc, .{ .cols = 10, .rows = 5 });
|
||||
defer t.deinit(alloc);
|
||||
|
||||
// OSC 133;A with cl=m (multiple)
|
||||
try t.semanticPrompt(.{
|
||||
.action = .fresh_line_new_prompt,
|
||||
.options_unvalidated = "cl=m",
|
||||
});
|
||||
|
||||
try testing.expectEqual(Screen.SemanticPrompt.SemanticClick{ .cl = .multiple }, t.screens.active.semantic_prompt.click);
|
||||
}
|
||||
|
||||
test "Terminal: OSC133A cl=line sets click to line" {
|
||||
const alloc = testing.allocator;
|
||||
var t = try init(alloc, .{ .cols = 10, .rows = 5 });
|
||||
defer t.deinit(alloc);
|
||||
|
||||
try t.semanticPrompt(.{
|
||||
.action = .fresh_line_new_prompt,
|
||||
.options_unvalidated = "cl=line",
|
||||
});
|
||||
|
||||
try testing.expectEqual(Screen.SemanticPrompt.SemanticClick{ .cl = .line }, t.screens.active.semantic_prompt.click);
|
||||
}
|
||||
|
||||
test "Terminal: OSC133A click_events=1 takes priority over cl" {
|
||||
const alloc = testing.allocator;
|
||||
var t = try init(alloc, .{ .cols = 10, .rows = 5 });
|
||||
defer t.deinit(alloc);
|
||||
|
||||
// OSC 133;A with both click_events=1 and cl=m
|
||||
try t.semanticPrompt(.{
|
||||
.action = .fresh_line_new_prompt,
|
||||
.options_unvalidated = "click_events=1;cl=m",
|
||||
});
|
||||
|
||||
// click_events should take priority
|
||||
try testing.expectEqual(.click_events, t.screens.active.semantic_prompt.click);
|
||||
}
|
||||
|
||||
test "Terminal: OSC133A click_events=0 falls back to cl" {
|
||||
const alloc = testing.allocator;
|
||||
var t = try init(alloc, .{ .cols = 10, .rows = 5 });
|
||||
defer t.deinit(alloc);
|
||||
|
||||
// OSC 133;A with click_events=0 and cl=v
|
||||
try t.semanticPrompt(.{
|
||||
.action = .fresh_line_new_prompt,
|
||||
.options_unvalidated = "click_events=0;cl=v",
|
||||
});
|
||||
|
||||
// Should fall back to cl since click_events is disabled
|
||||
try testing.expectEqual(Screen.SemanticPrompt.SemanticClick{ .cl = .conservative_vertical }, t.screens.active.semantic_prompt.click);
|
||||
}
|
||||
|
||||
test "Terminal: OSC133A no click options leaves click as none" {
|
||||
const alloc = testing.allocator;
|
||||
var t = try init(alloc, .{ .cols = 10, .rows = 5 });
|
||||
defer t.deinit(alloc);
|
||||
|
||||
// OSC 133;A with no click-related options
|
||||
try t.semanticPrompt(.{
|
||||
.action = .fresh_line_new_prompt,
|
||||
.options_unvalidated = "aid=123",
|
||||
});
|
||||
|
||||
try testing.expectEqual(.none, t.screens.active.semantic_prompt.click);
|
||||
}
|
||||
|
||||
test "Terminal: cursorIsAtPrompt" {
|
||||
const alloc = testing.allocator;
|
||||
var t = try init(alloc, .{ .cols = 10, .rows = 3 });
|
||||
|
||||
Reference in New Issue
Block a user