Selective diff with vim?

25 views
Skip to first unread message

Richard Hartmann

unread,
Jan 29, 2008, 4:21:30 PM1/29/08
to v...@vim.org
Hi all,

is there a way to define regions of the buffers I want to diff and
completely ignore all other regions of the buffers? I often merge code
files that share a similar, yet different function where the rest of the
files are vastly different. This clutters the UI at best and completely
disorients diff at worst, creating useless diff views that hurt more
than they help.


Any help appreciated :)
Richard

Richard Hartmann

unread,
Jan 29, 2008, 4:27:34 PM1/29/08
to v...@vim.org
PS: Alternatively, a way to tell vim to consider two specific lines as
two equivalent parts, i.e. setting markers in both buffers that help
diff to align the code correctly would help a lot, as well.

Tim Chase

unread,
Jan 29, 2008, 5:03:51 PM1/29/08
to vim...@googlegroups.com
> PS: Alternatively, a way to tell vim to consider two specific lines as
> two equivalent parts, i.e. setting markers in both buffers that help
> diff to align the code correctly would help a lot, as well.


I've done the inverse to do something similar to what you describe:

+==============+=============+
| [1] | [2] |
+==============+=============+
| [3] | [4] |
+==============+=============+


In window 3 and 4, I have the two source files. I then copy
extracts that I want to compare into the window above them. I
can then diff windows #1 and #2.

It's not an ideal solution, but you can use mappings to ease some
of the repetitive nature of it, if you do it frequently.

-tim


Reckoner

unread,
Jan 29, 2008, 7:47:50 PM1/29/08
to vim_use
how do you diff the two buffers as you describe?

thanks.

Tony Mechelynck

unread,
Jan 29, 2008, 8:08:04 PM1/29/08
to vim...@googlegroups.com
Reckoner wrote:
> how do you diff the two buffers as you describe?

Example: diff lines 7 to 45 of one window with line 250 to 300 of the other

The following is an example; most steps can be done in a different manner

Start with windows 3 and 4 only (^W below means "hit Ctrl-W")

1^Ww
go to first window
:7
go to line 7
V
set linewise visual
38j
go 38 lines down, to line 45
y
yank the selected lines
:abo new
split horizontally, creating an empty buffer
p
put
3^Ww
go to what is now the 3rd (last) window
:250
V
50j
y
:abo new
p
the same, mutatis mutandis
:diffthis
there will be a diff involving the current buffer
1^Ww
go to the other buffer to be diff'd
:diffthis
tell Vim the diff involves also this buffer


Best regards,
Tony.
--
"Avoid revolution or expect to get shot. Mother and I will grieve, but
we will gladly buy a dinner for the National Guardsman who shot you."
-- Dr. Paul Williamson, father of a Kent State student

Yegappan Lakshmanan

unread,
Jan 30, 2008, 1:46:45 AM1/30/08
to vim...@googlegroups.com
Hi,

On Jan 29, 2008 4:47 PM, Reckoner <reck...@gmail.com> wrote:
>
> how do you diff the two buffers as you describe?
>

I use the following functions. Copy them to the ~/.vim/plugin/diff.vim
file.

-------------------------------------------------------------------------
" Function to copy a selected range of lines into a new window and set
" diff for the new window
function! Diff_Range() range
let fname = fnamemodify(expand('%'), ':p')
exe a:firstline . ',' . a:lastline . 'yank'
new
0put ='# File: ' . fname
put ='# Start line: ' . a:firstline . ', End line: ' . a:lastline
put ='----------------------------------------'
put
normal! gg
set nomodified
diffthis
wincmd p
endfunction
command! -range -nargs=0 DiffRange <line1>,<line2>call Diff_Range()
command! -nargs=0 DiffBlock normal! VaB:call Diff_Range()<CR>
--------------------------------------------------------------------------------------------------------------

You can now use the ":DiffBlock" command to select a block and open a
new window with the selected block and set the diff option. You can also
use the ":DiffRange" command to select a range of lines.

- Yegappan

A.Politz

unread,
Jan 30, 2008, 10:46:33 AM1/30/08
to vim...@googlegroups.com
Richard Hartmann wrote:

You could use 'diffexpr' and tamper with the diffoutput. Suppose we
made clear, that we want to diff lines 10-20 in file1 and lines
20-30 in file2, probably by some commands executed before. First we
make only a diff of this lines. Second we adjust the linenumbers in
the diff (v:fname_out).

----------%<---------------

func! D() abort
"Pretend that '!diff' is working, see src/diff.c:690
let in =readfile(v:fname_in)
if len(in) == 1 && in[0] =~ '^line[12]$'
call writefile([ "1c1"],v:fname_out)
return
endif
"let in_range = [ 10,20 ]
"let new_range = [ 20,30 ]

"Diff lines 10-20 from file_in against lines 20-30 from file_new
call writefile(readfile(v:fname_in)[9:19],v:fname_in)
call writefile(readfile(v:fname_new)[19:29],v:fname_new)
silent exec '!diff -a '.v:fname_in.' '.v:fname_new.' > '.v:fname_out

let cur_bnr = bufnr('%')
exe 'e '.v:fname_out
"Adjust the linenumbers
g/^[^<>-]/s/\v([dca].*)@<!\d+/\=submatch(0)+10-1/
g/^[^<>-]/s/\v([dca].*)@<=\d+/\=submatch(0)+20-1/
w
exec cur_bnr.'bu|bw #'
endfun

set diffexpr=D()

----------%<---------------

Of course this is just the prinicple idea, nothing more. It would
even be possible to have more than one region.

-ap


--
Ich hab geträumt, der Krieg wär vorbei.

A.Politz

unread,
Jan 30, 2008, 11:01:50 AM1/30/08
to vim...@googlegroups.com
A.Politz wrote:

Should be global :
g/.../s/.../ g

Sushrut Sardeshmukh

unread,
Feb 6, 2008, 5:46:13 AM2/6/08
to vim_use

Richard Hartmann

unread,
Feb 6, 2008, 9:35:28 AM2/6/08
to vim...@googlegroups.com
On Feb 6, 2008 11:46 AM, Sushrut Sardeshmukh <best...@gmail.com> wrote:


> http://www.vim.org/scripts/script.php?script_id=2048

I am using VIM pretty much exclusively (the one exception being GMail,
with iceweasel's It's all text plugin for writing mails like this one),
so that particular script does not help me, but it will surely help
others searching the list.

I will poke the script and see what needs to be done (if anything) to
make this work with CLI VIM, as well.


Thanks :)
Richard

Reply all
Reply to author
Forward
0 new messages