485

I have just installed Ctags (to help with C++ development) with my Vim (or rather gVim), and would like to find out your favorite commands, macros, shortcuts, tips that go along with it...

Share your best arsenal. What other Vim add-ons you would recommend for C++ on Vim development?

EDIT What other add-on you would use in conjunction with Ctags?

EDIT2 What version of gVim you use with tags? Does it make a difference?

EDIT3 How do you enhance your programming experience for both big and small projects?

kenorb
  • 118,428
  • 63
  • 588
  • 624
  • 15
    Make sure you're using exuberant ctags (a modern implementation) for best results: http://ctags.sourceforge.net/ – idbrii Feb 23 '11 at 18:59
  • 17
    Perhaps the kev is not constructive? – Floyd Jun 06 '13 at 11:29
  • 1
    So, I answer here : Try clang + supertab + snipmate. It's like intellisense in vim ! http://zwiener.org/vimautocomplete.html – Zardoz89 Jun 23 '13 at 21:52
  • 27
    though `closed as not constructive` almost two years ago, it is so constructive for me – sazary Aug 10 '13 at 22:01
  • 15
    I think the real reason for closing this question should have been: "This question, despite being enormously helpful, doesn't fit in StackOverflow policy of Q&A. Let this question and answers move to Quora and grow that site while we stubbornly keep closing helpful questions and answers". – Diego Pino Feb 17 '14 at 11:25
  • 1
    The moment I saw this questions on google search result , I knew it would be closed as not constructive question ! – Pratik Singhal Nov 10 '14 at 13:30
  • `noremap zz`, just because I want the jump to be centered in screen ;) – Paschalis Feb 26 '15 at 11:29
  • 2
    I understand why this question was closed, given the rules of SO. But flagging a >400 upvote question with a >300-upvote answer for *deletion* is a bit on the grumpy side, isn't it? – DevSolar Aug 17 '15 at 10:54
  • 1
    I'm so sick of seeing questions closed as "not constructive" when they're obviously beneficial to so many people... – Chauncey Garrett Jun 09 '16 at 17:01

15 Answers15

394

Ctrl+] - go to definition
Ctrl+T - Jump back from the definition.
Ctrl+W Ctrl+] - Open the definition in a horizontal split

Add these lines in vimrc
map <C-\> :tab split<CR>:exec("tag ".expand("<cword>"))<CR>
map <A-]> :vsp <CR>:exec("tag ".expand("<cword>"))<CR>

Ctrl+\ - Open the definition in a new tab
Alt+] - Open the definition in a vertical split

After the tags are generated. You can use the following keys to tag into and tag out of functions:

Ctrl+Left MouseClick - Go to definition
Ctrl+Right MouseClick - Jump back from definition

Olivier Pons
  • 13,972
  • 24
  • 98
  • 190
Amjith
  • 20,116
  • 12
  • 40
  • 38
176

One line that always goes in my .vimrc:

set tags=./tags;/

This will look in the current directory for "tags", and work up the tree towards root until one is found. IOW, you can be anywhere in your source tree instead of just the root of it.

Conspicuous Compiler
  • 6,116
  • 1
  • 36
  • 50
uzi
  • 4,549
  • 2
  • 14
  • 11
  • 37
    Going up to root is excessive. I suggest only going up to home instead: tags+=tags;$HOME – gotgenes May 12 '09 at 06:03
  • 37
    The source trees I work on aren't always in my home directory... and being that $HOME tends to be two directories away from root... well, I can afford two more directory lookups. :) – uzi May 13 '09 at 19:50
  • 6
    I agree w/ uzi. If my cwd is /home/me/programming/foo/bar/baz/bang/bam that's only 8 directory lookups. I suppose it depends on your tolerance for speed, but the time to lookup 1 directory isn't noticeably different from 8 on my machine. – Nate Murray Oct 23 '09 at 15:04
  • I put my tags into a subdirectory, but use a similar trick (that yields the same fix mentioned by @Amit), `set tags=_tags/tags;c:/work` – dash-tom-bang Sep 29 '10 at 17:26
  • 1
    It does depend on your scenario, I need to use gotgenes suggestion on one of my machines because there are roughly 8,000 directories in /home, and that tends to be a bit sluggish. – jkerian Feb 22 '11 at 15:50
  • 1
    Is there something similar for `cscope`? – szx Dec 07 '12 at 11:19
  • 1
    You don't even need `/` if you go up to root directory. Just `;` is enough. – danadam Jun 28 '13 at 15:55
45

Another useful plugin for C development is cscope Just as Ctags lets you jump to definitions, Cscope jumps to the calling functions.

If you have cscope in your ~/bin/ directory, add the following to your .vimrc and use g^] to go to the calling function (see :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

Almost forgot... Just as ctags - you have to generate (and periodically update) the database. I use the following script

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

Where 'select_files' is another script that extracts the list of C and header files from the Makefile. This way I index only the files actually used by the project.

nimrodm
  • 21,218
  • 7
  • 51
  • 54
  • What is the advantage of cscope over ctags? Do they compliment eachother? – Whaledawg Feb 20 '09 at 04:53
  • 4
    They complement each other. Ctags finds the definition of a symbol or a function. Cscope can find all the places calling a function. using both of them makes navigation in large source trees very easy. – nimrodm Feb 20 '09 at 07:51
  • 1
    However, AFAIK cscope has a limited comprehension of C++. – Luc Hermitte Feb 21 '09 at 11:35
  • It is limited, and not very good. But for what it does (jumping to USAGES), there isn't any better alternative. Its main problem is that when you want to jump to function calls (f), you often need to jump to anywhere that symbol is used (s) instead and filter the results mentally... – Greg Rogers Apr 13 '09 at 13:17
  • ...because it hates namespaces. Global is also workable, but IMO slightly worse. – Greg Rogers Apr 13 '09 at 13:18
  • Can you show an example of select_files scripts ? – vehomzzz Sep 08 '09 at 11:44
  • 2
    @Whaledawg Yes, when I press CTRL+] my sound card sends "clap.wav" in output :) – Patrizio Rullo Feb 02 '11 at 14:14
  • @vehomzzz: nimrodm does something fancier with his makefiles, but you could just use find: `find . -type f \( -iname "*.cpp" -o -iname "*.h" \)` – idbrii Nov 24 '11 at 17:21
27

You can add directories to your ctags lookup. For example, I have a ctags index built for Qt4, and have this in my .vimrc:

set tags+=/usr/local/share/ctags/qt4
strager
  • 84,025
  • 24
  • 129
  • 172
23

All of the above and...

code_complete : function parameter complete, code snippets, and much more.

taglist.vim : Source code browser (supports C/C++, java, perl, python, tcl, sql, php, etc)

Johan
  • 18,177
  • 25
  • 89
  • 107
  • 5
    I think it would be good to add that taglist.vim is the most downloaded vim plugin. – amit Nov 28 '09 at 16:09
16

I use ALT-left and ALT-right to pop/push from/to the tag stack.

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

If you use hjkl for movement you can map <M-h> and <M-l> instead.

strager
  • 84,025
  • 24
  • 129
  • 172
10

Several definitions of the same name

<C-w>g<C-]> open the definition in a split, but also do :tjump which either goes to the definition or, if there are several definitions, presents you with a list of definitions to choose from.

Heikki Naski
  • 2,070
  • 1
  • 17
  • 13
  • 2
    Similar to the first command, vim has a `:ptag` command that opens the definition in a preview window. – idbrii Nov 24 '11 at 17:24
  • 1
    The preview window is nice because you can close it with :pc from any other window, without having to first move the cursor to the preview window. – Heikki Naski Mar 22 '12 at 13:59
  • There's also a neat autocmd trick with ptag at `:h CursorHold-example` which displays the tag for the item under the cursor in the preview window after a configurable timeout. – dash-tom-bang May 28 '13 at 00:11
  • +1 for :tjump i've now bound :tjump works better than imho Would love to combine this behaviour with :ptag – Andreas Fliesberg Jun 17 '13 at 10:38
  • `:help` is awesome sometimes... see `:help CTRL-W_g}` and `:ptjump` – Andreas Fliesberg Jun 17 '13 at 11:19
8

The command I am using most is C-] which jumps to the definition of the function under the cursor. You can use it more often to follow more calls. After that, C-o will bring you back one level, C-i goes deeper again.

raimue
  • 4,111
  • 1
  • 19
  • 30
  • 16
    C-t goes back one level in the C-] stack, while C-o goes back to a previous cursor position after a movement. So if you C-] to a function then page down, C-t will go back immediately while C-o will go back to the start of the function, *then* back to the call. – Greg Hewgill Feb 19 '09 at 02:21
6

I've found the taglist plug-in a must-have. It lists all tags that it knows about (files that you have opened) in a seperate window and makes it very easy to navigate larger files.

I use it mostly for Python development, but it can only be better for C/C++.

Walter
  • 7,159
  • 1
  • 27
  • 30
5

I've encapsulated tags manipulation in an experimental plugin of mine.

Regarding C++ development in vim, I've already answered there: I use my own suite, and a few other plugins.

Community
  • 1
  • 1
Luc Hermitte
  • 29,719
  • 7
  • 60
  • 74
5

I've been adapting my vim plugins for two years to support big enough c++ project. You can take a look at them.

They use ctags and cscsope.

http://www.vim.org/scripts/script.php?script_id=1638
http://www.vim.org/scripts/script.php?script_id=2507

Jens
  • 61,963
  • 14
  • 104
  • 160
Mykola Golubyev
  • 52,197
  • 14
  • 81
  • 101
4

I put the following in my .gvimrc file, which searches up the tree from any point for a tags file when gvim starts:

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()

I then periodically regenerate a tags file at the top of my source tree with a script that looks like:

#!/bin/bash

find . -regex ".*\.\(c\|h\|hpp\|cc\|cpp\)" -print | ctags --totals --recurse --extra="+qf" --fields="+i" -L -
alanwj
  • 483
  • 5
  • 5
  • 7
    You just re-invented upward search. See :h file-searching. See also http://stackoverflow.com/questions/563616/vimctags-tips-and-tricks/741486#741486 – gotgenes May 12 '09 at 06:10
2

I use vim in macos, and the original ctags doesn't work well, so I download newest and configure make make install it. I install ctgas in /usr/local/bin/ctags(to keep original one)

"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>
Zhenyu Li
  • 465
  • 1
  • 4
  • 11
1

I adapted the SetTags() search function above (which should be replaced by the equivalent set tags+=./tags;/) to work for cscope. Seems to work!

"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()
dergachev
  • 19
  • 1
  • 3
    As gotgenes said, You just re-invented upward search. See :h file-searching. See [this plugin](https://github.com/pydave/daveconfig/blob/master/multi/vim/.vim/after/plugin/tagfilehelpers.vim#L14) for a relevant example. – idbrii Nov 24 '11 at 17:25
1

Another iteration on the SetCscope() function above. That sets cscope pre-path to get matches without being on the dir where "cscope.out" is:

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
saoret.one
  • 21
  • 1
  • 3
    As gotgenes said, You just re-invented upward search. See :h file-searching. See [this plugin](https://github.com/pydave/daveconfig/blob/master/multi/vim/.vim/after/plugin/tagfilehelpers.vim#L14) for a relevant example. – idbrii Nov 24 '11 at 17:30