@@ -72,6 +72,123 @@ for key, app_name in pairs(apps) do
7272 end
7373end
7474
75+ ---- ----------------------- APP-SPECIFIC KEYMAPS ------------------------------
76+ local function ghosttySessionizer ()
77+ local home = os.getenv (" HOME" )
78+
79+ -- Get open Ghostty windows
80+ local windows = {}
81+ local ok , result = hs .osascript .applescript ([[
82+ tell application "Ghostty"
83+ set output to ""
84+ repeat with w in (every window)
85+ set wid to id of w
86+ set t to focused terminal of selected tab of w
87+ set wdir to working directory of t
88+ set output to output & wid & "|||" & wdir & ":::"
89+ end repeat
90+ return output
91+ end tell
92+ ]] )
93+ if ok and result then
94+ for entry in result :gmatch (" ([^:::]+):::" ) do
95+ local id , dir = entry :match (" (.+)|||(.+)" )
96+ if id and dir then
97+ windows [dir ] = id
98+ end
99+ end
100+ end
101+
102+ -- Get zoxide directories
103+ local zoxide_dirs = {}
104+ local handle = io.popen (" /opt/homebrew/bin/zoxide query -l -s 2>/dev/null" )
105+ if handle then
106+ local output = handle :read (" *a" )
107+ handle :close ()
108+ for score , dir in output :gmatch (" %s*([%d.]+)%s+([^\n ]+)" ) do
109+ table.insert (zoxide_dirs , { dir = dir , score = tonumber (score ) })
110+ end
111+ end
112+ table.sort (zoxide_dirs , function (a , b )
113+ return a .score > b .score
114+ end )
115+
116+ -- Build choices: zoxide order, tagging open windows
117+ local choices = {}
118+ local seen = {}
119+ for _ , entry in ipairs (zoxide_dirs ) do
120+ seen [entry .dir ] = true
121+ table.insert (choices , {
122+ text = entry .dir :gsub (home , " ~" ),
123+ subText = windows [entry .dir ] and " open" or nil ,
124+ dir = entry .dir ,
125+ windowId = windows [entry .dir ],
126+ })
127+ end
128+ for dir , id in pairs (windows ) do
129+ if not seen [dir ] then
130+ table.insert (choices , {
131+ text = dir :gsub (home , " ~" ),
132+ subText = " open" ,
133+ dir = dir ,
134+ windowId = id ,
135+ })
136+ end
137+ end
138+
139+ local chooser = hs .chooser .new (function (choice )
140+ if not choice then
141+ return
142+ end
143+
144+ if choice .windowId then
145+ hs .osascript .applescript (string.format (
146+ [[
147+ tell application "Ghostty"
148+ activate window (first window whose id is "%s")
149+ end tell
150+ ]] ,
151+ choice .windowId
152+ ))
153+ else
154+ hs .osascript .applescript (string.format (
155+ [[
156+ tell application "Ghostty"
157+ set cfg to new surface configuration
158+ set initial working directory of cfg to "%s"
159+ new window with configuration cfg
160+ end tell
161+ ]] ,
162+ choice .dir
163+ ))
164+ end
165+
166+ -- Bump zoxide score
167+ hs .execute (string.format (" /opt/homebrew/bin/zoxide add %q" , choice .dir ))
168+ end )
169+
170+ chooser :choices (choices )
171+ chooser :show ()
172+ end
173+
174+ local ghosttyKeys = hs .hotkey .modal .new ()
175+ ghosttyKeys :bind ({ " ctrl" }, " w" , ghosttySessionizer )
176+
177+ local appWatcher = hs .application .watcher .new (function (name , event )
178+ if name == " Ghostty" then
179+ if event == hs .application .watcher .activated then
180+ ghosttyKeys :enter ()
181+ elseif event == hs .application .watcher .deactivated then
182+ ghosttyKeys :exit ()
183+ end
184+ end
185+ end )
186+ appWatcher :start ()
187+
188+ if hs .application .frontmostApplication ():name () == " Ghostty" then
189+ ghosttyKeys :enter ()
190+ end
191+
75192---- ---------------------------------OTHERS-------------------------------------
76193hs .hotkey .bind (hyper , " H" , function ()
77194 hs .hints .windowHints ()
0 commit comments