Textobjekt für aktuelle Einrückungsstufe? [Duplikat]
Angenommen, ich habe so einen eingerückten Block
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{
würde hier funktionieren, weil die Einrückungen in geschweiften Klammern enthalten sind, aber nicht für Sprachen wie Python oder eingerückte Listen in Markdown usw.
Wäre es möglich, ein iI
Textobjekt zu definieren, beispielsweise ("in Einrückung") oder etwas Ähnliches, um nur auf der Einrückungsstufe zu arbeiten, auf der sich der Cursor befindet? Angenommen, wir befinden uns im if
Block (Ebene 3) und diI
werden dann nur in dieser Einrückungsstufe gelöscht. In ähnlicher Weise wird für Ebene 1 alles im Block gelöscht.
Antworten
Es gibt viele Implementierungen für eingerückte Textobjekte - ich denke aufgrund der unterschiedlichen Definition von "eingerückten" Objekten.
Ich habe meine eigene: überprüfen https://gist.github.com/habamax/4662821a1dad716f5c18205489203a67
Mit dem folgenden Snippet in Ihrem vimrc können Sie Einrückungen auswählen vii
oder vai
auswählen:
"" 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>