Basically I need to search only in areas marked red, not pink (in the default color scheme).

All I can find is how to search the unfolded areas. This is not very useful to me. I have long lines which sometimes differ only in a few characters. I need to search only in these characters.

I know how to make vimdiff unfold only lines with actual differences, but this is not enough either.

If it's possible to fold identical parts of lines, it would help somewhat. However the preferred solution would let me ignore identical parts in search without hiding them.

Perhaps a custom vim script can be written? Something along the lines of (pseudocode)

search pattern
while (found and not highlighted as diff)
       search pattern again
  • 1
    You might be interested in ]c and [c.
    – D. Ben Knoble
    Mar 15, 2021 at 14:36

1 Answer 1


You can do that with some vimscript, I wrote a function doing just what you need:

function! ComparePos(p1, p2)
    let linediff = a:p2[0] - a:p1[0]
    let coldiff = a:p2[1] - a:p1[1]
    return linediff + (!linediff) * coldiff

function! CurPos()
    return getpos('.')[1:2]

function! DiffSearch(pattern, flags)
    if !&diff | return | endif

    let wrapped = 0

    let startpos = CurPos()
    let prevpos = startpos

    let winsave = winsaveview()

    while search(a:pattern, a:flags)
        let curpos = CurPos()

        if synIDattr(diff_hlID(line('.'), col('.')), "name") == 'DiffText'
            " We found a proper match!
        if ComparePos(prevpos, curpos) < 0
            " We wrapped around the file
            let wrapped = 1
        if ComparePos(prevpos, curpos) == 0
            " We didn't move, there's no match in the file
        if wrapped && ComparePos(startpos, curpos) > 0
            " We searched through the whole file but no match with appropriate
            " syngroup was found
        let prevpos = curpos
    " No proper match found...
    echohl ErrorMsg | echo "Pattern not found: " . a:pattern | echohl None
    call winrestview(winsave)

nnoremap <silent> n :if &diff<BAR>call DiffSearch(@/, '')<BAR>else<BAR>exe 'norm! n'<BAR>endif<CR>
nnoremap <silent> N :if &diff<BAR>call DiffSearch(@/, 'b')<BAR>else<BAR>exe 'norm! N'<BAR>endif<CR>

The function you'll be interested in is DiffSearch, you can use it exactly as you'd use the search function, except it only searches in the diff parts.

I also added some mapping on n and N for ease of use!

Tell me if anything's unclear!

Side note: The function currently searches for the DiffText syntax group, but we can use it with pretty much any syntax group with some tweaking

  • 1
    also looks like you don't use the synStack variable. I was looking at some code I had for comparing positions to see if yours could be simplified, but my function returns true iff pos1 is before pos2; you do more case analysis than that, so I'm not sure it would help
    – D. Ben Knoble
    Mar 15, 2021 at 14:42
  • Thanks for the synStack variable, I started using synstack before realizing that the diff colorations were not given... For the ComparePos function, I made it smaller. Not sure which version is better for readability though...
    – Zorzi
    Mar 15, 2021 at 16:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.