Reputation: 55720
I occasionally see very long lines in my code that I need to check if they are the same. Is there a way in vim to select two lines and diff them to show any differences between the two?
For example, given the two lines in vim:
AVeryLongReturnType* MyLongClassName:hasAnEvenLongerFunction(That *is, Overloaded *with, Multiple *different, Parameter *lists);
AVeryLongReturnType* MyLongClassName:hasAnEvenLongerFunction(That *is, Overloaded *with, Multiple *different, Parameter *1ists);
I would like vim to tell me that the two lines are in fact different because each spells "lists" differently. Is this possible, and if so, how do I do it?
Upvotes: 42
Views: 15579
Reputation: 360
I like jelsayeh's answer for speed but if you want the "vimdiff" version, I came up with:
command! DL :tabnew | put! | diffthis | 2d | vnew | put! | diffthis
for my .vimrc. Then, select two lines into the unnamed buffer either with 2yy in normal mode or highlight and yank two lines in visual mode, then run :DL
from command mode and see it in "vimdiff".
There's a superfluous blank line in each split but it doesn't affect the display. You need to :q!
out of each split.
make "tabnew" just "new" if you would prefer in a split below instead.
Upvotes: 0
Reputation: 756
A quick and dirty solution is to just select both lines and sort them while removing duplicates:
An undo recovers everything again.
Upvotes: 58
Reputation: 4419
I used linediff.vim.
This plugin provides a simple command, ":Linediff", which is used to diff two separate blocks of text.
Upvotes: 10
Reputation: 393457
That is not a feature, however it is easily scripted, e.g. in your vimrc:
function! DiffLineWithNext()
let f1=tempname()
let f2=tempname()
exec ".write " . f1
exec ".+1write " . f2
exec "tabedit " . f1
exec "vert diffsplit " . f2
endfunction
This will open the current and next lines in vertical split in another tab. Note that this code is a sample
''
mark to select the other lineYou can leave off the 'vert' in order to have a horizontal split
Map it to something fancy so you don't have to :call
it manually:
:nnoremap <F10> :call DiffLineWithNext()^M
Upvotes: 7
Reputation: 547
you could also just create a new empty window buffer and copy line, then make command:
:windo diffthis
this should open a new window showing the differences of those 2 lines
Upvotes: 4
Reputation: 24044
An alternative to @sehe's approach would not require the use of temp files:
funct! DiffTwoTexts(text1, text2)
new
put =a:text1
normal ggdd
diffthis
new
put =a:text2
normal ggdd
diffthis
endfunct
funct! DiffTwoLines(line1, line2)
let text1 = getline(a:line1)
let text2 = getline(a:line2)
call DiffTwoTexts(text1, text2)
endfunct
comma! DiffWithNext call DiffTwoLines('.', line('.') + 1)
This will still be pretty hard to read, since it keeps everything on a single line, so I came up with this modification:
funct! EvalTextPreprocessor(expr, text)
let text = a:text
return eval(a:expr)
endfunct
comma! -nargs=1 DiffWithNextPre call DiffTwoTexts(
\ EvalTextPreprocessor(<q-args>, getline('.')),
\ EvalTextPreprocessor(<q-args>, getline(line('.') + 1)))
This new command takes a vimscript expression as its argument, wherein the variable text
refers to whichever line is being preprocessed. So you can call, e.g.
DiffWithNextPre split(text, '[(,)]\zs')
For your sample data, this gives the two buffers
AVeryLongReturnType* MyLongClassName:hasAnEvenLongerFunction(
That *is,
Overloaded *with,
Multiple *different,
Parameter *lists)
;
and
AVeryLongReturnType* MyLongClassName:hasAnEvenLongerFunction(
That *is,
Overloaded *with,
Multiple *different,
Parameter *1ists)
;
Only the lines that start with Parameter
are highlighted.
You can even build up from there, creating a command
comma! DiffTwoCFunctionSigs DiffWithNextPre split(text, '[(,)]\s*\zs')
Notice that I modified the regexp a bit so that it will keep trailing spaces at the end of lines. You could get it to ignore them entirely by moving the \s*
to after the \zs
. See :help /\zs
if you're unfamiliar with what that vim-specific RE atom does.
A nicety would be to make the command take a range (see :help command-range
), which you could use by diffing the first line of the range with the last line. So then you just visual-select from the first line to the second and call the command.
Upvotes: 9