All posts for the month February, 2018

Here are some details about how I use VIM with CSCOPE and CTAGS to navigate a codebase.

I keep all my different codebases/repositories in ~/repos/ – I then have a bash script (called “workon”, kept in ~/bin/workon) that is used to jump into a codebase and set up some environment variables. Edit the WORKSPACEROOT definition in the workon file if your repos live somewhere else.

Since “workon” modifies env vars in your current shell, you have to use it with the source command, like this:

$ source workon somecodebase

Since cscope and ctags need to store their database files somewhere, I chose to keep them in ~/scopetags/ so make a scopetags directory in your home directory first. After you’ve run the “source workon somecodebase” command to set up your env vars, run the “regen_cscope_ctags” bash script to analyze the selected codebase and store the database files in ~/scopetags/. Run this script whenever you want to update the database, so do it after you make changes or git fetch a bunch of new code.

Then, we need to tell vim how to interact with cscope/ctags. Edit the file ~/.vimrc and add this line to the end:

let &tags=$CTAGS_DB

Then, make a new directory ~/.vim/plugin/ and download this file into that plugin directory:

Now, once you do the “source workon” you can open vim and use the ctags or cscope shortcuts to navigate the codebase. Here are the most common things to do.

Put the cursor inside a variable or function name. Press ctrl + \ + a letter code:

  • g = goto definition of that variable/function
  • s = search for all uses of that variable/function
  • c = callers of that function

This will usually open a little menu where you can pick from a list of all the search results.

Press ctrl + t to jump back.

You can also use ctrl + \ + f to search for a filename under your cursor (great for #include “foobar.h” lines).

You can also use vim commands to do searches, when your search term isn’t under your cursor:

Use CTAGS to search for a variable/function/file/etc – You can use tab-complete here.
:ts searchterm

Use CSCOPE to find the defintion/callers/uses/files (same letter codes as above)

:cs f g somevariable
:cs f c somefunction
:cs f s something
:cs f f somefilename

Hope that helps!



# This script must be sourced
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    echo "You should source this script instead of calling it."
    exit 1


if [[ $# -ne 1 || ! -d "$WORKSPACEROOT/$1" ]]; then
    echo "Usage: source workon workspace"
    echo "Available workspaces:"

export WORKSPACE=$1

# for vim:
export CSCOPE_DB=$SCOPETAGSDIR/cscope.out




if [ -z "$WORKSPACEDIR" ]; then
    echo "Need to \"source workon $workspace\" first..."
    exit 1

if [[ ! -d $SCOPETAGSDIR ]]; then
    mkdir -p $SCOPETAGSDIR

find -H $WORKSPACEDIR -name '*.c' -o -name '*.h' -o -name '*.a' > $INDEXFILES

echo "Generating cscope files..."
cscope -i$INDEXFILES -b -q
# -b            Build the cross-reference only.
# -q            Enable fast symbol lookup via an inverted index.

echo "Generating ctags files..."
ctags -L $INDEXFILES --extra=+f
# -L            Read the list of file names from the specified file.
# --extra=+f    Also include entries for base filename.