gx

Setup ctags and gtags

Posted at — Nov 16, 2023

Ruby is a language with too much magic and bad performance. To be honest, the development experience is not quite good for me. When developing Go or Rust, what I need is a simple language server. But for Ruby, the language servers don’t work quite well. I have to learn to setup other tools like ctags and gtags to help me navigate the codebase.

To generate tags, ctags is necessary. It is easy to generate tags by ctags -R .. However, I don’t want some files included, such as unit tests or configurations. I generate tags by the following command.

ctags \
  --extras=+qr \
  --fields=+aimnzS \
  --exclude='db' \
  --exclude='spec' \
  --languages=Ruby \
  -aR .

If the third packages are installed under the project directory, their tags would be generated together. However, rvm maintains packages in extra directories. It is necessary to generate separately. It is recomended to use gem-ctags and vim-bundler to generate those tags automatically.

ctags can only be used to jump to definitions in Vim. I use gtags-cscope and pygments and to get function callers.

gtags uses a single file gtags.files to store files which need to be indexed. I use fd to generate the file and then generate tags.

fd -e rb -E 'spec' -E 'db' > gtags.files
export GTAGSLABEL=native-pygments
gtags -i

By default, gtags uses /usr/local/share/gtags/gtags.conf. However, the config file is located in /usr/share/gtags/gtags.conf in Arch Linux. Thus gtags cannot find configurations and then cannot use native-pygments. Besides, the default conig uses etags instead of ctags.

To make gtags use native-pygments in Arch Linux, I copy the config file to the home directory and modify it manually. It doesn’t cost lots of effort to do that. It can also be placed in the project directory with the filename gtags.conf if users don’t want to make home directory messy.

Homebrew maintains a modified gtags.conf so the following operation is not required in macOS.

sed 's/etags/ctags/g' /usr/share/gtags/gtags.conf > "$HOME/.globalrc"

ctags and gtags would generate some files in the working directory. It would be better to ignore them when using git. Add the following lines in the global ignore file.

# ~/.config/git/ignore
tags
GTAGS
GRTAGS
GPATH
gtags.conf
gtags.files

The post doesn’t include any content of how to use tags in vim. It can be found by :h tag-comands and :h cscope-suggestion easily. The only difference is that I use gtags-cscope and GTAGS instead of cscope and cscope.out. An extra configuration is required:

if executable('gtags-cscope')
    let &csprg = 'gtags-cscope'
endif

Now, I have a swift and functional navigation.