mac-dev-playbook icon indicating copy to clipboard operation
mac-dev-playbook copied to clipboard

Automate remapping Caps Lock to Escape

Open geerlingguy opened this issue 7 years ago • 16 comments

Now that macOS 10.12.1 includes built-in remapping for Caps Lock-to-Escape, I've ditched Karabiner Elements (since that was the only thing I used it for). See: Remapping the Caps Lock key to Escape in macOS Sierra

But I'd still like to have that setting automated so I don't have to click through the Keyboard system preferences when setting up my Mac fresh.

See: Updating modifier key mappings through defaults command tool; the setting has to be set per keyboard (in my case, I have two, an 'Apple Keyboard', and an 'Apple Internal Keyboard / Trackpad', with unique IDs. I'd have to set it up (maybe in the .osx bash script in my dotfiles?) to add the mapping for each keyboard detected.

geerlingguy avatar Oct 24 '16 21:10 geerlingguy

If someone already uses khd as a hotkey daemon (it's brilliant), you can also use it to remap caps-lock.

- capslock : khd -p "- escape"

oxyc avatar Jun 11 '17 14:06 oxyc

Seems a lot more automate-able/configurable... but my only hesitation is the permissions required to make it work—you're giving it basically full control over keystrokes and all other parts of the accessibility layer.

geerlingguy avatar Jun 11 '17 19:06 geerlingguy

I hesitated too, but now there's no going back :D

https://twitter.com/geerlingguy/status/859526910229041154

# re-map/disable quit shortcut
cmd - q [ Firefox, iTerm2, Google Chrome ] : khd -p "cmd - w"

In case someone lands here you can disable Secure Keyboard entry for iTerm2/Terminal with:

defaults write com.apple.terminal SecureKeyboardEntry -bool false
defaults write com.googlecode.iterm2 "Secure Input" -bool false

oxyc avatar Jun 11 '17 19:06 oxyc

Quick update on khd for others reading. Seems it's been more or less abandoned in favor of skhd which doesnt support capslock and application specific mappings.

oxyc avatar May 12 '18 22:05 oxyc

Hi @geerlingguy, maybe use the following for an automated key remapping solution ?

A short script remap_mac_keys to leverage MacOS native hidutil key remapping :

#!/bin/sh
# Credit to Brad Howes
FROM='"HIDKeyboardModifierMappingSrc"'
TO='"HIDKeyboardModifierMappingDst"'

ARGS=""
function Map # FROM TO
{
    CMD="${CMD:+${CMD},}{${FROM}: ${1}, ${TO}: ${2}}"
}

# Referencing :
# https://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-1035.41.2/IOHIDFamily/IOHIDUsageTables.h.auto.html
SECTION="0x700000064"
ESCAPE="0x700000029"
BACKQUOTE="0x700000035"
CAPS_LOCK="0x700000039"
L_SHIFT="0x7000000E1"
R_COMMAND="0x7000000E7"
L_CONTROL="0x7000000E0"

Map ${CAPS_LOCK} ${ESCAPE}
#Map ${SECTION} ${ESCAPE}
#Map ${R_COMMAND} ${SHIFT_LOCK}
#Map ${BACKQUOTE} ${L_CONTROL}

hidutil property --set "{\"UserKeyMapping\":[${CMD}]}"

A basic LaunchAgent com.user.loginscript.plist to perform the mapping at login :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
   <key>Label</key>
   <string>com.user.loginscript</string>
   <key>ProgramArguments</key>
   <array>
       <string>/usr/local/bin/remap_mac_keys</string>
   </array>
   <key>RunAtLoad</key>
   <true/>
</dict>
</plist>

And the following Ansible tasks to put them all in place :

- name: Copy remap_mac_keys to /usr/local/bin/
  copy:
    src: remap_mac_keys
    dest: /usr/local/bin/remap_mac_keys
    owner: root
    group: wheel
    mode: 0755
  become: yes

- name: Put LaunchAgent in place to remap keys on login
  copy:
    src: com.user.loginscript.plist
    dest: ~/Library/LaunchAgents/com.user.loginscript.plist
    mode: 0644

tomtastic avatar Aug 11 '18 16:08 tomtastic

This issue has been marked 'stale' due to lack of recent activity. If there is no further activity, the issue will be closed in another 30 days. Thank you for your contribution!

Please read this blog post to see the reasons why I mark issues as stale.

stale[bot] avatar Mar 06 '20 03:03 stale[bot]

This issue has been closed due to inactivity. If you feel this is in error, please reopen the issue or file a new issue with the relevant details.

stale[bot] avatar Apr 05 '20 03:04 stale[bot]

This issue is no longer marked for closure.

stale[bot] avatar May 26 '21 03:05 stale[bot]

Reopening... I still don't have this automated :(

geerlingguy avatar May 26 '21 03:05 geerlingguy

Hey @geerlingguy, I'd want to say a huge thank you to you first sir! I have been trying to automate my own developer MacBook setup with Ansible and I have been following your Ansible 101 live streams for the last couple days and also this repo and your Ansible Mac collections. They have been hugely helpful for my own setup.

I have a very rough first step Ansible playbook set up, here https://github.com/NicholasTD07/ansible-macOS-playbook.

I was just wondering about whether there's a way that I can use Ansible to remap caps-lock to control and Google has taken me here 😄

It seems like there still isn't a great automation solution for this yet. Is that right?

Seems like something just has to be done by hand to please the Apple God :P

NicholasTD07 avatar Mar 08 '22 09:03 NicholasTD07

@NicholasTD07 - I would imagine it has to be a plist somewhere, which would mean it is able to be automated. I just haven't had the time to go dig up where it's defined :(

geerlingguy avatar Mar 08 '22 15:03 geerlingguy

@geerlingguy Yes. Some people have done the research into that already. I think this answer looks the best https://apple.stackexchange.com/a/277544.

Basically, you can run defaults -currentHost read -g to get what has changed on your Mac in the system preferences from what I read.

nicholas.the.personal@Nicholass-MBP-2 ansible-macOS-playbook % defaults -currentHost read -g
{
    "com.apple.keyboard.modifiermapping.1118-1957-0" =     (
                {
            HIDKeyboardModifierMappingDst = 30064771300;
            HIDKeyboardModifierMappingSrc = 30064771129;
        }
    );
    "com.apple.keyboard.modifiermapping.1452-835-0" =     (
                {
            HIDKeyboardModifierMappingDst = 30064771300;
            HIDKeyboardModifierMappingSrc = 30064771129;
        }
    );
}

But notice how different keyboards have different "id"s, i.e. 1118-1957-0 vs 1452-835-0 which then "should"* be able to be read out by using ioreg -n IOHIDKeyboard -r (from this answer in that same question). But it's showing nothing for me.

Seems a bit fiddly and not very straightforward so far...

NicholasTD07 avatar Mar 09 '22 00:03 NicholasTD07

Why not just issue this? :

$ hidutil property --set {"UserKeyMapping":[{"HIDKeyboardModifierMappingSrc": 0x700000039, "HIDKeyboardModifierMappingDst": 0x700000029}]}

tomtastic avatar Mar 09 '22 10:03 tomtastic

@tomtastic thanks!

@geerlingguy That command works flawlessly... (Don't forget to quote the last section if you're on some weird shell)

thebiblelover7 avatar Aug 21 '22 20:08 thebiblelover7

$ hidutil property --set {"UserKeyMapping":[{"HIDKeyboardModifierMappingSrc": 0x700000039, "HIDKeyboardModifierMappingDst": 0x700000029}]}

Note: Key codes can be found here: https://developer.apple.com/library/archive/technotes/tn2450/_index.html#//apple_ref/doc/uid/DTS40017618-CH1-KEY_TABLE_USAGES

thomanq avatar Mar 01 '23 10:03 thomanq

I've managed to eventually solve this with Ansible. Apple realy hasn't made it easy, I've included details in https://github.com/andrasmaroy/dotfiles/commit/5815a8d137a028781a3f0cf9ccb10044301bf099.

andrasmaroy avatar Nov 26 '23 12:11 andrasmaroy