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?

1
  • PuTTY doesn't send usefully-distinct sequences for the control-arrows. None of the suggested answers are correct (or useful). Jan 13, 2018 at 12:38

6 Answers 6

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.

9
  • How do I tell what escape sequence is sent?
    – Alex B
    Sep 7, 2010 at 22:37
  • @Alex: I've tried to clarify my explanation, complain if you still don't understand my first sentence. Sep 7, 2010 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 8, 2010 at 0: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, 2011 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). Jan 18, 2011 at 23:30
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 +

1
  • Turning off Application Cursor Keys mode doesn't seem to help.
    – Alex B
    Sep 7, 2010 at 22:37
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
1
  • This creates some weird char behaviour.
    – Thibault
    Jul 12, 2017 at 13:58
0

for my this and other vim keyboard problems I simply do

vim ~/.vimrc
set nocompatible
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 <[email protected]>                                         
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:

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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .