vim recovery

¿Recuperación más inteligente de Vim?



recovery (7)

Acabo de descubrir esto:

http://vimdoc.sourceforge.net/htmldoc/diff.html#:DiffOrig

Copié y pegué el comando DiffOrig en mi archivo .vimrc y funciona como un amuleto. Esto facilita enormemente la recuperación de archivos de intercambio. No tengo idea de por qué no está incluido por defecto en VIM.

Aquí está el comando para aquellos que están apurados:

command DiffOrig vert new | set bt=nofile | r # | 0d_ | diffthis / | wincmd p | diffthis

Cuando una sesión anterior de Vim se cuelga, se le saluda con el "¡Intercambio de archivos ... ya existe!" para todos y cada uno de los archivos que se abrieron en la sesión anterior.

¿Puedes hacer que esta recuperación de Vim sea más inteligente? (¡Sin desconectar la recuperación!) Específicamente, estoy pensando en:

  • Si la versión intercambiada no contiene cambios no guardados y el proceso de edición ya no se está ejecutando, ¿puede hacer que Vim elimine automáticamente el archivo de intercambio?
  • ¿Se puede automatizar el proceso sugerido de guardar el archivo recuperado con un nuevo nombre, fusionándolo con un archivo en el disco y luego eliminando el antiguo archivo de intercambio, para que se requiera una interacción mínima? Especialmente cuando la versión de intercambio y la versión de disco son iguales, todo debe ser automático.

Descubrí el SwapExists pero no sé si puede ayudar con estas tareas.


Tengo vim almacenar mis archivos de intercambio en un solo directorio local, al tener esto en mi .vimrc:

set directory=~/.vim/swap,.

Entre otros beneficios, esto hace que los archivos de intercambio sean fáciles de encontrar a la vez. Ahora, cuando mi computadora portátil pierde potencia o lo que sea y empiezo de nuevo con un montón de archivos de intercambio, simplemente ejecuto mi script de cleanswap :

TMPDIR=$(mktemp -d) || exit 1 RECTXT="$TMPDIR/vim.recovery.$USER.txt" RECFN="$TMPDIR/vim.recovery.$USER.fn" trap ''rm -f "$RECTXT" "$RECFN"; rmdir "$TMPDIR"'' 0 1 2 3 15 for q in ~/.vim/swap/.*sw? ~/.vim/swap/*; do [[ -f $q ]] || continue rm -f "$RECTXT" "$RECFN" vim -X -r "$q" / -c "w! $RECTXT" / -c "let fn=expand(''%'')" / -c "new $RECFN" / -c "exec setline( 1, fn )" / -c w/! / -c "qa" if [[ ! -f $RECFN ]]; then echo "nothing to recover from $q" rm -f "$q" continue fi CRNT="$(cat $RECFN)" if diff --strip-trailing-cr --brief "$CRNT" "$RECTXT"; then echo "removing redundant $q" echo " for $CRNT" rm -f "$q" else echo $q contains changes vim -n -d "$CRNT" "$RECTXT" rm -i "$q" || exit fi done

Esto eliminará cualquier archivo de intercambio que esté actualizado con los archivos reales. Cualquiera que no concuerde aparece en una ventana de vimdiff para que pueda fusionarme en mis cambios no guardados.

--Chouser


La respuesta aceptada se descarta para un caso de uso muy importante. Digamos que creas un nuevo buffer y tecleas por 2 horas sin guardarlo, entonces tu portátil se cuelga. Si ejecuta el script sugerido , eliminará su único registro, el archivo swap .swp . No estoy seguro de cuál es la solución correcta, pero parece que el comando diff termina comparando el mismo archivo consigo mismo en este caso. La versión editada a continuación verifica este caso y le da al usuario la oportunidad de guardar el archivo en algún lugar.

#!/bin/bash SWAP_FILE_DIR=~/temp/vim_swp IFS=$''/n'' TMPDIR=$(mktemp -d) || exit 1 RECTXT="$TMPDIR/vim.recovery.$USER.txt" RECFN="$TMPDIR/vim.recovery.$USER.fn" trap ''rm -f "$RECTXT" "$RECFN"; rmdir "$TMPDIR"'' 0 1 2 3 15 for q in $SWAP_FILE_DIR/.*sw? $SWAP_FILE_DIR/*; do echo $q [[ -f $q ]] || continue rm -f "$RECTXT" "$RECFN" vim -X -r "$q" / -c "w! $RECTXT" / -c "let fn=expand(''%'')" / -c "new $RECFN" / -c "exec setline( 1, fn )" / -c w/! / -c "qa" if [[ ! -f $RECFN ]]; then echo "nothing to recover from $q" rm -f "$q" continue fi CRNT="$(cat $RECFN)" if [ "$CRNT" = "$RECTXT" ]; then echo "Can''t find original file. Press enter to open vim so you can save the file. The swap file will be deleted afterward!" read vim "$CRNT" rm -f "$q" else if diff --strip-trailing-cr --brief "$CRNT" "$RECTXT"; then echo "Removing redundant $q" echo " for $CRNT" rm -f "$q" else echo $q contains changes, or there may be no original saved file vim -n -d "$CRNT" "$RECTXT" rm -i "$q" || exit fi fi done


Prefiero no configurar mi directorio de trabajo VIM en .vimrc. Aquí hay una modificación de la secuencia de comandos de chouser que copia los archivos de intercambio en la ruta de intercambio bajo demanda para buscar duplicados y luego los reconcilia. Esto fue escrito apresurado, asegúrese de evaluarlo antes de ponerlo en práctica.

#!/bin/bash if [[ "$1" == "-h" ]] || [[ "$1" == "--help" ]]; then echo "Moves VIM swap files under <base-path> to ~/.vim/swap and reconciles differences" echo "usage: $0 <base-path>" exit 0 fi if [ -z "$1" ] || [ ! -d "$1" ]; then echo "directory path not provided or invalid, see $0 -h" exit 1 fi echo looking for duplicate file names in hierarchy swaps="$(find $1 -name ''.*.swp'' | while read file; do echo $(basename $file); done | sort | uniq -c | egrep -v "^[[:space:]]*1")" if [ -z "$swaps" ]; then echo no duplicates found files=$(find $1 -name ''.*.swp'') if [ ! -d ~/.vim/swap ]; then mkdir ~/.vim/swap; fi echo "moving files to swap space ~./vim/swap" mv $files ~/.vim/swap echo "executing reconciliation" TMPDIR=$(mktemp -d) || exit 1 RECTXT="$TMPDIR/vim.recovery.$USER.txt" RECFN="$TMPDIR/vim.recovery.$USER.fn" trap ''rm -f "$RECTXT" "$RECFN"; rmdir "$TMPDIR"'' 0 1 2 3 15 for q in ~/.vim/swap/.*sw? ~/.vim/swap/*; do [[ -f $q ]] || continue rm -f "$RECTXT" "$RECFN" vim -X -r "$q" / -c "w! $RECTXT" / -c "let fn=expand(''%'')" / -c "new $RECFN" / -c "exec setline( 1, fn )" / -c w/! / -c "qa" if [[ ! -f $RECFN ]]; then echo "nothing to recover from $q" rm -f "$q" continue fi CRNT="$(cat $RECFN)" if diff --strip-trailing-cr --brief "$CRNT" "$RECTXT"; then echo "removing redundant $q" echo " for $CRNT" rm -f "$q" else echo $q contains changes vim -n -d "$CRNT" "$RECTXT" rm -i "$q" || exit fi done else echo duplicates found, please address their swap reconciliation manually: find $1 -name ''.*.swp'' | while read file; do echo $(basename $file); done | sort | uniq -c | egrep ''^[[:space:]]*[2-9][0-9]*.*'' fi


Tengo esto en mi archivo .bashrc. Me gustaría dar crédito apropiado a parte de este código, pero olvidé de dónde lo saqué.

mswpclean(){ for i in `find -L -name ''*swp''` do swpf=$i aux=${swpf//"/."/"/"} orif=${aux//.swp/} bakf=${aux//.swp/.sbak} vim -r $swpf -c ":wq! $bakf" && rm $swpf if cmp "$bakf" "$orif" -s then rm $bakf && echo "Swap file was not different: Deleted" $swpf else vimdiff $bakf $orif fi done for i in `find -L -name ''*sbak''` do bakf=$i orif=${bakf//.sbak/} if test $orif -nt $bakf then rm $bakf && echo "Backup file deleted:" $bakf else echo "Backup file kept as:" $bakf fi done }

Simplemente ejecuto esto en la raíz de mi proyecto y, si el archivo es diferente, abre vim diff. Luego, se guardará el último archivo que se guardará. Para que sea perfecto, solo tendría que reemplazar el último:

else echo "Backup file kept as:" $bakf

por algo así como

else vim $bakf -c ":wq! $orif" && echo "Backup file kept and saved as:" $orif

pero no tuve tiempo para probarlo adecuadamente.

Espero eso ayude.


Gran consejo DiffOrig es perfecto. Aquí hay un script bash que uso para ejecutarlo en cada archivo swap bajo el directorio actual:

#!/bin/bash swap_files=`find . -name "*.swp"` for s in $swap_files ; do orig_file=`echo $s | perl -pe ''s!//.([^/]*).swp$!/$1!'' ` echo "Editing $orig_file" sleep 1 vim -r $orig_file -c "DiffOrig" echo -n " Ok to delete swap file? [y/n] " read resp if [ "$resp" == "y" ] ; then echo " Deleting $s" rm $s fi done

Probablemente podría utilizar un poco más de comprobación de errores y citas, pero ha funcionado hasta ahora.