현재 들여 쓰기 수준에 대한 텍스트 개체? [복제]

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{ 들여 쓰기가 중괄호 안에 포함되어 있기 때문에 여기에서 작동하지만 파이썬이나 마크 다운 등의 들여 쓰기 목록과 같은 언어에는 적합하지 않습니다.

iI커서가있는 들여 쓰기 수준에서만 작동 하도록 텍스트 개체 ( "indentation") 또는 이와 유사한 효과를 정의 할 수 있습니까? 따라서 우리가 if블록 (수준 3) 에 있다고 가정 diI하면 해당 들여 쓰기 수준에서만 삭제되고 마찬가지로 수준 1의 경우 블록의 모든 항목이 삭제됩니다.

답변

3 MaximKim Dec 02 2020 at 20:03

들여 쓰기 텍스트 객체에 대한 많은 구현이 있습니다. "indent"객체가 정의되는 방식이 다르기 때문이라고 생각합니다.

내 자신이 있습니다 : 확인 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>