Vim auto-generate ctags

Solution 1:

au BufWritePost *.c,*.cpp,*.h silent! !ctags -R &

The downside is that you won't have a useful tags file until it completes. As long as you're on a *nix system it should be ok to do multiple writes before the previous ctags has completed, but you should test that. On a Windows system it won't put it in the background and it'll complain that the file is locked until the first ctags finishes (which shouldn't cause problems in vim, but you'll end up with a slightly outdated tags file).

Note, you could use the --append option as tonylo suggests, but then you'll have to disable tagbsearch which could mean that tag searches take a lot longer, depending on the size of your tag file.

Solution 2:

Edit: A solution very much along the lines of the following has been posted as the AutoTag vim script. Note that the script needs a vim with Python support, however.

My solution shells out to awk instead, so it should work on many more systems.


au FileType {c,cpp} au BufWritePost <buffer> silent ! [ -e tags ] &&
    \ ( awk -F'\t' '$2\!="%:gs/'/'\''/"{print}' tags ; ctags -f- '%:gs/'/'\''/' )
    \ | sort -t$'\t' -k1,1 -o tags.new && mv tags.new tags

Note that you can only write it this way in a script, otherwise it has to go on a single line.

There’s lot going on in there:

  1. This auto-command triggers when a file has been detected to be C or C++, and adds in turn a buffer-local auto-command that is triggered by the BufWritePost event.

  2. It uses the % placeholder which is replaced by the buffer’s filename at execution time, together with the :gs modifier used to shell-quote the filename (by turning any embedded single-quotes into quote-escape-quote-quote).

  3. That way it runs a shell command that checks if a tags file exists, in which case its content is printed except for the lines that refer to the just-saved file, meanwhile ctags is invoked on just the just-saved file, and the result is then sorted and put back into place.

Caveat implementor: this assumes everything is in the same directory and that that is also the buffer-local current directory. I have not given any thought to path mangling.

Solution 3:

I wrote easytags.vim to do just this: automatically update and highlight tags. The plug-in can be configured to update just the file being edited or all files in the directory of the file being edited (recursively). It can use a global tags file, file type specific tags files and project specific tags files.

Solution 4:

I've noticed this is an old thread, however... Use incron in *nix like environments supporting inotify. It will always launch commands whenever files in a directory change. i.e.,

/home/me/Code/c/that_program IN_DELETE,IN_CLOSE_WRITE ctags --sort=yes *.c

That's it.