Writing Custom Rules for Exuberant Ctags

I use the program Exuberant Ctags for all my programming projects. What does it do? The official site provides a nice, terse description:

Ctags generates an index (or tag) file of language objects found in source files that allows these items to be quickly and easily located by a text editor or other utility. A tag signifies a language object for which an index entry is available (or, alternatively, the index entry created for that object).

GNU Emacs, my editor of choice, works well with those tags. For example, it allows me to find the definition of a function with a simple key-press.

Exuberant Ctags supports a lot of programming languages. But what about those it does not understand? Or what if it does not recognize certain items in your code? Today I will give you an example of how to extend Exuberant Ctags for an individual project.

The Target

One component we are building for our upcoming computer game has Lua code like this:

Opcode.Processor["set-scene-image"] = function (opcode)
    opcode.arguments.target = {}
    setmetatable(opcode.arguments.target, LNVL.Scene)
    return opcode
end

From the top-level directory of the project I could run Ctags like so:

$ ctags-exuberant -Re --languages=lua

The -R flag makes the program scan through directories recursively to build the list of tags. And -e creates output suitable for Emacs. The use of --languages=lua is not required but I prefer to be explicit.

However, Ctags will not create any entry for the Lua function above because the function is anonymous. But that anonymous function is a value in a table, and that does have a name. So we can use that to create a tag.

Extending Rules in Ctags

Ctags allows us to use write regular expressions that it will use to create tags. The expressions follow this format:

/Content to Match/Name of the New Tag/

First we start by writing a regular expression to match the content we want to use in order to create the tag. So in this case that means matching that Lua table. We can do that with this regular expression:

/Opcode\.Processor\[\"([a-z-]+)\"\].+/ ... /

Notice how we create a group for the name of the table key. So in our original example this regular expression would capture the name set-scene-image. We capture this because it is the closest we have to a function name in that code.

Now we need to complete our custom rule by telling Ctags the name of the tag to create. Ctags supports back-references which means we can write \1 to refer to the text we captured in the regular expression. That lets us write a complete rule like this:

/Opcode\.Processor\[\"([a-z-]+)\"\].+/Opcode.\1/

Because of the back-reference Ctags will create a tag named Opcode.set-scene-image that points to the position of the original code. The only thing left to do now is to tell Ctags to actually use our custom rule, and we can do this with an additional command-line argument:

$ ctags -Re --languages=lua --regex-lua="/Opcode\.Processor\[\"([a-z-]+)\"\].+/Opcode.\1/"

The argument --regex-lua tells the program to only apply our custom rule to Lua files. There are corresponding arguments for the other languages which Ctags supports. And you can even add support for new languages, but I will explain that another day.

Until then I hope you find this brief tutorial useful and can see the potential benefit in using Ctags on your projects.

Advertisements

4 thoughts on “Writing Custom Rules for Exuberant Ctags

  1. Sorry about that. It’s almost been a year and I still haven’t written the follow-up article about adding support for new languages to Ctags. I’ll try to write and post that soon.

Add Your Thoughts

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s