Comment changer la granularité d'annulation dans Vim?

11

À un moment donné, mon Vim annulerait un mot entier lorsque je frapperais u.

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

Résulterait en

typing some

Cependant, la granularité d'annulation semble avoir changé en supprimant une lettre à la fois.

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

Résulte en

typing some word

Je me souviens d'avoir lu quelque chose sur la personnalisation de la granularité d'annulation dans Practical Vim, mais je ne me souviens pas comment la contrôler. Toute aide appréciée!

Dan Prince
la source
2
Il y a probablement quelque chose dans votre vimrc qui fait cela. Je ne peux pas le répliquer et je ne trouve rien dans les :helpfichiers à ce sujet ... Voir: Comment déboguer mon fichier vimrc? ... De plus, utiliser <C-c>pour quitter le mode d'insertion peut avoir des effets secondaires ( voir ceci ) et peut faire partie du problème ... Je suggère d'utiliser Escou <C-[>( voir ceci )
Martin Tournoij

Réponses:

11

Rompre manuellement la séquence d'annulation

Vous pouvez interrompre manuellement la séquence d'annulation en mode Insertion avec <C-G>u. De l'aide :

CTRL-G u        break undo sequence, start new change

Exemple

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

Cela vous laissera avec le texte

Hello

Répartition des commandes

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

Solution automatique

Contrôle de niveau d'annulation à grain plus fin

Voici un petit extrait de VimScript qui permet <C-G>ude créer des sauts d'annulation lorsque vous commencez à supprimer du texte, et également lorsque vous recommencez à saisir du texte après une suppression.

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

Remarques

Cela fonctionne pour <BS>, <C-W>(supprimer un mot), et <C-U>(supprimer le début de la ligne). S'il existe d'autres façons de supprimer en mode Insertion, elles peuvent être prises en charge en ajoutant des inoremapappels supplémentaires à la fin.

tommcdo
la source
4
Le seul problème est que vous ne prévoyez pas d'annuler plus tard (sinon vous ne le ferez pas en premier lieu). Donc, vous vous retrouvez généralement avec une situation où vous auriez aimé avoir utilisé <C-G>u, ce qui est déjà trop tard.
Shahbaz
4
Oui. En fait, quelque chose qui me manque, c'est ça. Parfois, je le fais isuivi d'une longue phrase suivie d'un retour arrière pour supprimer une partie de ce que j'ai écrit (le tout en mode insertion). Ensuite, je réalise que je n'aurais pas dû revenir en arrière et ce que j'avais écrit était bien. J'annule, mais tout le texte inséré est annulé. Donc, soit je me retrouve avec aucune de la longue phrase, ou la partie qui n'est pas reculée. Il est impossible de récupérer la partie arrière. Existe-t-il un moyen de dire à vim de rompre la séquence d'annulation lors du retour arrière? (Maintenant que je le dis, maple retour arrière est une option bien sûr).
Shahbaz
2
Pour les futurs visiteurs, j'ai également ajouté de inoremap <CR> <C-G>u<CR>sorte que chaque annulation soit contenue dans une seule ligne (plus de défaire le paragraphe entier que vous tapiez sans arrêt).
Shahbaz
1
@Shahbaz, absolument :)
tommcdo
1
@Shahbaz "Suis-je autorisé à copier?" Voir le lien en bas de la page: "contributions des utilisateurs sous licence cc by-sa 3.0 avec attribution requise"