Linux – In Linux, how can I map SHIFT_L/SHIFT_R when pressed without additional key

keyboardkeymaplinuxxmodmap

Today I found this very nice article by Steven Losh in which he presents a couple of productivity boosting keyboard mappings. Among them is a dynamic mapping of the left and right shift keys.

The Idea

When Shift_L or Shift_R are pressed without an additional key they are mapped to '(' and ')' respectively, otherwise they function as usual.

The Problem

He does all of this under OSX. I am trying to achieve the same under Linux. There is no straightforward way for this since as I understand you can't use xmodmap to configure one key for Shift_L alone, and another for Shift when used as a modifier key.

I have googled around a bit and found people trying to do the same under Windows which is apparently possible using AutoHotKey, but I could not find anything for Linux.

Is there a way to solve this under Linux?

Best Answer

Wow! User teika kazura's comment on the original question is quite correct — not only is this effectively a duplicate of that other question, but the answer provided there ("use xcape") solves this problem!

After cloning the xcape repo and compiling (I had to install libXtst-devel on my Fedora box, first), I was able to obtain the exact behavior requested with the following command:

xcape -e "Shift_L=parenleft;Shift_R=parenright"

After admittedly-cursory testing, it seems to work extremely well. Nice!

Other Options

If you use the Shift key as a mouse modifier (i.e. if you ever shift-click anything), you'll probably want to include xcape's timeout option and find a comfortable timeout value, so that solo Shift keypresses used in combination with the mouse don't generate spurious parentheses. From the xcape README:

-t <timeout ms>

If you hold a key longer than this timeout, xcape will not generate a key event. Default is 500 ms.

So, by including the -t flag with a timeout value that works for you, you'll still be able to shift-click with the mouse as long as you hold down Shift for at least timeout ms milliseconds.

(Credit, again, to teika kazura for pointing out the other question, and also to don_crissti for the original answer there.)

Related Question