Jumping to a Ruby bang method using Ctags in Vim
Asked Answered
N

3

7

I'm having a problem with jumping to a Ruby bang method using Exhuberant Ctags. I have searched for others having a similar problem and am unable to find anything. An example of the problem can be shown using the following small Ruby class:

class Hello
  def start
    method!
  end

  def method
    # Blah
  end

  def method!
    # Blah
  end
end

When ctags -R . is run on this file the resulting tags file contains the following 2 lines demonstrating that both methods are discovered at generation:

method  test.rb /^  def method$/;"  f   class:Hello
method! test.rb /^  def method!$/;" f   class:Hello

However, if I place my cursor on the call to method! on line 3 and press ^] then the cursor jumps to the method definition rather than to the correct bang version. It seems as if the exclamation mark is not being included in the identifier that is searched for.

Is there a way to fix this so the correct method is jumped to?

Nacreous answered 5/5, 2012 at 2:21 Comment(2)
^] correctly jumps to the right method in my version of vim. What version of vim and ctags are you using? I do have vim-ruby and matchit installed and enabled. Not sure if that makes a difference.Petterson
I'm using MacVim Snapshot 63 which is built on Vim 7.3. I too have both of those plugins. The problem still persists even if I start vim with no configuration (mvim -u NONE).Nacreous
F
4

I realize this is super-old, but I ran into the same thing in both Vim 8.0 and Neovim. If I enter :tag mymethod! from vim's command-line, it finds the relevant tag, but if I try <C-]> with my cursor on the method name, it errors E426: tag not found: mymethod (note the lack of ! in the name it searched for).

You can fix this by adding ! to the list of characters recognized as keyword characters in Ruby syntax:

:set iskeyword+=!

You could add this to ~/.vim/after/syntax/ruby.vim to apply it in any Ruby file you open. I haven't tested this though, so can't say whether it will adversely affect anything else. I know it will change word jumping behavior. w will, for instance, treat the ! as part of the "small" word.

On second thought, it will definitely mishandle things like !some_test. If you were to hit <C-]> with the cursor anywhere in there, it would search for a method named !some_test, which is definitely not what you want. A better solution would be to write a wrapper function around the tag lookup for Ruby files. I'm actually working on something for that, so I'll post when I have something that presentable.

Update: I found a surprisingly simple workaround:

nnoremap <buffer><silent> <C-]> :tag <C-R><C-W><CR>

For some reason, the behavior of <C-R><C-W> in command-line mode differs from that of expand('<cword>'), and arguably from the documentation. Even though ! is not an 'iskeyword' character, and expand('<cword>') results in mymethod, <C-R><C-W> results in mymethod!. The same applies to is_this_your_method?. You could apply this workaround by putting the following in ~/.vim/ftplugin/ruby.vim:

nnoremap <buffer><silent>  <C-]> :tag     <C-R><C-W><CR>
nnoremap <buffer><silent>     g] :tselect <C-R><C-W><CR>
nnoremap <buffer><silent> g<C-]> :tjump   <C-R><C-W><CR>

Update 2

It turns out the special behavior of <C-R><C-W> was provided by vim-ruby (and included in Vim's runtime files by default). That script customizes <C-R><C-W> and also adds a <Plug><cword> mapping to correctly identify the Ruby cursor identifier. I only ran into the mishandling of ! because I had inadvertently clobbered the mappings already provided by vim-ruby when adding what I find to be more a comfortable keybinding:

nnoremap <C-.> <C-]>

If I'd done nmap instead, vim-ruby's mapping could have done its job. Alternatively, you could leverage what vim-ruby provides by doing (in a ruby ftplugin file):

nnoremap <buffer><silent>  <C-]> :<C-U>exe v:count1."tag <Plug><cword>"<CR>
nnoremap <buffer><silent>     g] :<C-U>tselect <Plug><cword><CR>
nnoremap <buffer><silent> g<C-]> :<C-U>tjump   <Plug><cword><CR>
Fineman answered 25/7, 2017 at 22:3 Comment(0)
K
3

You can always use :tag:

  :tag method!

Or visual mode - if you highlight any text (with v + movement) before you hit ^], it will use the highlighted text as the tag instead of trying to find an 'identifier' under the cursor. So if your cursor is on the m in method!, then

   vE^]

should do the trick. If your cursor is elsewhere in the word, then hit b first.

Karwan answered 5/5, 2012 at 3:54 Comment(1)
I've remapped ^] to viW^] for now, thank you! However, some of the semantics of this operation will have changed so I'm not sure this solution is ideal.Nacreous
N
0

I was using MacVim snapshot 63 at the time I posted this question. I'm now using snapshot 72 and the problem has gone. The only advice I can give here is to upgrade the version of Vim that you are using.

Nacreous answered 18/1, 2014 at 10:55 Comment(1)
Also check the version of ctags you're using. Older versions - like the no-version-numbered one that still ships with Xcode as of 6.1 - won't even generate tags for bang methods for vim to reference. I used Homebrew to install Exuberant Ctags 5.8 and regenerated the tags files; now vim navigates to bang (and question-mark) methods just fine.Karwan

© 2022 - 2024 — McMap. All rights reserved.