текстовый объект для текущего уровня отступа? [дубликат]
Скажем, у меня такой блок с отступом
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 или списки с отступом в markdown и т. д.
Можно ли было бы определить текстовый объект, скажем iI
(«in Indentation») или что-то подобное, чтобы работать только с уровнем отступа, на котором находится курсор? Итак, предположим, что мы находимся в if
блоке (уровень 3), тогда diI
удаляем только на этом уровне отступа, и аналогично для уровня 1 он удалит все в блоке.
Ответы
Существует множество реализаций для текстовых объектов с отступом - я думаю, из-за другого способа определения объекта «отступ».
У меня есть свой: проверить 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>