Tibor's Musings

One Key, Two Functions, or CapsLock as an Escape and Control

In search for greater keyboard ergonomy and improved typing productivity, the CapsLock key seems to be taking place for not much use. Many programmers redefine it to become a modifier key. One popular habit: Vi users prefer to set it to Escape, while Emacs users to Control. What if one likes both?

Best of both worlds

The best of the both worlds can be achieved by means of the xcape utility that permits to configure modifier keys to act as other keys when pressed and released on their own. By means of xcape, we can configure the keyboard in such a manner that CapsLock generates Escape when single-pressed, and Ctrl when pressed together with another key.

First install it:

sudo apt-get install xcape

Then configure it in the following way:

# make CapsLock behave like Ctrl:
setxkbmap -option ctrl:nocaps

# make short-pressed Ctrl behave like Escape:
xcape -e 'Control_L=Escape'

Done. When short-pressed, CapsLock will generate Esc. When pressed with another key like a, it will generate Ctrl-a sequence. Could we be any more efficient?

Usage context

I'm using xcape in my keyboard layout modification script together with several other useful utilities, such as xinput that permits to detect attached keyboards before performing layout modification operations on them.

For example I'm using Dvorak keyboard layout on both my laptop's internal keyboard and on the attached Kinesis Advantage external keyboard. xinput permits to detect attached devices and setxkmap permits then to modify them.

The core of the script looks like:

# set internal keyboard layout:
deviceid=$(xinput -list | grep 'AT .* keyboard' | head -1 | grep -oE 'id=[0-9]+' | sed 's/id=//g')
if [ "${deviceid}" != "" ]; then
    setxkbmap -device "${deviceid}" dvorak
    setxkbmap -device "${deviceid}" -option ctrl:nocaps # make CapsLock behave like Ctrl
fi

# set Kinesis keyboard layout:
for deviceid in $(xinput -list | grep ' HID ' | grep -oE 'id=[0-9]+' | sed 's/id=//g'); do
    if [ "${deviceid}" != "" ]; then
        setxkbmap -device "${deviceid}" us # 'us' but it means 'dvorak' actually due to Kinesis
        setxkbmap -device "${deviceid}" -option ctrl:nocaps # make CapsLock behave like Ctrl
    fi
done

Further keymap re-definitions are done via xmodmap statements. For example, on a ThinkPad x240 keyboard, the PrtSc key is located next to right Ctrl key, where it can be easily mis-pressed. So we can turn it into Control as well:

# amend PrtSc key: (useful for ThinkPad x240):
xmodmap -e "keycode 107 = Control_R"
xmodmap -e "add Control = Control_R"

Troubleshooting

If the CapsLock key gets "stuck" and produces say uppercase letter combinations instead of lowercase ones, the easiest way to remove xcape mapping is to revert CapsLock key function via xmodmap:

xmodmap -e 'keycode 0x42 = Caps_Lock'

followed by re-running of the keyboard modification script.

Conclusions

xcape, when paired with xinput, setxkbmap and other xmodmap friends, provides very efficient tool permitting to overload and remap even the modifier keys' behaviour to one's liking.

unix vi emacs