2008-09-15 40 views
46

Khi phiên Vim trước đó bị lỗi, bạn được chào đón với "tập tin hoán đổi ... đã tồn tại!" cho mỗi và mọi tệp đã được mở trong phiên trước đó.Khôi phục thông minh hơn Vim?

Bạn có thể thực hiện lời nhắc khôi phục Vim này thông minh hơn không? (Không tắt tính năng khôi phục!) Cụ thể, tôi đang nghĩ đến:

  • Nếu phiên bản hoán đổi không chứa các thay đổi chưa lưu và quá trình chỉnh sửa không còn chạy nữa, bạn có thể tự động xóa tệp hoán đổi không?
  • Bạn có thể tự động hoá quy trình được đề xuất để lưu tệp đã khôi phục dưới tên mới, hợp nhất tệp đó với tệp trên đĩa và sau đó xóa tệp hoán đổi cũ, sao cho tương tác tối thiểu được yêu cầu? Đặc biệt là khi phiên bản trao đổi và phiên bản đĩa là như nhau, mọi thứ nên được tự động.

Tôi đã phát hiện thấy chế độ tự động SwapExists nhưng tôi không biết liệu nó có thể trợ giúp với các tác vụ này hay không.

+0

Xem http: // valmikam. blogspot.com/2010/09/vim-auto-backup-configuration.html để có giải pháp có thể sao chép được. –

Trả lời

35

Tôi có cửa hàng vim file swap của tôi trong một thư mục địa phương duy nhất, bởi có này trong vimrc của tôi:

set directory=~/.vim/swap,. 

Trong số các lợi ích khác, điều này làm cho các tập tin hoán đổi dễ dàng để tìm tất cả cùng một lúc. Bây giờ khi máy tính xách tay của tôi bị mất điện hoặc bất cứ điều gì và tôi bắt đầu trở lại với một loạt các file swap đặt xung quanh, tôi chỉ cần chạy cleanswap kịch bản của tôi:

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 

này sẽ loại bỏ bất kỳ tập tin hoán đổi được up-to-date với các tệp thực. Bất kỳ thứ gì không khớp sẽ được đưa lên trong cửa sổ vimdiff để tôi có thể hợp nhất các thay đổi chưa được lưu của tôi.

--Chouser

+0

Điều gì sẽ xảy ra nếu bạn chỉnh sửa hai tệp cùng tên, ví dụ trong hai nhánh của một kho SVN –

+1

Khi chỉnh sửa nhiều tệp cùng tên, Vim sẽ quay ngược lại trong bảng chữ cái cho các phần mở rộng (* .swp, *. swo, * .swn, v.v.) Cần lưu ý rằng việc sử dụng phương pháp này sẽ vô hiệu hóa tính năng "trao đổi tệp tồn tại". Vì vậy, bạn sẽ * cần * để sử dụng tập lệnh 'cleanswap' được cung cấp ở trên. – matpie

+0

cũng thấy câu trả lời của @coppit, mà nên lưu bộ đệm không được viết? – alxndr

20

Tôi chỉ phát hiện ra điều này:

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

tôi sao chép và dán lệnh DiffOrig vào tập tin vimrc của tôi và nó hoạt động như một nét duyên dáng. Điều này giúp giảm đáng kể sự phục hồi của các tập tin hoán đổi. Tôi không có ý tưởng tại sao nó không được bao gồm theo mặc định trong VIM.

Dưới đây là các lệnh cho những người đang ở trong một vội vàng:

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

Vì vậy, sau khi tải tập tin hoán đổi, bạn gọi DiffOrig? –

+6

Vâng, vì vậy khi lời nhắc đến bạn nhấn "phục hồi", và sau đó gõ: DiffOrig. Sau đó, khi bạn hoàn tất, bạn lưu bộ đệm. Sau đó, để xóa các tập tin trao đổi (bởi vì nó vẫn sẽ nán lại và lỗi bạn thời gian tiếp theo), bạn chỉ cần gõ: e, mà sẽ trả lời nhắc một lần nữa, và bạn có thể nhấn "xóa". –

+1

Điều này bây giờ được bao gồm với Vim –

4

vĩ đại đầu DiffOrig là hoàn hảo. Đây là tập lệnh bash tôi sử dụng để chạy trên mỗi tệp hoán đổi theo thư mục hiện tại:

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

Có thể sử dụng một số lỗi kiểm tra và trích dẫn nhưng đã làm việc cho đến nay.

+0

Oh lòng tốt của tôi, rất hữu ích và đơn giản. Gắn với 'set directory = ~/.vim/swap, .' và nó hoạt động rất đẹp. –

+0

Mặc dù cần một vài sửa đổi để hỗ trợ các phần mở rộng trao đổi khác, như 'swo | swn' –

16

Câu trả lời được chấp nhận bị vỡ cho một trường hợp sử dụng rất quan trọng. Giả sử bạn tạo bộ đệm mới và nhập trong 2 giờ mà không bao giờ lưu, sau đó máy tính xách tay của bạn bị treo. Nếu bạn chạy tập lệnh được đề xuất , nó sẽ xóa bản ghi một và chỉ của bạn, tệp hoán đổi .swp. Tôi không chắc những gì sửa chữa đúng là, nhưng có vẻ như lệnh diff kết thúc lên so sánh cùng một tập tin cho chính nó trong trường hợp này. Phiên bản được chỉnh sửa bên dưới sẽ kiểm tra trường hợp này và cung cấp cho người dùng cơ hội lưu tệp ở đâu đó.

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

Nhập hai giờ mà không lưu? Bạn nên khắc phục thái độ của mình để tiết kiệm, không chấp nhận kịch bản. Tôi tự động lưu lại khi tôi dừng lại để suy nghĩ. – ZyX

+18

Cho dù đó là hai giờ hoặc hai giây, âm thầm mất dữ liệu là không thể chấp nhận và anh ấy hoàn toàn đúng để sửa chữa nó. Không cần phải hạ mình. – cecilkorik

+0

Nguy hiểm: nếu bạn cố gắng sử dụng tập lệnh này trên các tệp .swp mà không đặt thư mục tệp hoán đổi trung tâm (ví dụ: thay đổi 'SWAP_FILE_DIR' thành' .'), nó sẽ ** xóa ** nhiều tệp của bạn. Vì vậy, không làm điều đó. Hoặc lấy ra '$ SWAP_FILE_DIR/*' trong vòng lặp 'for'. – Dan

0

Tôi không muốn đặt thư mục làm việc VIM của mình trong .vimrc. Đây là một sửa đổi của kịch bản của chouser sao chép các tập tin trao đổi vào đường dẫn trao đổi theo yêu cầu kiểm tra cho các bản sao và sau đó hòa giải chúng. Điều này đã được viết vội vã, hãy chắc chắn để đánh giá nó trước khi đưa nó vào sử dụng thực tế.

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

Tôi có tệp này trên tệp .bashrc của tôi. Tôi muốn cung cấp tín dụng phù hợp cho một phần của mã này nhưng tôi quên nơi tôi đã nhận nó.

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 } 

Tôi chỉ chạy nó trên thư mục gốc của dự án và, NẾU tệp khác, nó sẽ mở ra khác biệt. Sau đó, tập tin cuối cùng được lưu sẽ được lưu giữ. Để làm cho nó hoàn hảo tôi sẽ chỉ cần phải thay thế cuối cùng khác:

else echo "Backup file kept as:" $bakf 

bởi một cái gì đó giống như

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

nhưng tôi đã không nhận được thời gian để kiểm tra nó đúng cách.

Hy vọng điều đó sẽ hữu ích.

Các vấn đề liên quan