Comment suspendre l'historique VIM?

8

Lorsque nous modifions un fichier, nous effectuons généralement plusieurs annulations consécutives, disons 20 fois. Dans VIM, cela se fait généralement en appuyant u20 fois, et cela fait remonter VIM dans la pile d'historique 20 positions. Si vous faites ensuite un certain change, toutes ces 20 dernières commandes d'historique sont perdues et remplacées par change. Je voudrais faire le changesans perdre ces 20 positions. Je suppose donc que je voudrais dire à VIM d'arrêter d'enregistrer l'historique avant de le faire changeet de reprendre l'historique après (je ne veux pas changedans l'histoire).

EDIT Essayer d'être plus clair: j'ai une fonction FFqui met à jour les dernières lignes d'un fichier lorsque le tampon est écrit. Donc, si je joue 20 undos + write, le dernier writeouvre une nouvelle branche d'annulation. J'ai essayé d'ajouter à l' undojoinintérieur FF(en essayant de suivre une suggestion de jlmg ci-dessous), mais une séquence écriture-annulation-écriture donne une erreur: undojoint non autorisé après l'annulation . Je pourrais plutôt en faire sed ....après avoir quitté à la vimplace, mais comme j'utilise ceci via, SSHje préfère une solution vim uniquement (exécuter une commande après avoir déchargé le tampon n'écrit pas dans le fichier).

EDIT 2 Essayez de faire ceci dans VIM: ouvrez un fichier vierge et faites:

i1<ESC>:wa2<ESC>:wa3<ESC>:wa4<ESC>uu:w

Si maintenant vous faites un <CTRL>R, VIM réécrira le «3», plus <CTRL>Rvous obtiendrez le 4. Cela se produit MÊME si vous faites un :waprès chacun <CTRL>R. Cependant, si à chaque fois que vous effectuez une :wexécution, vous n'effectuerez pas de fuction via BufWritePre, le <CTRL>Rne réécrira pas 3. Et c'est ce que je veux faire, c'est pourquoi j'ai écrit pour «suspendre l'histotrie», mais peut-être que ce que je demande n'est pas possible, en plus de travailler avec le plein undotree().

Luis A. Florit
la source
1
Cette question est sur le sujet de ce site, mais comme elle se rapporte à une fonctionnalité potentielle assez ésotérique de VIM, avez-vous envisagé d'essayer vim.stackexchange.com à la place? Je veux dire, je connais UNIX et je sais vi, mais pour moi, vila commande d'annulation annule une fois, puis lorsque vous appuyez à unouveau, elle annule l'annulation ("redo"). C'est vrai vi. Donc, moi et les autres utilisateurs de ce site ne connaissons peut-être pas la réponse à votre question.
Celada du
2
@Celada Je pense que c'est vi.stackexchange.com , ou Vi et Vim .
Satō Katsura
@SatoKatsura, vous avez absolument raison!
Celada
1
@Celada: Je ne savais pas vim.se, j'aurais essayé ça. Quoi qu'il en soit, il semble que Sato sait comment aider.
Luis A. Florit
Le problème que vous donnez "toutes les 20 dernières commandes d'historique sont perdues" est résolu avec l'existence des branches d'annulation, il est donc déroutant que vous souhaitiez ensuite résoudre votre problème en évitant leur création. Vous dites que vous pouvez obtenir le résultat souhaité sed, mais sed ne peut pas faire vos annulations, alors comment ça va marcher? Si vous pouviez "suspendre l'historique", quel comportement aimable attendriez-vous de Vim lorsque vous effectuerez une annulation par la suite? Le seul comportement que je pouvais visualiser est de regrouper ces changements (avec les annulations) dans un bloc d'annulation, d'où ma réponse. Mais si ce n'est pas ça, c'est quoi?
JoL

Réponses:

12

Vous n'avez pas besoin de suspendre l'historique de Vim. Les données réelles forment un arbre et vous pouvez les récupérer avec la undotree()fonction. Il existe, bien sûr, un certain nombre de plugins qui en font quelque chose de plus convivial, fi gundo , mundo et undotree . Si vous activez également l'annulation de la persistance (cf. :h undo-persistence), vous pouvez facilement parcourir tout l'historique des modifications d'un fichier.

Satō Katsura
la source
Intéressant, je ne savais pas que l'annulation était en fait un arbre. Dans mon cas, je ne veux revenir qu'une seule fois, c'est-à-dire à la branche d'annulation précédente. Savez-vous comment le faire? Cela undotree()devrait aider?
Luis A. Florit
En fait, dans ce cas particulier qui a motivé ma question, je veux que cela changen'apparaisse pas du tout, nulle part, ni dans history, ni dans l' undoarbre. C'est pourquoi ma question était de "suspendre l'histoire".
Luis A. Florit
@ LuisA.Florit: Le moyen rapide et facile de le faire est d'utiliser :earlier, qui accepte une unité de temps et traversera les branches d'annulation si nécessaire (par exemple, :earlier 1hfait ressembler le tampon à celui qu'il y a une heure). Si vous ne pouvez pas utiliser une unité de temps (parce que les changements étaient trop proches les uns des autres?), Vous devrez utiliser g-pour parcourir l'arbre d'annulation quelques étapes à la fois.
Kevin
0

Si je vous comprends bien, ce que vous voulez, c'est qu'après cela, une annulation soit changeannulée et les 20 annulations.

Lorsque vim exécute une fonction ou une commande, toutes les actions qu'il effectue sont annulées ensemble. Je ne sais pas si ces actions peuvent inclure des annulations. Peut-être que cette partie de la documentation peut aider:

3. Undo blocks                      *undo-blocks*

One undo command normally undoes a typed command, no matter how many changes
that command makes.  This sequence of undo-able changes forms an undo block.
Thus if the typed key(s) call a function, all the commands in the function are
undone together.

If you want to write a function or script that doesn't create a new undoable
change but joins in with the previous change use this command:

                        *:undoj* *:undojoin* *E790*
:undoj[oin]     Join further changes with the previous undo block.
            Warning: Use with care, it may prevent the user from
            properly undoing changes.  Don't use this after undo
            or redo.
            {not in Vi}

This is most useful when you need to prompt the user halfway through a change.
For example in a function that calls |getchar()|.  Do make sure that there was
a related change before this that you must join with.

This doesn't work by itself, because the next key press will start a new
change again.  But you can do something like this: >

    :undojoin | delete

After this an "u" command will undo the delete command and the previous
change.

To do the opposite, break a change into two undo blocks, in Insert mode use
CTRL-G u.  This is useful if you want an insert command to be undoable in
parts.  E.g., for each sentence.  |i_CTRL-G_u|
Setting the value of 'undolevels' also breaks undo.  Even when the new value
is equal to the old value.

Hélas, j'ai essayé d'utiliser :undo 2 | undojoin | normal ohi, mais j'ai reçu le message d'erreur E790: undojoin is not allowed after undo.

Cependant, si les actions sont effectuées dans une fonction comme celle-ci:

function F()
  undo 2
  normal ohi
endfunction

puis l'appeler avec :call F()effectue la undoet l'autre action dans un bloc d'annulation. Notez que parce que vous utilisez l'annulation, vous créez une nouvelle branche d'annulation. Une fois l'opération terminée, vous pouvez utiliser la commande du mode normal g-pour annuler F(); utiliser usera comme avoir fait :undo 3au début.

JoL
la source
Je ne sais pas si cela fonctionne ... Ce que je veux, c'est qu'après en avoir fait undo, tout ce que vous faites dans votre fonction F()n'ouvre pas une nouvelle branche d'annulation. Dans mon cas, F()est exécuté à chaque fois que j'écris le fichier, et si je le fais undo, puis j'écris le fichier, F()ouvre une nouvelle branche d'annulation. J'ai essayé avec undojoinau début de F(), mais une séquence d' écriture-undo-écriture donne une erreur: undojoint not allowed after undo.
Luis A. Florit
Mis à jour ma question en essayant d'être plus clair.
Luis A. Florit du
@ LuisA.Florit J'ai écrit dans la réponse qui :undojoinne fonctionnait pas pour ce que vous vouliez, en mentionnant la même erreur, et je ne proposais pas d'utiliser :undojoinau début F(). F()est censé faire ce qui :undojoinne pouvait pas, c'est-à-dire joindre les annulations et autres commandes dans un bloc d'annulation.
JoL
@ LuisA.Florit Vous dites que vous voulez éviter de créer une branche d'annulation, mais je ne trouve pas la raison pour laquelle vous le souhaitez. Je pensais que le but de votre question était de pouvoir annuler les commandes et les multiples annulations en une seule fois. En y repensant, je me demande si vous ne vouliez pas perdre les modifications que vous aviez annulées. Si tel est le cas, l'existence de l'arbre d'annulation est précisément ce que vous voulez. Vous pouvez le naviguer avec g-et g+.
JoL
Oui, il semble que l'arbre d'annulation soit ce dont j'ai besoin.
Luis A. Florit