/* Ajith - Syntax Higlighter - End ----------------------------------------------- */

12.17.2009

ctags - vim with steroids

Basically C/C++ projects have thousands of lines of code divided into hundreds in some cases thousands of files. Inorder to access various function definitions within the sourcecode repository effectively using a VIM editor there is a great need for using addons like ctags which provides easy code go through.

Eventhough there are many effective GUI based code editors like eclipse e.t.c I prefer to use VIM editor as my primary code editor. I am not much into GUI funda so still prefer basic editor like VIM.

1. Installing ctags package
Almost all the linux flavours with 2.6.X kernel might have ctags installed by default. If not download the appropriate .deb or rpm file. Sorry I am not dealing with installing of ctags as I havent came across this stage as I am using FEDORA 9.

2. Generating ctags on your source code.
We have to generate a file named 'tags' for all the source code files, use the following command:
ctags *.c *.h
When we have many files in many directories then we have to create a tags file in each of the directories. But VIM will only be able to jump to tags within the same directory. To find more tags files, we have to set the 'tags' option in VIM to include all the relevant tags files. Just set the following command in ~/.vimrc file.
:set tags=./tags,./../tags,./*/tags
This finds a tags file in the same directory as the current file, one directory level higher and in all subdirectories.

But VIM searching many places for tags files is not really robust enough as it may get a bit slow. It's better to generate one big tags file offcourse it takes more time to create a single tags files for whole project. Just give the following command to recursively add all files in your project.
$ cd /proj 
$ ctags -R *
-R is to recursively go across all the directories, and a ‘tags’ file will be created including all the files in the sub-directories also.

Now we can simply include this single tags files as shown below
:set tags=~/proj/tags
3. Start using ctags with VIM editor
We have 3 different ways to use ctags in VIM editor.

From Shell:
We can invoke directly the file or the files containing the definition for a particular function from shell.
vi -t function_name
This will find the correct file or list of files having function_name definition.

OR

VIM command line:
We can invoke from VIM commandline (in command mode) the definition of a function.
:tag function_name
or
:ta function_name
This will jump automatically from the current file to the file containing the function_name definition.

OR

By cursor position:
This option is more user-friendly as we use a key combination instead of giving commands.
ctrl + ]
Place the cursor on the first character of the function name and press ctrl-]. This will jump to the file containing the definition of function_name.
ctrl + t
This command will jump back to previous location.
ctrl + i
To travel forward through the tag history.
ctrl + o
To travel backward through the tag history.

History
To display the list of tags that we have traversed in past give the following command.
:tags
Shows tag stack (history).

Divide and Conquer
As we saw already 'ctrl + ]' replaces the file in the current window with the one containing the new function. But suppose if we want to see not only the old function but also the new one?

We can split the window using the ":split" command followed by the ":tag" command.
:stag function_name
Cursor command for above feature is
ctrl + w + ]
Auto Complete
VIM supports tag name completion. Start typing the tag name (i.e. function name) and then hit TAB key and name completion will be done automatically if there is a tag name.
:tag start-of-tag-name_TAB
Jump to a tag name found by a search.
:tag /search-string
When multiple entries exist in the tags file, such as a function declaration in a header file and a function definition (the function itself), the operator can choose by issuing this command. The user will be presented with all the references to the function and the user will be prompted to enter the number associated with the appropriate one.
:tselect function-name
Jumps to next matching tag.
:tnext
or
:tn
Jump to previous matching tag.
:tprevious
or
:tp
Jump to first matching tag.
:tfirst
or
:tf
or
:trewindor:tr
Jump to last matching tag.
:tlast
or
:tl
Finding global identifiers
You are editing a C program and wonder if a variable is declared as "int" or "unsigned". A quick way to find this is with the "[I" command. Suppose the cursor is on the word "column" then type
[ + shiftkey + i
Vim will list the matching lines it can find. Not only in the current file,
but also in all included files (and files included in them, etc.). The result
looks like this:

structs.h
1: 29 unsigned column; /* column number */
The advantage over using tags or the preview window is that included files are
searched. In most cases this results in the right declaration to be found.
Also when the tags file is out of date. Also when you don't have tags for the
included files.

However, a few things must be right for "[I" to do its work. First of all,
the 'include' option must specify how a file is included. The default value
works for C and C++. For other languages you will have to change it.

Reference:
ctags documentation

3 comments :

  1. Thanks for that post.

    ReplyDelete
  2. How to make ctags show by default the dialog box for multiple definitions for the same tags? Currently it goes to the first tag by default. I dont want to use tnext or tselect.

    ReplyDelete
  3. Just got this set up thanks to your post. Back to vim being my favorite editor :)

    ReplyDelete

Your comments are moderated