Vim: Difficulty setting up ctags. Source in subdirectories don't see tags file in project root
Asked Answered
F

5

73

I'm trying to get setup with (exuberant) ctags on Vim today and am having difficulty getting it to work properly. I generate my ctags file on the command line with with:

cd myproj
ctags -R

This puts the tags file in myproj root. However, Vim only seems to read from this tags file when I'm working on source that reside in root. As I navigate to deeper directories, if I try to jump to a tag using <C-]>, I get:

E433: No tags file
E426: tag not found: MyClassName

I've verified that MyClassName does have a tag in the tags file, it's just that Vim doesn't see it. Can someone please explain how to configure Vim to reference the root's tags file?

Thanks.

Furnary answered 16/2, 2011 at 14:16 Comment(0)
E
144

add this to .vimrc file set tags=tags;/

This will check the current folder for tags file and keep going one directory up all the way to the root folder.

So you can be in any sub-folder in your project and it'll be able to find the tags files.

Eosinophil answered 16/2, 2011 at 16:27 Comment(8)
If you have other tags file, you may want to set tags+=tags;/Formulaic
In case you get here and, like me, are puzzled by tags;/, the ;/ suffix directs vim to do an upward search from the directory containing tags up to the stop directory, in this case /. If you want to use your home directory as the stop-directory, use set tags+=tags;~ or set tags+=tags;$HOME. Or you could use the top directory of your project tree as the stop directory. (See :help file-searching to understand the semi-colon.) Note also that searching for the tags file will be affected by autochdir. I use in my .vimrc set tags=./tags,./TAGS,tags;~,TAGS;~Roselani
?? I had a tags file that was being ignored in the same directory and needed to use set tags=./tags;/.Sherrillsherrington
@Eosinophil We keep on changing files, so ctags also needs updation. Can we automate it?Toomey
I'm on a system with pretty old Vim: 7.4. set tags=tags;/ works fine ... but I can't find any reference to this mechanism in the :help documentation. :help tags-option has nothing. Searching help.txt and tagsrch.txt help files for ;/ also turns up nothing.Julesjuley
I can't find ;/ in vimdoc.sourceforge.net/vimum.html anywhere, either.Julesjuley
Just a note on this: check that set wildignore? doesn't contain patterns from the path of your project. It appears that i made a temporary worktree in a folder ./tmp/my_branch and I have set wildignore=*/tmp/* so file tags was ignoredDingman
Specifying / after ; is optional. tags;/ works the same as tags;Geotectonic
R
15

There is an option to tell Vim where to look for tag file.

I use the following configuration:

" search first in current directory then file directory for tag file
set tags=tags,./tags

Extract from help :

When a tag file name starts with "./", the '.' is replaced with the path of the current file. This makes it possible to use a tags file in the directory where the current file is (no matter what the current directory is). The idea of using "./" is that you can define which tag file is searched first: In the current directory ("tags,./tags") or in the directory of the current file ("./tags,tags").

For example: :set tags=./tags,tags,/home/user/commontags

And I keep my current working directory in the top project directory where my tagsfile is generated.

Use :pwd and then :cd myproj (inside Vim) to go to the directory containing your tags file.

See :help tags-option for more information on tags path.

You issue is probably that you are either in the wrong directory, or your tags option is not properly set.

Renaterenato answered 16/2, 2011 at 14:23 Comment(1)
This explains a great deal. Thank you. I only accepted the other answer as the correct one because, in my setup, the current working directory changes to match each buffer I'm editing. So it's more practical to jump up the directory structure to find the tags file in root.Furnary
E
2
#!/bin/sh

FREEZE_NAME=/* Give some version number */

mkdir $HOME/ctags/$FREEZE_NAME

V1=/* Software Path */

find $V1 -name "*.h" | xargs /usr/local/bin/ctags -a -f $HOME/ctags/$FREEZE_NAME/h.tags

find $V1 -name "*.c" | xargs /usr/local/bin/ctags -a -f $HOME/ctags/$FREEZE_NAME/c.tags

cd $HOME/ctags/$FREEZE_NAME/

rm -f all.tags

cat c.tags h.tags >> all.tags

sort all.tags > temp.tags

mv temp.tags all.tags

rm -f c.tags h.tags 

Put the above code in a .sh file and run... This will generate your tags for sure.

Expanse answered 25/4, 2016 at 8:4 Comment(0)
K
1

If you generate a tags file for every project, you might like this pattern, especially if you share your .vimrc across different machines:

let repohome=substitute($REPO_HOME, "\/", "\\\\/", "g")                         
let &tags=substitute(expand("%:p:h"), "\\(".repohome."/.\\{-}\/\\).*", "\\1tags", "")

You would then have to set the environment variable $REPO_HOME in your .bashrc to your main repo directory without the trailing space (e.g. /home/<yourusername>/repos) and it will automatically look for a tags file in each subdirectory of $REPO_HOME with a depth of 1, e.g. /home/<yourusername>/repos/myproj/tags.

Kenway answered 16/9, 2013 at 14:56 Comment(0)
L
0

Create a .sh file with below code. And run .sh file where you want tags. That will work for sure.

#!/bin/sh`enter code here`
filelist=`mktemp`
find . -name \*.h >> ${filelist}
find . -name \*.c >> ${filelist}
find . -name \*.cc >> ${filelist}
find . -name \*.cpp >> ${filelist}
find . -name \*.hpp >> ${filelist}
if [ "$SDKTARGETSYSROOT" != "" ]; then
find $SDKTARGETSYSROOT/usr/include -name \*.h >> ${filelist}
fi
cat ${filelist} | ctags -L -
Lynd answered 1/10, 2020 at 4:14 Comment(1)
This is great , you guys can try itLynd

© 2022 - 2024 — McMap. All rights reserved.