Is it possible to cancel the said behavior?
A task for extra credit: Figure out a way to force Vim to refresh the cursor position immediately after exiting Insert mode.
Is it possible to cancel the said behavior?
A task for extra credit: Figure out a way to force Vim to refresh the cursor position immediately after exiting Insert mode.
Although I would not recommend changing the default cursor mechanics, one way of achieving the behavior in question is to use the following Insert-mode mapping.
:inoremap <silent> <Esc> <Esc>`^
Here the Esc key is overloaded in Insert mode to additionally
run the `^
command which moves the cursor to the position where it
had been the last time Insert mode was left. Since in this mapping it
is executed immediately after leaving Insert mode with Esc,
the cursor is left one character to the right as compared to its
position with default behavior.
Unlike some other workarounds, this one does not require Vim to be
compiled with the +ex_extra
feature.
a
inserts at the current position and i
moves the cursor back and inserts. Either way is logical depending on where you consider the cursor to be. I guess the folks who wrote vi considered it to be after the highlighted character. –
Shadshadberry autocmd InsertLeave * :normal `^
–
Dnepropetrovsk Ctrl-[
instead of escape, see this. So instead of remapping my escape key I decided to take this excellent answer and change the key from [
to ]
for when I want to move forward: inoremap <silent> <C-]> <Esc>`^
–
Hollo Although there are tricks to deal with this (such as the ESC mappings mentioned in the previous two posts), there's no consistent way to do this. The reason is that there is no way to determine the method that was used to enter insert mode. Specifically, given the string abcDefg
with the cursor on the D
:
If you press i, the insert mode location will be between the c
and D
. A normal ESC will put the cursor on c
; <C-O>:stopinsert<CR>
(or the backtick method) will put the cursor on D
.
If you press a, the insert mode location will be between the D
and e
. A normal ESC will put the cursor on D
; <C-O>:stopinsert<CR>
will put the cursor on e
.
If you REALLY want to do this, you could fudge it with something like this:
let insert_command = "inoremap <ESC> <C-O>:stopinsert<CR>"
let append_command = "iunmap <ESC>"
nnoremap i :exe insert_command<CR>i
nnoremap a :exe append_command<CR>a
BUT: remember that this will only deal with i
and a
as methods of entry: if you use visual block mode, I
, or A
or whatever, you'll need to come up with new commands to match (and there are a lot of them). Therefore, I'd strongly recommend you don't do this.
Personally, I'd recommend getting used to the default behaviour. You can easily make it logical for i
OR logical for a
. If you change the default to logical for i
at the expense of logical for a
, you'll just get confused when you use a standard vi/vim install.
Based on Nathan Neff's comment, the best approach I've found is
autocmd InsertLeave * :normal! `^
set virtualedit=onemore
autocmd
moves the cursor back to where it was when insert mode ended (i.e. one forward compared to the default).
virtualedit
makes it act consistently at end of line (so it can be one forward of the last character on the line).
(Edited: normal!
to avoid recursive mappings)
autocmd InsertLeave * if !exists('b:visual_multi') | exe 'normal! `^' | endif
–
Inez inoremap <Esc> <C-o>m[single-backtick-here]<Esc>[double-backticks-here]
for VsCodeVim, but it messes up the .
to repeat last operation. So, better stick with inoremap <Esc> <Esc>l
and accept that cursor goes to column 2 when it's on column 1. –
Inez inoremap <silent> <Esc> <C-O>:stopinsert<CR>
in your .vimrc
.
i
but illogical if you enter insert mode with a
. –
Shadshadberry i
to set a flag, then remap insert mode <Esc>
to check that flag, and if set, use <C-O>:stopinsert<CR>
, and then clear the flag either way. –
Frodina a
. In general, after each change, when I leave that change, I'm done with that change, and the next thing I would like to do will probably involve making a different change. Thus, to me, upon leaving insert mode (no matter how I entered it), I'd generally prefer the cursor to be on the next character so I'm ready for my next change, rather than being ready to change what I just inserted. (mostly copied from my comment here: unix.stackexchange.com/a/11403/38050) –
Nicki I do believe the proper way to do this is
au InsertLeave * call cursor([getpos('.')[1], getpos('.')[2]+1])
if (getpos('.')[2] > 1) |
before the call
to fix it. (Also, it should be part of an augroup
to prevent cumulative jumps forward when reloading a .vimrc
that contains this autocommand.) –
Nicki augroup
thing? Thanks –
Tarkany ttimeoutlen
? I personally have ttimeoutlen
set to 10
milliseconds: ttimeoutlen
is the timeout leeway given to your terminal emulator client to emit terminal escape sequences, such as the 4-byte sequence \033[[C
for the right-arrow-key. The reason that insert mode is not actually exited for real until after this timeout should be evident -- Vim won't know if your terminal is about to follow up with an escape sequence, or to commit to Esc as an exit-insert-mode command. Notice carefully and realize that your Vim setup was already doing this, delaying exiting insert mode. –
Tarkany autocmd! InsertLeave * if (getpos('.')[2] > 1) | call cursor([getpos('.')[1], getpos('.')[2]+1]) | endif
So the autocommand won't break in the first column. Also, see a similar solution here: vim.fandom.com/wiki/… –
Maquette There is an approach from the Vim Tips wiki that has worked well for me for...I don't know how many years:
" Leave insert mode to the *right* of the final location of the insertion
" pointer
" From http://vim.wikia.com/wiki/Prevent_escape_from_moving_the_cursor_one_character_to_the_left
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
What about:
:imap <Esc> <Esc><Right>
i
but illogical if you enter insert mode with a
. –
Shadshadberry © 2022 - 2024 — McMap. All rights reserved.
a
ori
, so it assumesa
. And really: cursor does not "slide away" when usinga
and <kbd>Esc</kbd> repeatedly. – Fireeater<esc>D
and such. I would think that something based on:autocmd InsertLeave
could work?? – Tarkanyvirtualedit
option to fix that oddity as well. – Randazzo