Friday, May 25, 2012

Vim and Ctags tips and tricks


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?


Source: Tips4all

15 comments:

  1. C-] - go to definition
    C-T - Jump back from the definition.
    C-W C-] - 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>

    C-\ - Open the definition in a new tab
    A-] - 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

    ReplyDelete
  2. 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.

    ReplyDelete
  3. 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.

    ReplyDelete
  4. 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

    ReplyDelete
  5. All of the above and...

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


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


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


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

    ReplyDelete
  6. 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.

    ReplyDelete
  7. 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.

    ReplyDelete
  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.

    ReplyDelete
  9. 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++.

    ReplyDelete
  10. 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 -

    ReplyDelete
  11. 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.

    ReplyDelete
  12. I've been adobting 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

    ReplyDelete
  13. 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>

    ReplyDelete
  14. 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()

    ReplyDelete
  15. 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

    ReplyDelete