How to ‘diff’ two subroutines in the same file in Vim?
Is it possible to diff
or even vimdiff
two very similar subroutines occurring in the same file? If so, how?
I can think of copying the two subroutines in two separate开发者_StackOverflow社区 files and then diff
them, but is there a way to do it within the original file?
Plugin linediff.vim : Perform an interactive diff on two blocks of text is similar to the one pointed ou by Vincent with some additional features:
- has a command to close the opened buffer
- seems to work without GUI
- insert some visual indication on the original file(s) being diffed.
To use it you perform a visual selection on the first block to diff, enter command :Linediff
, and repeat it to the second block. To quit, :LineDiffReset
I've found the followings maps helpful:
noremap \ldt :Linediff<CR>
noremap \ldo :LinediffReset<CR>
You cannot do this within the original file, but you can do this without using separate files, only separate buffers. This should work if you copied one subroutine in register a
(for example, with "ay
typed in Visual mode) and other subroutine in register b
:
enew | call setline(1, split(@a, "\n")) | diffthis | vnew | call setline(1, split(@b, "\n")) | diffthis
To automate:
let g:diffed_buffers = []
function DiffText(a, b, diffed_buffers)
enew
setlocal buftype=nowrite
call add(a:diffed_buffers, bufnr('%'))
call setline(1, split(a:a, "\n"))
diffthis
vnew
setlocal buftype=nowrite
call add(a:diffed_buffers, bufnr('%'))
call setline(1, split(a:b, "\n"))
diffthis
endfunction
function WipeOutDiffs(diffed_buffers)
for buffer in a:diffed_buffers
execute 'bwipeout! ' . buffer
endfor
endfunction
nnoremap <special> <F7> :call DiffText(@a, @b, g:diffed_buffers)<CR>
nnoremap <special> <F8> :call WipeOutDiffs(g:diffed_buffers) | let g:diffed_buffers=[]<CR>
Note that you may want to set hidden
option if Vim refuses to abandon changed file (see :h abandon
).
You can write those two parts/subroutines/sections to two files and then use vimdiff to see the difference.
:1, 39 write part1 //any line range or marks can be used
:40, 79 write part2
:!vimdiff part1 part2
If you aren't comfortable with using line numbers, you can keep the cursor at start of the section , press v and select till the end of the section and then press : . it will show :'<,'>. Then type write and then file name in the command line itself. Press enter. Similary, do for second one also. Then you can execute vimdiff command as stated above.
(Write command saves the part to a new file.) Writing a new file may not be a good idea, but that helps me. Especially when we had to go through the comparison several times.
This is one of the simplest way without using plugin or if you aren't concerned about memory.
I really like ZyX's answer, but needed to make two modifications for it to work seamlessly:
As implemented, <F7> replaces the active buffer with the vertically split diff display. Then, while <F8> closes the diff, it does not reload the original buffer. To fix this, I changed
enew
on the third line toexecute 'tab split | enew'
.In order to minimize side-effects, I added
call remove(a:diffed_buffers, 0, -1)
just before the end of WipeOutDiffs().
HTH, - Stu
I've been using this command:
vimdiff <(cat file.foo | sed -n 10,15p) <(cat file.foo | sed -n 20,25p)
Where the numbers fed to sed
are the line number I want to diff in the file. <(*)
means evaluate and redirect as input.
you can try Block diff vim plugin, it will make 2 new buffer in a new tab to show the differences.
精彩评论