Vim [m motion with c#

I don't think the ]m family of mappings can be customized. In such cases, the usual practice is to override it with custom logic. I came up with some vimscript that should do what you describe. Basically, it jumps through curly braces and looks at the relevant line to decide what to do. In this case, it just ignores "class" and "namespace" declarations.

nnoremap <buffer> ]m :<c-u>call <SID>JumpMethod('{', 'W',  'n')<cr>
nnoremap <buffer> [m :<c-u>call <SID>JumpMethod('{', 'Wb', 'n')<cr>
nnoremap <buffer> ]M :<c-u>call <SID>JumpMethod('}', 'W',  'n')<cr>
nnoremap <buffer> [M :<c-u>call <SID>JumpMethod('}', 'Wb', 'n')<cr>

xnoremap <buffer> ]m :<c-u>call <SID>JumpMethod('{', 'W',  'v')<cr>
xnoremap <buffer> [m :<c-u>call <SID>JumpMethod('{', 'Wb', 'v')<cr>
xnoremap <buffer> ]M :<c-u>call <SID>JumpMethod('}', 'W',  'v')<cr>
xnoremap <buffer> [M :<c-u>call <SID>JumpMethod('}', 'Wb', 'v')<cr>

onoremap <buffer> ]m :<c-u>call <SID>JumpMethod('{', 'W',  'o')<cr>
onoremap <buffer> [m :<c-u>call <SID>JumpMethod('{', 'Wb', 'o')<cr>
onoremap <buffer> ]M :<c-u>call <SID>JumpMethod('}', 'W',  'o')<cr>
onoremap <buffer> [M :<c-u>call <SID>JumpMethod('}', 'Wb', 'o')<cr>

function! s:JumpMethod(char, flags, mode)
  let original_cursor = getpos('.')

  if a:mode == 'v'
    normal! gv
  elseif a:mode == 'o'
    normal! v
  endif

  while search(a:char, a:flags) > 0
    if a:char == '}'
      " jump to the opening one to analyze the definition
      normal! %
    endif

    let current_line = line('.')

    if getline(current_line) =~ '^\s*{'
      " it's alone on the line, check the above one
      let method_line = current_line - 1
    else
      let method_line = current_line
    endif

    let method_line_body = getline(method_line)

    if method_line_body =~ '\k\+\s*(.*)' && method_line_body !~ '\<\(for\|foreach\|if\|while\|switch\|using\|catch\|get\|set\)\>'
      " it's probably a function call

      if a:char == '}'
        " we need to go back to the closing bracket
        normal! %
      endif

      echo
      return
    else
      if a:char == '}'
        " we still need to go back to the closing bracket
        normal! %
      endif
    endif
  endwhile

  " if we're here, the search has failed, restore cursor position
  echo
  call setpos('.', original_cursor)
endfunction

Bear in mind that I don't really know a lot of C#, so it might not work properly in all cases, but if you give me examples that break, I might be able to figure something out.

To try it, you should put it somewhere under "ftplugin" in your vimfiles directory, as "cs.vim". Any other filename that starts with "cs" and ends in ".vim" is good too, if you already have a "cs.vim" file there.


OmniSharp now has :OmniSharpNavigateUp and :OmniSharpNavigateDown. It always goes to "start" (hence this is for ]m and [m mappings). I'm using these mappings (taken from another answer to this question) in ftplugin\cs.vim

nnoremap <buffer> ]m :OmniSharpNavigateDown<cr>
nnoremap <buffer> [m :OmniSharpNavigateUp<cr>
nnoremap <buffer> ]M :OmniSharpNavigateDown<cr>
nnoremap <buffer> [M :OmniSharpNavigateUp<cr>

xnoremap <buffer> ]m :OmniSharpNavigateDown<cr>
xnoremap <buffer> [m :OmniSharpNavigateUp<cr>
xnoremap <buffer> ]M :OmniSharpNavigateDown<cr>
xnoremap <buffer> [M :OmniSharpNavigateUp<cr>

onoremap <buffer> ]m :OmniSharpNavigateDown<cr>
onoremap <buffer> [m :OmniSharpNavigateUp<cr>
onoremap <buffer> ]M :OmniSharpNavigateDown<cr>
onoremap <buffer> [M :OmniSharpNavigateUp<cr>

A few weeks ago, a similar question has been asked on vim mailing list, but for C++. Here is the solution I came up with.

It relies on ctags and a few other plugins of mine: lh-dev, lh-tag, and lh-vim-lib. You can install lh-dev via vim-addon-manager, this will install lh-tag and lh-vim-lib in turn.

HTH,

Tags:

C#

Vim