2

New to vimscript. I am trying to invoke a function in insert-mode. The function is a bit complicated, but I am stuck at running "normal!".

Here is the mapping:

inoremap <buffer> <expr> <c-o> Tmp2()
nnoremap <buffer> <c-o> :call Tmp2()<cr>

Here is a very simple func that demonstrates my problem

function! Tmp2()
     normal! yiW
     echom @@
     return @@
endfunction

When I run the command in normal mode, it works fine. When I am in insert mode I get:

Line 1:
E523: Not allowed here
2

In :help <expr>, we find:

Be very careful about side effects!  The expression is evaluated while
obtaining characters, you may very well make the command dysfunctional.
For this reason the following is blocked:
- Changing the buffer text |textlock|.
- Editing another buffer.
- The |:normal| command.
- Moving the cursor is allowed, but it is restored afterwards.
If you want the mapping to do any of these let the returned characters do
that.

As filbranden points out in the comments, a method that works well here is

inoremap <buffer> <C-o> <C-r>=Tmp2()<CR>
5
  • 3
    Great answer! It would be nice to add that inoremap <buffer> <c-o> <C-R>=Tmp2()<CR> actually works for cases such as this one... Since the side effect in that case is happening during the execution of the macro, and not evaluation... – filbranden Aug 16 '20 at 16:58
  • 2
    That works! Thx! What is the role of <C-R> in that expression? – hba Aug 16 '20 at 17:24
  • @hba see :help <C-r>; it's used to insert the value of a register (in this case, the expression register) – D. Ben Knoble Aug 16 '20 at 18:07
  • 1
    @hba See :help i_CTRL-R. You might also want to read on the expression register, under :help "=. – filbranden Aug 16 '20 at 18:08
  • Thank you both. I just started with vimscript, and I find it very confusing :-) – hba Aug 16 '20 at 18:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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