Могу ли я увидеть изменения перед сохранением файла в Vim?

Я использую Vim. Я открываю файл. Я редактирую его и хочу посмотреть, что я отредактировал, прежде чем сохранить его.

Как я могу сделать это в Vim?

15 ответов

Решение

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' команда...

:w !diff % -

Потому что некоторые люди спрашивали об объяснении команды

:w !diff % -

Вот моя попытка написать более подробный ответ:

Я предполагаю, что вы работаете в системе с cat а также echo установлены (например, практически любые GNU/Linux, Mac OS, BSD и другие UNIX-подобные системы).

Вышеприведенная команда работает следующим образом:

  1. Синтаксис для сохранения файла в vim:

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

    :!<command>
    
  3. Внутри оболочки, выданной vim % случается, чтобы указать на текущее имя файла. Вы можете проверить это, выполнив следующее:

    :!echo %
    

    Это должно вывести имя файла (или ошибку, если vim был запущен без имени файла).

    Используя cat, мы также можем вывести содержимое файла:

    :!cat %
    

    Это должно вернуть содержимое файла в его последнее сохраненное состояние или сообщение об ошибке, если оно никогда не было сохранено.

  4. Программа diff умеет читать со стандартного ввода (stdin). На его странице руководства говорится следующее:

    [...] Если ФАЙЛ - '-', прочитайте стандартный ввод. [...]

  5. Выполнение команды save без имени файла, а скорее команды оболочки за ним, заставляет vim записывать содержимое файла в стандартный ввод оболочки вместо сохранения его в физическом файле. Вы можете проверить это, выполнив

    :w !cat
    

    Это должно всегда печатать файлы текущего содержимого (которые были бы записаны в файл вместо этого).

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

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

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

(Затем откройте readonly и закройте vimdiff, используя :qall)

Мне всегда нравятся diffchanges - красиво, просто, работает.

Из 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

Git поддерживает следующую команду

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

сопоставьте его с командой, добавив следующее в ваш ~/.vimrc

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

Сейчас выполняется :GitDiff становится удобной маленькой командой для быстрого отображения различий перед каждым сохранением.

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

Здесь есть плагин, основанный на разных ответах: https://github.com/gangleri/vim-diffsaved

Это обеспечивает :w !diff % - метод и более вовлеченный diffthis один.

Помимо этого, это не только разрешает дерево, но и многое другое (различается между различными контрольными точками отмены). Похож на Gundo.

Исходя из следующего и используйте: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()

Если вы хотите использовать vim для сравнения, как в vimdiff, вы можете сделать что-то вроде этого:

Отредактируйте ваш.vimrc и добавьте:

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

Оттуда вы увидите ваши изменения и можете выйти из режима просмотра различий, используя qall как в vimdiff, нажав F8 в командном режиме. Замените F8 на любую понравившуюся клавишу.

Редактировать: Добавлен -M, чтобы запретить любую модификацию, потому что она не сохраняется.

Я могу порекомендовать плагин Histwin.

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

Кроме того, он отображает список всех ветвей истории отмены и позволяет переключаться между ними.

PS: хотя плагин не отслеживает автоматически моменты в истории редактирования с момента каждого изменения файла, вы можете явно "пометить" момент сохранения файла таким образом, чтобы позже вы могли с ним vimdiff, если хотите. Может быть, это может быть автоматизировано?

Изменения, которые вы только что отредактировали [buffer], то есть те, которые отличаются от последней сохраненной версии (в рабочем каталоге), они могут отличаться от последней версии индекса (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:
  • Gdiff: При фиксации изменений вы видите только 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

AFAIK, для этого предназначена команда «changes»:

      :changes

:помочь изменения

Вы можете заставить 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

а затем выполните:diffthis на каждом сплите

Следуйте вышесказанному, я предлагаю использовать git diff, который мне очень нравится:

:w !git diff  % -
Другие вопросы по тегам