Skip to content

Instantly share code, notes, and snippets.

@philc
Created October 13, 2017 18:43
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save philc/ed70ae4e60062c2d494fae97d5da43ce to your computer and use it in GitHub Desktop.
Save philc/ed70ae4e60062c2d494fae97d5da43ce to your computer and use it in GitHub Desktop.
My hammerspoon config
-----------------------------------------------------------------------
-- References:
-- https://github.com/apesic/dotfiles/blob/master/.hammerspoon/init.lua
-- https://learnxinyminutes.com/docs/lua/
-----------------------------------------------------------------------
----------------
-- Configuration
----------------
-- Make the alerts look nicer.
hs.alert.defaultStyle.strokeColor = {white = 1, alpha = 0}
hs.alert.defaultStyle.fillColor = {white = 0.05, alpha = 0.75}
hs.alert.defaultStyle.radius = 10
-- Disable the slow default window animations.
hs.window.animationDuration = 0
-- Modifier sets that I use
local mash_app = {"cmd", "ctrl"}
---------------------
-- Window positioning
---------------------
function moveLeftHalf()
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 / 2
f.h = max.h
win:setFrame(f)
end
function moveRightHalf()
local win = hs.window.focusedWindow()
local f = win:frame()
local screen = win:screen()
local max = screen:frame()
f.x = max.x + (max.w / 2)
f.y = max.y
f.w = max.w / 2
f.h = max.h
win:setFrame(f)
end
function maximize()
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)
end
function moveToScreen(screenPos)
window = hs.window.focusedWindow()
screen = hs.screen.find({x=screenPos, y=0})
window:moveToScreen(screen)
end
hs.hotkey.bind(mash_app, "1", function()
moveToScreen(0)
moveLeftHalf()
end)
hs.hotkey.bind(mash_app, "2", function()
moveToScreen(0)
moveRightHalf()
end)
hs.hotkey.bind(mash_app, "3", function()
moveToScreen(1)
moveLeftHalf()
end)
hs.hotkey.bind(mash_app, "4", function()
moveToScreen(1)
moveRightHalf()
end)
hs.hotkey.bind(mash_app, "M", maximize)
-------------------------------------
-- Application focusing shortcuts
-------------------------------------
-- Like hs.application.launchOrFocus, except that it works for apps created using Epichrome.
-- I'm not sure why this implementation has different behavior than hs.application.launchOrFocus.
-- Reference: https://github.com/Hammerspoon/hammerspoon/issues/304
function myLaunchOrFocus(appName)
local app = hs.appfinder.appFromName(appName)
if app == nil then
hs.application.launchOrFocus(appName)
else
windows = app:allWindows()
if windows[1] then
windows[1]:focus()
end
end
end
hs.hotkey.bind(mash_app, 'L', function() myLaunchOrFocus('Google Chrome') end)
hs.hotkey.bind(mash_app, 'J', function() myLaunchOrFocus('Emacs') end)
hs.hotkey.bind(mash_app, 'K', function() myLaunchOrFocus('/Applications/iTerm.app') end)
hs.hotkey.bind(mash_app, 'U', function() myLaunchOrFocus('Gmail') end)
hs.hotkey.bind(mash_app, 'Y', function() myLaunchOrFocus('GmailPersonal') end)
hs.hotkey.bind(mash_app, ',', function() myLaunchOrFocus('Slack') end)
hs.hotkey.bind(mash_app, 'N', function() myLaunchOrFocus('Terminal') end)
hs.hotkey.bind({"cmd", "ctrl", "shift"}, 'N', function () myLaunchOrFocus('Spotify') end)
hs.hotkey.bind(mash_app, 'O', function() myLaunchOrFocus('Org') end)
hs.hotkey.bind(mash_app, 'C', function() myLaunchOrFocus('GCalendar') end)
-------------------------------------
-- Window layouts
-------------------------------------
local leftScreen = hs.screen{x=0,y=0}
local centerScreen = hs.screen{x=1,y=0}
local rightScreen = hs.screen{x=2,y=0}
local threeScreenLayout = {
{"Emacs", nil, centerScreen, hs.layout.maximized, nil, nil},
{"Google Chrome", nil, leftScreen, hs.layout.maximized, nil, nil},
{"iTerm2", nil, leftScreen, hs.layout.maximized, nil, nil},
{"Gmail", nil, leftScreen, hs.layout.maximized, nil, nil},
{"GmailPersonal", nil, leftScreen, hs.layout.right50, nil, nil},
{"GCalendar", nil, centerScreen, hs.layout.left50, nil, nil},
{"Slack", nil, leftScreen, hs.layout.right50, nil, nil},
{"MacVim", nil, leftScreen, hs.layout.right50, nil, nil},
{"Org", nil, leftScreen, hs.layout.left50, nil, nil},
{"Xcode", nil, centerScreen, hs.layout.right50, nil, nil},
{"Finder", nil, centerScreen, hs.layout.left50, nil, nil},
{"Preview", nil, centerScreen, hs.layout.left50, nil, nil},
{"OmniGraffle 6", nil, centerScreen, hs.layout.maximized, nil, nil},
{"Terminal", nil, centerScreen, hs.layout.left50, nil, nil},
{"Spotify", nil, centerScreen, hs.layout.left50, nil, nil},
{"PowerPoint", nil, leftScreen, hs.layout.left50, nil, nil},
{"Calendar", nil, leftScreen, hs.layout.maximized, nil, nil},
{"System Preferences", nil, leftScreen, hs.layout.left50, nil, nil}
}
local twoScreenLayout = {
{"Emacs", nil, leftScreen, hs.layout.maximized, nil, nil},
{"Google Chrome", nil, leftScreen, hs.layout.left50, nil, nil},
{"iTerm2", nil, leftScreen, hs.layout.maximized, nil, nil},
{"Gmail", nil, leftScreen, hs.layout.maximized, nil, nil},
{"GmailPersonal", nil, leftScreen, hs.layout.left50, nil, nil},
{"GCalendar", nil, leftScreen, hs.layout.left50, nil, nil},
{"Slack", nil, leftScreen, hs.layout.right50, nil, nil},
{"MacVim", nil, leftScreen, hs.layout.right50, nil, nil},
{"Org", nil, leftScreen, hs.layout.left50, nil, nil},
{"Xcode", nil, leftScreen, hs.layout.right50, nil, nil},
{"Finder", nil, leftScreen, hs.layout.left50, nil, nil},
{"Preview", nil, leftScreen, hs.layout.left50, nil, nil},
{"OmniGraffle 6", nil, leftScreen, hs.layout.maximized, nil, nil},
{"Terminal", nil, leftScreen, hs.layout.left50, nil, nil},
{"Spotify", nil, leftScreen, hs.layout.left50, nil, nil},
{"PowerPoint", nil, leftScreen, hs.layout.left50, nil, nil},
{"Calendar", nil, leftScreen, hs.layout.left50, nil, nil},
{"System Preferences", nil, leftScreen, hs.layout.left50, nil, nil}
}
function switchLayout()
local numScreens = #hs.screen.allScreens()
local layout = {}
if numScreens == 1 then
layout = twoScreenLayout
elseif numScreens == 2 then
layout = twoScreenLayout
elseif numScreens == 3 then
layout = threeScreenLayout
end
hs.layout.apply(layout)
end
hs.hotkey.bind(mash_app, "'", function()
switchLayout()
end)
-------------------
-- Other shortcuts
-------------------
-- Lock the screen. This may also be possible with hs.caffeinate.lockScreen.
hs.hotkey.bind({"cmd", "alt", "ctrl"}, "l", function()
os.execute("/Users/phil/scripts/macos/lock_screen.sh")
end)
-- Lock the screen. This may also be possible with hs.caffeinate.lockScreen.
hs.hotkey.bind(mash_app, "9", function()
os.execute("/Users/phil/scripts/macos/lock_screen.sh")
end)
function getVolumeIncrement()
local volume = hs.audiodevice.current().volume
-- When the volume gets near zero, change it in smaller increments. Otherwise even the first increment
-- above zero may be too loud.
-- NOTE(phil): I noticed that using a decimal smaller than 0.4 will sometimes result in the volume remaining
-- unchanged after calling setVolume, as if OSX only lets you change the volume by large increments.
if volume < 2 then return 0.4 else return 2 end
end
hs.hotkey.bind(mash_app, "9", function()
hs.audiodevice.defaultOutputDevice():setVolume(hs.audiodevice.current().volume - getVolumeIncrement())
end)
hs.hotkey.bind(mash_app, "0", function()
hs.audiodevice.defaultOutputDevice():setVolume(hs.audiodevice.current().volume + getVolumeIncrement())
end)
-- Show date time and battery
hs.hotkey.bind(mash_app, 'T', function()
local seconds = 3
local message = os.date("%I:%M%p") .. "\n" .. os.date("%a %b %d") .. "\nBattery: " ..
hs.battery.percentage() .. "%"
hs.alert.show(message, seconds)
end)
-- Shortcut to reload this hammerspoon config
hs.hotkey.bind({"cmd", "alt", "ctrl"}, "R", function() hs.reload() end)
hs.alert.show("Config loaded")
@philc
Copy link
Author

philc commented Nov 2, 2017

My hammerspoon config is now checked in here

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