有没有一种方法可以在vim中比较两个寄存器的差异?

12

可能重复:
(Vim)diff两个同一文件中的子程序

有时我看到一段代码,怀疑它与同一文件中的另一段代码相同,但是它太长了,无法通过视觉检查,而且我可能只是漏掉了某些东西。我尝试将该块可视化选择并复制到默认寄存器中,将该寄存器放入/(查找)中,但它甚至没有匹配原始块。

有没有一种方法可以选择一个部分,在一个寄存器中复制它,然后选择另一个部分,再对比两者,而不创建大量新文件? 我想象中的差异结果在一个选项卡或拆分中以新缓冲区的形式打开。

编辑:我的问题基本上是这个的重复。我发现这个答案最有帮助,最接近我所寻找的。唯一需要更改的是使其输出统一格式,以便它看起来像我习惯的差异输出(它还具有更多信息)。我想这意味着使用不同的差异工具。


我不知道有没有内置的方法...也许可以写一个小脚本,类似于:tabnew "ap :vsplit <c-w>l "bp - David Wolever
4个回答

5
受到我lh#path#strip_common()函数的启发:
echo matchstr(@a.'@@'.@b, '^\zs\(.*\)\ze.\{-}@@\1.*$')

将展示寄存器@a@b之间的共同点。

您可以使用以下方法显示更多信息:

function ShowDiff(a,b)
    " I expect neither string to contain '@@'
    let start = matchstr(a:a.'@@'.a:b, '^\zs\(.*\)\ze.\{-}@@\1.*$')
    let end= matchstr(a:a.'@@'.a:b, '^.\{-}\zs\(.*\)\ze@@.\{-}\1$')
    let a = a:a[len(start): -len(end)-1]
    let b = a:b[len(start): -len(end)-1]
    echo "identical beginning: ".strlen(start )." chars -> ".start
    echo "identical ending   : ".strlen(end)." chars -> ".end
    echo "typical to a       : ".strlen(a)." chars -> ".a
    echo "typical to b       : ".strlen(b)." chars -> ".b
endfunction

使用对象:

:call ShowDiff(@a, @b)

5
假设两个片段已经在寄存器中,您可以使用以下序列: 'a'b。 可能可以放入宏或函数中。
new
only
put a
diffthis
vnew
put b
diffthis

这将创建一个新的缓冲区,使其成为唯一可见的缓冲区,将'a放入其中,并设置它进行差异比较,然后在垂直分割中打开一个新的缓冲区,将'b放入此空缓冲区并设置它进行差异比较。立即vim(或gvim)将显示差异。

完成后,键入:ls获取缓冲区列表,使用:buffer *N*返回到原始文件,并使用:bdel! *N*删除已创建的缓冲区(名称为“[No Name]”)。


1
这不会创建新文件,只会在现有的vim会话中创建新缓冲区。缓冲区只有在写入缓冲区时才会变成文件。 - Arcege
你可以使用 setlocal buftype=nofile,这样它就不会被写入或要求保存。 - idbrii
1
请参考这个问题BlockDiff脚本。 - idbrii
@pydave,哇,这跟我的问题完全一样。:) 或许应该将它们合并或做些什么?那里的答案非常好,顺便说一下(被接受的那个)。 - Stop Slandering Monica Cellio
哦,是的,这个答案做了和这个链接 https://dev59.com/2XA65IYBdhLWcg3wzyH8#3621806 一样的事情。谢谢! - Stop Slandering Monica Cellio
显示剩余2条评论

3
这是一个函数,可以打开两个新窗口并排显示,每个窗口都包含指定的寄存器内容(例如调用DiffRegs(@a, @1)),并进行比较。新的缓冲区不会被写入或修改。
" A list for bookkeeping..
let g:diffreg_buffers = []

function! DiffRegs(reg1, reg2)
    " Preserve the unnamed register
    let s:nonamereg = @@
    let @@ = a:reg1
    " new window
    :new
    normal P
    setlocal nomodifiable
    setlocal buftype=nofile
    diffthis
    call add(g:diffreg_buffers, bufnr('%'))

    let @@ = a:reg2
    :vsp +enew
    normal P
    setlocal nomodifiable
    setlocal buftype=nofile
    diffthis
    call add(g:diffreg_buffers, bufnr('%'))

    let @@ = s:nonamereg
endfunction " DiffRegs(reg1, reg2)

" Function to wipe all buffers we're diffing with the function above
function! EndDiffs()
    for buffer in g:diffreg_buffers
        exe ':buffer '  . buffer
        diffoff
        quit
    endfor
    let g:diffreg_buffers = []
endfunction " EndDiffs()

你可以将它们绑定到你选择的按键组合上,但是如果在每次调用DiffRegs()后不调用EndDiffs(),那么就会遇到问题。

哇,这很不错!但是有几个问题:1. 它实际上并没有进行区分,所以如果你将第2-100行复制到一个缓冲区,将第1-99行复制到另一个缓冲区,它会告诉你有98行不同,即它没有考虑到额外的行。2. 运行了大约两次后,似乎不起作用: 在处理DiffRegs函数时检测到错误: 行9: 10行更多 行16: E96:不能比较超过4个缓冲区 10行更多 这非常接近我要找的(包括使用两个新缓冲区等)! - Stop Slandering Monica Cellio
我无法真正解决(1),但这不是 diff(在 vim 中也是如此)的工作方式 - 它绝对考虑了额外行。请参见更新的答案,以解决(2)。 - Michael Foukarakis

1

为了快速比较文件的两个不同部分,您可以使用以下方法将视图分成两个部分:

  • :sp 水平分割

或者

  • :vsp 垂直分割

一旦您拆分了屏幕,您必须在每个窗口中使用 :diffthis 来突出显示差异。(然后使用 :diffoff 退出 diff 模式)

然后要返回到单个窗口,您可以使用 :q 退出其中一个窗口,或使用 CTRLwo


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接