Right now I have the following in my .vimrc:
au BufWritePost *.c,*.cpp,*.h !ctags -R
There are a few problems with this:
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 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:
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.
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).
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.