Remap keys with pure macOS functionality.
Although the efforts of the Karabiner-Elements project are highly appreciated, using it always felt too intrusive and, recently, also like a liability. In fact, although quite unknown, if it comes to simple key remapping tasks, one can use features built directly into macOS.
This project helps in defining remappings easily through a straight-forward configuration file.
Clone this repository and make sure you have Python with pyyaml installed.
Edit config.yaml to your needs.
It has the following structure:
keyboard:
fromKey1: toKey1
fromKey2: toKey2
# ...
keypad:
fromKey1: toKey1
# ...The fromKey and the toKey label names correspond to .keyboard and .keypad
as defined in keytables.yaml.
For example, to remap
Caps lock to Backspace, and
Backspace to Delete
you have to define config.yaml as follows:
keyboard:
Capslock: Backspace
Backspace: DeleteApply your configuration as follows:
hidutil property --set `./remap.py --hidutil-property`To keep your remapping configuration in effect across restarts, you can load it automatically using launchd. To load your configuration automatically on the next restart, execute the following command:
./remap.py --launchd-plist ~/Library/LaunchAgents/ch.veehait.macos-remap-keys.plistIf you're using Nix with Home Manager on Darwin, you can use something like
the following to manage your mappings. It takes care of applying your remapping
configuration after a home-manager switch and also links the launchd plist
to get picked up on restarts.
{ config, pkgs, lib, ... }:
let
macos-remap-keys-flake = builtins.getFlake "github:veehaitch/macos-remap-keys";
macos-remap-keys = macos-remap-keys-flake.defaultPackage.x86_64-darwin;
keytables = builtins.toPath "${macos-remap-keys-flake}/keytables.yaml";
config = pkgs.writeText "macos-remap-config.yaml" (builtins.toJSON {
keyboard = {
Capslock = "Backspace";
Backspace = "Delete";
};
});
macos-remap-launchd = pkgs.runCommand "macos-remap-launchd" { } ''
mkdir -p $out
${macos-remap-keys}/bin/remap.py \
--config "${config}" \
--keytables "${keytables}" \
--launchd-plist \
"$out/ch.veehait.macos-remap-keys.plist" >/dev/null
'';
in
{
# Activate the remappings on switch
home.activation."macosRemapKeys" = lib.hm.dag.entryAfter ["writeBoundary"] ''
$DRY_RUN_CMD hidutil property --set \
`${macos-remap-keys}/bin/remap.py \
--config ${config} \
--keytables ${keytables} \
--hidutil-property` >/dev/null
'';
# Activate the remappings on boot
home.file."Library/LaunchAgents/ch.veehait.macos-remap-keys.plist".source = "${macos-remap-launchd}/ch.veehait.macos-remap-keys.plist";
}Although very similar, the format demanded by hidutil isn't JSON.
For hidutil property --set to work, the values of HIDKeyboardModifierMapping{Src,Dst}
have to be numbers in their hexadecimal representation. Using a decimal representation,
as supported by JSON, won't work.
That's a weird decision—just Apple things—which demands some Regex string manipulation.
Wonder what would happen if you'd just use a hex string instead of a number? macOS crashes—completely. Hard to believe? Go ahead and try it yourself but make sure you don't have any unsaved work:
hidutil property --set '{"UserKeyMapping":[{"HIDKeyboardModifierMappingSrc":"0x700000039","HIDKeyboardModifierMappingDst":"0x70000002A"}]}'