How to bind two distinct actions to Ctrl-Shift-Key and Ctrl-Key in vi

keyboard shortcutsvimxterm

I am trying to map two different actions to e.g. CtrlShifta and Ctrla:

map <C-S-a>    :echo "ctrl-shift-a received"<CR>
map <C-a>      :echo "ctrl-a received"<CR>

But all I ever get when pressing either of the two, is the output "ctrl-a received" in the status line. Apparently, vi does not see a difference between a capitalized control character and a lowercase one.

Is there a way to change this?

I am running vi (v7.4) in an xterm (X.Org 6.8.99).

Best Answer

This is a terminal restriction, because vi sees the keycodes as being the same. One can verify this by going into insert mode i, then hitting Ctrlv to put vi in a mode to expect the literal input of a special character and then hit e.g. CtrlShifta. A ^A output will appear. Now do the sequence Ctrlv, Ctrla, and again a ^A will appear: Both input sequences result in the same keycode being seen by vi.

For terminals such as xterm you can change that. For gnome-terminal which ignores the X resources settings I don't know how to do the following:

This SO question covers the same topic, and this example shows this in use for mapping multiple keys in the .Xresources file. E.g.:

XTerm*vt100.translations: #override \
  Ctrl ~Meta Shift <Key>a: string(0x1b) string("[65;5u") \n\
  Ctrl ~Meta Shift <Key>b: string(0x1b) string("[66;5u") \n\ 
  Ctrl ~Meta Shift <Key>f: string(0x1b) string("[70;5u")  

Now we have different key sequences coming into vi for Ctrla vs. CtrlShifta, Ctrlb vs. CtrlShiftb, Ctrlf vs. CtrlShiftf.

We can now map them differently in ~/.vimrc:

map <ESC>[65;5u   :echo "ctrl-shift-a received"<CR>
map <C-a>         :echo "ctrl-a received"<CR>