Vim Ctrl-]标记跳转仅适用于命令

时间:2019-02-20 16:58:06

标签: vim

我在vimscript上编写了一个插件,并希望使用标签跳转到函数定义。 我已经安装了ctags,在.vimrc中配置了vim选项set tags=./tags;,并在脚本目录中使用ctags -R创建了标记文件。 在我的脚本中,我具有以下功能:

func s:OnWipeoutEvent()
" ...
endfunc

和命令:

command! -bar -nargs=* -complete=file -bang TermdebugEasymaps
            \ call s:StartDebug(<bang>0, <f-args>)

当我尝试使用Ctrl-]跳转到函数(OnWipeoutEvent())定义时,vim会说:E257: ctag: tag not found.因此,它不适用于函数定义,但适用于vim命令定义。我可以使用Ctrl-]跳转到命令。为什么?我该如何解决这个问题?

UPD:我认为这种行为是s:函数名称中s:OnWipeoutEvent()前缀的结果。因为在vim命令行中输入tag s:OnWipeoutEvent时可以跳转到函数定义。可能是Ctrl-]使用不带此前缀的函数名称。知道如何解决吗?

UPD2:尝试使问题更清楚。下面是我的vim脚本的一部分:

func s:OnWipeoutEvent()
"...
endfunc

augroup termdebug-easymaps
    autocmd BufWipeout * call s:OnWipeoutEvent()
augroup END

command! -bar -nargs=* -complete=file -bang TermdebugEasymaps
            \ call s:StartDebug(<bang>0, <f-args>)

标记文件:

TermdebugEasymaps   termdebug-easymaps.vim  /^command! -bar -nargs=* -complete=file -bang TermdebugEasymaps$/;" c
TermdebugEasymapsCommand    termdebug-easymaps.vim  /^command! -bar -nargs=* -complete=file -bang TermdebugEasymapsCommand$/;"  c
TermdebugEasymapsStop   termdebug-easymaps.vim  /^command! -bar TermdebugEasymapsStop call s:Stop_termdebug()$/;"   c
s:CloseBuffers  termdebug-easymaps.vim  /^func s:CloseBuffers()$/;" f
s:CommOutput    termdebug-easymaps.vim  /^func s:CommOutput(out, msg)$/;"   f
s:CreateCommWin termdebug-easymaps.vim  /^func s:CreateCommWin()$/;"    f
s:DecodeMessage termdebug-easymaps.vim  /^func s:DecodeMessage(quotedText)$/;"  f
s:GetCurrentSourceFullname  termdebug-easymaps.vim  /^func s:GetCurrentSourceFullname()$/;" f
s:GetFullname   termdebug-easymaps.vim  /^func s:GetFullname(msg)$/;"   f
s:GetOpenedList termdebug-easymaps.vim  /^func s:GetOpenedList()$/;"    f
s:GoToDebugWindow   termdebug-easymaps.vim  /^func s:GoToDebugWindow()$/;"  f
s:MapsCurrentBuffer termdebug-easymaps.vim  /^func s:MapsCurrentBuffer()$/;"    f
s:OnWipeoutEvent    termdebug-easymaps.vim  /^func s:OnWipeoutEvent()$/;"   f
s:ProgramRunState   termdebug-easymaps.vim  /^func s:ProgramRunState()$/;"  f
s:RestoreBuffersState   termdebug-easymaps.vim  /^func s:RestoreBuffersState()$/;"  f
s:SaveCurrentBufferState    termdebug-easymaps.vim  /^func s:SaveCurrentBufferState()$/;"   f
s:SetRunMapForCurrent   termdebug-easymaps.vim  /^func s:SetRunMapForCurrent()$/;"  f
s:SetRunMapsForOpened   termdebug-easymaps.vim  /^func s:SetRunMapsForOpened()$/;"  f
s:SetRunMapsForTreated  termdebug-easymaps.vim  /^func s:SetRunMapsForTreated()$/;" f
s:StartDebug    termdebug-easymaps.vim  /^func s:StartDebug(bang, ...)  $/;"    f
s:StartDebugCommand termdebug-easymaps.vim  /^func s:StartDebugCommand(bang, ...)$/;"   f
s:StartDebug_internal   termdebug-easymaps.vim  /^func s:StartDebug_internal(command_mode, args, bang)$/;"  f
s:StopTermdebug termdebug-easymaps.vim  /^func s:StopTermdebug()$/;"    f
s:TerminateProgram  termdebug-easymaps.vim  /^func s:TerminateProgram()$/;" f
s:TreatOpened   termdebug-easymaps.vim  /^func s:TreatOpened()$/;"  f
s:comm_timeout  termdebug-easymaps.vim  /^let s:comm_timeout = 5000$/;" v
s:commflags termdebug-easymaps.vim  /^let s:commflags = { 'current_source': 0, 'all_sources': 0, 'program_run': 0 }$/;" v
s:sleeptime termdebug-easymaps.vim  /^let s:sleeptime = 10$/;"  v
termdebug   termdebug-easymaps.vim  /^augroup termdebug-easymaps$/;"    a

2 个答案:

答案 0 :(得分:1)

我写了临时解决方案:

let s:mapped_buffers = []

autocmd BufReadPost,BufWritePost,BufEnter *.vim call s:MapBuffer()

func s:MapBuffer()
    let nomap = 0
    for buf_i in s:mapped_buffers
        if bufnr('%') == buf_i
            let nomap = 1
        endif
    endfor
    if !nomap
        nnoremap <buffer> <silent> <C-]> :call <SID>JumpToTag()<CR>
        nnoremap <buffer> <silent> <C-W>] :call <SID>JumpToTagInNewWindow()<CR>
        nnoremap <buffer> <silent> g] :call <SID>SelectTag()<CR>
        nnoremap <buffer> <silent> <C-W>g] :call <SID>SelectTagInNewWindow()<CR>
        call add(s:mapped_buffers, bufnr('%'))
    endif
endfunc

func s:JumpToTag()
    exe 'tag ' . s:GetTagName()
endfunc

func s:JumpToTagInNewWindow()
    exe 'stag ' . s:GetTagName()
endfunc

func s:SelectTag()
    exe 'tjump ' . s:GetTagName()
endfunc

func s:SelectTagInNewWindow()
    exe 'stjump ' . s:GetTagName()
endfunc

func s:GetTagName()
    let short_word = expand("<cword>")
    let long_word = expand("<cWORD>")
    let mi = match(long_word, short_word)
    if mi >= 2 && long_word[mi - 1] == ':'
        " Add prefix
        let tag_name = long_word[mi - 2: mi - 1] . short_word
    else
        let tag_name = short_word
    endif
    return tag_name
endfunc

答案 1 :(得分:1)

我将以下内容放入~/.vim/after/ftplugin/vim.vim中以解决此问题:

if v:version >= 703
    " The runtime update of Vim 7.3.488 (changeset 2cfb68fa26cd) adds ":" to
    " 'iskeyword'; ostensibly "To make syntax highlighting of 'vimVar's work
    " correctly". But this breaks tag jumping, because ctags puts functions
    " without scope prefix into the tags database. (And this is better, because
    " prefixes are sometimes optional, and <SID> and s: are equivalent.)
    setlocal iskeyword-=:
endif