Skip to content

Instantly share code, notes, and snippets.

@hasantahir
Last active June 8, 2020 16:20
Show Gist options
  • Save hasantahir/5a86706661514b4b968219ecc41c224e to your computer and use it in GitHub Desktop.
Save hasantahir/5a86706661514b4b968219ecc41c224e to your computer and use it in GitHub Desktop.
My Config File of Hammerspoon
-- -----------------------------------------------------------------------
-- ** HammerSpoon Config File by S1ngS1ng with ❤️ ** --
-- -----------------------------------------------------------------------
-- *** Please refer to README.MD for instructions. Cheers! *** --
-- -----------------------------------------------------------------------
-- ** Something Global ** --
-- -----------------------------------------------------------------------
-- Uncomment this following line if you don't wish to see animations
-- hs.window.animationDuration = 0
-- -----------------------------------------------------------------------
-- ** Requires ** --
-- -----------------------------------------------------------------------
require "window-management"
-- require "vox-control"
-- require "vim-binding"
require "key-binding"
-- -----------------------------------------------------------------------
-- ** For Debug ** --
-- -----------------------------------------------------------------------
function reloadConfig(files)
local doReload = false
for _,file in pairs(files) do
if file:sub(-4) == ".lua" then
doReload = true
end
end
if doReload then
hs.reload()
hs.alert.show('Config Reloaded')
end
end
hs.pathwatcher.new(os.getenv("HOME") .. "/.hammerspoon/", reloadConfig):start()
-- Well, sometimes auto-reload is not working, you know u.u
hs.hotkey.bind({"cmd", "alt", "ctrl"}, "n", function()
hs.reload()
end)
hs.alert.show("Config loaded")
-- function move(dir)
-- local counter = {
-- right = 0,
-- left = 0
-- }
-- return function()
-- counter[dir] = _move(dir, counter[dir])
-- end
-- end
--
-- function _move(dir, ct)
-- local screenWidth = hs.screen.mainScreen():frame().w
-- local focusedWindowFrame = hs.window.focusedWindow():frame()
-- local x = focusedWindowFrame.x
-- local w = focusedWindowFrame.w
-- local value = dir == 'right' and x + w or x
-- local valueTarget = dir == 'right' and screenWidth or 0
-- if value ~= valueTarget then
-- hs.window.focusedWindow():moveToUnit(hs.layout[dir .. 50])
-- return 50
-- elseif ct == 50 then
-- hs.window.focusedWindow():moveToUnit(hs.layout[dir .. 70])
-- return 70
-- elseif ct == 70 then
-- hs.window.focusedWindow():moveToUnit(hs.layout[dir .. 30])
-- return 30
-- else
-- hs.window.focusedWindow():moveToUnit(hs.layout[dir .. 50])
-- return 50
-- end
-- end
--
-- --- window
-- hs.window.animationDuration = .05
-- hs.hotkey.bind({"ctrl", "cmd"}, "Right", move('right'))
-- hs.hotkey.bind({"ctrl", "cmd"}, "Left", move('left'))
--- App Hotkeys
function open(name)
return function()
hs.application.launchOrFocus(name)
if name == 'Finder' then
hs.appfinder.appFromName(name):activate()
end
end
end
--- quick open applications
hs.hotkey.bind({"alt"}, "E", open("Finder"))
hs.hotkey.bind({"alt"}, "A", open("Atom"))
hs.hotkey.bind({"alt"}, "C", open("Google Chrome"))
hs.hotkey.bind({"alt"}, "O", open("Microsoft Outlook"))
hs.hotkey.bind({"alt"}, "X", open("Microsoft Excel"))
hs.hotkey.bind({"alt"}, "W", open("Microsoft Word"))
hs.hotkey.bind({"alt"}, "P", open("Microsoft PowerPoint"))
hs.hotkey.bind({"alt"}, "R", open("Microsoft Remote Desktop"))
hs.hotkey.bind({"alt"}, "M", open("MATLAB_R2019a"))
hs.hotkey.bind({"alt"}, "T", open("Terminal"))
hs.hotkey.bind({"alt","cmd", "ctrl"}, "D", open("Dictionary"))
hs.hotkey.bind({"alt","cmd", "ctrl"}, "S", open("Textshot-OCR"))
local wm = require('window-management')
local hk = require "hs.hotkey"
-- * Key Binding Utility
--- Bind hotkey for window management.
-- @function windowBind
-- @param {table} hyper - hyper key set
-- @param { ...{key=value} } keyFuncTable - multiple hotkey and function pairs
-- @key {string} hotkey
-- @value {function} callback function
local function windowBind(hyper, keyFuncTable)
for key,fn in pairs(keyFuncTable) do
hk.bind(hyper, key, fn)
end
end
-- * Move window to screen
windowBind({"ctrl", "alt"}, {
left = wm.throwLeft,
right = wm.throwRight
})
-- * Set Window Position on screen
windowBind({"ctrl", "alt", "cmd"}, {
m = wm.maximizeWindow, -- ⌃⌥⌘ + M
c = wm.centerOnScreen, -- ⌃⌥⌘ + C
left = wm.leftHalf, -- ⌃⌥⌘ + ←
right = wm.rightHalf, -- ⌃⌥⌘ + →
up = wm.topHalf, -- ⌃⌥⌘ + ↑
down = wm.bottomHalf -- ⌃⌥⌘ + ↓
})
-- * Set Window Position on screen
windowBind({"ctrl", "alt", "shift"}, {
left = wm.rightToLeft, -- ⌃⌥⇧ + ←
right = wm.rightToRight, -- ⌃⌥⇧ + →
up = wm.bottomUp, -- ⌃⌥⇧ + ↑
down = wm.bottomDown -- ⌃⌥⇧ + ↓
})
-- * Set Window Position on screen
windowBind({"alt", "cmd", "shift"}, {
left = wm.leftToLeft, -- ⌥⌘⇧ + ←
right = wm.leftToRight, -- ⌥⌘⇧ + →
up = wm.topUp, -- ⌥⌘⇧ + ↑
down = wm.topDown -- ⌥⌘⇧ + ↓
})
-- * Windows-like cycle
windowBind({"ctrl", "alt", "cmd"}, {
u = wm.cycleLeft, -- ⌃⌥⌘ + u
i = wm.cycleRight -- ⌃⌥⌘ + i
})
-- -----------------------------------------------------------------------
-- ** Something Global ** --
-- -----------------------------------------------------------------------
-- Comment out this following line if you wish to see animations
local windowMeta = {}
window = require "hs.window"
hs.window.animationDuration = 0
grid = require "hs.grid"
grid.setMargins('0, 0')
module = {}
-- Set screen watcher, in case you connect a new monitor, or unplug a monitor
screens = {}
screenArr = {}
local screenwatcher = hs.screen.watcher.new(function()
screens = hs.screen.allScreens()
end)
screenwatcher:start()
-- Construct list of screens
indexDiff = 0
for index=1,#hs.screen.allScreens() do
local xIndex,yIndex = hs.screen.allScreens()[index]:position()
screenArr[xIndex] = hs.screen.allScreens()[index]
end
-- Find lowest screen index, save to indexDiff if negative
hs.fnutils.each(screenArr, function(e)
local currentIndex = hs.fnutils.indexOf(screenArr, e)
if currentIndex < 0 and currentIndex < indexDiff then
indexDiff = currentIndex
end
end)
-- Set screen grid depending on resolution
-- TODO: set grid according to pixels
for _index,screen in pairs(hs.screen.allScreens()) do
if screen:frame().w / screen:frame().h > 2 then
-- 10 * 4 for ultra wide screen
grid.setGrid('10 * 4', screen)
else
if screen:frame().w < screen:frame().h then
-- 4 * 8 for vertically aligned screen
grid.setGrid('4 * 8', screen)
else
-- 8 * 4 for normal screen
grid.setGrid('8 * 4', screen)
end
end
end
-- Some constructors, just for programming
function Cell(x, y, w, h)
return hs.geometry(x, y, w, h)
end
-- Bind new method to windowMeta
function windowMeta.new()
local self = setmetatable(windowMeta, {
-- Treate table like a function
-- Event listener when windowMeta() is called
__call = function (cls, ...)
return cls.new(...)
end,
})
self.window = window.focusedWindow()
self.screen = window.focusedWindow():screen()
self.windowGrid = grid.get(self.window)
self.screenGrid = grid.getGrid(self.screen)
return self
end
-- -----------------------------------------------------------------------
-- ** ALERT: GEEKS ONLY, GLHF :C ** --
-- ** Keybinding configurations locate at bottom ** --
-- -----------------------------------------------------------------------
module.maximizeWindow = function ()
local this = windowMeta.new()
hs.grid.maximizeWindow(this.window)
end
module.centerOnScreen = function ()
local this = windowMeta.new()
this.window:centerOnScreen(this.screen)
end
module.throwLeft = function ()
local this = windowMeta.new()
this.window:moveOneScreenWest()
end
module.throwRight = function ()
local this = windowMeta.new()
this.window:moveOneScreenEast()
end
module.leftHalf = function ()
local this = windowMeta.new()
local cell = Cell(0, 0, 0.5 * this.screenGrid.w, this.screenGrid.h)
grid.set(this.window, cell, this.screen)
this.window.setShadows(true)
end
module.rightHalf = function ()
local this = windowMeta.new()
local cell = Cell(0.5 * this.screenGrid.w, 0, 0.5 * this.screenGrid.w, this.screenGrid.h)
grid.set(this.window, cell, this.screen)
end
-- Windows-like cycle left
module.cycleLeft = function ()
local this = windowMeta.new()
-- Check if this window is on left or right
if this.windowGrid.x == 0 then
local currentIndex = hs.fnutils.indexOf(screenArr, this.screen)
local previousScreen = screenArr[(currentIndex - indexDiff - 1) % #hs.screen.allScreens() + indexDiff]
this.window:moveToScreen(previousScreen)
module.rightHalf()
else
module.leftHalf()
end
end
-- Windows-like cycle right
module.cycleRight = function ()
local this = windowMeta.new()
-- Check if this window is on left or right
if this.windowGrid.x == 0 then
module.rightHalf()
else
local currentIndex = hs.fnutils.indexOf(screenArr, this.screen)
local nextScreen = screenArr[(currentIndex - indexDiff + 1) % #hs.screen.allScreens() + indexDiff]
this.window:moveToScreen(nextScreen)
module.leftHalf()
end
end
module.topHalf = function ()
local this = windowMeta.new()
local cell = Cell(0, 0, this.screenGrid.w, 0.5 * this.screenGrid.h)
grid.set(this.window, cell, this.screen)
end
module.bottomHalf = function ()
local this = windowMeta.new()
local cell = Cell(0, 0.5 * this.screenGrid.h, this.screenGrid.w, 0.5 * this.screenGrid.h)
grid.set(this.window, cell, this.screen)
end
module.rightToLeft = function ()
local this = windowMeta.new()
local cell = Cell(this.windowGrid.x, this.windowGrid.y, this.windowGrid.w - 1, this.windowGrid.h)
if this.windowGrid.w > 1 then
grid.set(this.window, cell, this.screen)
else
hs.alert.show("Small Enough :)")
end
end
module.rightToRight = function ()
local this = windowMeta.new()
local cell = Cell(this.windowGrid.x, this.windowGrid.y, this.windowGrid.w + 1, this.windowGrid.h)
if this.windowGrid.w < this.screenGrid.w - this.windowGrid.x then
grid.set(this.window, cell, this.screen)
else
hs.alert.show("Touching Right Edge :|")
end
end
module.bottomUp = function ()
local this = windowMeta.new()
local cell = Cell(this.windowGrid.x, this.windowGrid.y, this.windowGrid.w, this.windowGrid.h - 1)
if this.windowGrid.h > 1 then
grid.set(this.window, cell, this.screen)
else
hs.alert.show("Small Enough :)")
end
end
module.bottomDown = function ()
local this = windowMeta.new()
local cell = Cell(this.windowGrid.x, this.windowGrid.y, this.windowGrid.w, this.windowGrid.h + 1)
if this.windowGrid.h < this.screenGrid.h - this.windowGrid.y then
grid.set(this.window, cell, this.screen)
else
hs.alert.show("Touching Bottom Edge :|")
end
end
module.leftToLeft = function ()
local this = windowMeta.new()
local cell = Cell(this.windowGrid.x - 1, this.windowGrid.y, this.windowGrid.w + 1, this.windowGrid.h)
if this.windowGrid.x > 0 then
grid.set(this.window, cell, this.screen)
else
hs.alert.show("Touching Left Edge :|")
end
end
module.leftToRight = function ()
local this = windowMeta.new()
local cell = Cell(this.windowGrid.x + 1, this.windowGrid.y, this.windowGrid.w - 1, this.windowGrid.h)
if this.windowGrid.w > 1 then
grid.set(this.window, cell, this.screen)
else
hs.alert.show("Small Enough :)")
end
end
module.topUp = function ()
local this = windowMeta.new()
local cell = Cell(this.windowGrid.x, this.windowGrid.y - 1, this.windowGrid.w, this.windowGrid.h + 1)
if this.windowGrid.y > 0 then
grid.set(this.window, cell, this.screen)
else
hs.alert.show("Touching Top Edge :|")
end
end
module.topDown = function ()
local this = windowMeta.new()
local cell = Cell(this.windowGrid.x, this.windowGrid.y + 1, this.windowGrid.w, this.windowGrid.h - 1)
if this.windowGrid.h > 1 then
grid.set(this.window, cell, this.screen)
else
hs.alert.show("Small Enough :)")
end
end
return module
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment