add end_search binding

pull/9709/head
Mitchell Hashimoto 2025-11-26 07:05:52 -08:00
parent f7b14a0142
commit c51170da9c
No known key found for this signature in database
GPG Key ID: 523D5DC389D273BC
5 changed files with 31 additions and 20 deletions

View File

@ -75,9 +75,8 @@ extension Ghostty {
// avoid kicking off expensive searches.
searchNeedleCancellable = searchState.$needle
.removeDuplicates()
.filter { $0.count > 0 }
.map { needle -> AnyPublisher<String, Never> in
if needle.count >= 3 {
if needle.isEmpty || needle.count >= 3 {
return Just(needle).eraseToAnyPublisher()
} else {
return Just(needle)

View File

@ -4943,19 +4943,24 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
);
},
.end_search => {
if (self.search) |*s| {
s.deinit();
self.search = null;
}
return try self.rt_app.performAction(
.{ .surface = self },
.end_search,
{},
);
},
.search => |text| search: {
const s: *Search = if (self.search) |*s| s else init: {
// If we're stopping the search and we had no prior search,
// then there is nothing to do.
if (text.len == 0) {
// So GUIs can hide visible search widgets.
_ = try self.rt_app.performAction(
.{ .surface = self },
.end_search,
{},
);
return false;
}
if (text.len == 0) return false;
// We need to assign directly to self.search because we need
// a stable pointer back to the thread state.
@ -4985,13 +4990,6 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
if (text.len == 0) {
s.deinit();
self.search = null;
// Notify apprt search has ended.
_ = try self.rt_app.performAction(
.{ .surface = self },
.end_search,
{},
);
break :search;
}

View File

@ -6413,7 +6413,7 @@ pub const Keybinds = struct {
try self.set.putFlags(
alloc,
.{ .key = .{ .unicode = 'f' }, .mods = .{ .super = true, .shift = true } },
.{ .search = "" },
.end_search,
.{ .performable = true },
);
try self.set.putFlags(

View File

@ -333,7 +333,11 @@ pub const Action = union(enum) {
set_font_size: f32,
/// Start a search for the given text. If the text is empty, then
/// the search is canceled. If a previous search is active, it is replaced.
/// the search is canceled. A canceled search will not disable any GUI
/// elements showing search. For that, the explicit end_search binding
/// should be used.
///
/// If a previous search is active, it is replaced.
search: []const u8,
/// Navigate the search results. If there is no active search, this
@ -344,6 +348,9 @@ pub const Action = union(enum) {
/// search terms, but opens the UI for searching.
start_search,
/// End the current search if any and hide any GUI elements.
end_search,
/// Clear the screen and all scrollback.
clear_screen,
@ -1172,6 +1179,7 @@ pub const Action = union(enum) {
.search,
.navigate_search,
.start_search,
.end_search,
.reset,
.copy_to_clipboard,
.copy_url_to_clipboard,

View File

@ -169,6 +169,12 @@ fn actionCommands(action: Action.Key) []const Command {
.description = "Start a search if one isn't already active.",
}},
.end_search => comptime &.{.{
.action = .end_search,
.title = "End Search",
.description = "End the current search if any and hide any GUI elements.",
}},
.navigate_search => comptime &.{ .{
.action = .{ .navigate_search = .next },
.title = "Next Search Result",