Created
July 13, 2014 18:38
-
-
Save jessfraz/46f55a8ed51cd40e3681 to your computer and use it in GitHub Desktop.
hydra config
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- make sure Hydra launches at login | |
autolaunch.set(true) | |
-- watch for changes | |
pathwatcher.new(os.getenv("HOME") .. "/.hydra/", hydra.reload):start() | |
-- notify on start | |
notify.show("Hydra", "Started!", "", "") | |
-- extensions | |
ext.frame = {} | |
ext.win = {} | |
-- window margins and positions | |
ext.win.margin = 10 | |
ext.win.positions = {} | |
-- returns frame pushed to screen edge | |
function ext.frame.push(screen, direction) | |
local frames = { | |
[ "up" ] = function() | |
return { | |
x = ext.win.margin + screen.x, | |
y = screen.y, | |
w = screen.w - ext.win.margin * 2, | |
h = screen.h / 2 - ext.win.margin | |
} | |
end, | |
[ "down" ] = function() | |
return { | |
x = ext.win.margin + screen.x, | |
y = ext.win.margin * 3 / 4 + screen.h / 2 + screen.y, | |
w = screen.w - ext.win.margin * 2, | |
h = screen.h / 2 - ext.win.margin * (2 - 1 / 4) | |
} | |
end, | |
[ "left" ] = function() | |
return { | |
x = ext.win.margin + screen.x, | |
y = screen.y, | |
w = screen.w / 2 - ext.win.margin * (2 - 1 / 4), | |
h = screen.h - ext.win.margin * (2 - 1 / 4) | |
} | |
end, | |
[ "right" ] = function() | |
return { | |
x = ext.win.margin / 2 + screen.w / 2 + screen.x, | |
y = screen.y, | |
w = screen.w / 2 - ext.win.margin * (2 - 1 / 4), | |
h = screen.h - ext.win.margin * (2 - 1 / 4) | |
} | |
end | |
} | |
return frames[direction]() | |
end | |
-- returns frame pushed to screen corner | |
function ext.frame.corner(screen, direction) | |
local frames = { | |
[ "up" ] = function() | |
return { | |
x = ext.win.margin + screen.x, | |
y = screen.y, | |
w = screen.w / 2 - ext.win.margin * (2 - 1 / 4), | |
h = screen.h / 2 - ext.win.margin | |
} | |
end, | |
[ "down" ] = function() | |
return { | |
x = ext.win.margin / 2 + screen.w / 2 + screen.x, | |
y = ext.win.margin * 3 / 4 + screen.h / 2 + screen.y, | |
w = screen.w / 2 - ext.win.margin * (2 - 1 / 4), | |
h = screen.h / 2 - ext.win.margin * (2 - 1 / 4) | |
} | |
end, | |
[ "left" ] = function() | |
return { | |
x = ext.win.margin + screen.x, | |
y = ext.win.margin * 3 / 4 + screen.h / 2 + screen.y, | |
w = screen.w / 2 - ext.win.margin * (2 - 1 / 4), | |
h = screen.h / 2 - ext.win.margin * (2 - 1 / 4) | |
} | |
end, | |
[ "right" ] = function() | |
return { | |
x = ext.win.margin / 2 + screen.w / 2 + screen.x, | |
y = screen.y, | |
w = screen.w / 2 - ext.win.margin * (2 - 1 / 4), | |
h = screen.h / 2 - ext.win.margin * (2 - 1 / 4) | |
} | |
end | |
} | |
return frames[direction]() | |
end | |
-- returns frame moved by ext.win.margin | |
function ext.frame.nudge(frame, screen, direction) | |
local modifyframe = { | |
[ "up" ] = function(frame) | |
frame.y = math.max(screen.y + ext.win.margin, frame.y - ext.win.margin) | |
return frame | |
end, | |
[ "down" ] = function(frame) | |
frame.y = math.min(screen.y + screen.h - frame.h - ext.win.margin * 3 / 4, frame.y + ext.win.margin) | |
return frame | |
end, | |
[ "left" ] = function(frame) | |
frame.x = math.max(screen.x + ext.win.margin, frame.x - ext.win.margin) | |
return frame | |
end, | |
[ "right" ] = function(frame) | |
frame.x = math.min(screen.x + screen.w - frame.w - ext.win.margin, frame.x + ext.win.margin) | |
return frame | |
end | |
} | |
return modifyframe[direction](frame) | |
end | |
-- returns frame fited inside screen | |
function ext.frame.fit(screen, frame) | |
frame.w = math.min(frame.w, screen.w - ext.win.margin * 2) | |
frame.h = math.min(frame.h, screen.h - ext.win.margin * (2 - 1 / 4)) | |
return frame | |
end | |
-- returns frame centered inside screen | |
function ext.frame.center(screen, frame) | |
frame.x = screen.w / 2 - frame.w / 2 + screen.x | |
frame.y = screen.h / 2 - frame.h / 2 + screen.y | |
return frame | |
end | |
-- ugly fix for problem with window height when it's as big as screen | |
function ext.win.fix(win) | |
local screen = win:screen():frame_without_dock_or_menu() | |
local frame = win:frame() | |
if (frame.h > (screen.h - ext.win.margin * (2 - 1 / 4))) then | |
frame.h = screen.h - ext.win.margin * 10 | |
win:setframe(frame) | |
end | |
end | |
-- pushes window to next screen | |
function ext.win.pushwindow_nextscreen() | |
local win = window.focusedwindow() | |
ext.grid.set(win, ext.grid.get(win), win:screen():next()) | |
end | |
-- pushes window to previous screen | |
function ext.win.pushwindow_prevscreen() | |
local win = window.focusedwindow() | |
ext.grid.set(win, ext.grid.get(win), win:screen():previous()) | |
end | |
-- pushes window in direction and nudges to edge, fixes terminal positioning | |
function ext.win.push(win, direction) | |
local screen = win:screen():frame_without_dock_or_menu() | |
local frame | |
frame = ext.frame.push(screen, direction) | |
-- frame = ext.frame.nudge(frame, screen, direction) | |
ext.win.fix(win) | |
win:setframe(frame) | |
end | |
-- pushes window in direction and nudges to corner, fixes terminal positioning | |
function ext.win.corner(win, direction) | |
local screen = win:screen():frame_without_dock_or_menu() | |
local frame | |
frame = ext.frame.corner(screen, direction) | |
-- frame = ext.frame.nudge(frame, screen, direction) | |
ext.win.fix(win) | |
win:setframe(frame) | |
end | |
-- nudges window in direction | |
function ext.win.nudge(win, direction) | |
local screen = win:screen():frame_without_dock_or_menu() | |
local frame = win:frame() | |
frame = ext.frame.nudge(frame, screen, direction) | |
win:setframe(frame) | |
end | |
-- centers window | |
function ext.win.center(win) | |
local screen = win:screen():frame_without_dock_or_menu() | |
local frame = win:frame() | |
frame = ext.frame.center(screen, frame) | |
win:setframe(frame) | |
end | |
-- fullscreen window with ext.win.margin | |
function ext.win.full(win) | |
local screen = win:screen():frame_without_dock_or_menu() | |
local frame = { | |
x = ext.win.margin + screen.x, | |
y = screen.y, | |
w = screen.w - ext.win.margin * 2, | |
h = screen.h - ext.win.margin * (2 - 1 / 4) | |
} | |
ext.win.fix(win) | |
win:setframe(frame) | |
end | |
-- throw to next screen, center and fit | |
function ext.win.throw(win) | |
local screen = win:screen():next():frame_without_dock_or_menu() | |
local frame = win:frame() | |
frame.x = screen.x | |
frame.y = screen.y | |
frame = ext.frame.fit(screen, frame) | |
frame = ext.frame.center(screen, frame) | |
ext.win.fix(win) | |
win:setframe(frame) | |
win:focus() | |
end | |
-- set window size and center | |
function ext.win.size(win, size) | |
local screen = win:screen():frame_without_dock_or_menu() | |
local frame = win:frame() | |
frame.w = size.w | |
frame.h = size.h | |
frame = ext.frame.fit(screen, frame) | |
frame = ext.frame.center(screen, frame) | |
win:setframe(frame) | |
end | |
-- save and restore window positions | |
function ext.win.pos(win, option) | |
local id = win:application():bundleid() | |
local frame = win:frame() | |
-- saves window position if not saved before | |
if option == "save" and not ext.win.positions[id] then | |
ext.win.positions[id] = frame | |
end | |
-- force update saved window position | |
if option == "update" then | |
ext.win.positions[id] = frame | |
end | |
-- restores window position | |
if option == "load" and ext.win.positions[id] then | |
win:setframe(ext.win.positions[id]) | |
end | |
end | |
-- cycle application windows | |
-- simplified and stolen from: https://github.com/nifoc/dotfiles/blob/master/hydra/cycle.lua | |
function ext.win.cycle(win) | |
local windows = win:application():visiblewindows() | |
windows = fnutils.filter(windows, function(win) return win:isstandard() end) | |
if #windows >= 2 then | |
table.sort(windows, function(a, b) return a:id() < b:id() end) | |
local activewindowindex = fnutils.indexof(windows, win) | |
if activewindowindex then | |
activewindowindex = activewindowindex + 1 | |
if activewindowindex > #windows then activewindowindex = 1 end | |
windows[activewindowindex]:focus() | |
end | |
end | |
end | |
-- apply function to a window with optional params, saving it's position for restore | |
function dowin(fn, param) | |
return function() | |
local win = window.focusedwindow() | |
ext.win.pos(win, "save") | |
fn(win, param) | |
end | |
end | |
-- keyboard modifier for bindings | |
local mod = { "cmd", "ctrl"} | |
local mod1 = { "cmd", "ctrl", "alt" } | |
local mod2 = { "cmd", "alt" } | |
-- basic bindings | |
hotkey.bind(mod, "c", dowin(ext.win.center)) | |
hotkey.bind(mod, "m", dowin(ext.win.full)) | |
hotkey.bind(mod, "s", dowin(ext.win.pos, "update")) | |
hotkey.bind(mod, "r", dowin(ext.win.pos, "load")) | |
hotkey.bind(mod, "w", dowin(ext.win.cycle)) | |
hotkey.bind(mod, "tab", dowin(ext.win.throw)) | |
hotkey.bind(mod, "j", dowin(ext.win.pushwindow_prevscreen)) | |
hotkey.bind(mod, "k", dowin(ext.win.pushwindow_nextscreen)) | |
-- push to edges and nudge | |
fnutils.each({ "up", "down", "left", "right" }, function(direction) | |
hotkey.bind(mod, direction, dowin(ext.win.push, direction)) | |
hotkey.bind(mod1, direction, dowin(ext.win.corner, direction)) | |
hotkey.bind(mod2, direction, dowin(ext.win.nudge, direction)) | |
end) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment