9

I want to remap <C-I> to print markdown * symbol around the previous word. For example:

# user actions inside <...>
some text typed in vim insert mode<cursor_position> <C-I>

# expected  vim output
some text typed in vim insert *mode*<cursor_position>

I am using the following line in my .vimrc for remapping

inoremap <C-i> <ESC>Bi*<ESC>ea*

Problem is, as per help :h i_CTRL-I, <C-I> in insert mode is already mapped to something and the mapping above doesn't work for me. Pressing <C-I> in insert mode leaves a <TAB> on editor.

<Tab> or CTRL-I Insert a tab. If the 'expandtab' option is on, the equivalent number of spaces is inserted (use CTRL-V to avoid the expansion; use CTRL-Q <Tab> if CTRL-V is mapped i_CTRL-Q). See also the 'smarttab' option and ins-expandtab.

  1. How do I make insert mode <C-I> mapping work?
  2. How can I override global vim key-mapping with my own key-mapping defined in .vimrc file?
1
  • 1
    Very similar which explains some context: Disable <Esc> but keep <C-[>. The short version is that Tab is ctrl+i. Perhaps there are workarounds specific for Tab, so not quite a duplicate. May 6, 2018 at 18:27

2 Answers 2

9

With a recent enough Vim binary, and for some terminals – including xterm and iterm2 if you enable the CSI u option – Vim can distinguish C-i from Tab.

You need at least the Vim patch 8.1.2134.

And you may need to add these lines in your vimrc:

let &t_TI = "\<Esc>[>4;2m"
let &t_TE = "\<Esc>[>4;m"

Unless your Vim binary also includes the patch 8.1.2194, in which case it should have been done automatically if Vim has properly detected it's running in xterm.


As a simple test, run this shell command:

vim -Nu NONE +'nno <C-i> :echom "C-i was pressed"<cr>' +'nno <tab> :echom "Tab was pressed"<cr>'

Then press Tab followed by C-i. The first keypress should log the message Tab was pressed, while the second one should log the message C-i was pressed (check out the output of :messages if you somehow missed the messages).

enter image description here

Make sure to install the Tab mapping after the C-i mapping; otherwise, the Tab mapping may be removed.


Vim can distinguish between many other keys; like C-a and C-S-a:

vim -Nu NONE +'nno <C-a> :echom "C-a was pressed"<cr>' +'nno <C-S-a> :echom "C-S-a was pressed"<cr>'

Here C- and S- stand for resp. the control and shift modifiers.

Or A-b and A-C-b:

vim -Nu NONE +'nno <A-b> :echom "A-b was pressed"<cr>' +'nno <A-C-b> :echom "A-C-b was pressed"<cr>'

Here A- stands for the Alt modifier.


For more info, see :h modifyOtherKeys.

2
  • 2
    This also works in iTerm2 by enabling the CSI u option iterm2.com/documentation-csiu.html
    – ruohola
    Jun 20, 2020 at 17:55
  • Actually now it seems to need the 'Control sequences can enable modifyOtherKeys mode' option from iTerm2 -> Preferences -> Profiles -> Keys
    – ruohola
    Jan 9, 2021 at 20:14
4

Short answer: you cannot.

Long answer: <C-i> being equivalent to <Tab> isn't a vim quirk or builtin. It's a quirk of how terminals represent characters (cf. https://bestasciitable.com).

You simply cannot avoid this fact. Now, it may be possible to force your mapping to take precedence over the tab-behavior of inserting tabs/spaces, but I haven't done much investigating there. I would recommend choosing another mapping.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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