add toggle command palette binding

This commit is contained in:
Mitchell Hashimoto
2025-04-21 09:52:21 -07:00
parent 8bd91e7104
commit 6d2685b5a2
14 changed files with 84 additions and 12 deletions

View File

@ -579,6 +579,7 @@ typedef enum {
GHOSTTY_ACTION_TOGGLE_TAB_OVERVIEW,
GHOSTTY_ACTION_TOGGLE_WINDOW_DECORATIONS,
GHOSTTY_ACTION_TOGGLE_QUICK_TERMINAL,
GHOSTTY_ACTION_TOGGLE_COMMAND_PALETTE,
GHOSTTY_ACTION_TOGGLE_VISIBILITY,
GHOSTTY_ACTION_MOVE_TAB,
GHOSTTY_ACTION_GOTO_TAB,

View File

@ -59,6 +59,7 @@ class AppDelegate: NSObject,
@IBOutlet private var menuChangeTitle: NSMenuItem?
@IBOutlet private var menuQuickTerminal: NSMenuItem?
@IBOutlet private var menuTerminalInspector: NSMenuItem?
@IBOutlet private var menuCommandPalette: NSMenuItem?
@IBOutlet private var menuEqualizeSplits: NSMenuItem?
@IBOutlet private var menuMoveSplitDividerUp: NSMenuItem?
@ -402,6 +403,7 @@ class AppDelegate: NSObject,
syncMenuShortcut(config, action: "toggle_quick_terminal", menuItem: self.menuQuickTerminal)
syncMenuShortcut(config, action: "toggle_visibility", menuItem: self.menuToggleVisibility)
syncMenuShortcut(config, action: "inspector:toggle", menuItem: self.menuTerminalInspector)
syncMenuShortcut(config, action: "toggle_command_palette", menuItem: self.menuCommandPalette)
syncMenuShortcut(config, action: "toggle_secure_input", menuItem: self.menuSecureInput)

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="23504" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="23727" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="23504"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="23727"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
@ -21,6 +21,7 @@
<outlet property="menuCloseAllWindows" destination="yKr-Vi-Yqw" id="Zet-Ir-zbm"/>
<outlet property="menuCloseTab" destination="Obb-Mk-j8J" id="Gda-L0-gdz"/>
<outlet property="menuCloseWindow" destination="W5w-UZ-crk" id="6ff-BT-ENV"/>
<outlet property="menuCommandPalette" destination="et6-de-Mh7" id="53t-cu-dm5"/>
<outlet property="menuCopy" destination="Jqf-pv-Zcu" id="bKd-1C-oy9"/>
<outlet property="menuDecreaseFontSize" destination="kzb-SZ-dOA" id="Y1B-Vh-6Z2"/>
<outlet property="menuEqualizeSplits" destination="3gH-VD-vL9" id="SiZ-ce-FOF"/>
@ -249,6 +250,12 @@
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="L3L-I8-sqk"/>
<menuItem title="Command Palette" id="et6-de-Mh7">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleCommandPalette:" target="-1" id="FcT-XD-gM1"/>
</connections>
</menuItem>
<menuItem title="Change Title..." id="24I-xg-qIq">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>

View File

@ -110,6 +110,11 @@ class BaseTerminalController: NSWindowController,
selector: #selector(ghosttyConfigDidChangeBase(_:)),
name: .ghosttyConfigDidChange,
object: nil)
center.addObserver(
self,
selector: #selector(ghosttyCommandPaletteDidToggle(_:)),
name: .ghosttyCommandPaletteDidToggle,
object: nil)
// Listen for local events that we need to know of outside of
// single surface handlers.
@ -222,6 +227,12 @@ class BaseTerminalController: NSWindowController,
self.derivedConfig = DerivedConfig(config)
}
@objc private func ghosttyCommandPaletteDidToggle(_ notification: Notification) {
guard let surfaceView = notification.object as? Ghostty.SurfaceView else { return }
guard surfaceTree?.contains(view: surfaceView) ?? false else { return }
toggleCommandPalette(nil)
}
// MARK: Local Events
private func localEventHandler(_ event: NSEvent) -> NSEvent? {
@ -631,6 +642,10 @@ class BaseTerminalController: NSWindowController,
ghostty.changeFontSize(surface: surface, .reset)
}
@IBAction func toggleCommandPalette(_ sender: Any?) {
commandPaletteIsShowing.toggle()
}
@objc func resetTerminal(_ sender: Any) {
guard let surface = focusedSurface?.surface else { return }
ghostty.resetTerminal(surface: surface)

View File

@ -93,16 +93,6 @@ struct TerminalView<ViewModel: TerminalViewModel>: View {
DebugBuildWarningView()
}
HStack {
Spacer()
Button("Command Palette") {
viewModel.commandPaletteIsShowing.toggle()
}
Spacer()
}
.background(Color(.windowBackgroundColor))
.frame(maxWidth: .infinity)
Ghostty.TerminalSplit(node: $viewModel.surfaceTree)
.environmentObject(ghostty)
.focused($focused)

View File

@ -520,6 +520,9 @@ extension Ghostty {
case GHOSTTY_ACTION_RENDERER_HEALTH:
rendererHealth(app, target: target, v: action.action.renderer_health)
case GHOSTTY_ACTION_TOGGLE_COMMAND_PALETTE:
toggleCommandPalette(app, target: target)
case GHOSTTY_ACTION_TOGGLE_QUICK_TERMINAL:
toggleQuickTerminal(app, target: target)
@ -742,6 +745,28 @@ extension Ghostty {
}
}
private static func toggleCommandPalette(
_ app: ghostty_app_t,
target: ghostty_target_s) {
switch (target.tag) {
case GHOSTTY_TARGET_APP:
Ghostty.logger.warning("toggle command palette does nothing with an app target")
return
case GHOSTTY_TARGET_SURFACE:
guard let surface = target.target.surface else { return }
guard let surfaceView = self.surfaceView(from: surface) else { return }
NotificationCenter.default.post(
name: .ghosttyCommandPaletteDidToggle,
object: surfaceView
)
default:
assertionFailure()
}
}
private static func toggleVisibility(
_ app: ghostty_app_t,
target: ghostty_target_s

View File

@ -256,6 +256,7 @@ extension Notification.Name {
/// Ring the bell
static let ghosttyBellDidRing = Notification.Name("com.mitchellh.ghostty.ghosttyBellDidRing")
static let ghosttyCommandPaletteDidToggle = Notification.Name("com.mitchellh.ghostty.commandPaletteDidToggle")
}
// NOTE: I am moving all of these to Notification.Name extensions over time. This

View File

@ -4295,6 +4295,12 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
.toggle,
),
.toggle_command_palette => return try self.rt_app.performAction(
.{ .surface = self },
.toggle_command_palette,
{},
),
.select_all => {
const sel = self.io.terminal.screen.selectAll();
if (sel) |s| {

View File

@ -107,6 +107,9 @@ pub const Action = union(Key) {
/// Toggle the quick terminal in or out.
toggle_quick_terminal,
/// Toggle the command palette. This currently only works on macOS.
toggle_command_palette,
/// Toggle the visibility of all Ghostty terminal windows.
toggle_visibility,
@ -244,6 +247,8 @@ pub const Action = union(Key) {
/// Closes the currently focused window.
close_window,
/// Called when the bell character is seen. The apprt should do whatever
/// it needs to ring the bell. This is usually a sound or visual effect.
ring_bell,
/// Sync with: ghostty_action_tag_e
@ -259,6 +264,7 @@ pub const Action = union(Key) {
toggle_tab_overview,
toggle_window_decorations,
toggle_quick_terminal,
toggle_command_palette,
toggle_visibility,
move_tab,
goto_tab,

View File

@ -228,6 +228,7 @@ pub const App = struct {
.toggle_tab_overview,
.toggle_window_decorations,
.toggle_quick_terminal,
.toggle_command_palette,
.toggle_visibility,
.goto_tab,
.move_tab,

View File

@ -488,6 +488,7 @@ pub fn performAction(
// Unimplemented
.close_all_windows,
.toggle_command_palette,
.toggle_visibility,
.cell_size,
.key_sequence,

View File

@ -4866,6 +4866,13 @@ pub const Keybinds = struct {
.{ .jump_to_prompt = 1 },
);
// Toggle command palette, matches VSCode
try self.set.put(
alloc,
.{ .key = .{ .translated = .p }, .mods = .{ .super = true, .shift = true } },
.{ .toggle_command_palette = {} },
);
// Inspector, matching Chromium
try self.set.put(
alloc,

View File

@ -441,6 +441,14 @@ pub const Action = union(enum) {
/// This only works on macOS, since this is a system API on macOS.
toggle_secure_input: void,
/// Toggle the command palette. The command palette is a UI element
/// that lets you see what actions you can perform, their associated
/// keybindings (if any), a search bar to filter the actions, and
/// the ability to then execute the action.
///
/// This only works on macOS.
toggle_command_palette,
/// Toggle the "quick" terminal. The quick terminal is a terminal that
/// appears on demand from a keybinding, often sliding in from a screen
/// edge such as the top. This is useful for quick access to a terminal
@ -790,6 +798,7 @@ pub const Action = union(enum) {
.toggle_fullscreen,
.toggle_window_decorations,
.toggle_secure_input,
.toggle_command_palette,
.reset_window_size,
.crash,
=> .surface,

View File

@ -365,6 +365,7 @@ fn actionCommands(action: Action.Key) []const Command {
// No commands because I'm not sure they make sense in a command
// palette context.
.toggle_command_palette,
.toggle_quick_terminal,
.toggle_visibility,
.previous_tab,