|
|
|
local LOGLEVEL = 'debug'
|
|
|
|
|
|
|
|
log = hs.logger.new('init', 'debug')
|
|
|
|
|
|
|
|
require 'autoscript'
|
|
|
|
require 'ime'
|
|
|
|
-- require 'usb'
|
|
|
|
|
|
|
|
-- hs.loadSpoon("ReloadConfiguration")
|
|
|
|
-- spoon.ReloadConfiguration:start()
|
|
|
|
-- hs.alert.show("Config reload!")
|
|
|
|
|
|
|
|
-- Hyper key in Sierra
|
|
|
|
k = hs.hotkey.modal.new({}, "F17")
|
|
|
|
|
|
|
|
-- Enter Hyper Mode when F18 (Hyper/Capslock) is pressed
|
|
|
|
pressedF18 = function() k:enter() end
|
|
|
|
|
|
|
|
-- Leave Hyper Mode when F18 (Hyper/Capslock) is pressed,
|
|
|
|
-- send ESCAPE if no other keys are pressed.
|
|
|
|
releasedF18 = function() k:exit() end
|
|
|
|
|
|
|
|
f18 = hs.hotkey.bind({}, 'F18', pressedF18, releasedF18)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hyper = {"ctrl", "alt", "cmd", "shift"}
|
|
|
|
|
|
|
|
-- hs.hotkey.bind(hyper, "C", function() hs.application.launchOrFocus("Google Chrome") end)
|
|
|
|
function moveWindowToDisplay(d)
|
|
|
|
return function()
|
|
|
|
local displays = hs.screen.allScreens()
|
|
|
|
log.i(displays)
|
|
|
|
local win = hs.window.focusedWindow()
|
|
|
|
win:moveToScreen(displays[d], false, true)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- hs.hotkey.bind(hyper, "m", moveWindowToDisplay(1))
|
|
|
|
-- hs.hotkey.bind(hyper, "8", moveWindowToDisplay(2))
|
|
|
|
-- hs.hotkey.bind(hyper, "9", moveWindowToDisplay(3))
|
|
|
|
|
|
|
|
function movieWinBetweenMonitors(d)
|
|
|
|
return function()
|
|
|
|
local win = hs.window.focusedWindow()
|
|
|
|
-- get the screen where the focused window is displayed, a.k.a current screen
|
|
|
|
local screen = win:screen()
|
|
|
|
-- compute the unitRect of the focused window relative to the current screen
|
|
|
|
-- and move the window to the next screen setting the same unitRect
|
|
|
|
-- https://www.hammerspoon.org/docs/hs.window.html#move
|
|
|
|
if d == 'next' then
|
|
|
|
win:move(win:frame():toUnitRect(screen:frame()), screen:next(), true, 0)
|
|
|
|
elseif d == 'previous' then
|
|
|
|
win:move(win:frame():toUnitRect(screen:frame()), screen:previous(), true, 0)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
hs.hotkey.bind(hyper, 'N', movieWinBetweenMonitors('next'))
|
|
|
|
hs.hotkey.bind(hyper, 'P', movieWinBetweenMonitors('previous'))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local grid = require 'hs.grid'
|
|
|
|
hs.hotkey.bind(hyper, ",", grid.show)
|
|
|
|
|
|
|
|
middle_monitor="DELL U2414H"
|
|
|
|
left_monitor="DELL P2417H"
|
|
|
|
right_monitor="DELL U2412M"
|
|
|
|
|
|
|
|
local reading_layout = {
|
|
|
|
{"Google Chrome", nil, middle_monitor, hs.layout.maximized, nil, nil},
|
|
|
|
{"iTerm", nil, left_monitor, hs.layout.maximized, nil, nil},
|
|
|
|
{"Miwork", nil, right_monitor, hs.layout.top50, nil, nil},
|
|
|
|
}
|
|
|
|
|
|
|
|
hs.hotkey.bind(hyper, "1", function()
|
|
|
|
hs.application.launchOrFocus('Google Chrome')
|
|
|
|
hs.application.launchOrFocus('iTerm')
|
|
|
|
hs.application.launchOrFocus('Miwork')
|
|
|
|
|
|
|
|
hs.layout.apply(reading_layout)
|
|
|
|
end)
|
|
|
|
|
|
|
|
local coding_layout = {
|
|
|
|
{"IntelliJ IDEA Ultimate", nil, middle_monitor, hs.layout.maximized, nil, nil},
|
|
|
|
{"iTerm", nil, left_monitor, hs.layout.maximized, nil, nil},
|
|
|
|
}
|
|
|
|
|
|
|
|
hs.hotkey.bind(hyper, "2", function()
|
|
|
|
hs.application.launchOrFocus('IntelliJ IDEA')
|
|
|
|
|
|
|
|
hs.layout.apply(coding_layout)
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
|
|
wifiWatcher = nil
|
|
|
|
homeSSID = "EinVerne_5G"
|
|
|
|
lastSSID = hs.wifi.currentNetwork()
|
|
|
|
|
|
|
|
workSSID = "MIOffice-5G"
|
|
|
|
|
|
|
|
function selectKarabinerProfile(profile)
|
|
|
|
hs.execute("'/Library/Application Support/org.pqrs/Karabiner-Elements/bin/karabiner_cli' --select-profile '" .. profile .. "'")
|
|
|
|
end
|
|
|
|
|
|
|
|
function ssidChangedCallback()
|
|
|
|
newSSID = hs.wifi.currentNetwork()
|
|
|
|
|
|
|
|
if newSSID == homeSSID and lastSSID ~= homeSSID then
|
|
|
|
-- We just joined our home WiFi network
|
|
|
|
hs.alert.show("Welcome home!")
|
|
|
|
hs.audiodevice.defaultOutputDevice():setVolume(25)
|
|
|
|
-- result = hs.network.configuration:setLocation("Home")
|
|
|
|
-- hs.alert.show(result)
|
|
|
|
elseif newSSID ~= homeSSID and lastSSID == homeSSID then
|
|
|
|
-- We just departed our home WiFi network
|
|
|
|
hs.alert.show("left home!")
|
|
|
|
hs.audiodevice.defaultOutputDevice():setVolume(0)
|
|
|
|
-- result = hs.network.configuration:setLocation("Automatic")
|
|
|
|
-- hs.alert.show(result)
|
|
|
|
end
|
|
|
|
|
|
|
|
if newSSID == workSSID then
|
|
|
|
hs.alert.show("work karabiner setup")
|
|
|
|
selectKarabinerProfile("Work")
|
|
|
|
else
|
|
|
|
hs.alert.show("built-in karabiner setup")
|
|
|
|
selectKarabinerProfile("Built-in")
|
|
|
|
end
|
|
|
|
|
|
|
|
lastSSID = newSSID
|
|
|
|
end
|
|
|
|
|
|
|
|
wifiWatcher = hs.wifi.watcher.new(ssidChangedCallback)
|
|
|
|
wifiWatcher:start()
|
|
|
|
|
|
|
|
networkConf = hs.network.configuration.open()
|
|
|
|
location = networkConf:location()
|
|
|
|
|
|
|
|
function switchNetworkLocation(location)
|
|
|
|
hs.execute('/usr/sbin/networksetup -switchtolocation ' .. location)
|
|
|
|
end
|
|
|
|
|
|
|
|
hs.hotkey.bind({"cmd", "alt", "ctrl"}, "H", function()
|
|
|
|
switchNetworkLocation("Home")
|
|
|
|
end)
|
|
|
|
hs.hotkey.bind({"cmd", "alt", "ctrl"}, "W", function()
|
|
|
|
switchNetworkLocation("Automatic")
|
|
|
|
end)
|
|
|
|
|
|
|
|
homeDNS="192.168.2.21"
|
|
|
|
automaticLocationUUID="/Sets/5783E8CE-BA08-4BE2-9799-5F00E15E5837"
|
|
|
|
homeLocationUUID="/Sets/C55127DB-F0CD-4573-890A-6F8EB59D9AFF"
|
|
|
|
|
|
|
|
hs.network.reachability.forAddress(homeDNS):setCallback(function(self, flags)
|
|
|
|
-- note that because having an internet connection at all will show the remote network
|
|
|
|
-- as "reachable", we instead look at whether or not our specific address is "local" instead
|
|
|
|
local networkConf = hs.network.configuration.open()
|
|
|
|
if (flags & hs.network.reachability.flags.reachable) > 0 and currentLocation ~= homeLocationUUID then
|
|
|
|
hs.alert.show("switch to Home network location")
|
|
|
|
networkConf:setLocation("Home")
|
|
|
|
elseif (flags & hs.network.reachability.flags.reachable) == 0 and currentLocation == homeLocationUUID then
|
|
|
|
hs.alert.show("switch back to Automatic network location")
|
|
|
|
networkConf:setLocation("Automatic")
|
|
|
|
end
|
|
|
|
end):start()
|
|
|
|
|
|
|
|
|
|
|
|
hs.hotkey.alertDuration = 0
|
|
|
|
hs.hints.showTitleThresh = 0
|
|
|
|
hs.window.animationDuration = 0
|
|
|
|
|
|
|
|
-- Use the standardized config location, if present
|
|
|
|
custom_config = hs.fs.pathToAbsolute(os.getenv("HOME") .. '/.config/hammerspoon/private/config.lua')
|
|
|
|
if custom_config then
|
|
|
|
print("Loading custom config")
|
|
|
|
dofile( os.getenv("HOME") .. "/.config/hammerspoon/private/config.lua")
|
|
|
|
privatepath = hs.fs.pathToAbsolute(hs.configdir .. '/private/config.lua')
|
|
|
|
if privatepath then
|
|
|
|
hs.alert("You have config in both .config/hammerspoon and .hammerspoon/private.\nThe .config/hammerspoon one will be used.")
|
|
|
|
end
|
|
|
|
else
|
|
|
|
-- otherwise fallback to 'classic' location.
|
|
|
|
if not privatepath then
|
|
|
|
privatepath = hs.fs.pathToAbsolute(hs.configdir .. '/private')
|
|
|
|
-- Create `~/.hammerspoon/private` directory if not exists.
|
|
|
|
hs.fs.mkdir(hs.configdir .. '/private')
|
|
|
|
end
|
|
|
|
privateconf = hs.fs.pathToAbsolute(hs.configdir .. '/private/config.lua')
|
|
|
|
if privateconf then
|
|
|
|
-- Load awesomeconfig file if exists
|
|
|
|
require('private/config')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
hsreload_keys = {hyper, "R"}
|
|
|
|
hsreload_keys = hsreload_keys or {{"cmd", "shift", "ctrl"}, "R"}
|
|
|
|
if string.len(hsreload_keys[2]) > 0 then
|
|
|
|
hs.hotkey.bind(hsreload_keys[1], hsreload_keys[2], "Reload Configuration", function() hs.reload() end)
|
|
|
|
hs.notify.new({title="Hammerspoon config reloaded", informativeText="Manually trigged via keyboard shortcut"}):send()
|
|
|
|
end
|
|
|
|
|
|
|
|
-- ModalMgr Spoon must be loaded explicitly, because this repository heavily relies upon it.
|
|
|
|
hs.loadSpoon("ModalMgr")
|
|
|
|
|
|
|
|
-- Define default Spoons which will be loaded later
|
|
|
|
if not hspoon_list then
|
|
|
|
hspoon_list = {
|
|
|
|
"AClock",
|
|
|
|
"BingDaily",
|
|
|
|
"CircleClock",
|
|
|
|
"ClipShow",
|
|
|
|
--"CountDown",
|
|
|
|
"HCalendar",
|
|
|
|
--"HSaria2",
|
|
|
|
"SpeedMenu",
|
|
|
|
"WinWin",
|
|
|
|
"WifiNotifier",
|
|
|
|
"WinRectangle",
|
|
|
|
"Caffeine",
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Load those Spoons
|
|
|
|
for _, v in pairs(hspoon_list) do
|
|
|
|
hs.loadSpoon(v)
|
|
|
|
end
|
|
|
|
|
|
|
|
----------------------------------------------------------------------------------------------------
|
|
|
|
-- Then we create/register all kinds of modal keybindings environments.
|
|
|
|
----------------------------------------------------------------------------------------------------
|
|
|
|
-- Register windowHints (Register a keybinding which is NOT modal environment with modal supervisor)
|
|
|
|
hswhints_keys = hswhints_keys or {"alt", "tab"}
|
|
|
|
if string.len(hswhints_keys[2]) > 0 then
|
|
|
|
spoon.ModalMgr.supervisor:bind(hswhints_keys[1], hswhints_keys[2], 'Show Window Hints', function()
|
|
|
|
spoon.ModalMgr:deactivateAll()
|
|
|
|
hs.hints.windowHints()
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
----------------------------------------------------------------------------------------------------
|
|
|
|
-- appM modal environment
|
|
|
|
spoon.ModalMgr:new("appM")
|
|
|
|
local cmodal = spoon.ModalMgr.modal_list["appM"]
|
|
|
|
cmodal:bind('', 'escape', 'Deactivate appM', function() spoon.ModalMgr:deactivate({"appM"}) end)
|
|
|
|
cmodal:bind('', 'Q', 'Deactivate appM', function() spoon.ModalMgr:deactivate({"appM"}) end)
|
|
|
|
cmodal:bind('', 'tab', 'Toggle Cheatsheet', function() spoon.ModalMgr:toggleCheatsheet() end)
|
|
|
|
if not hsapp_list then
|
|
|
|
hsapp_list = {
|
|
|
|
{key = 'f', name = 'Finder'},
|
|
|
|
{key = 'c', name = 'Google Chrome'},
|
|
|
|
{key = 'o', name = 'Obsidian'},
|
|
|
|
{key = 's', name = 'Safari'},
|
|
|
|
{key = 't', name = 'Terminal'},
|
|
|
|
{key = 'v', id = 'com.apple.ActivityMonitor'},
|
|
|
|
{key = 'y', id = 'com.apple.systempreferences'},
|
|
|
|
}
|
|
|
|
end
|
|
|
|
for _, v in ipairs(hsapp_list) do
|
|
|
|
if v.id then
|
|
|
|
local located_name = hs.application.nameForBundleID(v.id)
|
|
|
|
if located_name then
|
|
|
|
cmodal:bind('', v.key, located_name, function()
|
|
|
|
hs.application.launchOrFocusByBundleID(v.id)
|
|
|
|
spoon.ModalMgr:deactivate({"appM"})
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
elseif v.name then
|
|
|
|
cmodal:bind('', v.key, v.name, function()
|
|
|
|
hs.application.launchOrFocus(v.name)
|
|
|
|
spoon.ModalMgr:deactivate({"appM"})
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Then we register some keybindings with modal supervisor
|
|
|
|
hsappM_keys = hsappM_keys or {"alt", "A"}
|
|
|
|
if string.len(hsappM_keys[2]) > 0 then
|
|
|
|
spoon.ModalMgr.supervisor:bind(hsappM_keys[1], hsappM_keys[2], "Enter AppM Environment", function()
|
|
|
|
spoon.ModalMgr:deactivateAll()
|
|
|
|
-- Show the keybindings cheatsheet once appM is activated
|
|
|
|
spoon.ModalMgr:activate({"appM"}, "#FFBD2E", true)
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
----------------------------------------------------------------------------------------------------
|
|
|
|
-- clipshowM modal environment
|
|
|
|
if spoon.ClipShow then
|
|
|
|
spoon.ModalMgr:new("clipshowM")
|
|
|
|
local cmodal = spoon.ModalMgr.modal_list["clipshowM"]
|
|
|
|
cmodal:bind('', 'escape', 'Deactivate clipshowM', function()
|
|
|
|
spoon.ClipShow:toggleShow()
|
|
|
|
spoon.ModalMgr:deactivate({"clipshowM"})
|
|
|
|
end)
|
|
|
|
cmodal:bind('', 'Q', 'Deactivate clipshowM', function()
|
|
|
|
spoon.ClipShow:toggleShow()
|
|
|
|
spoon.ModalMgr:deactivate({"clipshowM"})
|
|
|
|
end)
|
|
|
|
cmodal:bind('', 'N', 'Save this Session', function()
|
|
|
|
spoon.ClipShow:saveToSession()
|
|
|
|
end)
|
|
|
|
cmodal:bind('', 'R', 'Restore last Session', function()
|
|
|
|
spoon.ClipShow:restoreLastSession()
|
|
|
|
end)
|
|
|
|
cmodal:bind('', 'B', 'Open in Browser', function()
|
|
|
|
spoon.ClipShow:openInBrowserWithRef()
|
|
|
|
spoon.ClipShow:toggleShow()
|
|
|
|
spoon.ModalMgr:deactivate({"clipshowM"})
|
|
|
|
end)
|
|
|
|
cmodal:bind('', 'S', 'Search with Bing', function()
|
|
|
|
spoon.ClipShow:openInBrowserWithRef("https://www.bing.com/search?q=")
|
|
|
|
spoon.ClipShow:toggleShow()
|
|
|
|
spoon.ModalMgr:deactivate({"clipshowM"})
|
|
|
|
end)
|
|
|
|
cmodal:bind('', 'M', 'Open in MacVim', function()
|
|
|
|
spoon.ClipShow:openWithCommand("/usr/local/bin/mvim")
|
|
|
|
spoon.ClipShow:toggleShow()
|
|
|
|
spoon.ModalMgr:deactivate({"clipshowM"})
|
|
|
|
end)
|
|
|
|
cmodal:bind('', 'F', 'Save to Desktop', function()
|
|
|
|
spoon.ClipShow:saveToFile()
|
|
|
|
spoon.ClipShow:toggleShow()
|
|
|
|
spoon.ModalMgr:deactivate({"clipshowM"})
|
|
|
|
end)
|
|
|
|
cmodal:bind('', 'H', 'Search in Github', function()
|
|
|
|
spoon.ClipShow:openInBrowserWithRef("https://github.com/search?q=")
|
|
|
|
spoon.ClipShow:toggleShow()
|
|
|
|
spoon.ModalMgr:deactivate({"clipshowM"})
|
|
|
|
end)
|
|
|
|
cmodal:bind('', 'G', 'Search with Google', function()
|
|
|
|
spoon.ClipShow:openInBrowserWithRef("https://www.google.com/search?q=")
|
|
|
|
spoon.ClipShow:toggleShow()
|
|
|
|
spoon.ModalMgr:deactivate({"clipshowM"})
|
|
|
|
end)
|
|
|
|
cmodal:bind('', 'L', 'Open in Sublime Text', function()
|
|
|
|
spoon.ClipShow:openWithCommand("/usr/local/bin/subl")
|
|
|
|
spoon.ClipShow:toggleShow()
|
|
|
|
spoon.ModalMgr:deactivate({"clipshowM"})
|
|
|
|
end)
|
|
|
|
|
|
|
|
-- Register clipshowM with modal supervisor
|
|
|
|
hsclipsM_keys = hsclipsM_keys or {"alt", "C"}
|
|
|
|
if string.len(hsclipsM_keys[2]) > 0 then
|
|
|
|
spoon.ModalMgr.supervisor:bind(hsclipsM_keys[1], hsclipsM_keys[2], "Enter clipshowM Environment", function()
|
|
|
|
-- We need to take action upon hsclipsM_keys is pressed, since pressing another key to showing ClipShow panel is redundant.
|
|
|
|
spoon.ClipShow:toggleShow()
|
|
|
|
-- Need a little trick here. Since the content type of system clipboard may be "URL", in which case we don't need to activate clipshowM.
|
|
|
|
if spoon.ClipShow.canvas:isShowing() then
|
|
|
|
spoon.ModalMgr:deactivateAll()
|
|
|
|
spoon.ModalMgr:activate({"clipshowM"})
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
----------------------------------------------------------------------------------------------------
|
|
|
|
-- Register HSaria2
|
|
|
|
if spoon.HSaria2 then
|
|
|
|
-- First we need to connect to aria2 rpc host
|
|
|
|
hsaria2_host = hsaria2_host or "http://localhost:6800/jsonrpc"
|
|
|
|
hsaria2_secret = hsaria2_secret or "token"
|
|
|
|
spoon.HSaria2:connectToHost(hsaria2_host, hsaria2_secret)
|
|
|
|
|
|
|
|
hsaria2_keys = hsaria2_keys or {"alt", "D"}
|
|
|
|
if string.len(hsaria2_keys[2]) > 0 then
|
|
|
|
spoon.ModalMgr.supervisor:bind(hsaria2_keys[1], hsaria2_keys[2], 'Toggle aria2 Panel', function() spoon.HSaria2:togglePanel() end)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
----------------------------------------------------------------------------------------------------
|
|
|
|
-- Register Hammerspoon Search
|
|
|
|
if spoon.HSearch then
|
|
|
|
hsearch_keys = hsearch_keys or {"alt", "G"}
|
|
|
|
if string.len(hsearch_keys[2]) > 0 then
|
|
|
|
spoon.ModalMgr.supervisor:bind(hsearch_keys[1], hsearch_keys[2], 'Launch Hammerspoon Search', function() spoon.HSearch:toggleShow() end)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
----------------------------------------------------------------------------------------------------
|
|
|
|
-- Register Hammerspoon API manual: Open Hammerspoon manual in default browser
|
|
|
|
hsman_keys = hsman_keys or {"alt", "H"}
|
|
|
|
if string.len(hsman_keys[2]) > 0 then
|
|
|
|
spoon.ModalMgr.supervisor:bind(hsman_keys[1], hsman_keys[2], "Read Hammerspoon Manual", function()
|
|
|
|
hs.doc.hsdocs.forceExternalBrowser(true)
|
|
|
|
hs.doc.hsdocs.moduleEntitiesInSidebar(true)
|
|
|
|
hs.doc.hsdocs.help()
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
----------------------------------------------------------------------------------------------------
|
|
|
|
-- countdownM modal environment
|
|
|
|
if spoon.CountDown then
|
|
|
|
spoon.ModalMgr:new("countdownM")
|
|
|
|
local cmodal = spoon.ModalMgr.modal_list["countdownM"]
|
|
|
|
cmodal:bind('', 'escape', 'Deactivate countdownM', function() spoon.ModalMgr:deactivate({"countdownM"}) end)
|
|
|
|
cmodal:bind('', 'Q', 'Deactivate countdownM', function() spoon.ModalMgr:deactivate({"countdownM"}) end)
|
|
|
|
cmodal:bind('', 'tab', 'Toggle Cheatsheet', function() spoon.ModalMgr:toggleCheatsheet() end)
|
|
|
|
cmodal:bind('', '0', '5 Minutes Countdown', function()
|
|
|
|
spoon.CountDown:startFor(5)
|
|
|
|
spoon.ModalMgr:deactivate({"countdownM"})
|
|
|
|
end)
|
|
|
|
for i = 1, 9 do
|
|
|
|
cmodal:bind('', tostring(i), string.format("%s Minutes Countdown", 10 * i), function()
|
|
|
|
spoon.CountDown:startFor(10 * i)
|
|
|
|
spoon.ModalMgr:deactivate({"countdownM"})
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
cmodal:bind('', 'return', '25 Minutes Countdown', function()
|
|
|
|
spoon.CountDown:startFor(25)
|
|
|
|
spoon.ModalMgr:deactivate({"countdownM"})
|
|
|
|
end)
|
|
|
|
cmodal:bind('', 'space', 'Pause/Resume CountDown', function()
|
|
|
|
spoon.CountDown:pauseOrResume()
|
|
|
|
spoon.ModalMgr:deactivate({"countdownM"})
|
|
|
|
end)
|
|
|
|
|
|
|
|
-- Register countdownM with modal supervisor
|
|
|
|
hscountdM_keys = hscountdM_keys or {"alt", "I"}
|
|
|
|
if string.len(hscountdM_keys[2]) > 0 then
|
|
|
|
spoon.ModalMgr.supervisor:bind(hscountdM_keys[1], hscountdM_keys[2], "Enter countdownM Environment", function()
|
|
|
|
spoon.ModalMgr:deactivateAll()
|
|
|
|
-- Show the keybindings cheatsheet once countdownM is activated
|
|
|
|
spoon.ModalMgr:activate({"countdownM"}, "#FF6347", true)
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
----------------------------------------------------------------------------------------------------
|
|
|
|
-- Register lock screen
|
|
|
|
hslock_keys = hslock_keys or {"alt", "L"}
|
|
|
|
if string.len(hslock_keys[2]) > 0 then
|
|
|
|
spoon.ModalMgr.supervisor:bind(hslock_keys[1], hslock_keys[2], "Lock Screen", function()
|
|
|
|
hs.caffeinate.lockScreen()
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
----------------------------------------------------------------------------------------------------
|
|
|
|
-- resizeM modal environment
|
|
|
|
if spoon.WinWin then
|
|
|
|
spoon.ModalMgr:new("resizeM")
|
|
|
|
local cmodal = spoon.ModalMgr.modal_list["resizeM"]
|
|
|
|
cmodal:bind('', 'escape', 'Deactivate resizeM', function() spoon.ModalMgr:deactivate({"resizeM"}) end)
|
|
|
|
cmodal:bind('', 'Q', 'Deactivate resizeM', function() spoon.ModalMgr:deactivate({"resizeM"}) end)
|
|
|
|
cmodal:bind('', 'tab', 'Toggle Cheatsheet', function() spoon.ModalMgr:toggleCheatsheet() end)
|
|
|
|
cmodal:bind('', 'A', 'Move Leftward', function() spoon.WinWin:stepMove("left") end, nil, function() spoon.WinWin:stepMove("left") end)
|
|
|
|
cmodal:bind('', 'D', 'Move Rightward', function() spoon.WinWin:stepMove("right") end, nil, function() spoon.WinWin:stepMove("right") end)
|
|
|
|
cmodal:bind('', 'W', 'Move Upward', function() spoon.WinWin:stepMove("up") end, nil, function() spoon.WinWin:stepMove("up") end)
|
|
|
|
cmodal:bind('', 'S', 'Move Downward', function() spoon.WinWin:stepMove("down") end, nil, function() spoon.WinWin:stepMove("down") end)
|
|
|
|
cmodal:bind('', 'H', 'Lefthalf of Screen', function() spoon.WinWin:stash() spoon.WinWin:moveAndResize("halfleft") end)
|
|
|
|
cmodal:bind('', 'L', 'Righthalf of Screen', function() spoon.WinWin:stash() spoon.WinWin:moveAndResize("halfright") end)
|
|
|
|
cmodal:bind('', 'K', 'Uphalf of Screen', function() spoon.WinWin:stash() spoon.WinWin:moveAndResize("halfup") end)
|
|
|
|
cmodal:bind('', 'J', 'Downhalf of Screen', function() spoon.WinWin:stash() spoon.WinWin:moveAndResize("halfdown") end)
|
|
|
|
cmodal:bind('', 'Y', 'NorthWest Corner', function() spoon.WinWin:stash() spoon.WinWin:moveAndResize("cornerNW") end)
|
|
|
|
cmodal:bind('', 'O', 'NorthEast Corner', function() spoon.WinWin:stash() spoon.WinWin:moveAndResize("cornerNE") end)
|
|
|
|
cmodal:bind('', 'U', 'SouthWest Corner', function() spoon.WinWin:stash() spoon.WinWin:moveAndResize("cornerSW") end)
|
|
|
|
cmodal:bind('', 'I', 'SouthEast Corner', function() spoon.WinWin:stash() spoon.WinWin:moveAndResize("cornerSE") end)
|
|
|
|
cmodal:bind('', 'F', 'Fullscreen', function() spoon.WinWin:stash() spoon.WinWin:moveAndResize("fullscreen") end)
|
|
|
|
cmodal:bind('', 'C', 'Center Window', function() spoon.WinWin:stash() spoon.WinWin:moveAndResize("center") end)
|
|
|
|
cmodal:bind('', '=', 'Stretch Outward', function() spoon.WinWin:moveAndResize("expand") end, nil, function() spoon.WinWin:moveAndResize("expand") end)
|
|
|
|
cmodal:bind('', '-', 'Shrink Inward', function() spoon.WinWin:moveAndResize("shrink") end, nil, function() spoon.WinWin:moveAndResize("shrink") end)
|
|
|
|
cmodal:bind('shift', 'H', 'Move Leftward', function() spoon.WinWin:stepResize("left") end, nil, function() spoon.WinWin:stepResize("left") end)
|
|
|
|
cmodal:bind('shift', 'L', 'Move Rightward', function() spoon.WinWin:stepResize("right") end, nil, function() spoon.WinWin:stepResize("right") end)
|
|
|
|
cmodal:bind('shift', 'K', 'Move Upward', function() spoon.WinWin:stepResize("up") end, nil, function() spoon.WinWin:stepResize("up") end)
|
|
|
|
cmodal:bind('shift', 'J', 'Move Downward', function() spoon.WinWin:stepResize("down") end, nil, function() spoon.WinWin:stepResize("down") end)
|
|
|
|
cmodal:bind('', 'left', 'Move to Left Monitor', function() spoon.WinWin:stash() spoon.WinWin:moveToScreen("left") end)
|
|
|
|
cmodal:bind('', 'right', 'Move to Right Monitor', function() spoon.WinWin:stash() spoon.WinWin:moveToScreen("right") end)
|
|
|
|
cmodal:bind('', 'up', 'Move to Above Monitor', function() spoon.WinWin:stash() spoon.WinWin:moveToScreen("up") end)
|
|
|
|
cmodal:bind('', 'down', 'Move to Below Monitor', function() spoon.WinWin:stash() spoon.WinWin:moveToScreen("down") end)
|
|
|
|
cmodal:bind('', 'space', 'Move to Next Monitor', function() spoon.WinWin:stash() spoon.WinWin:moveToScreen("next") end)
|
|
|
|
cmodal:bind('', '[', 'Undo Window Manipulation', function() spoon.WinWin:undo() end)
|
|
|
|
cmodal:bind('', ']', 'Redo Window Manipulation', function() spoon.WinWin:redo() end)
|
|
|
|
cmodal:bind('', '`', 'Center Cursor', function() spoon.WinWin:centerCursor() end)
|
|
|
|
|
|
|
|
-- Register resizeM with modal supervisor
|
|
|
|
hsresizeM_keys = hsresizeM_keys or {"alt", "R"}
|
|
|
|
if string.len(hsresizeM_keys[2]) > 0 then
|
|
|
|
spoon.ModalMgr.supervisor:bind(hsresizeM_keys[1], hsresizeM_keys[2], "Enter resizeM Environment", function()
|
|
|
|
-- Deactivate some modal environments or not before activating a new one
|
|
|
|
spoon.ModalMgr:deactivateAll()
|
|
|
|
-- Show an status indicator so we know we're in some modal environment now
|
|
|
|
spoon.ModalMgr:activate({"resizeM"}, "#B22222")
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
----------------------------------------------------------------------------------------------------
|
|
|
|
-- cheatsheetM modal environment (Because KSheet Spoon is NOT loaded, cheatsheetM will NOT be activated)
|
|
|
|
if spoon.KSheet then
|
|
|
|
spoon.ModalMgr:new("cheatsheetM")
|
|
|
|
local cmodal = spoon.ModalMgr.modal_list["cheatsheetM"]
|
|
|
|
cmodal:bind('', 'escape', 'Deactivate cheatsheetM', function()
|
|
|
|
spoon.KSheet:hide()
|
|
|
|
spoon.ModalMgr:deactivate({"cheatsheetM"})
|
|
|
|
end)
|
|
|
|
cmodal:bind('', 'Q', 'Deactivate cheatsheetM', function()
|
|
|
|
spoon.KSheet:hide()
|
|
|
|
spoon.ModalMgr:deactivate({"cheatsheetM"})
|
|
|
|
end)
|
|
|
|
|
|
|
|
-- Register cheatsheetM with modal supervisor
|
|
|
|
hscheats_keys = hscheats_keys or {"alt", "S"}
|
|
|
|
if string.len(hscheats_keys[2]) > 0 then
|
|
|
|
spoon.ModalMgr.supervisor:bind(hscheats_keys[1], hscheats_keys[2], "Enter cheatsheetM Environment", function()
|
|
|
|
spoon.KSheet:show()
|
|
|
|
spoon.ModalMgr:deactivateAll()
|
|
|
|
spoon.ModalMgr:activate({"cheatsheetM"})
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
----------------------------------------------------------------------------------------------------
|
|
|
|
-- Register AClock
|
|
|
|
if spoon.AClock then
|
|
|
|
hsaclock_keys = hsaclock_keys or {"alt", "T"}
|
|
|
|
if string.len(hsaclock_keys[2]) > 0 then
|
|
|
|
spoon.ModalMgr.supervisor:bind(hsaclock_keys[1], hsaclock_keys[2], "Toggle Floating Clock", function() spoon.AClock:toggleShow() end)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Register WinRectangle
|
|
|
|
if spoon.WinRectangle then
|
|
|
|
spoon.WinRectangle:bindHotkeys(spoon.WinRectangle.defaultHotkeys)
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Register Caffeine
|
|
|
|
if spoon.Caffeine then
|
|
|
|
spoon.Caffeine:start()
|
|
|
|
end
|
|
|
|
|
|
|
|
if spoon.wifiNotifier then
|
|
|
|
spoon.wifiNotifier:start()
|
|
|
|
end
|
|
|
|
|
|
|
|
----------------------------------------------------------------------------------------------------
|
|
|
|
-- Register browser tab typist: Type URL of current tab of running browser in markdown format. i.e. [title](link)
|
|
|
|
hstype_keys = hstype_keys or {"alt", "V"}
|
|
|
|
if string.len(hstype_keys[2]) > 0 then
|
|
|
|
spoon.ModalMgr.supervisor:bind(hstype_keys[1], hstype_keys[2], "Type Browser Link", function()
|
|
|
|
local safari_running = hs.application.applicationsForBundleID("com.apple.Safari")
|
|
|
|
local chrome_running = hs.application.applicationsForBundleID("com.google.Chrome")
|
|
|
|
if #safari_running > 0 then
|
|
|
|
local stat, data = hs.applescript('tell application "Safari" to get {URL, name} of current tab of window 1')
|
|
|
|
if stat then hs.eventtap.keyStrokes("[" .. data[2] .. "](" .. data[1] .. ")") end
|
|
|
|
elseif #chrome_running > 0 then
|
|
|
|
local stat, data = hs.applescript('tell application "Google Chrome" to get {URL, title} of active tab of window 1')
|
|
|
|
if stat then hs.eventtap.keyStrokes("[" .. data[2] .. "](" .. data[1] .. ")") end
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
----------------------------------------------------------------------------------------------------
|
|
|
|
-- Register Hammerspoon console
|
|
|
|
hsconsole_keys = hsconsole_keys or {"alt", "Z"}
|
|
|
|
if string.len(hsconsole_keys[2]) > 0 then
|
|
|
|
spoon.ModalMgr.supervisor:bind(hsconsole_keys[1], hsconsole_keys[2], "Toggle Hammerspoon Console", function() hs.toggleConsole() end)
|
|
|
|
end
|
|
|
|
|
|
|
|
----------------------------------------------------------------------------------------------------
|
|
|
|
-- Finally we initialize ModalMgr supervisor
|
|
|
|
spoon.ModalMgr.supervisor:enter()
|