From 7d0157e69a7b8082b4c56baa466304768f68cbc6 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 6 Jan 2026 14:28:54 -0800 Subject: [PATCH] macOS: add Cmd+J "Jump to Selection" menu item and default binding This matches other built-in macOS apps like Terminal, Notes, Safari. We already had the binding, just needed to create the menu. https://ampcode.com/threads/T-019b956a-f4e6-71b4-87fa-4162258d33ff --- macos/Sources/App/macOS/AppDelegate.swift | 2 ++ macos/Sources/App/macOS/MainMenu.xib | 6 ++++++ .../Features/Terminal/BaseTerminalController.swift | 4 ++++ .../Sources/Ghostty/Surface View/SurfaceView_AppKit.swift | 8 ++++++++ src/config/Config.zig | 6 ++++++ 5 files changed, 26 insertions(+) diff --git a/macos/Sources/App/macOS/AppDelegate.swift b/macos/Sources/App/macOS/AppDelegate.swift index c0886607c..2e62d033b 100644 --- a/macos/Sources/App/macOS/AppDelegate.swift +++ b/macos/Sources/App/macOS/AppDelegate.swift @@ -47,6 +47,7 @@ class AppDelegate: NSObject, @IBOutlet private var menuFindParent: NSMenuItem? @IBOutlet private var menuFind: NSMenuItem? @IBOutlet private var menuSelectionForFind: NSMenuItem? + @IBOutlet private var menuScrollToSelection: NSMenuItem? @IBOutlet private var menuFindNext: NSMenuItem? @IBOutlet private var menuFindPrevious: NSMenuItem? @IBOutlet private var menuHideFindBar: NSMenuItem? @@ -617,6 +618,7 @@ class AppDelegate: NSObject, syncMenuShortcut(config, action: "select_all", menuItem: self.menuSelectAll) syncMenuShortcut(config, action: "start_search", menuItem: self.menuFind) syncMenuShortcut(config, action: "search_selection", menuItem: self.menuSelectionForFind) + syncMenuShortcut(config, action: "scroll_to_selection", menuItem: self.menuScrollToSelection) syncMenuShortcut(config, action: "search:next", menuItem: self.menuFindNext) syncMenuShortcut(config, action: "search:previous", menuItem: self.menuFindPrevious) diff --git a/macos/Sources/App/macOS/MainMenu.xib b/macos/Sources/App/macOS/MainMenu.xib index aa9aca952..e28344098 100644 --- a/macos/Sources/App/macOS/MainMenu.xib +++ b/macos/Sources/App/macOS/MainMenu.xib @@ -289,6 +289,12 @@ + + + + + + diff --git a/macos/Sources/Features/Terminal/BaseTerminalController.swift b/macos/Sources/Features/Terminal/BaseTerminalController.swift index a4e0da7ee..98175eabc 100644 --- a/macos/Sources/Features/Terminal/BaseTerminalController.swift +++ b/macos/Sources/Features/Terminal/BaseTerminalController.swift @@ -1388,6 +1388,10 @@ class BaseTerminalController: NSWindowController, focusedSurface?.selectionForFind(sender) } + @IBAction func scrollToSelection(_ sender: Any) { + focusedSurface?.scrollToSelection(sender) + } + @IBAction func findNext(_ sender: Any) { focusedSurface?.findNext(sender) } diff --git a/macos/Sources/Ghostty/Surface View/SurfaceView_AppKit.swift b/macos/Sources/Ghostty/Surface View/SurfaceView_AppKit.swift index a5ba62571..ca74c7815 100644 --- a/macos/Sources/Ghostty/Surface View/SurfaceView_AppKit.swift +++ b/macos/Sources/Ghostty/Surface View/SurfaceView_AppKit.swift @@ -1527,6 +1527,14 @@ extension Ghostty { } } + @IBAction func scrollToSelection(_ sender: Any?) { + guard let surface = self.surface else { return } + let action = "scroll_to_selection" + if (!ghostty_surface_binding_action(surface, action, UInt(action.lengthOfBytes(using: .utf8)))) { + AppDelegate.logger.warning("action failed action=\(action)") + } + } + @IBAction func findNext(_ sender: Any?) { guard let surface = self.surface else { return } let action = "search:next" diff --git a/src/config/Config.zig b/src/config/Config.zig index ef6132912..1aacf78fd 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -6446,6 +6446,12 @@ pub const Keybinds = struct { .{ .key = .{ .physical = .page_down }, .mods = .{ .super = true } }, .{ .scroll_page_down = {} }, ); + try self.set.putFlags( + alloc, + .{ .key = .{ .unicode = 'j' }, .mods = .{ .super = true } }, + .{ .scroll_to_selection = {} }, + .{ .performable = true }, + ); // Semantic prompts try self.set.put(