34

I am using Putty, Suse box and Vim 7.2 combo for editing and I want to remap Ctrl + Arrow keypresses to a particular task. But for some reason, Vim ignores the shortcut, goes into insert mode, and inserts character D (for Ctrl + ) or character C (for Ctrl + ).

Which part of my keyboard/terminal configuration is to blame and how to fix it?

dsimic
  • 123
Alex B
  • 4,478
  • PuTTY doesn't send usefully-distinct sequences for the control-arrows. None of the suggested answers are correct (or useful). – Thomas Dickey Jan 13 '18 at 12:38

6 Answers6

35

Figure out exactly what escape sequence your terminal sends for Ctrl+arrow by typing Ctrl+V, Ctrl+arrow in insert mode: this will insert the leading ESC character (shown as ^[ in vim) literally, followed by the rest of the escape sequence. Then tell vim about these escape sequences with something like

map <ESC>[5D <C-Left>
map <ESC>[5C <C-Right>
map! <ESC>[5D <C-Left>
map! <ESC>[5C <C-Right>

I seem to recall that Putty has a default setting for Application Cursor Keys mode that's inconvenient (I forget why), you might want to toggle this setting first.

Note that although escape sequences vary between terminals, conflicts (i.e. an escape sequence that corresponds to different keys in different terminals) are rare, so there's no particular need to try to apply the mappings only on a particular terminal type.

  • How do I tell what escape sequence is sent? – Alex B Sep 07 '10 at 22:37
  • @Alex: I've tried to clarify my explanation, complain if you still don't understand my first sentence. – Gilles 'SO- stop being evil' Sep 07 '10 at 22:43
  • You can also run od -a or od -c if you dig octal and then type the keys in question. See "added" in my answer for an example. – msw Sep 08 '10 at 00:14
  • Sorry for getting back to this question so late, but I've figured out that PuTTY still sends application cursor keys to the terminal, even after I turn it off completely. I am at a loss what else should I tweak to make it go away. – Alex B Jan 18 '11 at 23:25
  • @Alex: You don't need to make it go away, you can tell your applications about them (which I've found to be the path of least resistance). Or you can replace PuTTY by one of the alternatives such as mintty plus Cygwin ssh (but that's getting off-topic for this site). – Gilles 'SO- stop being evil' Jan 18 '11 at 23:30
  • @Gilles Finally fixed it. Just one typo in map commands: should be map <ESC>5D, rather than <ESC>[5D, since ESC is already ^[. – Alex B Jan 18 '11 at 23:41
  • @Alex: On the terminal I chose as an example, C-Left sends ESC [ 5 D (4 characters). Another common sequence if ESC O 5 D. I don't think any terminal sends ESC 5 D for any key, these sequences usually start with ESC [ or ESC O. – Gilles 'SO- stop being evil' Jan 18 '11 at 23:47
  • @Gilles ah OK, got it. – Alex B Jan 19 '11 at 00:15
  • @Gilles thanks for posting this answer. on debian, i get ESC[1;5A whereas on mac i get ESC[5A. your answer helped me solve my vim mapping problem. – rev Apr 01 '12 at 19:23
7

Your best bet is probably to look at PuTTY's Application Cursor Keys mode configuration.

The default sequences send ESC as a prefix and [ followed by Append or Change or other things throwing you into insert mode.

added, following Gilles

A slightly more explicit version of the ^V escape can be seen with od(1). Here is me typing ^Up, ^Down, ^Right, ^Left at my terminal:

$ od -a
0000000 esc   [   1   ;   5   A esc   [   1   ;   5   B esc   [   1   ;
0000020   5   C esc   [   1   ;   5   D

So my terminal sends ^[[1;5A when I press Ctrl +

msw
  • 10,593
2

I found a better solution here: http://vim.wikia.com/wiki/Fix_arrow_keys_that_display_A_B_C_D_on_remote_shell

Just put this string in your .vimrc file:

:set term=cons25

Update

Copy this file to your /home, renaming it .vimrc:

/usr/share/vim/vim_VERSION_/vimrc_example.vim
jasonwryan
  • 73,126
trigal
  • 21
0

for my this and other vim keyboard problems I simply do

vim ~/.vimrc
set nocompatible
0

I've implemented the vimscript code below to fix the issues with the escape sequences generated by my terminal emulator for the Ctrl + Arrow, Shift + Arrow, and Ctrl + Shift + Arrow keypresses; all these keypresses create issues on their own, so it's usually best to fix them all in one fell swoop.

Here's the vimscript code from my ~/.vimrc:

" Just a temporary shorthand
function! NoRemapNXIC(lhs, rhs_nxi, rhs_c = v:null)
  execute "nnoremap " .. a:lhs .. " " .. a:rhs_nxi
  execute "xnoremap " .. a:lhs .. " " .. a:rhs_nxi
  execute "inoremap " .. a:lhs .. " <C-O>" .. a:rhs_nxi
  if a:rhs_c isnot v:null
    execute "cnoremap " .. a:lhs .. " " .. a:rhs_c
  endif
endfunction

" Make navigating through long lines easy call NoRemapNXIC("<Up>", "gk") call NoRemapNXIC("<Down>", "gj")

call NoRemapNXIC("<C-Left>", "b") call NoRemapNXIC("<C-Right>", "e") call NoRemapNXIC("<S-Left>", "B") call NoRemapNXIC("<S-Right>", "E")

" Handle <Ctrl> + <Arrow> escape sequences call NoRemapNXIC("<ESC>[1;5A", "gk", "<Nop>") call NoRemapNXIC("<ESC>[1;5B", "gj", "<Nop>") call NoRemapNXIC("<ESC>[1;5D", "b", "<C-Left>") call NoRemapNXIC("<ESC>[1;5C", "e", "<C-Right>")

" Handle <Shift> + <Arrow> escape sequences call NoRemapNXIC("<ESC>[1;2A", "<PageUp>", "<Nop>") call NoRemapNXIC("<ESC>[1;2B", "<PageDown>", "<Nop>") call NoRemapNXIC("<ESC>[1;2D", "B", "<S-Left>") call NoRemapNXIC("<ESC>[1;2C", "E", "<S-Right>")

" Handle <Ctrl> + <Shift> + <Arrow> escape sequences call NoRemapNXIC("<ESC>[1;6D", "ge", "<C-Left>") call NoRemapNXIC("<ESC>[1;6C", "w", "<C-Right>")

delfunction NoRemapNXIC

Of course, you'll need to check what escape sequences for those keypresses are actually generated by your particular terminal emulator, and adjust this vimscript code appropriately. It's already described how to check that in another answer, but you can also simply run cat(1) in a separate terminal emulator window or tab, and see what are you getting back for those keypresses.

As you can see, I also remapped the actual cursor movement commands a bit, to use b, e, B, E, ge and w, which makes them more suitable to my own preferences. Of course, you can tailor those to your own needs.

Please note that remapping <Up> and <Down> to gk and gj, respectively, and remapping to gk and gj commands in other places isn't directly related to the OP's question, but I included those here as well for the sake of completeness, and simply because my ~/.vimrc does it that way. Having those remaps as well might be a good idea, see this question and this answer for more details.

See also :h i_CTRL-O in vim's built-in help.

dsimic
  • 123
0

When this question was asked in 2010 (and when the other answers were supplied, none later than 2013), PuTTY had no means for distinguishing a control modifier for the cursor keys. It would send only VT100-style normal and application cursor keys. In particular, any answer with text such as "<ESC>[1;5A" was not addressing OP's question.

More than ten years later, PuTTY provided a scheme derived from xterm, seen in this commit:

commit 22911ccdcc37c7955bfc1c45a88d3762d1206da7                                 
Author: Simon Tatham <anakin@pobox.com>                                         
Date:   Mon Oct 18 20:00:25 2021 +0100
New config option for shifted arrow key handling.                           

This commit introduces a new config option for how to handle shifted        
arrow keys.                                                                 

In the default mode (SHARROW_APPLICATION), we do what we've always          
done: Ctrl flips the arrow keys between sending their most usual            
escape sequences (ESC [ A ... ESC [ D) and sending the 'application         
cursor keys' sequences (ESC O A ... ESC O D). Whichever of those modes      
is currently configured, Ctrl+arrow sends the other one.                    

In the new mode (SHARROW_BITMAP), application cursor key mode is            
unaffected by any shift keys, but the default sequences acquire two         
numeric arguments. The first argument is 1 (reflecting the fact that a      
shifted arrow key still notionally moves just 1 character cell); the        
second is the bitmap (1 for Shift) + (2 for Alt) + (4 for Ctrl),            
offset by 1. (Except that if _none_ of those modifiers is pressed,          
both numeric arguments are simply omitted.)                                 

The new bitmap mode is what current xterm generates, and also what          
Windows ConPTY seems to expect. If you start an ordinary Command            
Prompt and launch into WSL, those are the sequences it will generate        
for shifted arrow keys; conversely, if you run a Command Prompt within      
a ConPTY, then these sequences for Ctrl+arrow will have the effect you      
expect in cmd.exe command-line editing (going backward or forward a         
word). For that reason, I enable this mode unconditionally when             
launching Windows pterm.    

The settings dialog entry for that is in config.c:

    ctrl_radiobuttons(s, "Shift/Ctrl/Alt with the arrow keys", 'w', 2,          
                      HELPCTX(keyboard_sharrow),                                
                      conf_radiobutton_handler,                                 
                      I(CONF_sharrow_type),                                     
                      "Ctrl toggles app mode", I(SHARROW_APPLICATION),          
                      "xterm-style bitmap", I(SHARROW_BITMAP));   

That "bitmap" refers to this table in XTerm Control Sequences:

                    Code     Modifiers
                  ---------+---------------------------
                     2     | Shift
                     3     | Alt
                     4     | Shift + Alt
                     5     | Control
                     6     | Shift + Control
                     7     | Alt + Control
                     8     | Shift + Alt + Control
                     9     | Meta
                     10    | Meta + Shift
                     11    | Meta + Alt
                     12    | Meta + Alt + Shift
                     13    | Meta + Ctrl
                     14    | Meta + Ctrl + Shift
                     15    | Meta + Ctrl + Alt
                     16    | Meta + Ctrl + Alt + Shift
                  ---------+---------------------------

So... according to the developer's description, settings which happen to work with xterm should work in PuTTY. Since PuTTY development began around 2000, and this was a feature of xterm since 2002, fixing this detail in 2021 was "long anticipated".

Further reading:

Thomas Dickey
  • 76,765