aboutsummaryrefslogtreecommitdiff
path: root/menubar/hotkey.swift
diff options
context:
space:
mode:
authorIgor Soarez <igor@soarez.org>2026-10-22 18:01:04 +0300
committerIgor Soarez <igor@soarez.org>2026-10-22 18:01:04 +0300
commitf4a7346fd32f906ccc814364462c18afb3f10616 (patch)
treec4502bc0a6725233e9ba45c5350bf7be44100f1d /menubar/hotkey.swift
parent7649396bf30a65096fc3944e1404835e661f00af (diff)
agent search: spotlight-style fuzzy finder on ctrl+opt+cmd+shift+u
a centered, non-activating key panel that lists every agent and jumps to the chosen one through the same dingger focus path as a row click. - fzf-style matching: each word must match one of name, session, window, harness, status, or directory, letters in order; the best alignment wins (word starts and consecutive runs score higher), matched title letters are highlighted. - empty query keeps the menu's order, so enter jumps to the top waiting agent. - the selection follows the agent, not the position, as states change; the list scrolls to keep it visible. - keys: arrows, ctrl+n/p, ctrl+j/k, enter, esc, ctrl+u; the shortcut again or clicking elsewhere closes it. - search_hotkey setting; an unedited config file is upgraded. menu item "Search Agents...". rows carry the pane's directory. - --print-search and --snapshot-search debug flags; the panel's background and snapshot code are shared. selftest covers matching, ranking, highlighting, and selection; e2e step 15 checks queries through the real binary (fails when search only looks at titles). e2e resolves relative binary paths, which tmux hooks need.
Diffstat (limited to 'menubar/hotkey.swift')
-rw-r--r--menubar/hotkey.swift25
1 files changed, 23 insertions, 2 deletions
diff --git a/menubar/hotkey.swift b/menubar/hotkey.swift
index c5ab178..136d94d 100644
--- a/menubar/hotkey.swift
+++ b/menubar/hotkey.swift
@@ -12,6 +12,7 @@ import Carbon.HIToolbox
struct Settings: Equatable {
var hotkey = "ctrl+opt+cmd+e"
var jumpHotkey = "ctrl+opt+cmd+u"
+ var searchHotkey = "ctrl+opt+cmd+shift+u"
static var directory: String {
environment["DINGGER_CONFIG_DIR"] ?? (NSHomeDirectory() + "/.config/dingger")
@@ -28,10 +29,28 @@ struct Settings: Equatable {
# Jump to the agent at the top of the waiting list (blocked first, then
# the longest done), like clicking the tmux status line.
jump_hotkey = "ctrl+opt+cmd+u"
+ # Search all agents by name, session, window, harness, status, or
+ # directory, and jump to one.
+ search_hotkey = "ctrl+opt+cmd+shift+u"
+
+ """
+
+ /// Earlier templates, replaced on upgrade if the user never edited them.
+ private static let olderTemplates = [firstTemplate, secondTemplate]
+
+ private static let secondTemplate = """
+ # dingger settings. The menu bar app reloads this file when you save it.
+ # Shortcuts: modifiers ctrl, opt, cmd, shift; keys a-z, 0-9, f1-f12, space.
+
+ [shortcuts]
+ # Show or hide the floating panel.
+ hotkey = "ctrl+opt+cmd+e"
+ # Jump to the agent at the top of the waiting list (blocked first, then
+ # the longest done), like clicking the tmux status line.
+ jump_hotkey = "ctrl+opt+cmd+u"
"""
- /// The first template, replaced on upgrade if the user never edited it.
private static let firstTemplate = """
# dingger settings. The menu bar app reloads this file when you save it.
@@ -46,7 +65,7 @@ struct Settings: Equatable {
/// upgrade it if it is still an unedited older template.
static func ensureFile() {
let existing = try? String(contentsOfFile: path, encoding: .utf8)
- guard existing == nil || existing == firstTemplate else { return }
+ guard existing == nil || olderTemplates.contains(existing!) else { return }
try? FileManager.default.createDirectory(atPath: directory, withIntermediateDirectories: true)
try? template.write(toFile: path, atomically: true, encoding: .utf8)
}
@@ -64,6 +83,7 @@ struct Settings: Equatable {
switch parts[0] {
case "hotkey": settings.hotkey = value
case "jump_hotkey": settings.jumpHotkey = value
+ case "search_hotkey": settings.searchHotkey = value
default: break
}
}
@@ -139,6 +159,7 @@ enum GlobalHotkey {
enum Id: UInt32 {
case panel = 1
case jump = 2
+ case search = 3
}
private static var references: [UInt32: EventHotKeyRef] = [:]