vimautocommand

Vim how to leave cursor at the end of the line after autocommand


I'm trying to make my own snippets in pure vimscript using autocommands. I want to make it so that after I type a specific character sequence, it is replaced by another character sequence. I made one like this, that replaces "hello" with "bye" when you type it.

function F()
  if (strpart (getline('.'), 0, col('.')-1) =~ 'hello$')
    execute "normal 5i\<Backspace>"
    normal! abye
    normal! l
  endif
endfunction

autocmd TextChangedI *.tex call F()

And it works fine if there are characters after the cursor. However, if I am writing at the end of the line, after the change the cursor is between 'y' and 'e', because the autocommand calls the function, the cursor is at the end of the line, and then it enters insert mode which starts inserting before the last character.

How can I make it so that the cursor is always left after 'bye'? I don't want to use iabbrev for a couple of reasons, one being that it doesn't expand as soon as I type.

I can do it with the option

  set ve+=onemore

but I don't like it's effects on normal writing.


Solution

  • How about the following, which uses setline and cursor functions rather than normal keymaps:

    function! F() abort
      let [l:line, l:col] = [getline('.'), col('.')]
      if strpart(l:line, 0, l:col-1) =~ 'hello$'
        let l:left = strpart(l:line, 0, l:col-6)
        let l:right = strpart(l:line, l:col-1)
        call setline('.', l:left . 'bye' . l:right)
        call cursor('.', l:col-2) " 2 = length diff between hello and bye
      endif
    endfunction
    

    This seems working for me (on Neovim 0.6).