My Profile Photo

Chris Arcand


Principal Engineer building Terraform at 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