現在のインデントレベルのテキストオブジェクト?[複製]
Dec 02 2020
そのようにインデントされたブロックがあるとしましょう
int main(int argc, char **argv){
printf ("odd numbers between 1 and 10:\n");
// level 1
for (int i = 1; i <= 10 ; i ++) {
// level 2
if (i % 2 == 1){
printf (" %d",i);
// level 3
....
}
...
}
}
i{
インデントは中括弧内に含まれているため、ここでは機能しますが、Pythonやマークダウンのインデントリストなどの言語では機能しません。
iI
カーソルが置かれているインデントレベルでのみ動作するように、テキストオブジェクト(「インデント内」)またはその効果に類似したものを定義することは可能でしょうか?したがって、if
ブロック(レベル3)にいるdiI
とすると、そのインデントレベルでのみ削除され、レベル1の場合も同様に、ブロック内のすべてが削除されます。
回答
3 MaximKim Dec 02 2020 at 20:03
インデントテキストオブジェクトの実装はたくさんあります。「インデント」オブジェクトの定義方法が異なるためだと思います。
私は自分のものを持っています:チェック https://gist.github.com/habamax/4662821a1dad716f5c18205489203a67
vimrcで次のスニペットをvii
使用vai
すると、インデントを選択したり選択したりできます。
"" Indent text object
"" Useful for python-like indentation based programming languages
func! s:indent_textobj(inner)
if getline('.') =~ '^\s*$' let ln_start = s:detect_nearest_line() let ln_end = ln_start else let ln_start = line('.') let ln_end = ln_start endif let indent = indent(ln_start) if indent > 0 while indent(ln_start) >= indent && ln_start > 0 let ln_start = prevnonblank(ln_start-1) endwhile while indent(ln_end) >= indent && ln_end <= line('$')
let ln_end = s:nextnonblank(ln_end+1)
endwhile
else
while indent(ln_start) == 0 && ln_start > 0 && getline(ln_start) !~ '^\s*$' let ln_start -= 1 endwhile while indent(ln_start) > 0 && ln_start > 0 let ln_start = prevnonblank(ln_start-1) endwhile while indent(ln_start) == 0 && ln_start > 0 && getline(ln_start) !~ '^\s*$'
let ln_start -= 1
endwhile
while indent(ln_end) == 0 && ln_end <= line('$') && getline(ln_end) !~ '^\s*$'
let ln_end += 1
endwhile
while indent(ln_end) > 0 && ln_end <= line('$') let ln_end = s:nextnonblank(ln_end+1) endwhile endif if a:inner || indent == 0 let ln_start = s:nextnonblank(ln_start+1) endif if a:inner let ln_end = prevnonblank(ln_end-1) else let ln_end = ln_end-1 endif if ln_end < ln_start let ln_end = ln_start endif exe ln_end normal! V exe ln_start endfunc func! s:nextnonblank(lnum) abort let res = nextnonblank(a:lnum) if res == 0 let res = line('$')+1
endif
return res
endfunc
func! s:detect_nearest_line() abort
let lnum = line('.')
let nline = s:nextnonblank(lnum)
let pline = prevnonblank(lnum)
if abs(nline - lnum) > abs(pline - lnum) || getline(nline) =~ '^\s*$'
return pline
else
return nline
endif
endfunc
onoremap <silent>ii :<C-u>call <sid>indent_textobj(v:true)<CR>
onoremap <silent>ai :<C-u>call <sid>indent_textobj(v:false)<CR>
xnoremap <silent>ii :<C-u>call <sid>indent_textobj(v:true)<CR>
xnoremap <silent>ai :<C-u>call <sid>indent_textobj(v:false)<CR>