I use the shift keys a lot and it is an unnecessary strain on the pinky. The enter and backspace functionalities are conveniently located under a dominant finger (ctrl-m and ctrl-h). Similarly:

Is there a way to map the shift function to a dominant finger?

But in the vim spirit I want to get this functionality with a key combination rather than finger acrobatics; e.g., lets use the extremely rare key combination fd (in insert mode!).

For the alphanumerical keys one could dump an entire list of imaps: fd1 !, fd2 @, ..., fda A etc. into vimrc. I'm hoping there is a better way.

Ideally, fd would be mapped to a "sticky shift" that waits for a one letter input, shifts it, then turns off the sticky shift. Is this possible?

Many thanks!

Post mortem

Rich has a function down below which can be modified to have the complete effect. Last night someone wrote a neat solution and then erased it so I will include it here:

imap <expr> fd nr2char(getchar()-32)

This does the trick if all you want to capitalize letters. Otherwise it seems like a good way to do function calls.

Another good suggestion in the comments below is modifying the keyboard at the firmware level using this.

Thanks for the help everyone!

  • 2
    But then how would you type "serfdom"?! More seriously, I don't know of a better way than simply mapping all the combos (not sure what you ask for is even possible in Vim), but I'd note that you could create the mappings with a little Vimscript loop, rather than having add them all individually to your vimrc; I'll add an answer that does this if no-one comes up with a proper solution. – Rich Jan 21 '16 at 17:24
  • I guess you could also map fd to a function that takes input and converts it if appropriate. Marginally cleaner. I'll write this, too. – Rich Jan 21 '16 at 17:34
  • 3
    > Is there a way to map the shift function to a dominant finger? Depending on your keyboard, yes. tmk keyboard firmware can remap different keys into different layers, or even remap key sequences into different macros. Personally, I've got my 'f' to cause the right half of my keyboard to turn into a numpad when held down, for example. If you care a lot about your hands/fingers, or are currently suffering from RSI, check it out! – fruglemonkey Jan 22 '16 at 1:12
  • 1
    You may be interested in enabling "sticky keys" in your OS. I think doing that would mostly resolve your situation, plus perhaps remapping your shift key to another more convenient key at an abstraction level above (below?) Vim itself.... – Wildcard Jan 22 '16 at 2:45
  • And here I was thinking that mentioning Hasu's TMK would be too 'hardcore' stuff :D In any case, your problem should be solved much better at OS or even keyboard firmware level (if possible). – VanLaser Jan 22 '16 at 10:15

I'm not sure if a clean implementation of this feature is possible in Vimscript. (I suspect it's not, and I fully agree with the commenters who suggest it's better to implement this outside of Vim.)

Nevertheless, here's a proof-of-concept of a hacky function that maps insert-mode fd to a function which waits for a single character of input, and capitalises it if it's a-z before re-entering insert mode and writing it back out. This is marginally nicer than your "create all the mappings individually" idea.

It would need a bit more logic to handle all the other keyboard keys, but this should be sufficient to demonstrate the general concept. Note that getchar() returns an ASCII value, so all the if block is doing is converting the ASCII values for lowercase letters into uppercase ones.

Let me know if you decide to go down this path and need any more help filling the rest of it in.

inoremap fd <Esc>:call StickyShift()<CR>

function! StickyShift()
  let l:key_pressed = getchar()
  " Capitalise a-z
  if l:key_pressed >= 97 && l:key_pressed <= 122
    let l:key_pressed -= 32
  call feedkeys("a". nr2char(l:key_pressed))
  • This is great! I can add the values for other keys, but I couldn't have done this. Thanks for the 'proof of concept'. – Emre Jan 22 '16 at 20:29

inoremap fd <C-o>gUl

Would allow you to type afd and get A etc. if you are open to reverse the order of your bind.

Does not work for the 1 to ! etc unfortunately.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.