[nvim] add an indentation block motion

This commit is contained in:
Dmytro Meleshko 2021-03-07 15:24:42 +02:00
parent b60438f49b
commit 0a3c9b7424
3 changed files with 78 additions and 0 deletions

View file

@ -0,0 +1,63 @@
" Based on <https://github.com/kana/vim-textobj-indent/blob/deb76867c302f933c8f21753806cbf2d8461b548/autoload/textobj/indent.vim>
" A motion for moving over enclosing indentation blocks. Primarily intended
" for reverse-engineering CrossCode.
function dotfiles#indent_motion#run(direction)
let l:cursor_linenr = line(".")
let l:max_linenr = line("$")
let l:retry = 0
while l:retry <# 2
let l:retry += 1
let l:base_linenr = l:cursor_linenr
let l:base_indent = 0
while 1 <=# l:base_linenr && l:base_linenr <=# l:max_linenr
let l:base_indent = dotfiles#indent_motion#indent_level_of(l:base_linenr)
if l:base_indent >=# 0
break
endif
let l:base_linenr += a:direction
endwhile
let l:target_linenr = l:base_linenr
let l:curr_linenr = l:base_linenr + a:direction
let l:prev_indent = l:base_indent
while 1 <=# l:curr_linenr && l:curr_linenr <=# l:max_linenr
let l:indent = dotfiles#indent_motion#indent_level_of(l:curr_linenr)
if l:indent >=# 0
if l:indent <# l:base_indent
break
else
let l:target_linenr = l:curr_linenr
endif
elseif l:base_indent ==# 0 && l:prev_indent ==# 0
break
endif
let l:prev_indent = l:indent
let l:curr_linenr += a:direction
endwhile
if l:target_linenr ==# l:cursor_linenr
let l:cursor_linenr += a:direction
if 1 <=# l:cursor_linenr && l:cursor_linenr <=# l:max_linenr
continue
endif
endif
break
endwhile
execute "normal! " . l:target_linenr . "G^"
endfunction
" <https://github.com/kana/vim-textobj-indent/blob/deb76867c302f933c8f21753806cbf2d8461b548/autoload/textobj/indent.vim#L120-L127>
function dotfiles#indent_motion#indent_level_of(linenr) "{{{2
if getline(a:linenr) ==# ""
return -1
endif
return indent(a:linenr)
endfunction

View file

@ -0,0 +1,6 @@
function dotfiles#utils#array_remove_element(array, element)
let l:index = index(a:array, a:element)
if l:index >= 0
call remove(a:array, l:index)
endif
endfunction

View file

@ -0,0 +1,9 @@
for [s:plug_mapping, s:direction, s:user_mapping] in [["prev", -1, "("], ["next", 1, ")"]]
let s:plug_mapping = "<Plug>dotfiles_indent_motion_".s:plug_mapping
for s:mode in ["n", "v", "o"]
execute s:mode."noremap" "<silent>" s:plug_mapping "<Cmd>call dotfiles#indent_motion#run(".s:direction.")<CR>"
if !empty(s:user_mapping)
execute s:mode."map" s:user_mapping s:plug_mapping
endif
endfor
endfor