Tiki
Tiki

Reputation: 780

Vim:E523: Not allowed here

I received this error when i tab in vim.

Traceback (most recent call last):
File "< string >", line 1, in < module >
File "utils.py", line 15, in write
current_buffer.append('some text')
vim.error: Vim:E523: Not allowed here


I have the current .vim file

if expand("%:e") == 'xml'                                                                                                                                                             
    inoremap <expr> <tab> WriteFile()                                                                                                                                                 
endif                                                                                                                                                                                 
function! WriteFile()                                                                                                                                                                 
    python3 utils.write()                                                                                                                                                             
endfunction 

and this .py file

import vim

def write():
    current_buffer = vim.current.buffer
    current_buffer.append('some text')

Upvotes: 4

Views: 1691

Answers (1)

filbranden
filbranden

Reputation: 8898

This issue is happening because you're not allowed to modify the current buffer while evaluating an expression for a mapping.

See :help :map-expression, more specifically:

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.

You should either have the function return the characters to be inserted, or consider using a non-<expr> mapping, with an explicit :call.

For the former, returning the characters to be inserted:

inoremap <expr> <tab> WriteFile()
function! WriteFile()
    return py3eval('utils.write()')
endfunction

And the utils.py file:

def write():
    return 'some text'

Or, the alternative approach of using a non-<expr> mapping:

inoremap <tab> <C-O>:call WriteFile()<CR>

(The latter might have some unwanted side-effects, as you'll return to insert mode after modifying the buffer, but you'll return to the same position you were before the mapping. You might want to consider using setpos() or similar to move the cursor after the mapping, if needed.)

Upvotes: 6

Related Questions