Block wrong shift key in Vim

7

1

I know that I should use the right shift key for letters that I type with my left hand. But I often insert the colon with the right hand only, moving the ring finger to shift and the index finger to the colon key.

I'd like to force myself to stop that, at least within Vim. Is there some way to prevent myself of using “Right-Shift” with “Q” for instance?

Martin Ueding

Posted 2012-08-12T20:35:02.223

Reputation: 1 857

2Vim doesn't (and probably actually can not) distinguish between left and right shift/meta keys, so you can't do what you want within Vim. I'm guessing that if this is possible at all, it will be at a "higher level" than the Vim application level.

What operating system do you use? – Heptite – 2012-08-12T21:17:23.980

1+1 for "I often insert the colon with the right hand" – Sirex – 2012-08-12T22:28:21.120

@Heptite: Kubuntu (Linux with KDE) – Martin Ueding – 2012-08-13T12:46:25.447

My best suggestion is to see if you can get your window manager / desktop environment to map left-shift+whatever and right-shift+whatever and bind them to some sort of null operation. – Heptite – 2012-08-13T19:43:21.167

1

This may be a bit overkill but you may find this interesting as an alternative to using Xmodmap which I'm told is outdated. http://madduck.net/docs/extending-xkb/

– jmathew – 2013-09-26T17:08:20.820

Answers

4

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
    

Dennis

Posted 2012-08-12T20:35:02.223

Reputation: 42 934

That seems doable. Doen't it break the <kbd>AltGr</kbd> for all keas, so that <kbd>AltGr</kbd> + <kbd>v</kbd> will enter V instead of ? Capslock can be broken, I have it mapped to AltGr anyway. – Martin Ueding – 2012-08-15T09:30:21.733

You'd have to try. My AltGr key triggers ISOLevel3Shift, not ModeSwitch. If it breaks your AltGr key, let me know and tell me which keyboard layout you're using. – Dennis – 2012-08-15T12:06:27.307

1

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.

dshepherd

Posted 2012-08-12T20:35:02.223

Reputation: 288