Open hbhargava7 opened 1 year ago
Full config:
-- [1] WINDOW MANAGEMENT
-- [1A] arrow key window management via MiroWindowsManager
local hyper = {"cmd"}
hs.loadSpoon("MiroWindowsManager")
hs.window.animationDuration = 0
spoon.MiroWindowsManager.sizes_x = {2}
spoon.MiroWindowsManager:bindHotkeys({
up = {hyper, "up"},
right = {hyper, "right"},
down = {hyper, "down"},
left = {hyper, "left"},
fullscreen = {hyper, "up"}
})
-- [1B] cmd + option + hjkl window management
positions = {
maximized = hs.layout.maximized,
centered = {x=0.15, y=0.15, w=0.7, h=0.7},
centered33 = {x=(1-0.333)/2, y=0, w=0.333, h=1},
left33 = {x=0, y=0, w=0.333, h=1},
left50 = hs.layout.left50,
left66 = {x=0, y=0, w=0.666, h=1},
right33 = {x=0.666, y=0, w=0.333, h=1},
right50 = hs.layout.right50,
right66 = {x=0.34, y=0, w=0.666, h=1},
upper50 = {x=0, y=0, w=1, h=0.5},
upper50Left50 = {x=0, y=0, w=0.5, h=0.5},
upper50Right50 = {x=0.5, y=0, w=0.5, h=0.5},
lower50 = {x=0, y=0.5, w=1, h=0.5},
lower50Left50 = {x=0, y=0.5, w=0.5, h=0.5},
lower50Right50 = {x=0.5, y=0.5, w=0.5, h=0.5}
}
function bindKey(key, fn)
hs.hotkey.bind({"alt", "shift"}, key, fn)
end
grid = {
{key="h", units={positions.left50, positions.left66, positions.left33}},
{key="k", units={positions.maximized, positions.centered33}},
{key="j", units={positions.lower50, positions.maximized}},
{key="l", units={positions.right50, positions.right66, positions.right33}},
}
hs.fnutils.each(grid, function(entry)
bindKey(entry.key, function()
local units = entry.units
local screen = hs.screen.mainScreen()
local window = hs.window.focusedWindow()
local windowGeo = window:frame()
local index = 0
hs.fnutils.find(units, function(unit)
index = index + 1
local geo = hs.geometry.new(unit):fromUnitRect(screen:frame())
local x_within_tolerance = math.abs(geo.x - windowGeo.x) < 0.03 * windowGeo.w
local y_within_tolerance = math.abs(geo.y - windowGeo.y) < 0.03 * windowGeo.h
local w_within_tolerance = math.abs(geo.w - windowGeo.w) < 0.03 * windowGeo.w
local h_within_tolerance = math.abs(geo.h - windowGeo.h) < 0.03 * windowGeo.h
return x_within_tolerance and y_within_tolerance and w_within_tolerance and h_within_tolerance
end)
if index == #units then index = 0 end
window:moveToUnit(units[index + 1])
end)
end)
-- [1C] switch focus left or right
function focus_right()
local win = hs.window.focusedWindow()
local f = win:frame()
local screen = win:screen()
local max = screen:frame()
-- Check if the window is already at the right edge of the screen
if f.x + f.w == max.x + max.w then
-- If it is, move the focus to the window to the right of the current screen
local newScreen = screen:toEast()
if newScreen then
-- Get the list of windows for the new screen
local windows = hs.fnutils.filter(hs.window.orderedWindows(), function(w) return w:screen() == newScreen end)
-- If there are any windows on the new screen, focus the last one
if #windows > 0 then windows[#windows]:focus() end
end
else
-- If the window is not at the right edge of the screen, get the list of windows to the right
local windows = hs.fnutils.filter(hs.window.orderedWindows(), function(w)
local wf = w:frame()
return wf.x > f.x and wf.y == f.y
end)
-- If there are any windows to the right, focus the frontmost one
if #windows > 0 then windows[1]:focus() end
end
end
function focus_left()
local win = hs.window.focusedWindow()
local f = win:frame()
local screen = win:screen()
local max = screen:frame()
-- Check if the window is already at the left edge of the screen
if f.x == max.x then
-- If it is, move the focus to the window to the left of the current screen
local newScreen = screen:toWest()
if newScreen then
-- Get the list of windows for the new screen
local windows = hs.fnutils.filter(hs.window.orderedWindows(), function(w) return w:screen() == newScreen end)
-- If there are any windows on the new screen, focus the last one
if #windows > 0 then windows[#windows]:focus() end
end
else
-- If the window is not at the left edge of the screen, get the list of windows to the left
local windows = hs.fnutils.filter(hs.window.orderedWindows(), function(w)
local wf = w:frame()
return wf.x < f.x and wf.y == f.y
end)
-- If there are any windows to the left, focus the frontmost one
if #windows > 0 then windows[1]:focus() end
end
end
hs.hotkey.bind({'cmd', 'alt'}, 'l', focus_right)
hs.hotkey.bind({'cmd', 'alt'}, 'h', focus_left)
-- [2] APPLICATION HOTKEYS
-- [2A] Hotkeys to open specific applications
function open(name)
return function()
hs.application.launchOrFocus(name)
if name == 'Finder' then
hs.appfinder.appFromName(name):activate()
end
end
end
hs.hotkey.bind({"alt"}, "F", open("Finder"))
hs.hotkey.bind({"alt"}, "C", open("Google Chrome"))
hs.hotkey.bind({"alt"}, "T", open("iTerm"))
hs.hotkey.bind({"alt"}, "V", open("Visual Studio Code"))
hs.hotkey.bind({"alt"}, "S", open("Sublime Text"))
hs.hotkey.bind({"alt"}, "M", open("Messages"))
hs.hotkey.bind({"alt"}, "K", open("Fantastical"))
hs.hotkey.bind({"alt"}, "N", open("Notion"))
hs.hotkey.bind({"alt", "shift"}, "S", open("Spotify"))
hs.hotkey.bind({"alt", "shift"}, "F", open("Figma"))
-- [2B] Hotkeys to open specific Chrome tabs
-- Open specific chrome tabs based on string search within the URL
function chrome_active_tab_with_url(url)
return function()
hs.osascript.javascript([[
// below is javascript code
(function() {
var chrome = Application('Google Chrome');
chrome.activate();
for (win of chrome.windows()) {
var tabIndex = win.tabs().findIndex(tab => tab.url().match(']] .. url .. [['));
if (tabIndex != -1) {
win.activeTabIndex = (tabIndex + 1);
win.index = 1
}
}
})();
// end of javascript
]])
end
end
--- Bind
hs.hotkey.bind({"alt"}, "P", chrome_active_tab_with_url("polymail"))
hs.hotkey.bind({"alt"}, "A", chrome_active_tab_with_url("notion.so"))
-- 3 EMOJI SELECTOR
-- Build the list of emojis to be displayed.
local choices = {}
for _, emoji in ipairs(hs.json.decode(io.open("emojis/emojis.json"):read())) do
table.insert(choices,
{text=emoji['name'],
subText=table.concat(emoji['kwds'], ", "),
image=hs.image.imageFromPath("emojis/" .. emoji['id'] .. ".png"),
chars=emoji['chars']
})
end
-- Focus the last used window.
local function focusLastFocused()
local wf = hs.window.filter
local lastFocused = wf.defaultCurrentSpace:getWindows(wf.sortByFocusedLast)
if #lastFocused > 0 then lastFocused[1]:focus() end
end
-- Create the chooser.
-- On selection, copy the emoji and type it into the focused application.
local chooser = hs.chooser.new(function(choice)
if not choice then focusLastFocused(); return end
hs.pasteboard.setContents(choice["chars"])
focusLastFocused()
hs.eventtap.keyStrokes(hs.pasteboard.getContents())
end)
chooser:searchSubText(true)
chooser:choices(choices)
chooser:rows(5)
chooser:bgDark(true)
hs.hotkey.bind({"cmd", "alt"}, "E", function() chooser:show() end)
I'm also getting hangs (beach ball on Hammerspoon icon in taskbar) after upgrading macOS to Ventura.
Also running into this.
Experiencing an intermittent (1-2x per day) hang in Hammerspoon that causes:
Since it's an intermittent issue, it's been difficult to debug. My Console doesn't show any red flags.
I believe the issue is triggered when I call my application hotkeys (full init.lua below):
I ran Activity Monitor -> Sample during a hang. Note that the hangs are detected by Activity Monitor. I'm not sure how to interpret that info, but I saw it was done in #2923 by @n8henrie. Can provide the rest of the file if useful.