2008-09-15 50 views
46

當以前的Vim會話崩潰時,您會收到「Swap file ... already exists!對於前一個會話中打開的每個文件。更智能的Vim恢復?

你可以讓這個Vim恢復提示更聰明嗎? (!沒有切斷的情況恢復)具體來說,我在想:

  • 如果換版本不包含未保存的更改和編輯過程中不再運行,則可以使Vim自動刪除交換文件?
  • 是否可以自動執行建議的以新名稱保存恢復文件的過程,將它與磁盤上的文件合併,然後刪除舊的交換文件,以便實現最少的交互?特別是當交換版本和磁盤版本相同時,一切都應該是自動的。

我發現了SwapExists自動命令,但我不知道它是否可以幫助完成這些任務。

+0

請訪問http:// valmikam。 blogspot.com/2010/09/vim-auto-backup-configuration.html以獲得可複製的解決方案。 – 2011-08-28 01:03:34

回答

35

我有vim的商城我的交換文件在一個單一的本地目錄,在我的.vimrc有這樣的:

set directory=~/.vim/swap,. 

除了其它的優點,這使得交換文件容易找到的一次。 現在,當我的筆記本電腦斷電或什麼,我開始背了一堆的交換文件奠定左右,我只是跑我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 

這將刪除是跟上時代的任何交換文件與真實的文件。任何不匹配的東西都會出現在vimdiff窗口中,以便我可以合併未保存的更改。

--Chouser

+0

如果您編輯兩個同名文件,例如在SVN存儲庫的兩個分支中,該怎麼辦? – 2008-09-15 18:44:46

+1

當編輯多個具有相同名稱的文件時,Vim將在字母表中向後倒換擴展名(* .swp,*)。 swo,* .swn等)。 應該注意的是,使用此方法禁用「交換文件存在」功能。所以你需要*使用上面提供的`cleanswap`腳本。 – matpie 2009-02-05 22:20:39

+0

也可以通過@coppit看到答案,它應該保存未寫入的緩衝區? – alxndr 2013-02-10 06:34:16

20

我剛剛發現這一點:

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

我複製並粘貼DiffOrig命令放到我的.vimrc文件中,它就像一個魅力。這大大簡化了交換文件的恢復。我不知道爲什麼它在默認情況下不包含在VIM中。

這裏的命令對於那些誰是着急:

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

大尖DiffOrig是完美的。這裏是一個bash腳本我使用到當前目錄下的每個交換文件運行它:

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

大概可以多用一些錯誤檢查和報價,但至今工作。

16

被接受的答案是一個非常重要的用例。假設您創建了一個新的緩衝區並輸入了2個小時而沒有保存,那麼您的筆記本電腦就會崩潰。如果您運行建議的腳本它將刪除您的唯一記錄,即.swp交換文件。我不知道什麼是正確的解決方案,但它看起來像diff命令最終比較相同的文件本身在這種情況下。下面的編輯版本檢查這種情況,併爲用戶提供了將文件保存在某處的機會。

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

我更喜歡不在.vimrc中設置我的VIM工作目錄。以下是Chouser腳本的一種修改,可以根據需要將交換文件複製到交換路徑中,以檢查重複項,然後進行協調。這是寫的急,確保在實際使用前評估它。

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

我在我的.bashrc文件中有這個。我想給這段代碼的一部分給予適當的評價,但我忘記了從哪裏得到的。

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 } 

我只是在我的項目的根目錄上運行它,如果文件不同,它會打開vim diff。然後,要保存的最後一個文件將被保留。爲了讓完美的我只需要更換最後還有:

else echo "Backup file kept as:" $bakf 

通過類似

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

,但我沒有時間好好測試它。

希望它有幫助。