¿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.
find ./ -type f -name ". * sw [klmnop]" -delete
Crédito: @Shwaydogg https://superuser.com/questions/480367/whats-the-easiest-way-to-delete-vim-swapfiles-ive-already-recovered-from
Navega al directorio primero