-
-
Save juanmiret/81a21a5ae8d6b6061b0a4e72a8be61b2 to your computer and use it in GitHub Desktop.
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 | |
} | |
}] | |
} |
Hi,
Thank you so much for your work! I have a question regarding the quick press of the CapsLock to activate it. The code you provided didn't work for me.
The following is my JSON file:
{
"profiles": [
{
"devices": [],
"fn_function_keys": {
"f1": "display_brightness_decrement",
"f10": "mute",
"f11": "volume_decrement",
"f12": "volume_increment",
"f2": "display_brightness_increment",
"f3": "mission_control",
"f4": "launchpad",
"f5": "illumination_decrement",
"f6": "illumination_increment",
"f7": "rewind",
"f8": "play_or_pause",
"f9": "fastforward"
},
"name": "Default profile",
"one_to_many_mappings": {},
"selected": true,
"simple_modifications": {
"caps_lock": "fn"
},
"standalone_keys": {
"caps_lock": "caps_lock"
},
"virtual_hid_keyboard": {
"caps_lock_delay_milliseconds": 0,
"keyboard_type": "ansi",
"standalone_keys_delay_milliseconds": 100
}
}
]
}
Please let me know what I did wrong. Thank you in advance!
You have to use the version of Karabiner-Elements by @wwwjfy for this to work. See https://github.com/wwwjfy/Karabiner-Elements/releases for releases and pqrs-org/Karabiner-Elements#247 for the pull request.
More accurately, it's the standalone_keys
bit that requires the alternative version.
Not work for me. I use Karabiner-Elements v0.90.77 and Hammerspoon v0.9.52.
I change module.debugging = false
to module.debugging = true
, but no message in the Hammerspoon console.
This is just plain awesome. Thanks a lot!
very helpful~ Thanks a lot~
something related Hammerspoon/hammerspoon#1252 (comment)
It works. Thanks a lot!
Love it! Can't wait until vi mode comes back into karabiner-elements, but until then, thank you 👌
Thanks!
@sengngykouch hey i'm sorry i didn't answer on time, I never saw the notification. I think the solution is what alf says.
You have to use the version of Karabiner-Elements by @wwwjfy for this to work. See https://github.com/wwwjfy/Karabiner-Elements/releases for releases and pqrs-org/Karabiner-Elements#247 for the pull request.
This is a configuration for Karabiner-elements and Hammerspoon to bring back Simple Vi mode from old Karabiner
What it does:
First it maps caps_lock to fn when you press and hold, and keeps caps_lock functionality if you press and release quick, all this in karabiner.json file
Then with the help of Hammerspoon, in init.lua we map:
fn + hjkl to arrows
fn + u to delete
fn + i to forward_delete
Hope it helps!!
You can easily modify the bindings to your taste or to add more functionalities in the watchFor variable, line 4 of init.lua
EDIT: If you feel a little lag with the caps_lock, you can do the following:
in karabiner.json map caps_lock to fn and fn to caps_lock, then delete the "standalone_keys" mappings and set the "standalone_keys_delay_miliseconds" to 0
"simple_modifications": {
"caps_lock": "fn",
"fn": "caps_lock"
}