My Profile Photo

Chris Arcand


Principal Engineer building Terraform at IBM / HashiCorp 👨‍💻 Formerly: Red Hat, NBC SportsEngine, RubyMN organizer. Once played the clarinet for a living, now making a living to play hockey. I make pointless connections to Minnesota as a Minnesotan does.

St. Paul, MN


Inline scoped Ruby methods with Ctags

TLDR: You can use this in your .ctags file to parse method definitions like private def method_name in Ruby 2.1+

Starting in Ruby 2.1, defining a method returns the name of the method as a symbol, not just nil. This was frequently suggested to be able to take advantage of fact that module methods like public, private and protected can accept a symbol as an argument, allowing for the following elegant-looking (or at least more commonly seen in other languages like C# or Java) code:

protected def some_protected_method
  # ...
end

private def some_private_method
  # ...
end

At Sport Ngin we’ve been using a more explicit convention in declaring a method private after each and every private method definition for some time:

def some_private_method
  # ...
end
private :some_private_method

There are many arguments for and against this and I won’t go over it here. I personally prefer the format you most commonly see with private and all of the private methods at the bottom of your class, but I do think that the new syntax that Ruby 2.1+ allows is better than private :method_name declarations - it’s easier to see and saves a line every definition with less clutter.

We’ve since changed our styleguide to use this new syntax, which I’ve started to call ‘inline scoped methods’.

New syntax, old Ctags

I don’t use Ctags for everything. With vim I usually navigate a project with various keybindings to CtrlP and The Silver Searcher with combinations of grep/awk. What I do use frequently is CtrlP’s CtrlPBufTag command, which uses Ctags on the fly to jump to methods in the file you have open:

A demo of CtrlPBufTag

But Ctags, having last been updated in July 2009, doesn’t recognize this new inline scoped method syntax. I dug in to figure out how to add this functionality. It turns out that adding options and new parsings for Ctags is as simple as editing (or creating) ~/.ctags

The Solution

It took me a bit as I’m very unfamiliar with POSIX regular expressions, but the following addition I wrote seems to work well:

--regex-ruby=/(^|;)[ \t]*(private|protected|public)(_class_method)?\(? def *(self.)?([[:alnum:]_]+)/\5/f,inline scoped method,inline scoped methods (Ruby 2.1+)/

This will match inline scoped definitions for private, protected, and public instance methods as well as private class methods.

Now CtrlP works with the new syntax

Even if you don’t plan on using the new syntax afforded by Ruby 2.1+, I suggest that if you use Ctags you add this functionality as if other people do use it, you suddenly won’t be able to find these sorts of methods at all.

Misc:

  • In digging into this issue I learned a ton about Ctags and what you can do with them. I consider myself fairly skilled at navigating a project quickly using the text searching tools mentioned earlier, but I certainly plan to dig in to Ctags more. They seem to have unlimited potential as a fully fledged project navigation tool. People who navigate very large projects all the time seem to enjoy them…
  • I also found a bunch of other useful additions to Ctags, specifically for Rails developers.

  • Lastly, I discovered a maintained successor to the original Exuberant Ctags, Universal Ctags. As of this writing, I don’t believe functionality for the syntax in this post has been added.
<- Back