Last active
June 3, 2020 19:03
-
-
Save runningskull/ddb2befbbcb3d8f75331c071827a2a70 to your computer and use it in GitHub Desktop.
Hammerspoon config to enable naming (ie. labeling) windows and switching to them by name
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Utils -- | |
curwin = hs.window.focusedWindow | |
function err(msg) | |
hs.alert.show(' ✗ '..msg, {fillColor={red=0.618}}) | |
end | |
function prompt(main, sub) -- like built-in prompt, but automatically focuses the text input | |
local win = curwin() | |
hs.focus() | |
local _,input = hs.dialog.textPrompt(main, (sub or '')) | |
win:focus() | |
return input | |
end | |
-- Named Windows -- | |
namewins = { | |
choices = {}, | |
watchers = {}, | |
create = function() | |
local win, name = curwin(), nil | |
while true do | |
name = prompt('Window Name:') | |
if name:len() == 0 then return end | |
if namewins.find(name) then err('There is already a window named '..name) | |
else break end | |
end | |
local nw = {text=name, winid=win:id(), appid=win:application():pid()} | |
table.insert(namewins.choices, nw) | |
namewins.watch(nw) | |
namewins.save() | |
end, | |
switch = function() | |
hs.chooser.new(function(choice) | |
if not choice then return end | |
-- add current window as first choice: | |
local _,i = namewins.find(curwin():id()) | |
table.insert(namewins.choices, 1, table.remove(namewins.choices, i)) | |
-- switch to chosen window: | |
local win = hs.window.get(choice.winid) | |
if win then win:focus() end | |
namewins.save() | |
end):choices(namewins.choices):show() | |
end, | |
rename = function() | |
hs.chooser.new(function(choice) | |
if not choice then return end | |
local old_name = choice.text | |
local nw,i = namewins.find(old_name) | |
if nw then | |
local new_name = prompt('Rename Window ['..old_name..'] to:') | |
if new_name:len() > 0 then | |
nw.text = new_name | |
namewins.watchers[new_name] = namewins.watchers[old_name] | |
namewins.watchers[old_name] = nil | |
else | |
table.remove(namewins.choices, i) | |
end | |
end | |
namewins.save() | |
end):choices(namewins.choices):show() | |
end, | |
watch = function(nw) | |
local watch = {} | |
local del = function() namewins.delete(nw.text) end | |
watch.app = hs.application.watcher.new(function(_, evt, app) | |
if (evt == hs.application.watcher.terminated) and (app:pid() == nw.appid) then del() end | |
end) ; watch.app:start() | |
watch.win = hs.window.get(nw.winid):newWatcher(del) | |
watch.win:start{hs.uielement.watcher.elementDestroyed} | |
namewins.watchers[nw.text] = watch | |
end, | |
delete = function(name) | |
local nw,i = namewins.find(name) | |
if not nw then return end | |
table.remove(namewins.choices, i) | |
local watch = namewins.watchers[name] | |
if watch then | |
watch.win:stop() ; watch.app:stop() | |
namewins.watchers[name] = nil | |
end | |
end, | |
init = function() | |
local saved = hs.settings.get('namewins') or {} | |
for i,nw in ipairs(saved) do | |
local win = hs.window.get(nw.winid) | |
if (not win) or (win:application():pid() ~= nw.appid) then | |
table.remove(saved, i) | |
else | |
namewins.watch(nw) | |
end | |
end | |
namewins.choices = saved | |
namewins.save() | |
end, | |
clear = function() | |
hs.settings.clear('namewins') | |
namewins.choices = {} | |
for _,watch in pairs(namewins.watchers) do | |
watch.win:stop() ; watch.app:stop() | |
end | |
namewins.watchers = {} | |
end, | |
save = function() | |
hs.settings.set('namewins', namewins.choices) | |
end, | |
find = function(name_or_winid) | |
local field = (type(name_or_winid)=='string' and 'text' or 'winid') | |
for i,nw in ipairs(namewins.choices) do | |
if nw[field] == name_or_winid then return nw,i end | |
end | |
end, | |
} | |
namewins.init() | |
hs.hotkey.bind({'alt', 'shift'}, 'space', namewins.create) | |
hs.hotkey.bind({'cmd', 'shift'}, 'space', namewins.switch) | |
hs.hotkey.bind({'alt', 'shift'}, 'delete', namewins.rename) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage
Alt+Shift+Space
→ Enter nameCmd+Shift+Space
→ Choose a windowCmd+Shift+Space → Enter
without having to type the window name.Alt+Shift+Delete
→ Choose a window → Enter new nameNotes
namewins.clear()
from the Hammerspoon console.Known Bugs/Quirks