Vim:E523: 这里不允许

Vim:E523: Not allowed here

我在 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


我有当前的 .vim 文件

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

和这个 .py 文件

import vim

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

出现此问题是因为您在评估映射表达式时不允许修改当前缓冲区。

参见:help :map-expression,更具体地说:

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.

您应该使用 return 函数来插入字符,或者考虑使用非 <expr> 映射,显式 :call.

对于前者,returning要插入的字符:

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

utils.py 文件:

def write():
    return 'some text'

或者,使用非<expr>映射的替代方法:

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

(后者可能会产生一些不需要的副作用,因为您将 return 在修改缓冲区后进入插入模式,但您将 return 到与之前相同的位置映射。如果需要,您可能需要考虑使用 setpos() 或类似的方法在映射后移动光标。)