Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to diff two registers in vim? [duplicate]

Tags:

vim

diff

Possible Duplicate:
(Vim)diff two subroutines in same file

Sometimes I see a block of code I suspect to be identical to another block in the same file, but it's a bit too long for visual inspection and I may just be missing something. I've tried to visually select the block and yank to the the default register, put that register into / (find), but it didn't match even the original block.

Is there a way to select a section, yank it in a register, select another section then diff the two, without creating a bunch of new files? I imagine the diff results opening in a new buffer in a tab or split.

EDIT: My question is basically a duplicate of This one. I found this answer to be the most helpful & closest to what I was looking for. The only thing I'd change is to make it output in Unified format so it looks like the diff output I'm used to (it has more info as well). I suppose this means using a different diff utility.

like image 303
Stop Slandering Monica Cellio Avatar asked Sep 08 '11 17:09

Stop Slandering Monica Cellio


4 Answers

Inspired from my lh#path#strip_common() function:

echo matchstr(@a.'@@'.@b, '^\zs\(.*\)\ze.\{-}@@\1.*$')

will show what is common between registers @a and @b.

You can show more information with:

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

Used with:

:call ShowDiff(@a, @b)
like image 194
Luc Hermitte Avatar answered Nov 14 '22 14:11

Luc Hermitte


You could use the following sequence assuming that the two segments are already in registers, 'a and 'b. Could probably be put into a macro or function.

new
only
put a
diffthis
vnew
put b
diffthis

This creates a new buffer, makes it the only visible buffer, puts 'a into it, sets it up to be diff'd, then opens a new buffer in a vertical split, puts 'b into this split empty buffer and also sets it up to diff. Immediately vim (or gvim) will show the differences.

When done, type :ls to get the list of buffers, use :buffer *N* to return back to the original file and use :bdel! *N* to delete the created buffers (named "[No Name]").

like image 38
Arcege Avatar answered Nov 14 '22 14:11

Arcege


Here's a function to open two new windows side by side, each containing the specified register contents (called as DiffRegs(@a, @1), for instance) and diff them. The new buffers will not be written or modifiable:

" 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()

You can bind those to key combinations of your choice, but if you don't call EndDiffs() after each call to DiffRegs(), you'll run into issues.

like image 3
Michael Foukarakis Avatar answered Nov 14 '22 14:11

Michael Foukarakis


To compare quickly two different parts of a file, you can split the view in two by using:

  • :sp horizontal split

or

  • :vsp vertical split

Once you have splitted the screen, you must use :diffthis in each window to hightlight the differences. (Then :diffoff to leave diff mode)

Then to go back to a single window you can quit one of them with :q or use CTRLwo

like image 1
Xavier T. Avatar answered Nov 14 '22 16:11

Xavier T.