Search code examples
vimtextmaterubymacvim

Is there any easy way to toggle "do/end" and "{}" in ruby in Vim?


Is there any easy way to toggle "do/end" and "{}" in ruby in Vim?

(TextMate does this with ^{.)


Solution

  • You'd have to either use searchpair(), or to play with % (as long as matchit is installed, and as you are on begin/end), then mark the two positions, test whether it's text or brackets, and finally update the two lines.

    nnoremap <buffer> <c-x>{ :call <sid>ToggleBeginOrBracket()<cr>
    
    let s:k_be = [ 'begin', 'end' ]
    function! s:ToggleBeginOrBracket()
      let c = lh#position#char_at_mark('.')
      if c =~ '[{}]'
        " don't use matchit for {,}
        exe 'normal! %s'.s:k_be[1-(c=='}')]."\<esc>``s".s:k_be[(c=='}')]."\<esc>"
      else
        let w = expand('<cword>')
        if w == 'begin'
          " use mathit
          normal %
          exe "normal! ciw}\<esc>``ciw{\<esc>"
        elseif w == 'end'
          " use mathit
          normal %
          exe "normal! ciw{\<esc>``ciw}\<esc>"
        else
          throw 'Cannot toggle block: cursor is not on {, }, begin, nor end'
        endif
      endif
    endfunction
    

    Where lh#position#char_at_mark() is defined here.

    PS: this is definitively a SO question as it combines ruby context, and advanced vim scripting.