objeto de texto para o nível de recuo atual? [duplicado]

Dec 02 2020

Digamos que eu tenha um bloco recuado assim

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{ funcionaria aqui porque os recuos estão contidos entre colchetes, mas não funcionaria para linguagens como python ou listas recuadas em markdown, etc.

Seria possível definir um objeto de texto, digamos iI("em indentação") ou algo semelhante a esse efeito para operar apenas no nível de indentação em que o cursor está? Então, suponha que estamos no ifbloco (nível 3), então diIexcluiremos apenas aquele nível de indentação e, da mesma forma, para o nível 1, excluiremos tudo no bloco.

Respostas

3 MaximKim Dec 02 2020 at 20:03

Existem muitas implementações para objetos de texto de indentação - eu acho que devido à maneira diferente de definir o objeto de "indentação".

Eu tenho meu próprio: cheque https://gist.github.com/habamax/4662821a1dad716f5c18205489203a67

Com o seguinte snippet em seu vimrc, você poderá selecionar viiou vaiselecionar o recuo:

"" 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>