¿Cómo cambiar la granularidad de deshacer en Vim?

11

En algún momento mi Vim deshacería una palabra completa cuando golpeara u.

[i]typing some words[C-c][u]

Resultaría en

typing some

Sin embargo, la granularidad de deshacer parece haber cambiado para eliminar una letra a la vez.

[i]typing some words[C-c][u]

Resultados en

typing some word

Recuerdo haber leído algo sobre la personalización de la granularidad de deshacer en Practical Vim, pero no recuerdo cómo controlarlo. Cualquier ayuda apreciada!

Dan Prince
fuente
2
Probablemente hay algo en su vimrc que hace esto. No puedo replicarlo, y no puedo encontrar nada en los :helparchivos al respecto ... Vea: ¿Cómo depuro mi archivo vimrc? ... Además, usar <C-c>para salir del modo de inserción puede tener efectos secundarios ( ver esto ) y puede ser parte del problema ... Sugeriría usar Esco <C-[>( ver esto )
Martin Tournoij

Respuestas:

11

Romper manualmente la secuencia de deshacer

Puede romper manualmente la secuencia de deshacer en modo Insertar con <C-G>u. De la ayuda :

CTRL-G u        break undo sequence, start new change

Ejemplo

iHello<C-G>u world!<Esc>u

Esto te dejará con el texto

Hello

Desglose de comandos

i                           " Enter Insert mode
 Hello                      " Type 'Hello'
      <C-G>u                " Break the undo sequence
             world!         " Type ' world!'
                   <Esc>    " Return to Normal mode
                        u   " Undo

Solución automática

Control de nivel de deshacer más fino

Aquí hay un pequeño fragmento de VimScript que se usa <C-G>upara crear saltos de deshacer cuando comienza a eliminar texto, y también cuando comienza a ingresar texto nuevamente después de una eliminación.

function! s:start_delete(key)
    let l:result = a:key
    if !s:deleting
        let l:result = "\<C-G>u".l:result
    endif
    let s:deleting = 1
    return l:result
endfunction

function! s:check_undo_break(char)
    if s:deleting
        let s:deleting = 0
        call feedkeys("\<BS>\<C-G>u".a:char, 'n')
    endif
endfunction

augroup smartundo
    autocmd!
    autocmd InsertEnter * let s:deleting = 0
    autocmd InsertCharPre * call s:check_undo_break(v:char)
augroup END

inoremap <expr> <BS> <SID>start_delete("\<BS>")
inoremap <expr> <C-W> <SID>start_delete("\<C-W>")
inoremap <expr> <C-U> <SID>start_delete("\<C-U>")

Notas

Esto funcionará para <BS>, <C-W>(eliminar una palabra), y <C-U>(eliminar al principio de la línea). Si hay más formas de eliminar en el modo Insertar, se pueden admitir agregando inoremapllamadas adicionales al final.

tommcdo
fuente
44
El único problema es que no prevé que va a deshacer más tarde (de lo contrario, no lo hará en primer lugar). Por lo tanto, generalmente termina con una situación en la que desearía haber utilizado <C-G>u, que ya es demasiado tarde.
Shahbaz
44
Si. En realidad, algo que me he estado perdiendo es esto. A veces hago esto iseguido de una oración larga seguida de retroceso para eliminar parte de lo que he escrito (todo en modo de inserción). Entonces me doy cuenta de que no debería haber retrocedido y lo que había escrito estaba bien. Deshago, pero luego todo el texto insertado se deshace. Entonces, o no me queda nada de la oración larga, o la parte que no tiene retroceso. Es imposible recuperar la parte de retroceso. ¿Hay alguna manera de decirle a Vim que rompa la secuencia de deshacer en el espacio de retroceso? (Ahora que lo digo, maping backspace es una opción, por supuesto).
Shahbaz
2
Para futuros visitantes, también agregué inoremap <CR> <C-G>u<CR>para que cada deshacer esté contenido en una sola línea (no más deshacer todo el párrafo que estaba escribiendo sin parar).
Shahbaz
1
@Shahbaz, absolutamente :)
tommcdo 9/15
1
@Shahbaz "¿Se me permite copiar?" Vea el enlace en la parte inferior de la página: "contribuciones de usuarios con licencia bajo cc by-sa 3.0 con atribución requerida"