Block wrong shift key in Vim

Solution 1:

Xmodmap can do what you're asking for, as long as you don't mind breaking your CapsLock key.

Xmodmap can distinguish between the left and right shift key, so we can initially remap RightShift to ModeSwitch to get our way:

xmodmap -e "keysym Shift_R = Mode_switch"

The basic syntax for modifying the behavior of a key is

xmodmap -e "keycode  KEYCODE = KEYSYMBOL1 KEYSYMBOL1 KEYSYMBOL3 KEYSYMBOL4"
xmodmap -e "keysym KEYSYMBOL = KEYSYMBOL1 KEYSYMBOL1 KEYSYMBOL3 KEYSYMBOL4"

where

  • KEYSYMBOL2 gets triggered when pressing the key while pressing Shift.
  • KEYSYMBOL3 gets triggered when pressing the key while pressing ModeSwitch.
  • KEYSYMBOL4 gets triggered when pressing the key while pressing Shift + ModeSwitch.
  • KEYSYMBOL1 gets triggered when pressing the key with none of the above.
  • ModeSwitch is AltGr by default (only works on some keyboard layouts).

So much for the theory. In practice, these remappings might behave a little different when modifying a Shift + Letter combination. I can't speak for Kubuntu, but some Unity application will will override the behavior specified by Xmodmap in these cases.

To reconfigure each key to only accept the proper modifier, I found the most robust way to be the following:

  • To make R accept only RightShift, execute the following command:

    xmodmap r r R R
    
  • To make L accept only LeftShift, execute the following command:

    xmodmap l L l l
    

Tips:

  • To make the remappings permanent, create/edit a shell script in ~/.kde/Autostart/, make it executable and save the corresponding commands in it.

  • To undo all remappings, simply execute the following command:

    setxkbmap
    

Solution 2:

I wrote a script to carry out Dennis' idea (this is for UK ascii keyboards, should be easy to modify for US keyboards)

! A script to rebind all shifted keys to force you to use the correct shift
! button for minimum risk of rsi.

! Buttons not really on either side, make either shift work:
keysym 6 = 6 asciicircum asciicircum asciicircum
keysym y = y Y Y Y
keysym b = b B B B


! Might need to replace 0x3571 with a keysym which is not used elsewhere in
! your key map so that pressing the wrong key generates nothing. This
! keysym should be fine for most people. Note: this may interfere with
! emacs in annoying ways because emacs because it print warnings when
! undefined keys are pressed, the answer is to learn not to press them!


! Set right shift to be a sort of temporary caps lock (only on while button held)
keysym Shift_R = Mode_switch


! Bind lhs of keyboard to only work with this "temporary caps lock
! modifier" as shift and rhs to only work with Shift_L.

! lhs letters
keysym q = q 0x3571 Q Q
keysym w = w 0x3571 W W
keysym e = e 0x3571 E E
keysym r = r 0x3571 R R
keysym t = t 0x3571 T T
keysym a = a 0x3571 A A
keysym s = s 0x3571 S S
keysym d = d 0x3571 D D
keysym f = f 0x3571 F F
keysym g = g 0x3571 G G
keysym z = z 0x3571 Z Z
keysym x = x 0x3571 X X
keysym c = c 0x3571 C C
keysym v = v 0x3571 V V

! lhs symbols
keysym backslash = backslash 0x3571 bar bar
keysym grave = grave 0x3571 notsign notsign
keysym 1 = 1 0x3571 exclam
keysym 2 = 2 0x3571 quotedbl
keysym 3 = 3 0x3571 sterling
keysym 4 = 4 0x3571 dollar
keysym 5 = 5 0x3571 percent

! rhs letters
keysym u = u U 0x3571 U
keysym i = i I 0x3571 I
keysym o = o O 0x3571 O
keysym p = p P 0x3571 P
keysym h = h H 0x3571 H
keysym j = j J 0x3571 J
keysym k = k K 0x3571 K
keysym l = l L 0x3571 L
keysym n = n N 0x3571 N
keysym m = m M 0x3571 M

! rhs symbols
keysym 7 = 7 ampersand 0x3571 ampersand
keysym 8 = 8 asterisk 0x3571 asterisk
keysym 9 = 9 parenleft 0x3571 parenleft
keysym 0 = 0 parenright 0x3571 parenright
keysym minus = minus underscore 0x3571 underscore
keysym equal = equal plus 0x3571 plus
keysym bracketleft = bracketleft braceleft 0x3571 braceleft
keysym bracketright = bracketright braceright 0x3571 braceright
keysym semicolon = semicolon colon 0x3571 colon
keysym apostrophe = apostrophe at 0x3571 at
keysym numbersign = numbersign asciitilde 0x3571 asciitilde
keysym comma = comma less 0x3571 less
keysym period = period greater 0x3571 greater
keysym slash = slash question 0x3571 question

To use it: save in a text file and run with:

xmodmap [script_name]

Also could someone with more reputation modify Dennis' answer to replace

xmodmap r r R R

with

xmodmap -e 'keysym r = r r R R'

and similarly for L, this is the actual command needed.