{"id":438,"date":"2018-02-05T12:01:55","date_gmt":"2018-02-05T17:01:55","guid":{"rendered":"http:\/\/www.mbeckler.org\/blog\/?p=438"},"modified":"2018-02-05T12:01:55","modified_gmt":"2018-02-05T17:01:55","slug":"using-vim-with-cscope-and-ctags","status":"publish","type":"post","link":"https:\/\/www.mbeckler.org\/blog\/?p=438","title":{"rendered":"Using VIM with CSCOPE and CTAGS"},"content":{"rendered":"<p>Here are some details about how I use VIM with CSCOPE and CTAGS to navigate a codebase.<\/p>\n<p>I keep all my different codebases\/repositories in ~\/repos\/ &#8211; I then have a bash script (called &#8220;workon&#8221;, 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.<\/p>\n<p>Since &#8220;workon&#8221; modifies env vars in your current shell, you have to use it with the source command, like this:<\/p>\n<p><code>$ source workon somecodebase<\/code><\/p>\n<p>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&#8217;ve run the &#8220;source workon somecodebase&#8221; command to set up your env vars, run the &#8220;regen_cscope_ctags&#8221; 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.<\/p>\n<p>Then, we need to tell vim how to interact with cscope\/ctags. Edit the file ~\/.vimrc and add this line to the end:<\/p>\n<p><code>let &tags=$CTAGS_DB<\/code><\/p>\n<p>Then, make a new directory ~\/.vim\/plugin\/ and download this file into that plugin directory: <a href=\"http:\/\/cscope.sourceforge.net\/cscope_maps.vim\">http:\/\/cscope.sourceforge.net\/cscope_maps.vim<\/a><\/p>\n<p>Now, once you do the &#8220;source workon&#8221; you can open vim and use the ctags or cscope shortcuts to navigate the codebase. Here are the most common things to do.<\/p>\n<p>Put the cursor inside a variable or function name. Press ctrl + \\ + a letter code:<\/p>\n<ul>\n<li>g = goto definition of that variable\/function<\/li>\n<li>s = search for all uses of that variable\/function<\/li>\n<li>c = callers of that function<\/li>\n<\/ul>\n<p>This will usually open a little menu where you can pick from a list of all the search results.<\/p>\n<p>Press ctrl + t to jump back.<\/p>\n<p>You can also use ctrl + \\ + f to search for a filename under your cursor (great for #include &#8220;foobar.h&#8221; lines).<\/p>\n<p>You can also use vim commands to do searches, when your search term isn&#8217;t under your cursor:<\/p>\n<p>Use CTAGS to search for a variable\/function\/file\/etc &#8211; You can use tab-complete here.<br \/>\n<code>:ts searchterm<\/code><\/p>\n<p>Use CSCOPE to find the defintion\/callers\/uses\/files (same letter codes as above)<\/p>\n<pre>:cs f g somevariable\r\n:cs f c somefunction\r\n:cs f s something\r\n:cs f f somefilename<\/pre>\n<p>Hope that helps!<\/p>\n<hr \/>\n<p><strong>~\/bin\/workon<\/strong><\/p>\n<pre>#!\/bin\/bash\r\n#vi:syntax=sh\r\n\r\n# This script must be sourced\r\nif [[ \"${BASH_SOURCE[0]}\" == \"${0}\" ]]; then\r\n    echo \"You should source this script instead of calling it.\"\r\n    exit 1\r\nfi\r\n\r\nWORKSPACEROOT=$HOME\/repos\r\n\r\nif [[ $# -ne 1 || ! -d \"$WORKSPACEROOT\/$1\" ]]; then\r\n    echo \"Usage: source workon workspace\"\r\n    echo \"Available workspaces:\"\r\n    ls -1 $WORKSPACEROOT\r\nfi\r\n\r\nexport WORKSPACE=$1\r\nexport WORKSPACEDIR=$WORKSPACEROOT\/$WORKSPACE\r\n\r\n# for vim:\r\nSCOPETAGSDIR=$HOME\/scopetags\/$WORKSPACE\r\nexport CSCOPE_DB=$SCOPETAGSDIR\/cscope.out\r\nexport CTAGS_DB=$SCOPETAGSDIR\/tags\r\n\r\ncd $WORKSPACEDIR<\/pre>\n<hr \/>\n<p><strong>~\/bin\/regen_cscope_ctags<\/strong><\/p>\n<pre>#!\/bin\/bash\r\n#vi:syntax=sh\r\n\r\nif [ -z \"$WORKSPACEDIR\" ]; then\r\n    echo \"Need to \\\"source workon $workspace\\\" first...\"\r\n    exit 1\r\nfi\r\n\r\nSCOPETAGSDIR=$HOME\/scopetags\/$WORKSPACE\r\nif [[ ! -d $SCOPETAGSDIR ]]; then\r\n    mkdir -p $SCOPETAGSDIR\r\nfi\r\ncd $SCOPETAGSDIR\r\nINDEXFILES=$SCOPETAGSDIR\/files\r\n\r\nfind -H $WORKSPACEDIR -name '*.c' -o -name '*.h' -o -name '*.a' > $INDEXFILES\r\n\r\necho \"Generating cscope files...\"\r\ncscope -i$INDEXFILES -b -q\r\n# -b            Build the cross-reference only.\r\n# -q            Enable fast symbol lookup via an inverted index.\r\n\r\n\r\necho \"Generating ctags files...\"\r\nctags -L $INDEXFILES --extra=+f\r\n# -L            Read the list of file names from the specified file.\r\n# --extra=+f    Also include entries for base filename.<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>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\/ &#8211; I then have a bash script (called &#8220;workon&#8221;, kept in ~\/bin\/workon) that is used to jump into a codebase and set up some environment variables. Edit the WORKSPACEROOT definition [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[1],"tags":[],"class_list":["post-438","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p2BznB-74","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.mbeckler.org\/blog\/index.php?rest_route=\/wp\/v2\/posts\/438","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.mbeckler.org\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.mbeckler.org\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.mbeckler.org\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.mbeckler.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=438"}],"version-history":[{"count":7,"href":"https:\/\/www.mbeckler.org\/blog\/index.php?rest_route=\/wp\/v2\/posts\/438\/revisions"}],"predecessor-version":[{"id":446,"href":"https:\/\/www.mbeckler.org\/blog\/index.php?rest_route=\/wp\/v2\/posts\/438\/revisions\/446"}],"wp:attachment":[{"href":"https:\/\/www.mbeckler.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=438"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.mbeckler.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=438"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.mbeckler.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=438"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}