¿Cómo suspender el historial de VIM?

8

Cuando editamos un archivo, generalmente hacemos muchas UNDO seguidas, por ejemplo, 20 veces. En VIM, eso generalmente se realiza presionando u20 veces, y eso hace que VIM "suba" en la pila de historial 20 posiciones. Si luego se asegura change, todos los últimos 20 comandos del historial se pierden y se reemplazan por change. Me gustaría hacer changesin perder esas 20 posiciones. Así que supongo que me gustaría decirle a VIM que deje de grabar el historial antes de hacerlo changey que reanude el historial después (no quiero changeen el historial).

EDITAR Tratando de ser más claro: tengo una función FFque actualiza las últimas líneas de un archivo cuando se escribe el búfer. Entonces, si realizo 20 undos + write, el último writeabre una nueva rama de deshacer. Intenté agregar undojoindentro FF(tratando de seguir una sugerencia de jlmg a continuación), pero una secuencia write-undo-write da un error: undojoint no está permitido después de deshacer . En cambio, podría hacer algo sed ....después de irme vim, pero como uso esto SSHprefiero una solución solo vim (ejecutar un comando después de descargar el búfer no escribe en el archivo).

EDITAR 2 Intente hacer esto en VIM: abra un archivo en blanco y haga:

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

Si ahora hace un <CTRL>R, VIM escribirá el '3' de regreso, más <CTRL>Robtendrá el 4. Esto sucede INCLUSO si haces un :wdespués de cada uno <CTRL>R. Sin embargo, si cada vez que realiza una :wejecución a través de una función BufWritePre, <CTRL>Rno escribirá la 3respuesta. Y esto es lo que quiero hacer, es por eso que escribí para 'suspender la historia', pero tal vez lo que pido no sea posible, además de trabajar con todo undotree().

Luis A. Florit
fuente
1
Esta pregunta es sobre el tema de este sitio, pero dado que se trata de una característica potencial bastante esotérica de VIM, ¿ha considerado probar vim.stackexchange.com en su lugar? Quiero decir, sé UNIX y lo sé vi, pero para mí viel comando deshacer se deshace una vez, y luego, cuando presionas unuevamente, deshace el deshacer ("rehacer"). Eso es real vi. Por lo tanto, yo y otros usuarios de este sitio podrían no saber la respuesta a su pregunta.
Celada
2
@Celada Creo que es vi.stackexchange.com , o Vi y Vim .
Satō Katsura
@SatoKatsura tienes toda la razón!
Celada
1
@Celada: No lo sabía vim.se, lo habría intentado. De todos modos, parece que Sato sabe cómo ayudar.
Luis A. Florit
El problema que le da a "todos los últimos 20 comandos de historial se han perdido" se soluciona con la existencia de las ramas de deshacer, por lo que es confuso que luego desee solucionar su problema evitando su creación. Dices que puedes obtener el resultado que deseas sed, pero sed no puede deshacer las cosas, entonces, ¿cómo va a funcionar eso? Si pudieras "suspender el historial", ¿qué comportamiento amable esperarías de vim cuando hagas un deshacer después? El único comportamiento que podría visualizar es agrupar esos cambios (junto con los deshacer) en un bloque de deshacer, de ahí mi respuesta. Pero si no es así, ¿qué es?
JoL

Respuestas:

12

No necesita suspender el historial de Vim. Los datos reales forman un árbol y puede recuperarlos con la undotree()función. Hay, por supuesto, una serie de complementos que lo convierten en algo más fácil de usar, fi gundo , mundo e indescifrable . Si también habilita la persistencia de deshacer (cf. :h undo-persistence), puede navegar fácilmente por todo el historial de cambios de un archivo.

Satō Katsura
fuente
Interesante, no sabía que deshacer era en realidad un árbol. En mi caso, solo quiero volver una vez, es decir, a la rama de deshacer anterior. ¿Sabes como hacer esto? Parece que undotree()debería ayudar?
Luis A. Florit
En realidad, en este caso particular que motivó mi pregunta, quiero que changeno aparezca en absoluto, en ninguna parte, ni en history, ni en el undoárbol. Por eso mi pregunta era "suspender la historia".
Luis A. Florit
@ LuisA.Florit: La forma rápida y fácil de hacerlo es con :earlier, que acepta una unidad de tiempo y cruzará las ramas de deshacer si es necesario (por ejemplo, :earlier 1hhace que el búfer se vea como lo hizo hace una hora). Si no puede usar una unidad de tiempo (¿porque los cambios fueron demasiado juntos?), Entonces tendrá que usar g-para caminar el árbol de deshacer unos pasos a la vez.
Kevin
0

Si te entiendo correctamente, lo que quieres es que luego deshacer deshaga eso changey deshaga las 20 acciones.

Cuando vim ejecuta una función o comando, todas las acciones que realiza se deshacen juntas. No estoy seguro de si esas acciones pueden incluir deshacer. Quizás esta parte de la documentación pueda ayudar:

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.

Por desgracia, intenté usar :undo 2 | undojoin | normal ohi, pero recibí el mensaje de error E790: undojoin is not allowed after undo.

Sin embargo, si las acciones se realizan en una función como esta:

function F()
  undo 2
  normal ohi
endfunction

luego llamarlo con :call F()realiza la undootra acción en un bloque de deshacer. Tenga en cuenta que debido a que está utilizando deshacer, está creando una nueva rama de deshacer. Una vez hecho esto, puede usar el comando de modo normal g-para deshacer F(); usar userá como haberlo hecho :undo 3al principio.

JoL
fuente
No estoy seguro si esto funciona ... Lo que quiero es que, después de hacer algo undo, todo lo que haces en tu función F()no abra una nueva rama de deshacer. En mi caso, F()se ejecuta cada vez que escribo el archivo, y si lo hago undoy luego escribo el archivo, F()abre una nueva rama de deshacer. Probé con undojoinal comienzo de F(), pero una secuencia de escritura-undo-escritura da un error: undojoint not allowed after undo.
Luis A. Florit
Actualicé mi pregunta tratando de ser más clara.
Luis A. Florit
@ LuisA.Florit Escribí en la respuesta que :undojoinno funcionó para lo que querías, mencionando el mismo error, y no estaba sugiriendo usarlo :undojoinal comienzo de F(). F()está destinado a hacer lo :undojoinque no podría, que es unir los comandos deshacer y otros en un bloque de deshacer.
JoL
@ LuisA.Florit Dices que quieres evitar crear una rama de deshacer, pero no puedo encontrar la razón por la que quieres eso. Pensé que el punto de su pregunta era poder deshacer los comandos y las múltiples deshacer de una vez. Mirando hacia atrás, me pregunto si su punto era no perder los cambios que había deshecho. Si ese es el caso, la existencia del árbol de deshacer es precisamente lo que quieres. Puedes navegar con g-y g+.
JoL
Sí, parece que el árbol de deshacer es lo que necesito.
Luis A. Florit