objeto de texto para el nivel de sangría actual? [duplicar]

Dec 02 2020

Di que tengo un bloque con sangría como ese

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{ funcionaría aquí porque las sangrías están contenidas entre llaves, pero no para lenguajes como Python o listas con sangría en Markdown, etc.

¿Sería posible definir un objeto de texto, digamos iI("en sangría") o algo similar a ese efecto para operar solo en el nivel de sangría en el que se encuentra el cursor? Entonces, supongamos que estamos en el ifbloque (nivel 3), luego diIsolo eliminaremos en ese nivel de sangría y, de manera similar, para el nivel 1 eliminará todo en el bloque.

Respuestas

3 MaximKim Dec 02 2020 at 20:03

Hay muchas implementaciones para los objetos de texto con sangría - supongo que debido a la forma diferente en que se define el objeto "sangría".

Yo tengo el mío: comprobar https://gist.github.com/habamax/4662821a1dad716f5c18205489203a67

Con el siguiente fragmento en su vimrc, podrá viio vaiseleccionar sangría:

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