Skip to content

Instantly share code, notes, and snippets.

@treyharris
Last active October 29, 2024 03:00
Show Gist options
  • Save treyharris/e19bb74d72af432dd6984ad9907ae538 to your computer and use it in GitHub Desktop.
Save treyharris/e19bb74d72af432dd6984ad9907ae538 to your computer and use it in GitHub Desktop.
Installing universal-ctags on Ubuntu so Emacs/Vim can use it

Installing universal-ctags on Ubuntu

This is my preferred way to go about it.

1. Download and build universal-ctags

These instructions are described in some detail in the universal-ctags install instructions on GitHub. But here’s what I ran:

% cd ~/src
% hub clone universal-ctags/ctags universal-ctags && cd universal-ctags
% ./autogen.sh
% ./configure

I initially wanted to use --program-prefix=universal- to result in the final code being installed into /usr/local/bin/universal-ctags/ instead of just as ctags. But it turned out that breaks because of how universal-ctags handles etags compatibility: it must be called as ${PROGRAM_PREFIX}etags. But via the alternatives system, it will actually be called as plain old etags, so it needed to be built with no --program-prefix argument.

Continuing the build:

% make

2. Install universal-ctags

Simply:

% sudo make install

3. Add universal-ctags to Ubuntu ctags alternatives

Here, we want to tell Ubuntu that it can use universal-ctags as a ctags variant. The update-alternatives command is used for this. First, let’s have a look at what’s already been installed as known alternatives:

% update-alternatives --display ctags
ctags - auto mode
  link best version is /usr/bin/ctags.emacs24
  link currently points to /usr/bin/ctags.emacs24
  link ctags is /usr/bin/ctags
  slave ctags.1.gz is /usr/share/man/man1/ctags.1.gz
/usr/bin/ctags.emacs24 - priority 27
  slave ctags.1.gz: /usr/share/man/man1/ctags.emacs24.1.gz

This may look complex, but it’s just telling us that a version of ctags has been automatically selected from the single known alternative — ctags.emacs24, installed as part of Emacs.

As earlier mentioned, if you examine the manpage for universal-ctags, you’ll note that to run in Emacs mode, it expects to be called as etags. So let’s see what’s currently in use as etags:

% update-alternatives --display etags
etags - auto mode
  link best version is /usr/bin/etags.emacs24
  link currently points to /usr/bin/etags.emacs24
  link etags is /usr/bin/etags
  slave etags.1.gz is /usr/share/man/man1/etags.1.gz
/usr/bin/etags.emacs24 - priority 27
  slave etags.1.gz: /usr/share/man/man1/etags.emacs24.1.gz

Much the same thing.

So now, we have to inform Ubuntu’s alternatives system about the new command.

% sudo update-alternatives --install /usr/bin/ctags ctags /usr/local/bin/ctags 50 --slave /usr/share/man/man1/ctags.1.gz ctags.1.gz /usr/local/share/man/man1/ctags.1

Here, we tell it that /usr/local/bin/ctags is an acceptable version of ctags, and that its manpage can be found at /usr/local/share/man/man1/ctags.1.gz. Note the 50 — that argument sets the “priority” when autoselecting an alternative. The above output told us that Emacs’ version was set to priority 27, so 50 has been arbitrarily chosen as a higher priority, forcing universal-ctags to be preferred.

We need to do the same with etags, as so:

% sudo update-alternatives --install /usr/bin/etags etags /usr/local/bin/ctags 50 --slave /usr/share/man/man1/etags.1.gz etags.1.gz /usr/local/share/man/man1/ctags.1

Now we can see the links are right:

% echo =ctags =etags
/usr/local/bin/ctags /usr/bin/etags
% readlink -f =etags =ctags
/usr/local/bin/ctags
/usr/local/bin/ctags
Note
The syntax =ctags tells zsh to replace the string with the full path name to the ctags command. In bash, $(which ctags) would be equivalent.

The most obvious difference between ordinary ctags and etags is where they put the tagfile: the former uses tags, the latter TAGS. So we can test this as so to ensure that universal-ctags is being called correctly; if etags creates a TAGS file instead of a tags file, we’re good:

% ls tags TAGS
ls: cannot access 'tags': No such file or directory
ls: cannot access 'TAGS': No such file or directory
% ctags -R .
% ls tags TAGS
ls: cannot access 'TAGS': No such file or directory
tags
% etags -R .
% ls tags TAGS
TAGS  tags

Now, all that’s required is to use your tags as normal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment