Чи можу я побачити зміни, перш ніж зберегти файл у Vim?


135

Я використовую Vim. Відкриваю файл. Я редагую його і хочу побачити, що я редагував, перш ніж зберегти його.

Як я можу це зробити у Vim?

Відповіді:


57

http://vim.wikia.com/wiki/Diff_current_buffer_and_the_original_file

Ось функція та команда, щоб побачити різницю між відредагованим файлом та його немодифікованою версією у файловій системі. Просто покладіть це у свій vimrc або у каталог плагінів, відкрийте файл, внесіть деякі зміни, не зберігаючи їх, і зробіть :DiffSaved.

function! s:DiffWithSaved()
  let filetype=&ft
  diffthis
  vnew | r # | normal! 1Gdd
  diffthis
  exe "setlocal bt=nofile bh=wipe nobl noswf ro ft=" . filetype
endfunction
com! DiffSaved call s:DiffWithSaved()

Для виходу з розрізнення ви можете скористатися :diffoffкомандою.

Нижче наведена аналогічна функція, пристосована для імітації 'cvs diff'команди ...


7
@ luc-hermitte Не є альтернативою :w !diff % -вищої версії, коли ви використовуєте vim на постійній та великій кількості коробок, які ви не можете легко змінити .vimrc для? (За умови, що вони встановлені
різними

1
Вім - не інструмент останньої надії. Той, який працюватиме, коли нічого іншого немає. Це мій головний робочий інструмент.
Люк Ермітт

12
Просто надання посилання насправді не є відповіддю
Skurpi

3
Відповідь Хаоса є вищою, і у відповіді Тобіаса пояснення є повним.
Аві Коен

1
Чи можете ви додати трохи вмісту, а не лише посилання? Так вказівки ...
Błażej Michalik

160
:w !diff % -

4
Чи є спосіб зробити це з vimdiff? Я спробував: w! Vimdiff% - але без успіху.
Джо Дж.

14
Хтось може це пояснити? Я не розумію, що відбувається. Я розумію, що ви це обстрілюєте diff. %відноситься до відкритого поточного файлового шляху. Чому все це є аргументом для :wкоманди? Крім того, як -призначається вміст робочого буфера? Це автоматично в vim, що вміст буфера (або, можливо, певний діапазон у буфері) присвоюється stdin для команд оболонки?
Натан Уоллес

9
@NathanWallace: Це аргумент :wтому, що ми пишемо файл у команду (on stdin). У команді -вказує прочитати з stdin.
хаос

14
Або використовувати :w !git diff % -для кольорової версії, якщо у вас встановлений git!
Дергачов

5
@Dergachev Я отримую помилку, fatal: bad flag '-' used after filenameколи бігаю :w !git diff % -.
Відтінки сірого

100

Тому що дехто запитав про пояснення команди

:w !diff % -

Ось моя спроба написати більш детальну відповідь:

Я припускаю , що ви працюєте в системі з catі echoвстановлено (наприклад , практично будь-який GNU / Linux, Mac OS, BSD та інших UNIX-подібних систем).

Наведена вище команда працює наступним чином:

  1. Синтаксис збереження файлу у vim:

    :w <filename>
    
  2. Синтаксис для виконання команди оболонки в vim є:

    :!<command>
    
  3. Всередині середовища оболонки, виданого vim, %трапляється вказівка на поточне ім'я файлу. Ви можете підтвердити це, виконавши наступне:

    :!echo %
    

    Це повинно вивести ім'я файлу (або помилку, якщо vim запускався без імені файлу).

    Використовуючи cat, ми також можемо вивести вміст файлу:

    :!cat %
    

    Це повинно повернути вміст файлів у останньому збереженому стані або помилку, якщо він ніколи не був збережений.

  4. Програма відрізняється здатністю читати зі стандартного вводу (stdin). На його довідковій сторінці зазначено наступне:

    [...] Якщо FILE "-", прочитайте стандартний ввід. [...]

  5. Виконання команди збереження без імені файлу, а скоріше команди оболонки за нею викликає vim записувати вміст файлів у stdin оболонки замість збереження у фізичному файлі. Ви можете перевірити це, виконавши

    :w !cat
    

    Це завжди має друкувати файли поточного вмісту (який був би записаний натомість у файл).

Збирання його разом (або tl; dr): файл "зберігається" в stdin, diff працює з іменем файлу та stdin як вхідним.

Знаючи це, ви також можете порівняти файли з vimdiff, що робить щось подібне - це лише ідея, яку ви не хочете робити цього:

:w !cat > /tmp/tempFile && vimdiff /tmp/tempFile % && rm /tmp/tempFile

(Потім відкрийте лише для читання та закрийте vimdiff за допомогою :qall)


Більш розумним підходом до використання vimdiff було б створення скрипту оболонки, що містить наступне vim - -c ":vnew $1 |windo diffthis", зробивши його виконуваним, збереження його в PATH, наприклад, vimdiffWithStdinа потім порівняння зі такою командою в vim::w !vimdiffWithStdin %
Tobias Heinicke

Ще простіше: :w !vimdiff % /dev/stdin. Я не знаю, чи існує подібний трюк для Windows.
deft_code

12

Мені завжди подобаються відмінності - приємно, просто, працює.


Це працює на ЛОТУ краще, ніж більш високооцінені варіанти. Це дає можливість перемикати його.
Стівен Лу

1
@StevenLu - Мех ... що ти можеш зробити? У будь-якому випадку, радий, що вам це подобається. Я вважаю це більш практичним, ніж інший підхід.
Грак

Мені, я другий @Steven, ваші запропоновані зміни є відмінними. Дякую!
AS

Це також можна встановити як плагін того ж розробника: github.com/jmcantrell/vim-diffchanges
Sumanth Lingappa

приємний плагін, але він не видаляє патч, який він створює після цього? Редагувати: Моє погано! Це робить. Я використовував це неправильно. Мені довелося користуватися :DiffChangesDiffToggle.
адерхокс

10

від vimrc_example.vim:

" Convenient command to see the difference between the current buffer and the
" file it was loaded from, thus the changes you made.
if !exists(":DiffOrig")
  command DiffOrig vert new | set bt=nofile | r # | 0d_ | diffthis
          \ | wincmd p | diffthis
endif

... як це зафіксовано на vimdoc.sourceforge.net/htmldoc/diff.html#:DiffOrig . Перевага над цим в w !diff % -тому , що вона працює над віддаленими джерелами теж (наприклад: vim sftp://example.com/foo.txt)
Lekensteyn

1
Мені це подобається більше, тому що ми бачимо різницю безпосередньо в самому буфері vim, а не в терміналі
Niko Bellic

Як ви повернетесь до норми, як тільки закінчите вивчення відмінностей?
Ніко Белік

Ви можете позбутися пункту if, замінивши команду командою! (див .: h E174)
elig

@NikoBellic Спочатку закрийте "старе" вікно (позначене як буфер нуля) символом ": q". Ви можете переходити між вікнами, натиснувши ctrl-W двічі, перебуваючи у звичайному режимі. Тоді ви можете вимкнути diff, написавши: diffoff
brunch875

2

Джерело: та команда DIFF

function! s:diff()
    let tmpa = tempname()
    let tmpb = tempname()
    earlier 100h
    exec 'w '.tmpa
    later 100h
    exec 'w '.tmpb
    update
    exec 'tabnew '.tmpa
    diffthis
    vert split
    exec 'edit '.tmpb
    diffthis
endfunction
command! -nargs=0 DIFF call <SID>diff()

2

Не зовсім те, що ви шукаєте, але SCMDiff.vim - це справді круто. Одне натискання клавіші, і воно різко підкреслює ваш поточний файл з переглядом голови в репо-контролі джерела. Це призначено для роботи з багатьма SCMS. Я використовую це з перфорсом.


2

Тут є плагін, заснований на різних відповідях: https://github.com/gangleri/vim-diffsaved

Він надає :w !diff % -метод та більше залучений diffthis.

Окрім того, це скасування заборони дозволяє і це, але також набагато більше (відрізняється між різними контрольними пунктами скасування). Схожий на Gundo .


1

Я можу порекомендувати плагін histwin .

Хоча він не відрізняється від поточної збереженої версії файлу (як і інші відповіді), він може зменшити зміни, коли ви почали редагувати , і навіть повторно змінити їх у порядку. Різниця показує, якщо ви заощаджуєте проміжно.

Крім того, він відображає список усіх гілок історії скасування та дозволяє перемикатися або відрізнятися між ними.

PS: Хоча плагін автоматично не відстежує моменти в історії редагування після кожної зміни файлу, ви можете явно «помітити» момент, коли ви збережете файл, таким чином, щоб ви могли згодом з ним змінити, якщо цього хочете. Можливо, це можна було автоматизувати?


1

Якщо ви хочете використовувати vim для порівняння, як у vimdiff, ви можете зробити щось подібне:

Відредагуйте .vimrc та додайте:

nmap <F8> :w !vim -M -R - -c ":vnew % \| windo diffthis"<CR><CR>

З цього моменту ви побачите свої зміни та можете вийти з перегляду розгляду, використовуючи qall як in vimdiff, натиснувши F8 в командному режимі. Замініть F8 будь-яким вашим ключем.

Редагувати: Додано -М, щоб заборонити будь-які зміни, оскільки це не збереження.


Ця команда починає працювати для мене, вона показує мені різну сторону. Однак, як тільки я спробую і відредагувати все, вім-вікно зійде з розуму. Я починаю набирати текст і отримую підказку за словами in vim з обох боків екрана. Тож, здається, відображається різниця, але потім vim збоїв. Крім того, я отримую з цією помилкою Vim: Error reading input, exiting...будь-які ідеї, що тут не так?
Тревор

@Trevor: Я міг лише здогадуватися, у чому проблеми. Дійсно не врятувати будь-які модифікації, відрізняючись від цього. Отже, я додав параметр "-M", щоб повністю його заборонити. Вибачте.
Тобіас Хайнікке

1

git підтримує таку команду

:w !git diff --no-index -- % -

відобразіть його в команду, додавши до вашого ~ / .vimrc наступне

command GitDiff execute "w !git diff --no-index -- % -"

Тепер виконання :GitDiffстає зручною маленькою командою для швидкого показу розрізнень перед кожним збереженням.


0

Ви можете змусити vim створити останню резервну копію та оригінальну резервну копію за допомогою:

:set backup
:set patchmode=.orig 

Після цього ви можете відкрити їх у розкол:

:vsp %:p~ or :vsp %:.orig

І звідти зробіть:

:vimdiff in each buffer

Якщо ви мертвий, що не залишився, але хочете vimdiff, ви також можете зробити:

ggVGy    # copy the whole buffer
:vnew    # open a split
CTRL-W w # switch to it
shift-P  # paste at start

а потім зробіть: різниться на кожен розкол


0

Зміни, які ви щойно відредагували [ буфер ], тобто ті, що відрізняються від останньої збереженої версії (у робочому режимі), вони можуть відрізнятися від останньої версії індексу ( Git ). Я зіставив обидва:

" Find diff inbetween currrent buffer and ... A{last index version} vs B{last saved version in working directory}
"  - A{last index version}: the file as you last commited it
    " git diff to vimdiff against the index version of the file:
    nnoremap <leader>gd <Esc>:Gvdiff<CR><Esc>:echo "currentBuffer vs lastIndexVersion (last commited)"<CR>
"  - B{last saved version in working directory}: the file you last :w,
"   not neccesary commited it (not commited for sure if it is in NO git project)
    " https://vim.fandom.com/wiki/Diff_current_buffer_and_the_original_file
    nnoremap <leader>gd2 <Esc>:DiffSaved<CR><Esc>:echo "currentBuffer vs lastSaved (not neccesary equal to last commited)"<CR>
    function! s:DiffWithSaved()
        let filetype=&ft
        diffthis
        vnew | r # | normal! 1Gdd
        diffthis
        exe "setlocal bt=nofile bh=wipe nobl noswf ro ft=" . filetype
    endfunction
    com! DiffSaved call s:DiffWithSaved()

Приклад vimdiff vs Gdiff.

  • vimdiff: : vimdiff
  • Gdiff: Гдіфф Здійснюючи зміни, ви бачите лише Gdiff, що може або може мати ті самі зміни, що і vimdiff: здійснюючи зміни, ви бачите лише Gdiff, що може, або НЕ може мати такі самі зміни, як vimdiff

Крім того, до простого vimdiffфайлу омоніму в іншому шляху:

    " vimdiff homonym file 
   nnoremap <leader>dh  <Esc>:vsplit %:p:h/../__/%:t <bar> :windo diffthis<Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left>
        "E.g."$ vim /path01/proj02_pg064/processorder.php
        ":vsplit %:p:h/../proj01_pg05/%:t | :windo diffthis

1
Можна просто зробити 1 карту, яка виконує: a, Gdiffякщо можливо, інакше (наприклад, не проект Git), то виконайте a :vimdiff. З try-catch-endtry. Але цього шляху :DiffWithSavedв проекті Git бракує.
Xopi García

-2

Дотримуйтесь вищесказаного, я використовую git diff, який мені дуже подобається:

:w !git diff  % -
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.