47 votes

Une récupération plus intelligente de Vim ?

Lorsqu'une session précédente de Vim s'interrompt, vous êtes accueilli par le message "Swap file ... already exists !" pour chacun des fichiers ouverts dans la session précédente.

Pouvez-vous rendre cette invite de récupération de Vim plus intelligente ? (Sans désactiver la récupération !) Plus précisément, je pense à :

  • Si la version permutée ne contient pas de modifications non sauvegardées et que le processus d'édition n'est plus en cours, pouvez-vous faire en sorte que Vim supprime automatiquement le fichier permuté ?
  • Pouvez-vous automatiser le processus suggéré consistant à enregistrer le fichier récupéré sous un nouveau nom, à le fusionner avec le fichier sur le disque, puis à supprimer l'ancien fichier d'échange, de sorte qu'une interaction minimale soit nécessaire ? En particulier lorsque la version swap et la version disque sont les mêmes, tout devrait être automatique.

J'ai découvert le SwapExists autocommand mais je ne sais pas s'il peut aider dans ces tâches.

37voto

Chouser Points 3248

J'ai fait en sorte que vim stocke mes fichiers d'échange dans un seul répertoire local, en ayant ceci dans mon .vimrc :

set directory=~/.vim/swap,.

Entre autres avantages, cela permet de trouver facilement les fichiers d'échange en une seule fois. Maintenant, lorsque mon ordinateur portable perd de l'énergie ou autre et que je redémarre avec un tas de fichiers d'échange qui traînent, j'exécute simplement ma commande cleanswap script :

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

Cela supprimera tous les fichiers d'échange qui sont à jour avec les fichiers réels. Tous ceux qui ne correspondent pas sont affichés dans une fenêtre vimdiff afin que je puisse fusionner mes changements non sauvegardés.

--Chouser

20voto

Jack Senechal Points 710

Je viens de découvrir ça :

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

J'ai copié et collé la commande DiffOrig dans mon fichier .vimrc et cela fonctionne à merveille. Cela facilite grandement la récupération des fichiers de swap. Je ne sais pas pourquoi elle n'est pas incluse par défaut dans VIM.

Voici la commande pour ceux qui sont pressés :

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

16voto

coppit Points 111

La réponse acceptée n'est pas valable pour un cas d'utilisation très important. Disons que vous créez un nouveau tampon et tapez pendant 2 heures sans jamais sauvegarder, puis votre ordinateur portable se plante. Si vous exécutez le script suggéré cela supprimera votre seul et unique enregistrement, le fichier swap .swp. . Je ne suis pas sûr de la bonne solution, mais il semble que la commande diff finisse par comparer le même fichier à lui-même dans ce cas. La version modifiée ci-dessous vérifie ce cas et donne à l'utilisateur la possibilité de sauvegarder le fichier quelque part.

#!/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

4voto

Mark Grimes Points 317

Bon conseil, DiffOrig est parfait. Voici un bash script que j'utilise pour l'exécuter sur chaque fichier swap sous le répertoire courant :

#!/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

La vérification des erreurs et la citation pourraient probablement être améliorées, mais cela a fonctionné jusqu'à présent.

-Mark

0voto

Mario Aguilera Points 408

Je préfère ne pas définir mon répertoire de travail VIM dans le .vimrc. Voici une modification du script de chouser qui copie les fichiers d'échange dans le chemin d'échange à la demande en vérifiant les doublons, puis les réconcilie. Ceci a été écrit à la va-vite, assurez-vous de l'évaluer avant de le mettre en pratique.

#!/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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X