在将文件保存到Vim之前可以看到更改吗?


134

我使用Vim。我打开一个文件。我对其进行了编辑,并且想要在保存之前查看自己所做的编辑。

我该如何在Vim中做到这一点?

Answers:


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 % -且数量众多且无法轻易更改.vimrc的盒子上使用vim时,这不是替代方法吗?(只要提供了差异安装即可。)
thomanski 2012年

1
Vim并不是最后的希望。当没有其他可用时将起作用的那个。这是我的主要工作工具。
卢克·赫米特

12
仅提供链接并不是一个真正的答案
Skurpi 2014年

3
混沌的答案是优越的,而在托比亚斯的答案中,解释是完整的。
阿维·科恩

1
您能添加一些内容而不只是一个链接吗?SO指引...
Błażej米哈利克

160
:w !diff % -

4
有没有办法用vimdiff做到这一点?我尝试了:w!vimdiff%-但没有成功。
乔J

14
有人可以解释吗?我不明白发生了什么。我了解您会向diff%指当前打开的文件路径。为什么所有这些都是:w命令的参数?另外,如何-分配给工作缓冲区的内容?这在vim中是自动的,缓冲区的内容(或缓冲区中的特定范围)被分配给shell命令的stdin吗?
内森·华莱士

9
@NathanWallace:这是一个参数,:w因为我们正在将文件写入命令(在上stdin)。在命令中,-告诉它从中读取stdin
混乱

14
或使用:w !git diff % -了彩色版本,如果你已经安装的git!
Dergachev

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中执行shell命令的语法是:

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

    :!echo %
    

    这应该输出文件名(如果在没有文件名的情况下运行vim,则会输出错误)。

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

    :!cat %
    

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

  4. 程序diff可以从标准输入(stdin)中读取。其手册页指出以下内容:

    [...]如果FILE为'-',则读取标准输入。[...]

  5. 执行不带文件名而是紧随其后的shell命令的save命令会使vim将文件内容写入shell的stdin中,而不是将其保存在物理文件中。您可以通过执行

    :w !cat
    

    这应该始终打印文件的当前内容(该内容将被写入文件中)。

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

知道这一点也可以使用vimdiff将文件进行类似的比较-这只是您不希望这样做的想法:

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

(然后使用来打开只读并关闭vimdiff :qall


使用vimdiff的更合理的方法是创建一个包含以下内容的shell脚本vim - -c ":vnew $1 |windo diffthis",使其成为可执行文件,例如将其保存在PATH中vimdiffWithStdin,然后与vim中的以下命令进行比较::w !vimdiffWithStdin %
Tobias Heinicke 2014年

甚至更简单::w !vimdiff % /dev/stdin。我不知道Windows是否存在类似的技巧。
deft_code 2015年


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

检查完差异后,如何恢复正常?
Niko

您可以通过用command代替command来摆脱if子句!(请参阅:h E174)
符合

@NikoBellic首先使用“:q”关闭“旧”窗口(标记为暂存缓冲区)。您可以在正常模式下通过按两次ctrl-W来在窗口之间进行切换。然后,您可以通过编写: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一起使用。我将它与perforce一起使用。



1

我可以推荐histwin插件。

尽管它不会与文件的当前保存版本有所不同(与其他答案一样),但是它可以vimdiff自您开始edting以来的更改,甚至可以按顺序重放更改。区别显示您是否进行中间保存。

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

PS:尽管自从每个文件更改以来,插件都不会自动跟踪编辑历史记录中的时刻,但是您可以显式“标记”保存文件的时刻,以便以后可以使用该文件进行vimdiff。也许这可以自动化吗?


1

如果要像在vimdiff中一样使用vim进行比较,则可以执行以下操作:

编辑您的.vimrc并添加:

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

从那里开始,您将看到qall所做的更改,并且可以像在vimdiff中一样通过在命令模式下按F8 退出diff视图。用任意键替换F8。

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


该命令开始为我工作,它并排显示diff。但是,一旦我尝试编辑任何内容,vim窗口就会发疯。我开始打字,在屏幕两边的vim文字后面出现一个bash提示。因此它似乎显示了差异,但随后vim崩溃了。此外,我收到此错误的Vim: Error reading input, exiting...任何提示,这里出了什么问题?
Trevor

@Trevor:我只能猜测出什么问题了。像这样进行差异化时,确实不节省任何修改。因此,我添加了“ -M”参数以完全禁止使用它。抱歉。
Tobias Heinicke 2014年

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

然后在每个分割上执行:diffthis


0

您刚刚编辑的更改[ 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与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
一个人可能只制作了一张要执行的地图:Gdiff如果可能,则执行(否则不是Git项目),然后执行:vimdiff。用try-catch-endtry。但是:DiffWithSaved在Git项目中却缺乏这种方式。
XopiGarcía

-2

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

:w !git diff  % -
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.