Tuesday, April 10, 2012

I'm a pretty naive user of Vim. It started while watching a professor of mine do code examples on a projector during class. I was amazed at the speed of which he was copying and pasting code, editing text, etc... all without using the mouse.

When I asked him how he did that, he talked about how he had been using those techniques for 20 years. I had watched other people use emacs, but they were still moving their hands away from the home row. That alone motivated me to pick and learn Vi. (Yeah yeah, I know, a proficient emacs user could have been just as impressive. More on that later.)

Learning Vim turned out to be a great investment, as I worked on several unix and embedded systems where it was normal to have some form of Vi installed. It's even usable in the Dvorak layout! (I'll have to save those details for another post).

Back to the topic at hand: Vim is also great for reading and navigating source code. I would see people using an IDE that would push a button and it would take them to the declaration of a variable, function, etc... "How did you do that!?" See, I've never used a "real IDE" on a regular basis, and was unaccustomed to such features (feel free to flog me for this). I had to figure out how to get those features inside of Vim. (Another sidenote: I can't use anything besides Vim now. Even my MS words docs often have rows of jjjjj kkkkk sporadically placed. Another sidenote #2: One of the eclipse Vim plugins I tried last year made eclipse usable, but I still prefer Vim... I'll have to save that one for another post as well.)

Turns out there were several options to get source code navigation working in Vim. ctags, cscope, an eclipse ipc method, and one I stumbled on because of a co-worker: gnu global. Anthony swore by global, and indeed, his source code navigation was impressive... even while using emacs!

In any case, after trying all the above tools, I settled on gnu global, although it took some work to get it working with Vim and my setup. That's what this post is really about: documenting my usage of Vim and gnu global.

global is great in that you can store the generated tags outside the source tree (in this case $HOME/wa/globaltags/). Plus, you can be anywhere in your source tree and it correctly finds the tags. You can also have automatic per project tag databases. These are some of the main reasons I chose gnu global over the alternatives. I don't want to jump to spots in an unrelated code base.

Apparently Vim doesn't have a plugin architecture for tagging systems. So, global provides a cscope adapter in order to make Vim think it's using cscope, when it's really using global.

Next, drop gtags-cscope.vim into $HOME/.vim/plugins. You may need to make sure you have the correct version for the version of global you're using. global also has "gtags.vim", but like I said, Vim doesn't expose an api to allow different tagging systems, making the tag stack unavailable (which, is one of the best features of this setup).

Another sidenote/tip from Anthony: if you ever google for it, make sure you google "gnu global" and not "global" or "gtags". I know... "gnu global" is a terrible name marketing wise.

this brings up a list, and you can enter the number to go to that spot. You can then do ":tn" and ":tN" from the Vim command line to go forward and backwards through the tag list.

global also has a method to find all functions that call the function in question. I don't remember the shortcut, but honestly, I normally use the above item instead.

several other search methods that I can't remember right now

Whenever the tags start getting out of date (because of modified code), you can simply go to the root of source code again and run maketags_cpp. The updates are fast and incremental, which was another reason for choosing global.

There are some warts that I haven't figured out: sometimes the first "common operation" can't find the definition like it should. In those cases, I use the 3rd "common operation" as a backup.

There are support for other languages, and some have configured global to work with unsupported languages, but googling for those is left as an exercise for the reader.

That's about it. Just as my co-worker warned, it's pretty hard to work without this functionality after having enjoyed it.