Skip to content

Instantly share code, notes, and snippets.

@mediafinger
Created February 12, 2020 11:45
Show Gist options
  • Save mediafinger/86f08583b67b22825c8e8d0a50f9bb42 to your computer and use it in GitHub Desktop.
Save mediafinger/86f08583b67b22825c8e8d0a50f9bb42 to your computer and use it in GitHub Desktop.
Metakey setup macOS / use CAPS LOCK to open or switch to apps with Hammerspoon and Karabiner
-- A global variable for the Hyper Mode
hyper = hs.hotkey.modal.new({}, 'F17')
-- Enter Hyper Mode when F18 (Hyper/Capslock) is pressed
function enterHyperMode()
hyper.triggered = false
hyper:enter()
end
-- Leave Hyper Mode when F18 (Hyper/Capslock) is pressed,
-- send ESCAPE if no other keys are pressed.
function exitHyperMode()
hyper:exit()
if not hyper.triggered then
hs.eventtap.keyStroke({}, 'ESCAPE')
end
end
-- Bind the Hyper key
f18 = hs.hotkey.bind({}, 'F18', enterHyperMode, exitHyperMode)
-- Setup shortcuts, press "CAPS LOCK + X" to activate one
--
hyper:bind({}, "R", function()
hs.reload()
end)
hs.alert.show("Config Re-loaded")
-- Lock the Screen
hyper:bind({}, "L", function()
hs.caffeinate.lockScreen()
end)
function forceLaunchOrFocus(appName)
-- first focus with hammerspoon
hs.application.launchOrFocus(appName)
-- clear timer if exists
if ext.cache.launchTimer then ext.cache.launchTimer:stop() end
-- wait 500ms for window to appear and try hard to show the window
ext.cache.launchTimer = hs.timer.doAfter(0.5, function()
local frontmostApp = hs.application.frontmostApplication()
local frontmostWindows = hs.fnutils.filter(frontmostApp:allWindows(), function(win) return win:isStandard() end)
-- break if this app is not frontmost (when/why?)
if frontmostApp:title() ~= appName then
print('Expected app in front: ' .. appName .. ' got: ' .. frontmostApp:title())
return
end
if #frontmostWindows == 0 then
-- check if there's app name in window menu (Calendar, Messages, etc...)
if frontmostApp:findMenuItem({ 'Window', appName }) then
-- select it, usually moves to space with this window
frontmostApp:selectMenuItem({ 'Window', appName })
else
-- otherwise send cmd-n to create new window
hs.eventtap.keyStroke({ 'cmd' }, 'n')
end
end
end)
end
-- smart app launch or focus or cycle windows
function smartLaunchOrFocus(launchApps)
local frontmostWindow = hs.window.frontmostWindow()
local runningApps = hs.application.runningApplications()
local runningWindows = {}
-- filter running applications by apps array
local runningApps = hs.fnutils.map(launchApps, function(launchApp)
return hs.application.get(launchApp)
end)
-- create table of sorted windows per application
hs.fnutils.each(runningApps, function(runningApp)
local standardWindows = hs.fnutils.filter(runningApp:allWindows(), function(win)
return win:isStandard()
end)
table.sort(standardWindows, function(a, b) return a:id() < b:id() end)
runningWindows = standardWindows
end)
if #runningApps == 0 then
-- if no apps are running then launch first one in list
forceLaunchOrFocus(launchApps[1])
elseif #runningWindows == 0 then
-- if some apps are running, but no windows - force create one
forceLaunchOrFocus(runningApps[1]:title())
else
-- check if one of windows is already focused
local currentIndex = hs.fnutils.indexOf(runningWindows, frontmostWindow)
if not currentIndex then
-- if none of them is selected focus the first one
runningWindows[1]:focus()
else
-- otherwise cycle through all the windows
local newIndex = currentIndex + 1
if newIndex > #runningWindows then newIndex = 1 end
runningWindows[newIndex]:focus()
end
end
end
hyper:bind({}, "A", function()
smartLaunchOrFocus({"Atom"})
end)
hyper:bind({}, "C", function()
smartLaunchOrFocus({"Google Chrome"})
end)
hyper:bind({}, "E", function()
hs.application.launchOrFocus("ExpressVPN")
end)
hyper:bind({}, "F", function()
hs.application.launchOrFocus("Firefox")
end)
hyper:bind({}, "G", function()
smartLaunchOrFocus({"GitX"})
end)
hyper:bind({}, "H", function()
hs.application.launchOrFocus("HTTP Toolkit")
end)
hyper:bind({}, "T", function()
smartLaunchOrFocus({"iTerm"})
end)
hyper:bind({}, "P", function()
hs.application.launchOrFocus("Postman")
end)
hyper:bind({}, "Q", function()
hs.application.launchOrFocus("Qbserve")
end)
hyper:bind({}, "S", function()
hs.application.launchOrFocus("Slack")
end)
hyper:bind({}, "Z", function()
hs.application.launchOrFocus("zoom.us")
end)
@mediafinger
Copy link
Author

For this hammerspoon config to work, you have to map CAPS LOCK to F18 with Karabiner-Elements.

http://www.hammerspoon.org/

https://github.com/pqrs-org/Karabiner-Elements

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment