Using Cscope in Vim
Total Page:16
File Type:pdf, Size:1020Kb
How to incorporate Cscope functionality into VIM. It also supports the use of the cursor to select source code symbols in VIM where you can type custom keystrokes to invoke powerful Cscope functionality. Not only that, it will allow you to invoke Cscope symbols from within any directory in your source code tree. That is because the Cscope database will be built from source- code file path-names referenced from your root directory instead of the standard present directory if you built the Cscope file without the necessary trickery. OS/ program requirements Cscope must be installed on your system. If you don’t have it, then install it be typing in the Terminal ‘yum install cscope’ if running Fedora or ‘sudo apt-get cscope’ if you are running Ubuntu. Note: You must have at least VIM 6.x for this to work correctly. Setting it up You must have cscope_maps.vim. This file should be located in ~/.vim/plugin. If this directory does not exist, then create it. Step 1) Add the .vim plugin directory to your $PATH. Add these lines to the end of your ~/.bash_profile or ~/.bashrc file. PATH=$PATH:$HOME/.vim/plugin EDITOR="vim" Step 2) Add the following code to the bottom of your ~/.bashrc file. This is the function and alias which builds the cscope database. This one is setup to find .c and .h files. Change for the file extensions that are in your source code. function build_cscope_db_func() { local PROJDIR=$PWD cd / find $PROJDIR –name ‘*.c’ –o –name ‘*.h’ > $PROJDIR/cscope.files cd $PROJDIR cscope –Rbkq } alias csbuild=‘build_cscope_db_func’ Step 3) Launch another bash session by typing ‘bash’ at the command prompt. Step 4) In the parent directory of your project directories, create a script file for each project which you will be looking at. For example, I created a file called MyApp_env.cscope. Inside this file, create the environment variable CSCOPE_DB to point to the cscope database that you will be working on. See below for the path that I used. You could make this an alias if you wanted. CSCOPE_DB=$HOME/ProjDir/cscope.out export CSCOPE_DB Using Cscope in Vim Step 1) Build the cscope database. This has to be done each time a change is made to code, if desired. Cd to your project directory and type ‘csbuild’. This creates several files. Cscope.out is the only one you will need. Step 2) Go to the directory where you created the script file with the CSCOPE_DB env variable (MyApp_env.cscope) and run it. Step 3) Open Vim and start using the new Cscope functionality and keycodes There are many commands to start using cscope/vim, but here are a few. To get started, open a .c file and highlight a function with the mouse. Type CTRL–spacebar and then ‘s’. This will search for a symbol and open a chosen file horizontally. Two spacebars before the ‘s’ will open it vertically. To browse from one window to another, type Ctrl-w and then arrow key to the window that you want to go, basic Vim stuff. Other functions (s=find uses of symbol, g=find global def of symbol, c=find all calls to a func, f=open filename under cursor). There are more functions described in the cscope_maps.vim file. *************************************************************************** cscope, ctags, and Vim are powerful tools for reading a lot of code. ctags can be used to take you to the definition of a variable (e.g., a function, variable, or macro). cscope can be used to take you to the call site of a definition (e.g., all function calls, all variable uses, all macro uses). These tools can be used independently of Vim, but having a powerful editor that can use these tools in an integrated fashion speeds development. Theory of cscope, ctags, & vim Your choice of tool will depend on the language you are developing in primarily: C: Use cscope + ctags C++ or anything else: Use just ctags. It has the benefit of knowing about class names, where as cscope does not and will not know the difference between namespc1::bob and namespc2::bob. You instruct cscope and ctags to build a database for a directory tree. These databases are a list of <variable, line_number> pairs sorted by 'variable'. Vim does a binary search on these databases to answer your queries (e.g., find definition of 'variable' means searching the database to find the appropriate variable='variable', then moving the cursor to that line_number). Vim allows you to specify the order in which it searches its databases. Typically your list of databases will be ordered as such: C-kernel: <kernel-cscope> C-user: <ctags-stdlib, cscope-project> C++-user: <ctags-stdlib, ctags-project> other: <ctags-project> Setting up cscope, ctags, & vim We first have to build our databases. When you build the database you want to make sure your repository system ignores the database files as they are generated and will waste space in your versioning database (that you won't be able to reclaim). The running example used here will focus on the Linux kernel using git. We have two files that we want our repo system (git) to track, 'gentagdb', and 'gentagfiles'. The first script takes a list of files, and indexes their variables creating the actual ctags and cscope DBs. The second script generates that list of files. The second script is important when you have a big project like the kernel. If you don't exclude redundant files, you will waste time paging through hundreds of 'write' functions for strange architectures and irrelevant drivers. o The first script (gentagfiles). Note when pasting code into Vim first type ':set paste' so Vim doesn't try to indent it, then type ':set nopaste' when done. #!/bin/bash . #gentagfiles file list build script . set -x . find | grep "\.c$\|\.h$" | grep "\.\/arch\/x86" > cscope.files . find | grep "\.c$\|\.h$" | grep "\.\/fs" >> cscope.files . find | grep "\.c$\|\.h$" | grep "\.\/mm" >> cscope.files . find | grep "\.c$\|\.h$" | grep "\.\/include\/asm-x86" >> cscope.files . find | grep "\.c$\|\.h$" | grep "\.\/include" | grep -v "\.\/include\/asm-" | grep -v "\.\/include\/config\/" >> cscope.files . find | grep "\.c$\|\.h$" | grep "\.\/kernel" >> cscope.files . find | grep "\.c$\|\.h$" | grep "\.\/block" >> cscope.files . find | grep "\.c$\|\.h$" | grep "\.\/lib" >> cscope.files . sort cscope.files > cscope.files.sorted . mv cscope.files.sorted cscope.files o The second script (gentagdb). #!/bin/bash . #gentagdb database build script . cscope -b . ctags -L cscope.files Now you can build the databases for cscope and ctags. I've found in practice that running gen* as a make target doesn't work so well and use it manually. You now have to modify Vim to support ctags and cscope. Emacs (as far as I know) only supports ctags, but regardless, I provide only Vim instructions here. You can use my entire vimrc, or you can just take the part under "Jeff's cscope settings. My vimrc is the result of years of Vim tweaking and has some awesome features (pressing 'j' twice equals escape from insert mode). o Add the desired subset of this file to your vimrc. o Make sure 'set csto=0' is included in your vimrc if you are coding C, and 'set csto=1' is included in your vimrc if you are coding C++ (see 'Theory' section above if you want to know why). Now you are ready to start using it. Simply type ':cs help' to see the commands right there. Type ':tags' to see where you currently are in the tag stack. Finally ':tag' will take you to an arbitrary symbol (and tab-completion works). Try typing ':tag sys_' and the press the Tab key and you should see it try going through several possible completions. Use Control-\ g to find the definition of a variable, and Control-\ s to find its occurrence as a symbol in other code. Use Control-\ c to see where the symbol is called from. The command 'q:' allows you to edit the command line history so you can paste large identifier names into a 'cs find g' command (Ctrl-C exits 'q:' mode). Conclusions Good luck. The key to understanding technology is using it. Go ahead and try to incorporate these scripts into your work process and you should see a rapid improvement in development speed. **************************************************************************** Cscope is a very powerful interface allowing you to easily navigate C-like code files. While Cscope comes with its own stand-alone interface, Vim provides the capability to navigate code without ever leaving the editor. Using Cscope, you can search for identifier or function definitions, their uses, or even any regular expression. With the proper configuration, "standard" include files of your compiler are automatically searched along with your sources. The output from :help :cscope says it all: cscope commands: add : Add a new database (Usage: add file|dir [pre-path] [flags]) find : Query for a pattern (Usage: find c|d|e|f|g|i|s|t name) c: Find functions calling this function d: Find functions called by this function e: Find this egrep pattern f: Find this file g: Find this definition i: Find files #including this file s: Find this C symbol t: Find assignments to help : Show this message (Usage: help) kill : Kill a connection (Usage: kill #) reset: Reinit all connections (Usage: reset) show : Show connections (Usage: show) Contents [show] Setting up Vim to use cscope Edit Adding the following snippet to your .vimrc will set up Vim to use cscope more efficiently: if has('cscope') set cscopetag cscopeverbose if has('quickfix') set cscopequickfix=s-,c-,d-,i-,t-,e- endif cnoreabbrev csa cs add cnoreabbrev csf cs find cnoreabbrev csk cs kill cnoreabbrev csr cs reset cnoreabbrev css cs show cnoreabbrev csh cs help command -nargs=0 Cscope cs add $VIMSRC/src/cscope.out $VIMSRC/src endif Explanation: if has('cscope') Edit If Vim hasn't got support for cscope, it's no use trying to use that support, so we bracket this whole snippet in this if statement to avoid unnecessary errors.