Skip to content

Instantly share code, notes, and snippets.

@amirrajan
Last active January 8, 2024 06:17
Show Gist options
  • Save amirrajan/cc5ead4015a8b9252060ce6345eebe76 to your computer and use it in GitHub Desktop.
Save amirrajan/cc5ead4015a8b9252060ce6345eebe76 to your computer and use it in GitHub Desktop.
Full Hammerspoon File
require("hs.ipc")
function shell(command)
hs.execute(command .. ' &', true)
end
--- ==========================================
--- Window Management
--- ==========================================
-- ctrl+option+left resizes window to left half of screen
hs.hotkey.bind({'ctrl', 'option'}, "Left", function()
local win = hs.window.focusedWindow()
local f = win:frame()
local screen = win:screen()
local max = screen:frame()
local target_w_half = math.floor(max.w / 2)
local target_w_third = math.floor(max.w / 3)
local target_w_two_thirds = math.floor(max.w * 2 / 3)
f.x = max.x
f.y = max.y
if f.w == target_w_half then
f.w = target_w_third
elseif f.w == target_w_third then
f.w = target_w_two_thirds
else
f.w = target_w_half
end
f.h = max.h
win:setFrame(f, 0)
end)
-- ctrl+option+right resizes window to right half of screen
hs.hotkey.bind({'ctrl', 'option'}, "Right", function()
local win = hs.window.focusedWindow()
local f = win:frame()
local screen = win:screen()
local max = screen:frame()
local target_w_half = math.floor(max.w / 2)
local target_w_third = math.floor(max.w / 3)
local target_w_two_thirds = math.floor(max.w * 2 / 3)
f.y = max.y
if f.w == target_w_half and f.x == max.x + (max.w / 2) then
f.x = max.x + (max.w - target_w_third)
f.w = target_w_third
elseif f.w == target_w_third then
f.x = max.x + (max.w - target_w_two_thirds)
f.w = target_w_two_thirds
else
f.x = max.x + target_w_half
f.w = target_w_half
end
f.h = max.h
win:setFrame(f, 0)
end)
-- ctrl+option+j resizes window to fill screen
hs.hotkey.bind({'ctrl', 'option'}, "j", function()
local win = hs.window.focusedWindow()
local f = win:frame()
local screen = win:screen()
local max = screen:frame()
f.x = max.x
f.y = max.y
f.w = max.w
f.h = max.h
win:setFrame(f, 0)
end)
-- ctrl+option+, centers window and toggles between 1280x720 and full vertical height
hs.hotkey.bind({'ctrl', 'option'}, ",", function()
local win = hs.window.focusedWindow()
local f = win:frame()
local screen = win:screen()
local max = screen:frame()
local h = 748
if f.w == 1280 and f.h == h then
f.x = max.x + (max.w / 4)
f.w = max.w / 2
f.y = max.y
f.h = max.h
elseif f.w == max.w / 2 and f.x == max.x + (max.w / 4)then
f.w = 1280
f.h = h
f.x = max.x + ((max.w - f.w) / 2)
f.y = max.y + ((max.h - f.h) / 2)
else
f.x = max.x + (max.w / 4)
f.w = max.w / 2
f.y = max.y
f.h = max.h
end
win:setFrame(f, 0)
end)
-- ctrl+option+up sends window to next screen
hs.hotkey.bind({'ctrl', 'option'}, "Up", function()
local win = hs.window.focusedWindow()
win:moveToScreen(win:screen():previous(), 0)
end)
-- ctrl+option+down sends window to prev screen
hs.hotkey.bind({'ctrl', 'option'}, "Down", function()
local win = hs.window.focusedWindow()
win:moveToScreen(win:screen():next(), 0)
end)
--- ==========================================
--- Terminal <> Browser ctrl+t
--- ==========================================
-- I spend all my time in chrome and terminal, ctrl+t swaps between the two
hs.hotkey.bind({'ctrl'}, "t", function()
app_name = hs.application.frontmostApplication():name()
if app_name == 'Alacritty' then
hs.osascript.applescript('tell application "Chrome" to activate')
else
hs.osascript.applescript('tell application "Alacritty" to activate')
end
end)
--- ==========================================
--- Reload Hammerspoon
--- ==========================================
function reloadConfig(files)
hs.alert('Reloading Hammerspoon...')
shouldReload = false
for _,file in pairs(files) do
if file:sub(-4) == ".lua" then
shouldReload = true
end
end
if shouldReload then
hs.timer.delayed.new(0.1, doReload):start()
end
end
function doReload(evt)
if doReload then
result, success = hs.execute("luac -p ~/.hammerspoon/init.lua 2>&1 >/dev/null", true)
if not success then
hs.alert(result)
return
end
result, success = hs.execute("luac -p ~/.hammerspoon/Spoons/KeyFu.spoon/init.lua 2>&1 >/dev/null", true)
if not success then
hs.alert(result)
return
end
hs.reload()
end
end
hs_config_watcher = hs.pathwatcher.new(os.getenv("HOME") .. "/.hammerspoon/", reloadConfig):start()
-- ==========================================
-- ESC
-- ==========================================
g_mod_keys = true
send_escape = false
last_mods = {}
control_key_handler = function()
send_escape = false
end
control_key_timer = hs.timer.delayed.new(0.10, control_key_handler)
control_handler = function(evt)
if not g_mod_keys then
return
end
local new_mods = evt:getFlags()
if last_mods["ctrl"] == new_mods["ctrl"] then
return false
end
if not last_mods["ctrl"] then
last_mods = new_mods
send_escape = true
control_key_timer:start()
else
if send_escape then
if not g_hs_mode then
hs.eventtap.event.newKeyEvent({}, 'escape', true):post()
hs.eventtap.event.newKeyEvent({}, 'escape', false):post()
end
end
last_mods = new_mods
control_key_timer:stop()
end
return false
end
control_tap = hs.eventtap.new({hs.eventtap.event.types.flagsChanged}, control_handler)
control_tap:start()
other_handler = function(evt)
send_escape = false
return false
end
other_tap = hs.eventtap.new({hs.eventtap.event.types.keyDown}, other_handler)
other_tap:start()
-- ==========================================
-- Hammerspoon Mode
-- ==========================================
-- OS level Hammerspoon Leader Key is ctrl+m
g_hs_mode = false
g_hs_mode_command = ''
hs.hotkey.bind({'ctrl'}, "m", function()
if not g_hs_mode then
hs.alert('hs mode: on')
g_hs_mode = true
end
end)
-- when in Hammerspoon mode, process keyboard input and execute a command
hs_mode_handler = function(evt)
local new_mods = evt:getFlags()
if not g_hs_mode then
return
end
if evt:getCharacters(true) then
g_hs_mode_command = g_hs_mode_command .. evt:getCharacters(true)
end
local was_processed = false
if evt:getCharacters(true) == 'i' then -- i takes you back to insert mode
was_processed = true
hs.alert('hs mode: off')
elseif g_hs_mode_command == 'go' then -- go takes you to google
shell('open http://google.com')
was_processed = true
elseif g_hs_mode_command == 'gm' then -- gm takes you to gmail
shell('open http://gmail.com')
was_processed = true
elseif g_hs_mode_command == 'tmw' then -- tmw "top most window"
-- run the applescript and get the result
-- alert the result
local ok, r = hs.osascript.applescript('tell application "System Events" to get the name of the first window of (first process where it is frontmost)')
hs.alert(r)
was_processed = true
elseif g_hs_mode_command == 'l' then
hs.alert(hs.mouse.absolutePosition().x)
hs.alert(hs.mouse.absolutePosition().y)
was_processed = true
elseif g_hs_mode_command == 'c' then
shell("sh ~/clicker.sh")
-- local centerPoint = hs.mouse.absolutePosition() --{x = hs.screen.mainScreen():frame().w / 2, y = hs.screen.mainScreen():frame().h / 2}
-- hs.mouse.absolutePosition(centerPoint)
-- local radius = 400
-- local angle = 0
-- local step = 100
-- local ordinal_x = 0
-- local ordinal_y = 0
-- for i=radius, 0, -step do
-- local position = {x = centerPoint.x - 450 + ordinal_x, y = centerPoint.y + ordinal_y}
-- ordinal_x = ordinal_x + 64
-- if ordinal_x > 900 then
-- ordinal_x = 0
-- ordinal_y = ordinal_y + 32
-- end
-- local offPoint = {x = hs.screen.mainScreen():frame().w / 2 - 600, y = hs.screen.mainScreen():frame().h / 2}
-- print(string.format("cliclick dd:%.0f,%.0f du:%.0f,%.0f c:%.0f,%.0f",
-- math.floor(position.x - 1),
-- math.floor(position.y - 1),
-- math.floor(position.x - 2),
-- math.floor(position.y - 2),
-- math.floor(position.x - 2),
-- math.floor(position.y - 2)))
-- shell(string.format("cliclick dd:%.0f,%.0f du:%.0f,%.0f c:%.0f,%.0f",
-- math.floor(position.x - 1),
-- math.floor(position.y - 1),
-- math.floor(position.x - 2),
-- math.floor(position.y - 2),
-- math.floor(position.x - 2),
-- math.floor(position.y - 2)))
-- shell(string.format("cliclick ", math.floor(position.x), math.floor(position.y)))
-- shell(string.format("cliclick c:%.0f,%.0f", math.floor(position.x), math.floor(position.y)))
-- end
hs.alert('complete')
was_processed = true
end
if was_processed then
g_hs_mode = false
g_hs_mode_command = ''
return true
end
if string.len(g_hs_mode_command) > 3 then
hs.alert("exiting (unknown command): " .. g_hs_mode_command)
g_hs_mode = false
g_hs_mode_command = ''
end
return true
end
hs_mode = hs.eventtap.new({hs.eventtap.event.types.keyDown}, hs_mode_handler)
hs_mode:start()
hs.alert.show("Hammerspoon Loaded.")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment