Skip to content

Instantly share code, notes, and snippets.

@jeremija
Forked from juanmiret/init.lua
Created May 24, 2017 12:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jeremija/2246d2a112c3e2a68c086955a55377f1 to your computer and use it in GitHub Desktop.
Save jeremija/2246d2a112c3e2a68c086955a55377f1 to your computer and use it in GitHub Desktop.
Simple Vi mode with Karabiner-elements and Hammerspoon
local module = {}
module.debugging = false -- whether to print status updates
local eventtap = require "hs.eventtap"
local event = eventtap.event
local inspect = require "hs.inspect"
local keyHandler = function(e)
local watchFor = {
h = "left",
j = "down",
k = "up",
l = "right",
u = "delete",
i = "forwarddelete"
}
local actualKey = e:getCharacters(true)
local replacement = watchFor[actualKey:lower()]
if replacement then
local isDown = e:getType() == event.types.keyDown
local flags = {}
for k, v in pairs(e:getFlags()) do
if v and k ~= "fn" then -- fn will be down because that's our "wrapper", so ignore it
table.insert(flags, k)
end
end
if module.debugging then print("viKeys: " .. replacement, inspect(flags), isDown) end
local replacementEvent = event.newKeyEvent(flags, replacement, isDown)
if isDown then
-- allow for auto-repeat
replacementEvent:setProperty(event.properties.keyboardEventAutorepeat, e:getProperty(event.properties.keyboardEventAutorepeat))
end
return true, { replacementEvent }
else
return false -- do nothing to the event, just pass it along
end
end
local modifierHandler = function(e)
local flags = e:getFlags()
local onlyControlPressed = false
for k, v in pairs(flags) do
onlyControlPressed = v and k == "fn"
if not onlyControlPressed then break end
end
-- you must tap and hold fn by itself to turn this on
if onlyControlPressed and not module.keyListener then
if module.debugging then print("viKeys: keyhandler on") end
module.keyListener = eventtap.new({ event.types.keyDown, event.types.keyUp }, keyHandler):start()
-- however, adding additional modifiers afterwards is ok... its only when fn isn't down that we switch back off
elseif not flags.fn and module.keyListener then
if module.debugging then print("viKeys: keyhandler off") end
module.keyListener:stop()
module.keyListener = nil
end
return false
end
module.modifierListener = eventtap.new({ event.types.flagsChanged }, modifierHandler)
module.start = function()
module.modifierListener:start()
end
module.stop = function()
if module.keyListener then
module.keyListener:stop()
module.keyListener = nil
end
module.modifierListener:stop()
end
module.start() -- autostart
return module
{
"profiles": [{
"devices": [],
"name": "Default profile",
"selected": true,
"simple_modifications": {
"caps_lock": "fn"
},
"standalone_keys": {
"caps_lock": "caps_lock"
},
"one_to_many_mappings": {},
"virtual_hid_keyboard": {
"caps_lock_delay_milliseconds": 0,
"keyboard_type": "ansi",
"standalone_keys_delay_milliseconds": 100
}
}]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment