¿Recuperación de Vim más inteligente?
Pregunta
Cuando una sesión anterior de Vim falla, aparece el mensaje "Archivo de intercambio...¡ya existe!" para todos y cada uno de los archivos que se abrieron en la sesión anterior.
¿Puedes hacer que este mensaje de recuperación de Vim sea más inteligente?(¡Sin desactivar 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 ejecuta, ¿puede hacer que Vim elimine automáticamente el archivo de intercambio?
- ¿Puede automatizar el proceso sugerido de guardar el archivo recuperado con un nuevo nombre, fusionarlo con el archivo en el disco y luego eliminar el archivo de intercambio anterior, de modo que se requiera una interacción mínima?Especialmente cuando la versión de intercambio y la versión de disco son las mismas, todo debería ser automático.
descubrí el SwapExists
autocommand pero no sé si puede ayudar con estas tareas.
Solución
Tengo vim para almacenar mis archivos de intercambio en un único directorio local, teniendo esto en mi .vimrc:
set directory=~/.vim/swap,.
Entre otros beneficios, esto hace que los archivos de intercambio sean fáciles de encontrar todos a la vez.Ahora, cuando mi computadora portátil se queda sin energía o lo que sea y empiezo a reiniciar con un montón de archivos de intercambio por ahí, simplemente ejecuto mi cleanswap
guion:
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 coincida aparece en una ventana de vimdiff para que pueda fusionar mis cambios no guardados.
--Chouser
Otros consejos
Acabo de descubrir esto:
http://vimdoc.sourceforge.net/htmldoc/diff.html#:DiffOrig
Copié y pegué el comando DiffOrig en mi archivo .vimrc y funciona de maravilla.Esto facilita enormemente la recuperación de archivos de intercambio.No tengo idea de por qué no está incluido de forma predeterminada en VIM.
Aquí está el comando para los que tienen prisa:
command DiffOrig vert new | set bt=nofile | r # | 0d_ | diffthis
\ | wincmd p | diffthis
La respuesta aceptada es errónea para un caso de uso muy importante.Digamos que crea un nuevo búfer y escribe durante 2 horas sin guardarlo, luego su computadora portátil falla.Si ejecuta el script sugerido eliminará su único registro, el archivo de intercambio .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 comprueba 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
Gran consejo DiffOrig es perfecto.Aquí hay un script bash que uso para ejecutarlo en cada archivo de intercambio en 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 le vendría bien un poco más de verificación de errores y citas, pero hasta ahora ha funcionado.
Prefiero no configurar mi directorio de trabajo VIM en .vimrc.Aquí hay una modificación del script de chouser que copia los archivos de intercambio a la ruta de intercambio a pedido, verifica si hay duplicados y luego los concilia.Esto fue escrito apresuradamente, 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 el 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 conservará el último archivo que se guardó.Para hacerlo perfecto solo necesitaría reemplazar lo último:
else echo "Backup file kept as:" $bakf
por algo como
else vim $bakf -c ":wq! $orif" && echo "Backup file kept and saved as:" $orif
pero no tuve tiempo de probarlo adecuadamente.
Espero eso ayude.
buscar ./ -tipo f -nombre ".*sw[klmnop]" -eliminar
Crédito:@shwaydogghttps://superuser.com/questions/480367/cuál-es-la-forma-más-fácil-de-eliminar-vim-swapfiles-ive-already-recovered-from
Navegue al directorio primero