Say I have a session like this:


Where | is the cursor in insert mode. If I press Esc, I get this:


but I want this:


As I want to select the second "word", and if I go into visual mode, the y will be part of the selection. I found that I can use Ctrl + O instead of Esc and the cursor is correct, but it only allows one command and goes back into insert mode. I want to stay in normal mode.

Is some key available for this purpose?

2 Answers 2


You can press Ctrl-OCtrl-C. Control-C effectively cancels any pending mode and takes you into Normal in the current cursor position. Of course, you can create some mapping if you want.

To make things working also for the last character on line, make sure you have :set ve=all or :set ve=onemore in your vimrc. Or use Ctrl-\Ctrl-O instead of just Ctrl-O.

  • This is great. For some reason Vim has i and a (before and after), but only Esc (before). So this is a good workaround
    – Zombo
    Apr 22, 2020 at 11:49

This is regular vi compatible behaviour. After pressing Esc the cursor is always moved one character back. I believe the reason is the following: If the cursor in insert mode is at the end of the entered text and you press Esc, there is no text on which to place the cursor, therefore it is moved back to the last entered character. The one exception to this rule is, if the cursor is on the start of the line, in which case it obviously cannot be moved to the left and will be placed on an empty cell (press ga on it and notice the NUL result, which basically means there is no character)

If you don't want that behavior, I would suggest to map it to a behavior that you want, e.g.

inoremap <silent><expr> <esc> col('.')>1&&col('$')<col('.')?'<esc>l':'<esc>'

This uses an expression mapping that checks whether the cursor is either after column 1 or before the last column in the current row and only in those cases will try to move the cursor after pressing Esc in insert mode back to the character it was in insert mode.

Slightly related, you might want to also allow to put the cursor after the last character. This can be done using :set ve=onemore. In that case, you do not need the condition &&col('$')<col('.') above and you can skip that.

Your Answer

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

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