153

我使用 Vim。我打开一个文件。我编辑它,我想在保存之前查看我编辑的内容。

我怎样才能在 Vim 中做到这一点?

4

14 回答 14

181
:w !diff % -
于 2009-04-14T20:45:58.573 回答
120

因为有人问关于命令的解释

:w !diff % -

这是我尝试写一个更详细的答案:

我假设您正在使用catecho安装了一个系统(例如几乎所有 GNU/Linux、Mac OS、BSD 和其他类 UNIX 系统)。

上述命令的工作原理如下:

  1. 在 vim 中保存文件的语法是:

    :w <filename>
    
  2. 在 vim 中执行 shell 命令的语法是:

    :!<command>
    
  3. vim发出的shell环境里面%恰好指向当前文件名。您可以通过执行以下操作来验证这一点:

    :!echo %
    

    这应该输出文件名(或错误,如果 vim 运行时没有文件名)。

    使用 cat 我们还可以输出文件的内容:

    :!cat %
    

    这应该返回上次保存状态的文件内容,如果从未保存过,则返回错误。

  4. 程序 diff 能够从标准输入(stdin)读取。它的手册页说明了以下内容:

    [...] 如果 FILE 是“-”,则读取标准输入。[...]

  5. 执行不带文件名而是在其后面的 shell 命令的 save 命令会导致 vim 将文件内容写入 shell 的标准输入,而不是将其保存在物理文件中。您可以通过执行来验证这一点

    :w !cat
    

    这应该总是打印文件的当前内容(这将被写入文件)。

把它放在一起(或tl;dr):文件被“保存”到stdin,diff以文件名和stdin作为输入运行。

知道这一点也可以将文件与 vimdiff 做这样的事情进行比较——这只是一个你不想这样做的想法:

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

(然后打开 readonly 并使用关闭 vimdiff :qall

于 2014-03-12T18:27:48.067 回答
60

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'命令...

于 2009-04-14T20:46:31.427 回答
14

我一直很喜欢diffchanges - 很好,很简单,很有效。

于 2009-04-14T21:24:21.040 回答
11

来自 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
于 2009-09-05T22:15:40.533 回答
3

git 支持以下命令

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

通过将以下内容添加到 ~/.vimrc 将其映射到命令

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

现在执行:GitDiff变成了一个方便的小命令,可以在每次保存之前快速显示差异。

于 2019-11-05T18:55:24.113 回答
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()
于 2009-04-14T20:54:25.200 回答
2

不完全是你要找的,但SCMDiff.vim真的很酷。一个按键,它会在源代码控制 repo 中突出显示您当前的文件与头部修订。它适用于许多 SCMS。我将它与 perforce 一起使用。

于 2010-01-19T18:24:37.357 回答
2

有一个插件,基于不同的答案在这里:https ://github.com/gangleri/vim-diffsaved

它提供了:w !diff % -方法和更多涉及的方法diffthis

除了那个undotree 还允许这样做,但还有更多(不同撤消检查点之间的差异)。类似于Gundo

于 2014-12-18T00:56:23.333 回答
1

我可以推荐histwin插件。

虽然它与文件的当前保存版本没有差异(就像其他答案一样),但它可以vimdiff 更改,因为您开始 edting,甚至可以按顺序重播您的更改。如果您中间保存,差异就会显示出来。

此外,它显示所有撤消历史分支的列表,并允许您在它们之间切换或区分。

PS:虽然插件不会在每次文件更改后自动跟踪编辑历史记录中的时刻,但您可以明确地“标记”保存文件的时刻,以便以后可以根据需要使用它进行 vimdiff。也许这可以自动化?

于 2010-09-23T01:27:03.057 回答
1

如果你想像 vimdiff 那样使用 vim 进行比较,你可以这样做:

编辑您的 .vimrc 并添加:

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

从那里您将看到您的更改,并且可以qall通过在命令模式下按 F8 在 vi​​mdiff 中使用 like 退出差异视图。用您喜欢的任何键替换 F8。

编辑:添加 -M 以禁止任何修改,因为它不保存。

于 2014-03-12T19:01:49.030 回答
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

然后在每次拆分时执行 :diffthis

于 2020-02-24T07:05:11.680 回答
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 与 Gdiff 的示例。

  • vimdiff: :vimdiff
  • Gdiff: 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
于 2020-05-14T20:23:28.483 回答
-2

按照上面的建议,我使用我非常喜欢的 git diff:

:w !git diff  % -
于 2017-01-25T12:55:31.907 回答