I use vim C++ tag file for navigation using Ctrl-]. The problem is whenever some file gets modified, the links are no longer valid and I have to re-run ctags and update the tag
From its repository: vim-gutentags
is a plugin that takes care of the much needed management of tags files in Vim. It will (re)generate tag files as you work while staying completely out of your way. It will even do its best to keep those tag files out of your way too. It has no dependencies and just works.
You can give it a try at https://github.com/ludovicchabant/vim-gutentags.
This logic works for most cases: When opening a new file in vim, change to the directory of that file and generate a tags file there if it does not already exist. When saving a changed buffer, generate a tags file in the directory of the file being saved:
function! GenerateTagsFile()
if (!filereadable("tags"))
exec ":!start /min ctags -R --c++-kinds=+p --fields=+iaS --extra=+q --sort=foldcase ."
endif
endfunction
" Always change to directory of the buffer currently in focus.
autocmd! bufenter *.* :cd %:p:h
autocmd! bufread *.* :cd %:p:h
" Generate tags on opening an existing file.
autocmd! bufreadpost *.cpp :call GenerateTagsFile()
autocmd! bufreadpost *.c :call GenerateTagsFile()
autocmd! bufreadpost *.h :call GenerateTagsFile()
" Generate tags on save. Note that this regenerates tags for all files in current folder.
autocmd! bufwritepost *.cpp :call GenerateTagsFile()
autocmd! bufwritepost *.c :call GenerateTagsFile()
autocmd! bufwritepost *.h :call GenerateTagsFile()
Further to Blixtor's answer, you'll need to think a little carefully about the design of the script. I'd recommend segregating the design such that the autocommand uses the Windows "start" command or similar to run an external script in the background: thereby preventing Vim from being unresponsive while the tag file is generated.
That script could then generate the tag file using a different file name (i.e. not "tags": ctags -R -o newtags .
) and, when ctags is complete, delete tags
and rename newtags
to tags
. This will prevent the tag file from being unavailable in Vim while the generation is done.
I already wrote a plugin to do all the hard job with ctags: Indexer.
It provides painless automatic tags generation for the whole project(s) and keeps tags up-to-date. Tags is generated in background, so, you do not have to wait while ctags generates tags. You can use it independently or as an add-on for another plugin project.tar.gz.
In the first way, you can declare your projects in ~/.indexer_files
like this:
[CoolProject]
/home/user/cool_project
[AnotherProject]
option:ctags_params = "--languages=c++"
/home/user/another_project/src
/home/user/another_project/lib
And then, when you open any file from /home/user/cool_project
, all this project will be indexed by ctags. When you open tags from another project, tags is generated for it too. Tags from different projects is never mixed. When you save file from project, tags is silently updated. You do not have to care about it, it just works.
For detailed information, see the article: Vim: convenient code navigation for your projects, which explains the usage of Indexer + Vimprj thoroughly.
It is successfully tested on Vim 7.3, on the following systems:
Archlinux
Ubuntu 10.4
Windows XP
Mac OS X Lion
An idea:
Use Vim autocommands (:help autocommand) to trigger running of a script every time a buffer is saved using the BufWritePost event.
This script starts the ctags generation and contains some additional small logic to not run while it's already running (or to run at most every 10 minutes, etc.).
Edit:
Something similar was asked here beforehand, see Vim auto-generate ctags
I wrote the vim-easytags plug-in to do exactly this. I initialize my tags file once by scanning a whole project (using the command :UpdateTags **/*.[hc]
for example) and afterwards the plug-in will automatically update the tags file as I edit and :update
my source code files in Vim. While it updates the tags file it will block Vim, but because it only scans the current file it doesn't take long.
Update (2014-07-30): Still working on the vim-easytags plug-in :-). Nowadays it supports an asynchronous mode to avoid blocking Vim. At the time I write this the asynchronous mode is not the default mode yet, but after some more feedback I'll probably switch the default mode.