2008-09-15 2 views
46

Когда предыдущая сессия Vim потерпела крах, вас приветствует «файл подкачки ... уже существует!». для каждого файла, который был открыт в предыдущем сеансе.Умное восстановление 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 совершенен. Вот скрипт Баш я использую, чтобы запустить его на каждый файл подкачки в текущем каталоге:

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

Я предпочитаю не устанавливать рабочий каталог VIM в .vimrc. Вот модификация скрипта 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 

, но я не получил время, чтобы должным образом проверить его.

Надеюсь, это поможет.