" Falling motions for Vim. "Falling" means moving the cursor down until it hits " text that doesn't match a pattern. " Returns an expression to be used in normal mode that results in the falling " motion. The semantics are as follows: " " The motion moves in the direction given by a:dir (which must be 'j' or 'k'). " The motion moves while the character under the cursor does not match the " pattern, then it moves while the character under the cursor matches the " pattern stopping when the character under the cursor does not match the " pattern once again. " " ex. " " fall#fall('j', '^\s*$') " " for " " | t⌷is is some text " | this is some other text " | " | " | this is some bottom text " | this is some other bottom text " " will return an expression to update the cursor position to: " " | this is some text " | this is some other text " | " | " | t⌷is is some bottom text " | this is some other bottom text " " This works pretty well for navigating around languages that use indentation " and lack braces for bodies, i.e. vimscript, ruby. Less well for python, but " still okay. function! fall#fall(dir, pattern) abort let i = 0 let n = 0 if a:dir == 'j' let delta = 1 else let delta = -1 endif let line = line('.') let column = col('.') let c = v:count if c == 0 let c = 1 endif while i < c let match = matchstr(getline(line), '\%' . column . 'c.') while ! (match =~ a:pattern) let n += 1 let line += delta if line <= 0 || line >= line('$') return "m'" . n . a:dir endif let match = matchstr(getline(line), '\%' . column . 'c.') endwhile while (match =~ a:pattern) let n += 1 let line += delta if line <= 0 || line >= line('$') return "m'" . n . a:dir endif let match = matchstr(getline(line), '\%' . column . 'c.') endwhile let i += 1 endwhile return "m'" . n . a:dir endfunction function! fall#visual_same_character(dir) let start_line = line(".") let line = start_line let column = col(".") let char_to_match = matchstr(getline(line), '\%' . column . 'c.') let expr = "" if a:dir =~ 'k' while line > 1 let line -= 1 if matchstr(getline(line), '\%' . column . 'c.') != char_to_match break endif let expr .= 'k' endwhile endif if a:dir == 'jk' let expr .= 'o' let line = start_line endif if a:dir =~ 'j' while line <= line("$") let line += 1 if matchstr(getline(line), '\%' . column . 'c.') != char_to_match break endif let expr .= 'j' endwhile endif return expr endfunction function! fall#visual_vertical_word(dir, def_class) let start_line = line(".") let line = start_line let column = col(".") let start_char = matchstr(getline(line), '\%' . column . 'c.') if (start_char =~# '\s') let class = '\s' elseif (start_char =~# a:def_class) let class = a:def_class else return "" endif let expr = "" if a:dir =~ 'k' while line > 1 let line -= 1 if ! (matchstr(getline(line), '\%' . column . 'c.') =~# class) break endif let expr .= 'k' endwhile endif if a:dir == 'jk' let expr .= 'o' let line = start_line endif if a:dir =~ 'j' while line <= line("$") let line += 1 if ! (matchstr(getline(line), '\%' . column . 'c.') =~# class) break endif let expr .= 'j' endwhile endif return expr endfunction