2008-09-15 18 views
46

Kiedy poprzednia sesja Vima uległa awarii, powitano "Plik wymiany ... już istnieje!" dla każdego pliku otwartego w poprzedniej sesji.Lepsze odzyskiwanie Vima?

Czy sprawisz, że zachęta do odtwarzania Vim będzie bardziej inteligentna? (! Bez wyłączenie odzysku) Konkretnie mam na myśli:

  • Jeśli wersja zamienione nie zawiera niezapisane zmiany i proces edycji już nie działa, można dokonać Vim automatycznie usunąć plik wymiany?
  • Czy można zautomatyzować sugerowany proces zapisywania odzyskanego pliku pod nową nazwą, scalając go z plikiem na dysku, a następnie usuwając stary plik wymiany, aby minimalna interakcja była wymagana? Zwłaszcza gdy wersja swap i wersja dysku są takie same, wszystko powinno być automatyczne.

Odkryłem automatyczną komendę SwapExists, ale nie wiem, czy może pomóc w tych zadaniach.

+0

Zobacz http: // valmikam. blogspot.com/2010/09/vim-auto-backup-configuration.html dla kopiowalnego rozwiązania. –

Odpowiedz

35

muszę przechowywać odnośniki vim moich plików wymiany w jednym katalogu lokalnego, poprzez to w moim .vimrc:

set directory=~/.vim/swap,. 

Wśród innych korzyści, to sprawia, że ​​konwersja plików łatwo znaleźć wszystkie naraz. Teraz kiedy mój laptop traci moc lub cokolwiek i zacznę z powrotem z wieloma plikami swapowych r dookoła, po prostu uruchomić mój cleanswap skrypt:

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 

To usunie żadnych plików wymiany, które są up-to-date z prawdziwymi plikami. Wszystkie, które nie pasują, są wyświetlane w oknie vimdiff, więc mogę scalić moje niezapisane zmiany.

--Chouser

+0

Co jeśli edytujesz dwa pliki o tej samej nazwie, na przykład w dwóch gałęziach repozytorium SVN –

+1

Podczas edycji więcej niż jednego pliku o tej samej nazwie, Vim cofnie się w alfabecie dla rozszerzeń (* .swp, *. swo, * .swn, itp.). Należy zauważyć, że za pomocą tej metody wyłączono funkcję "plik wymiany istnieje". Będziesz więc * potrzebował *, aby użyć skryptu 'cleanswap' podanego powyżej. – matpie

+0

zobacz także odpowiedź @coppit, która powinna zapisywać niepisane bufory? – alxndr

20

Właśnie odkryłem to:

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

skopiowane i wklejone polecenie DiffOrig w moim pliku .vimrc i działa jak czar. Znacznie ułatwia to odzyskiwanie plików wymiany. Nie mam pojęcia, dlaczego nie jest ona domyślnie włączona w VIM.

Oto polecenia dla tych, którzy są w pośpiechu:

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

Więc po załadowaniu pliku wymiany wywołujemy DiffOrig? –

+6

Tak, więc gdy pojawi się monit, klikniesz "odzysk", a następnie wpisz: DiffOrig. Następnie, gdy skończysz, zapisujesz bufor. Następnie, aby usunąć plik wymiany (ponieważ nadal będzie się utrzymywał i następnym razem będziesz robił błędy), wystarczy wpisać: e, który ponownie wyświetli monit, a możesz nacisnąć "usuń". –

+1

To jest teraz dołączone do Vim –

4

Świetna końcówka DiffOrig jest doskonały. Tutaj jest skrypt bash używam go uruchomić na każdym pliku wymiany w bieżącym katalogu:

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

Prawdopodobnie mogłby więcej sprawdzanie błędów i powołując ale pracował do tej pory.

+0

O mój Boże, tak użyteczny i prosty. Związany z 'set directory = ~/.vim/swap, .' i to działa pięknie. –

+0

Mimo że wymaga kilku modyfikacji, aby obsługiwać inne rozszerzenia wymiany, np. 'Swo | swn' –

16

Przyjęta odpowiedź zostaje odrzucona z powodu bardzo ważnego przypadku użycia. Załóżmy, że tworzysz nowy bufor i piszesz przez 2 godziny bez żadnego oszczędzania, a potem zawiesza się twój laptop. Jeśli uruchomisz sugerowany skrypt , usuniesz swój jedyny rekord, plik wymiany sws.. Nie jestem pewien, jaka jest właściwa poprawka, ale wygląda na to, że polecenie diff kończy porównywanie tego samego pliku z samym sobą w tym przypadku. Edytowana wersja poniżej sprawdza, czy jest to przypadek i daje użytkownikowi szansę na zapisanie pliku w dowolnym miejscu.

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

Wpisz dwie godziny bez zapisywania? Powinieneś naprawić swoje nastawienie do zapisywania, a nie akceptowanego skryptu. Oszczędzam automatycznie, gdy zatrzymam się na myślenie. – ZyX

+18

Bez względu na to, czy chodzi o dwie godziny czy dwie sekundy, utrata danych w trybie cichym jest nie do zaakceptowania i miał absolutną rację, aby to naprawić. Nie musisz być protekcjonalny. – cecilkorik

+0

Niebezpieczeństwo: jeśli spróbujesz użyć tego skryptu w plikach .swp bez ustawienia centralnego katalogu wymiany plików (na przykład, zmieniając 'SWAP_FILE_DIR' na' .'), ** usunie ** wiele twoich plików. Więc nie rób tego. Lub wyjmij '$ SWAP_FILE_DIR/*' w pętli 'for'. – Dan

0

Wolę nie ustawiać mojego katalogu roboczego VIM w .vimrc. Oto modyfikacja skryptu chouser, który kopiuje pliki wymiany do ścieżki wymiany na żądanie sprawdzając duplikaty, a następnie je pojedna. Zostało to napisane pośpiesznie, upewnij się, że ocenisz je przed wprowadzeniem do praktycznego użytku.

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

Mam to na moim pliku .bashrc. Chciałbym wyrazić odpowiednie uznanie dla części tego kodu, ale zapomniałem skąd go wziąłem.

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 } 

Po prostu uruchamiam to w katalogu głównym mojego projektu i, jeśli plik jest inny, otwiera vim diff. Następnie zostanie zachowany ostatni zapisany plik. Aby uczynić go idealnym byłoby po prostu trzeba zastąpić ostatni else:

else echo "Backup file kept as:" $bakf 

coś jak

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

ale nie miałem czasu, aby odpowiednio go przetestować.

Mam nadzieję, że to pomaga.