我有以下vimscript .vim / ftplugin目录:
" change to header file from c file or vice versa
function! CppAlter()
python << endpy
import vim
import os
bufferNames = [os.path.basename(b.name) for b in vim.buffers]
currentBufName = vim.eval("expand('%:p:t')")
currentBufStem, currentBufExt = os.path.splitext(currentBufName)
if currentBufExt == ".cpp" or currentBufExt == ".c" or currentBufExt == ".cc":
altBufName1 = currentBufStem + ".h"
altBufName2 = currentBufStem + ".hpp"
if altBufName1 in bufferNames:
vim.command("b " + altBufName1)
elif altBufName2 in bufferNames:
vim.command("b " + altBufName2)
else:
raise ValueError("No header file corresponding to this c file")
elif currentBufExt == ".h" or currentBufExt == ".hpp":
altBufName1 = currentBufStem + ".cpp"
altBufName2 = currentBufStem + ".c"
altBufName3 = currentBufStem + ".cc"
if altBufName1 in bufferNames:
vim.command("b " + altBufName1)
elif altBufName2 in bufferNames:
vim.command("b " + altBufName2)
elif altBufName3 in bufferNames:
vim.command("b " + altBufName3)
else:
raise ValueError("No c file corresponding to this header file")
else:
raise ValueError("This is not a c type file")
endpy
endfunction
nnoremap <leader>vc :call CppAlter()<cr>
inoremap <leader>vc <esc>:call CppAlter()<cr>
当我打开vim时出现错误:
" vim.error: Vim(function):E127: Cannot redefine function CppAlter: It is in use
但是如果我将它保存在/ tmp中并明确地保存:so /tmp/x.vim,则没有错误消息。 想知道这里有什么问题。
答案 0 :(得分:8)
在您的函数内部,您正在加载另一个缓冲区(例如vim.command("b " + altBufName1)
)。当该缓冲区具有相同的文件类型时,当前的ftplugin脚本将作为 filetype plugin 处理的一部分再次获取,但原始函数尚未返回,因此您获得E127
。
我建议将功能本身放入自动加载脚本,例如在~/.vim/autoload/ft/cppalter.vim
:
function! ft#cppalter#CppAlter()
...
您的ftplugin脚本变得更小更高效,因为该功能仅来源一次:
nnoremap <leader>vc :call ft#cppalter#CppAlter()<cr>
...
(你应该在这里使用:nnoremap <buffer>
来限制映射的范围。)
如果您不想解决此问题,请将功能定义移至底部并添加一个警卫,例如:
nnoremap <leader>vc :...
if exists('*CppAlter')
finish
endif
function! CppAlter()
...
答案 1 :(得分:1)
我遇到了一个有趣的 E127
案例,它几乎总结了为什么它几乎在任何情况下都会发生。让我解释一下。
首先,让我们看看文档是怎么说的。
E127 E122
When a function by this name already exists and [!] is
not used an error message is given. There is one
exception: When sourcing a script again, a function
that was previously defined in that script will be
silently replaced.
When [!] is used, an existing function is silently
replaced. **Unless it is currently being executed, that
is an error.**
对于下一部分,请注意最后一行要说的内容。
让我们通过一个例子来理解这一点。下面是一个函数,它根据当前脚本的文件类型猜测和获取当前脚本的来源。请注意 exec
命令如何在调用此函数时启动当前文件的无限递归源。
function! s:SourceScriptImplicit()
if !&readonly
w
endif
let l:bin=system("which " . &filetype)[:-2]
let l:sourcecommand=
\ #{
\ vim: "source %",
\ sh: "!source %",
\ javascript: "!node %",
\ python: "!python3 %"
\ }
exec l:sourcecommand[split(l:bin, "/")[-1]]
endfunction
要解决这个问题,只需从函数中删除递归部分即可。
function! s:SourceScriptImplicit()
if !&readonly
w
endif
let l:bin=system("which " . &filetype)[:-2]
let l:sourcecommand=
\ #{
\ vim: "source %",
\ sh: "!source %",
\ javascript: "!node %",
\ python: "!python3 %"
\ }
return l:sourcecommand[split(l:bin, "/")[-1]]
endfunction
nn <leader>so :exec <SID>SourceScriptImplicit()<cr>
现在完美运行!
答案 2 :(得分:0)
我想你应该注意到 |
对于在底部命令行中执行命令很有用,例如 :source expand("%") | source ./awesome.vim
这是我的 .init.vim
(或 .vimrc
)代码段,其 func 正在获取 .vim
目录中的所有 /home/zarkli/.config/nvim/myInitCustom/
文件:
function SourceVimScripts()
let l:command = ""
let l:files = split(globpath('/home/zarkli/.config/nvim/myInitCustom/','*.vim'),'\n') " use absolute path to avoid problems when opening an non-nvim_init file
for l:file in l:files
let l:command .= "source ".l:file." |"
endfor
" the end of the l:command should be '|',but that doesn't matter
return l:command
endfunction
exec SourceVimScripts()
它可以完美地解决您的问题。