This looked nice at the beginning, but was way to slow for large projects. And, anyway, there's gtags, which looks really great. So this project is dead and only left here for posterity.
I'm not a fan of ctags (probably because I don't know much about it yet), but gtags seems pretty neat!
But here's a quick guide on using gtags.
Got a linker error. You need to link with libtinfo:
$ tar xf global*
$ cd global-*
$ LIBS=-ltinfo ./configure --prefix=...
$ make -j check
$ make -j install
Now, to create tags for a large project:
$ cd proj/
$ gtags
To locate functions:
$ global -x func
...
See http://tbaggery.com/2011/08/08/effortless-ctags-with-git.html
And use gtags instead of ctags. Then all your git operations (checkout, pull, rebase, etc) will reindex in the background.
You can probably do this cleverly, but to get started, this is what I did. I
added hooks/gtags
:
#! /bin/sh
set -e
dir="`git rev-parse --git-dir`"
cd $dir/..
if [ ! -f GTAGS ]; then
gtags
fi
global -u
It basically places GTAGS
etc in your project root. You probably want to
place the GTAGS files elsewhere and then move them over when they're finished,
so that global
won't attempt to use a half-finished gtags file (since it's
run int he background; see below).
Also, you can probably do gtags --single-update filename
as in the original
script with git ls
, which will be faster.
The hooks/post-rewrite
does this:
#! /bin/sh
case "$1" in
rebase) exec .git/hooks/post-merge ;;
esac
And post-merge
, post-commit
and post-checkout
do:
#! /bin/sh
.git/hooks/gtags >/dev/null 2>&1 &
Seems to work nicely, except that many of our .h
files are actually C++, so I
need to figure out how to get gtags to parse them as such (gtags --explain
indicates
that they are parsed as C files).
To fix that, I just added this into ~/.globalrc
:
default:\
:langmap=cpp\:.c++.cc.hh.cpp.cxx.hxx.hpp.C.H.c.h:
To grep for something, do
$ global -g pattern
I've added an alias that displays some details:
$ alias gg='global -x'
So now I can do:
$ gg foobar # exact search
$ gg -g foobar # grep-like search
You can also use gtags.vim for vim. To do that:
$ vim
:source .../gtags.vim
Now you can do
:Gtags func
Prints C/C++ definitions, usages and so on for all files in the current directory.
The point is to easily grep for class definitions, calls to specific functions,
and so on. For example, to find the declaration of the function foo_file
,
just do:
$ q -r | grep function-decl:foo_file
tests/foo/foo.c:1:5:function-decl:foo_file:int foo_file() {
To find out where this function is called from:
$ q -r | grep call:foo_file
tests/foo/foo.c:7:14:call:foo_file: return 1 + foo_file();
Of course, q doesn't care about stuff like namespaces, compilation units and so
on, and thus won't discern between multiple foo_file
functions.
To find calls to either foo
or bar
:
$ q -r | egrep 'call:(foo|bar):'
tests/test.cpp:40:3:call:foo: f.foo();
tests/test.cpp:41:3:call:bar: f.bar();
tests/test.cpp:42:3:call:foo: foo();
tests/test.cpp:43:3:call:bar: bar();
For large code bases, you can just dump everything to a cache:
$ q -r > .qcache
$ grep call:foo_file .qcache
tests/foo/foo.c:7:14:call:foo_file: return 1 + foo_file();
I've been looking for a tool like this for some time, but haven't found anything. (Perhaps I haven't looked hard enough). If you know any, please let me know! (Or let me know how ctags actually works)
But if you like this one, let me know as well, and I just might add some spit and polish.
- libclang for Python
- pip install ansicolors (well, not strictly used right now)
Note that the hash bang sets LD_LIBRARY_PATH
to a specific value I use on
my machine. I know it's ugly, but this is sooo alpha.
- -r: Optional flag to recurse into subdirectories
Public domain
$ q -r | grep function-decl | grep foo_file
tests/foo/foo.c:1:5:function-decl:foo_file:int foo_file() {
$ q -r
tests/test.cpp:5:7:class-decl:Foo:class Foo; // forward
tests/test.cpp:6:6:function-decl:foo:void foo(); // forward
tests/test.cpp:8:7:class-decl:Foo:class Foo {
tests/test.cpp:10:3:ctor:Foo: Foo()
tests/test.cpp:14:3:dtor:~Foo: ~Foo()
tests/test.cpp:18:8:method:bar: void bar() {
...