this repo has no description
at main 3.1 kB view raw
1local appBindings = { 2 ["1"] = "Slack", 3 ["2"] = "Discord", 4 ["3"] = "Messages", 5 ["4"] = "Mail", 6 ["7"] = "Spotify", 7 ["8"] = "Firefox", 8 ["9"] = "Ghostty", 9 ["0"] = "Obsidian", 10} 11 12for key, app in pairs(appBindings) do 13 hs.hotkey.bind({ "cmd", "ctrl" }, key, function() 14 hs.application.launchOrFocus(app) 15 end) 16end 17 18hs.hotkey.bind({ "cmd", "ctrl" }, "r", function() 19 hs.reload() 20end) 21 22-- Window management 23hs.window.animationDuration = 0 24 25local function moveWindow(fn) 26 local win = hs.window.focusedWindow() 27 if not win then return end 28 local screen = win:screen():frame() 29 fn(win, screen) 30end 31 32local windowBindings = { 33 h = function(w, s) w:setFrame({ x = s.x, y = s.y, w = s.w / 2, h = s.h }) end, 34 l = function(w, s) w:setFrame({ x = s.x + s.w / 2, y = s.y, w = s.w / 2, h = s.h }) end, 35 Return = function(w, s) w:setFrame(s) end, 36 u = function(w, s) w:setFrame({ x = s.x, y = s.y, w = s.w / 2, h = s.h / 2 }) end, 37 i = function(w, s) w:setFrame({ x = s.x + s.w / 2, y = s.y, w = s.w / 2, h = s.h / 2 }) end, 38 j = function(w, s) w:setFrame({ x = s.x, y = s.y + s.h / 2, w = s.w / 2, h = s.h / 2 }) end, 39 k = function(w, s) w:setFrame({ x = s.x + s.w / 2, y = s.y + s.h / 2, w = s.w / 2, h = s.h / 2 }) end, 40} 41 42for key, fn in pairs(windowBindings) do 43 hs.hotkey.bind({ "ctrl", "alt" }, key, function() moveWindow(fn) end) 44end 45 46-- Cycling window positions (thirds and 2/3rds) 47local cycleState = { g = 0, e = 0 } 48 49-- g: 1/3 width, cycles right → middle → left 50hs.hotkey.bind({ "ctrl", "alt" }, "g", function() 51 local win = hs.window.focusedWindow() 52 if not win then return end 53 local s = win:screen():frame() 54 local positions = { 55 { x = s.x + s.w * 2 / 3, y = s.y, w = s.w / 3, h = s.h }, 56 { x = s.x + s.w / 3, y = s.y, w = s.w / 3, h = s.h }, 57 { x = s.x, y = s.y, w = s.w / 3, h = s.h }, 58 } 59 cycleState.g = (cycleState.g % #positions) + 1 60 win:setFrame(positions[cycleState.g]) 61end) 62 63-- e: 2/3 width, cycles left → right 64hs.hotkey.bind({ "ctrl", "alt" }, "e", function() 65 local win = hs.window.focusedWindow() 66 if not win then return end 67 local s = win:screen():frame() 68 local positions = { 69 { x = s.x, y = s.y, w = s.w * 2 / 3, h = s.h }, 70 { x = s.x + s.w / 3, y = s.y, w = s.w * 2 / 3, h = s.h }, 71 } 72 cycleState.e = (cycleState.e % #positions) + 1 73 win:setFrame(positions[cycleState.e]) 74end) 75 76-- Volume control 77local volumeStep = 5 78local volumeMods = { "ctrl", "shift", "cmd" } 79local volumeAlertId = nil 80 81local function showVolumeAlert(vol) 82 if volumeAlertId then hs.alert.closeSpecific(volumeAlertId) end 83 volumeAlertId = hs.alert.show("Volume: " .. math.floor(vol) .. "%") 84end 85 86hs.hotkey.bind(volumeMods, "=", function() 87 local device = hs.audiodevice.defaultOutputDevice() 88 device:setVolume(math.min(100, device:volume() + volumeStep)) 89 showVolumeAlert(device:volume()) 90end) 91 92hs.hotkey.bind(volumeMods, "-", function() 93 local device = hs.audiodevice.defaultOutputDevice() 94 device:setVolume(math.max(0, device:volume() - volumeStep)) 95 showVolumeAlert(device:volume()) 96end) 97 98hs.alert.show("Config loaded")