Skip to content

Added ability to match do/end pairs plus fixed various bugs. #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 31 additions & 15 deletions plugin/ruby-matchit.vim
Original file line number Diff line number Diff line change
Expand Up @@ -19,52 +19,68 @@
" }}}
function! s:Ruby_Matchit()

let block_start_words = 'if\|do\|unless\|elsif\|else\|case\|when\|while\|'
\.'until\|def\|module\|class'
" use default matching for parenthesis, brackets and braces:
if strpart(getline("."), col(".")-1, 1) =~ '(\|)\|{\|}\|\[\|\]'
normal \\\\\
normal! %
return
endif

normal ^
sil! let curr_word = expand('<cword>')
if curr_word == ""
" use word under cursor if it looks like a block beginning/ending keyword
sil! let starting_curr_word = expand('<cword>')
if starting_curr_word !~ '\<\(' . block_start_words . '\|end\)\>'
" otherwise, use the word at the beginning of the line
" remember where we were in case we abort
normal! mZ
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the hacky use of mZ.
It is a problem in that if the user had marked something else with mZ, this will override that and
would likely cause extreme confusion and frustration.
I am open to suggestions of how else to return to the exact location (line and column) at which user started.

normal! ^
sil! let starting_curr_word = expand('<cword>')
endif
if starting_curr_word == ""
return
endif

let curr_line = line(".")
let spaces = strlen(matchstr(getline("."), "^\\s*"))

if curr_word =~ '\<end\>'
if starting_curr_word =~ '\<end\>'
while 1
normal k
normal! k
if strlen(matchstr(getline("."), "^\\s*")) == spaces
\&& getline(".") !~ "^\\s*$"
\&& getline(".") !~ "^#"
normal ^
" Go to beginning of line unless it is not a block-starting
" word in which case we go to the end of line
" (handles cases like: describe "x" do)
normal! ^
sil! let ending_curr_word = expand('<cword>')
if ending_curr_word !~ '\<\(' . block_start_words . '\)\>'
normal! $
endif
break
elseif line(".") == 1
exe 'normal ' . curr_line . 'G'
normal! `Z
break
endif
endwhile
elseif curr_word =~ '\<\(if\|unless\|elsif\|else\|case\|when\|while\|'
\.'until\|def\|\|module\|class\)\>'
elseif starting_curr_word =~ '\<\(' . block_start_words . '\)\>'
while 1
normal j
normal! j
if strlen(matchstr(getline("."), "^\\s*")) == spaces
\&& getline(".") !~ "^\\s*$"
\&& getline(".") !~ "^#"
normal ^
normal! ^
break
elseif line(".") == line("$")
exe 'normal ' . curr_line . 'G'
normal! `Z
break
endif
endwhile
else
normal! `Z
endif

endfunction

nnoremap <buffer> \\\\\ %
nnoremap <buffer> % :call <SID>Ruby_Matchit()<CR>