Vim和Ctags技巧和窍门[关闭]


485

我刚刚在我的Vim(或更确切地说是gVim)中安装了Ctags(以帮助C ++开发),并且想找出自己喜欢的命令,宏,快捷方式以及与之配套的技巧...

分享您最好的武器库。您会为Vim开发上的C ++建议其他哪些Vim插件?

编辑您还将与Ctags一起使用的其他附加组件吗?

EDIT2与标签一起使用的gVim是哪个版本?这有什么不同吗?

EDIT3如何提高大型和小型项目的编程经验?


15
确保您使用旺盛的ctags(现代实现)以获得最佳效果:ctags.sourceforge.net
idbrii 2011年

17
也许凯夫不是建设性的?
弗洛伊德

27
尽管closed as not constructive差不多两年前,但对我来说却如此具有建设性
sazary

15
我认为关闭此问题的真正原因应该是:“尽管有很大帮助,但此问题仍不符合Q&A的StackOverflow政策。让此问题和答案移至Quora并扩大该站点,同时我们顽固地保持关闭帮助问题和解答”。
迭戈·皮诺

2
根据SO的规则,我理解为什么这个问题没有解决。但是将> 400赞成的问题标记为> 300赞成的答案以供删除,这有点脾气暴躁,不是吗?
DevSolar

Answers:


394

Ctrl+ ]-转到定义
Ctrl+ T-从定义跳回。
Ctrl+ W Ctrl+ ]-水平分割打开定义

在vimrc中添加这些行
map <C-\> :tab split<CR>:exec("tag ".expand("<cword>"))<CR>
map <A-]> :vsp <CR>:exec("tag ".expand("<cword>"))<CR>

Ctrl+ \-在新选项卡中打开定义
Alt+ ]-垂直拆分中打开定义

标签生成后。您可以使用以下键标记和标记功能:

Ctrl+ Left MouseClick-转到定义
Ctrl+ Right MouseClick-从定义跳回


8
C-] =>(控制键)和]键C-T =>(控制键)和T键仅用于ctag的新手。感谢您使用新的制表符
kumar

6
同样,在拆分窗口后,Ctrl-w C-]您可以C-w T(也称为Shift-t)将其拆分为一个新选项卡。
dash-tom-bang 2010年

1
@Will如果在终端上使用vim,则必须更改终端首选项,以使选项键的行为类似于alt键。如果您使用的是MacVim,则将此行添加到vimrc'set macmeta'。macmeta有文档,:h macmeta。
Amjith'1

17
g C-]非常有用 它打开一个快速对话框,以在多个定义中选择一个。
Vincenzo Pii 2012年

3
g]也很有用 您可以将光标放在标签名称上,然后按g]以获得匹配标签的列表。
zeekvfu

176

我的.vimrc中总是存在以下一行:

set tags=./tags;/

这将在当前目录中查找“标签”,并使树朝根工作直到找到一个。IOW,您可以在源代码树中的任何位置,而不仅仅是其根目录。


37
扎根是多余的。我建议只去家里:tags + = tags; $ HOME
gotgenes,

37
我正在处理的源树并不总是在我的主目录中……而且$ HOME往往是远离根目录的两个目录……好吧,我可以负担得起另外两个目录。:)
2009年

6
我同意w / uzi。如果我的cwd是/ home / me / programming / foo / bar / baz / bang / bam,则只有8个目录查找。我想这取决于您对速度的容忍度,但是在我的计算机上查找1目录的时间与8的时间没有明显不同。
Nate Murray

1
它的确取决于您的情况,我需要在我的一台计算机上使用gotgenes建议,因为/ home中大约有8,000个目录,而且这往往有些迟钝。
jkerian 2011年

1
有类似的东西cscope吗?
szx 2012年

45

Cscope的另一个有用的插件是cscope就像Ctags可以跳转到定义一样,Cscope可以跳转到调用函数。

如果〜/ bin /目录中有cscope,请将以下内容添加到.vimrc中,并使用g ^]转到调用函数(请参阅:help cscope)。

if has("cscope")
    set csprg=~/bin/cscope
    set csto=0
    set cst
    set nocsverb
    " add any database in current directory
    if filereadable("cscope.out")
        cs add cscope.out
        " else add database pointed to by environment
    elseif $CSCOPE_DB != ""
        cs add $CSCOPE_DB
    endif
endif

几乎忘了...就像ctags一样,您必须生成(并定期更新)数据库。我使用以下脚本

select_files > cscope.files
ctags -L cscope.files
ctags -e -L cscope.files
cscope -ub -i cscope.files

其中“ select_files”是另一个脚本,它从Makefile中提取C和头文件的列表。这样,我仅索引项目实际使用的文件。


cscope比ctags有什么优势?他们互相称赞吗?
Whaledawg

4
他们互相补充。Ctags查找符号或函数的定义。Cscope可以找到所有调用函数的地方。同时使用它们可以使在大型源代码树中导航变得非常容易。
nimrodm

1
但是,AFAIK cscope对C ++的理解有限。
卢克·赫米特

它是有限的,不是很好。但是对于它所做的(跳转到USAGES),没有更好的选择。它的主要问题是,当您想跳转到函数调用(f)时,通常需要跳转到使用符号(s)的任何地方,并在心理上过滤结果...
Greg Rogers

2
@Whaledawg是的,当我按CTRL +]时,我的声卡在输出中发送“ clap.wav” :)
Patrizio Rullo 2011年

27

您可以将目录添加到您的ctags查找。例如,我为Qt4构建了一个ctags索引,并将其保存在我的.vimrc中:

set tags+=/usr/local/share/ctags/qt4


16

我使用ALT-left和ALT-right从标签堆栈弹出/推送。

" Alt-right/left to navigate forward/backward in the tags stack
map <M-Left> <C-T>
map <M-Right> <C-]>

如果hjkl用于运动,则可以映射<M-h><M-l>代替。


与ctrl-]和ctrl-t不同-我想,您的建议会更清晰一些。

@Sasha,对不起?不知道你在说什么 = X注意,这也可以在:help中使用。
斯特拉格

2
我认为这比默认设置更直观,更干净。
艾曼(Ayman)

1
@Ayman但是也违反了不必将手从母行上移开的原理,例如使用hjkl vs箭头键。
TankorSmash 2013年

@TankorSmash,什么原理?
斯特拉格

10

同名的几个定义

<C-w>g<C-]>打开拆分中的定义,但也可以执行:tjump定义中的定义,或者如果有多个定义,则为您提供可供选择的定义列表。


2
与第一个命令相似,vim具有:ptag在预览窗口中打开定义的命令。
idbrii

1
预览窗口很不错,因为您可以从任何其他窗口中使用:pc将其关闭,而无需先将光标移至预览窗口。
Heikki Naski 2012年

还有一个带有ptag的巧妙的autocmd技巧,在:h CursorHold-example可配置的超时后,该标签在预览窗口中的光标下方显示该项目的标签。
dash-tom-bang,

+1:tjump我现在绑定了:tjump <Cr> <Cw> <CR>比<C-]>效果更好imho希望将这种行为与:ptag结合使用
Andreas Fliesberg 2013年

:help是真棒有时......看到:help CTRL-W_g}:ptjump
安德烈亚斯Fliesberg

8

我最常用的命令是C-],它会跳转到光标下的函数定义。您可以更频繁地使用它来接听更多电话。之后,Co将带您回到一个新的高度,Ci会再次变得更深。


16
Ct返回C-]堆栈中的上一层,而Co在移动后返回上一个光标位置。因此,如果您C–]到某个函数然后向下翻页,Ct将立即返回,而Co将返回到该函数的开头,然后返回到调用。
Greg Hewgill

6

我发现标签列表插件是必须的。它在一个单独的窗口中列出了它所知道的所有标记(已打开的文件),并使浏览较大的文件变得非常容易。

我主要将其用于Python开发,但仅对C / C ++更好。




4

我将以下内容放在我的.gvimrc文件中,该文件在gvim启动时从任何点搜索树中的标签文件:

function SetTags()
    let curdir = getcwd()

    while !filereadable("tags") && getcwd() != "/"
        cd ..
    endwhile

    if filereadable("tags")
        execute "set tags=" . getcwd() . "/tags"
    endif

    execute "cd " . curdir
endfunction

call SetTags()

然后,我使用如下脚本定期在源代码树的顶部重新生成标签文件:

#!/bin/bash

find . -regex ".*\.\(c\|h\|hpp\|cc\|cpp\)" -print | ctags --totals --recurse --extra="+qf" --fields="+i" -L -

7
您只是重新发明了向上搜索。参见:h文件搜索。又见stackoverflow.com/questions/563616/vimctags-tips-and-tricks/...
gotgenes

2

我在macOS中使用vim,原始的ctags不能正常工作,因此我下载了最新的并配置make make install。我在/ usr / local / bin / ctags中安装了ctgas(以保持原始状态)

"taglist
let Tlist_Ctags_Cmd = "/usr/local/bin/ctags"
let Tlist_WinWidth = 50
map <leader>ta :TlistToggle<cr>
map <leader>bta :!/usr/local/bin/ctags -R .<CR>
set tags=tags;/
map <M-j> <C-]>
map <M-k> <C-T>

1

我修改了上面的SetTags()搜索功能(应由等效的替换set tags+=./tags;/)以适用于cscope。似乎可以工作!

"cscope file-searching alternative
function SetCscope()
    let curdir = getcwd()

    while !filereadable("cscope.out") && getcwd() != "/"
            cd ..
                endwhile

    if filereadable("cscope.out")
            execute "cs add " . getcwd() . "/cscope.out"
                endif

    execute "cd " . curdir
    endfunction

call SetCscope()

3
正如gotgenes所说,您只是重新发明了向上搜索。参见:h文件搜索。有关相关示例,请参见此插件
idbrii 2011年

1

上面的SetCscope()函数的另一个迭代。这会将cscope前置路径设置为获取匹配项,而无需放在“ cscope.out”所在的目录中:

function s:FindFile(file)
    let curdir = getcwd()
    let found = curdir
    while !filereadable(a:file) && found != "/"
        cd ..
        let found = getcwd()
    endwhile
    execute "cd " . curdir
    return found
endfunction

if has('cscope')    
    let $CSCOPE_DIR=s:FindFile("cscope.out")
    let $CSCOPE_DB=$CSCOPE_DIR."/cscope.out"
    if filereadable($CSCOPE_DB)
        cscope add $CSCOPE_DB $CSCOPE_DIR
    endif

    command -nargs=0 Cscope !cscope -ub -R &
endif

3
正如gotgenes所说,您只是重新发明了向上搜索。参见:h文件搜索。有关相关示例,请参见此插件
idbrii
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.