Wikia

Vim Tips Wiki

Changes: Prevent escape from moving the cursor one character to the left

Edit

Back to page

m
Line 56: Line 56:
 
</pre>
 
</pre>
   
The above viml keeps track of the cursor position in INSERT mode, then when exiting INSERT mode, it will move the cursor ahead one column one only if the cursor position has changed after leaving insert.
+
Putting the above in your vimrc keeps track of the cursor position when in INSERT mode. When exiting INSERT mode, it will move the cursor ahead one column if the cursor position has changed after leaving insert.
   
 
==Comments==
 
==Comments==

Revision as of 10:52, April 21, 2013

Tip 1167 Printable Monobook Previous Next

created March 13, 2006, Updated April 21, 2013 · complexity intermediate · author Paul Donohue (Alternative by Joe Pea) · version 7.0


Original Solution

From the Vim FAQ:

10.2. In insert mode, when I press the <Esc> key to go to command mode, the
 cursor moves one character to the left (except when the cursor is on
 the first character of the line). Is it possible to change this
 behavior to keep the cursor at the same column?

No. It is not possible to change this behavior. The cursor is *always*
positioned on a valid character (unless you have virtual-edit mode
enabled). So, if you are appending text to the end of a line, when you
return to command mode the cursor *must* drop back onto the last character
you typed. For consistency sake, the cursor drops back everywhere, even if
you are in the middle of a line.

You can use the CTRL-O command in insert mode to execute a single ex
command and return back to insert mode without moving the cursor column.

If you don't care about consistency and only want the cursor to drop back when necessary when exiting insert mode, try:

inoremap <silent> <Esc> <C-O>:stopinsert<CR>

If the cursor is not on a valid character (for example, at the end of a line), it will still be moved back one character (unless virtual-edit mode is enabled).

If you are in paste mode and hit <Esc>, the cursor will still be moved back one character (since all mappings are ignored in paste mode).

But, otherwise, when using this mapping, <Esc> generally won't move the cursor.

If you have any other mappings which begin with <Esc> (for example, 'map <S-Up> ...' doesn't seem to work right for me, so I use 'map ^[[1;2A ...', which starts with <Esc>), then 'timeoutlen' will apply to this mapping, and the cursor will move one character to the left until 'timeoutlen' expires, then will move back to the proper position.

Programmatic Alternative

Mapping the <esc> key leads to problems most of the time. Here's how to do it programmatically:

let CursorColumnI = 0 "the cursor column position in INSERT
autocmd InsertEnter * let CursorColumnI = col('.')
autocmd CursorMovedI * let CursorColumnI = col('.')
autocmd InsertLeave * if col('.') != CursorColumnI | call cursor(0, col('.')+1) | endif

Putting the above in your vimrc keeps track of the cursor position when in INSERT mode. When exiting INSERT mode, it will move the cursor ahead one column if the cursor position has changed after leaving insert.

Comments

The way it's suggested in the tip, it breaks the immensely useful Visual-block Insert mode (:h v_b_i). This seems to not break anything (except when used in console Vim over ssh -- then any <Esc> remapping breaks escape sequences for some reason):

inoremap <silent> <Esc> <Esc>`^

Here are some suggestions regarding making keycode maps more responsive:

http://groups.yahoo.com/group/vim/message/66414
http://groups.yahoo.com/group/vim/message/66451

hmmm... interesting... when I remove all my mappings beginning with an <Esc> character, this little trick causes all sorts of problems. It only seems to work properly when there is some mapping beginning with an <Esc> character. Very strange behavior.

Perhaps that's why the Karma on this tip is horrible?


Around Wikia's network

Random Wiki