7

I want to be able to search only within the DiffText regions of a file that I'm editing.

Related question: https://stackoverflow.com/questions/2683521/vim-search-in-c-c-code-lines

The accepted answer here seems to work great for say, Comment or Type syntax groups, but any of the Diff groups don't work. I surmise it something to do with the diff groups being nested within other groups.

My specific scenario is that I've removed a bunch of tabs and trailing spaces from a bunch of files. I've diffed the files with the originals and want to make sure that nothing except tabs and trailing spaces are different.

P.S. I don't want to do a global replace of all the tabs because my predecessor used inconsistent indentation and I need to manually check all of it.

4
  • 2
    :set diffopt+=iwhite, or have I misunderstood?
    – Antony
    Jun 7, 2016 at 17:24
  • Hmm, I suppose that would work for my specific scenario. Thanks! However, I would still be interested to know if there is a way to restrict search results for other possible scenarios.
    – Tumbler41
    Jun 7, 2016 at 18:21
  • Related post: Search within syntax group? Jun 8, 2016 at 16:17
  • That post links to the Q I posted. :P
    – Tumbler41
    Jun 8, 2016 at 16:52

2 Answers 2

7

Not natively (also I have written a patch, that would allow to add a skip expression to the search() function, but this hasn't been included yet).

But you can workaround it by writing your own function that checks, whether the match is in a diff region contained. Something like this (very basic approach):

function! Search(pat)
    while search(a:pat, 'w') > 0
        if diff_hlID(line('.'),col('.')) != 0
            break
        endif
    endwhile
endfunction

com! -nargs=1 Search :call Search(<q-args>)

Error checking and handling more edge cases (abort after the search has wrapped around, eg.) left as excercise to the user.

4
  • Man, vim is huge; didn't even know diff_hlID existed. Thanks!
    – Antony
    Jun 8, 2016 at 10:27
  • 1
    Awesome! Only, unless I understand something wrong, I think your if statement should be if... != 0 So that it breaks from searching when it lands on a diff. That's what seemed to work for me at lest. (I know your function wasn't intended to be complete, but I'm pretty sure this is backwards.)
    – Tumbler41
    Jun 8, 2016 at 17:18
  • @Tumbler41 I think this you are correct. Jun 8, 2016 at 20:18
  • @ChristianBrabandt Mind editing for future readers? :)
    – Tumbler41
    Jun 8, 2016 at 20:39
3

Well, the simple way to search the differences (all different lines, not just DiffText, sorry) would be to run diff on the two files, put the output in a buffer and search there. Assuming you're viewing filea and fileb in vimdiff:

:new | r! diff -u0 filea fileb
/search-for-something

Line numbers will be in the output, in lines like

@@ -9,3 +8,6 @@

so you could easily jump to the line (9) in the original file:

?@@<CR>0/\d<CR>yw:q!:@"<CR>

This searches backwards for a line-number line, yanks the line number into @", closes the temporary search buffer, and jumps to the line number. You'll probably want to massage that to take into account your window layout, etc., and maybe map it to a key.

You could also include context lines in the diff, to make it easier read, but make sure that your searches look in lines with changes, i.e. those that start with a non-blank:

/^\S.*\zssearch-for-something
4
  • 2
    Ah, a filtering approach. Not quite what I had in mind, but I can get behind this. Still trying to fully understand your macro though. My header lines are in the form of: @@ -292,2 +283,7 @@. That being said, I can't quite figure out what the 0/ is for in your search pattern. Additionally yW will yank the WORD, meaning 292,2. When you execute :@" This takes you to line 2 instead of 292. I think I would come up with something like this: ?@@.*+?e+1<CR>yw:q!<CR>:@"<CR>. You could change the first + to - depending on which file you wanted to look at. Thoughts?
    – Tumbler41
    Jun 7, 2016 at 22:55
  • Oops, typo there, sorry. Edited.
    – Antony
    Jun 7, 2016 at 23:13
  • 1
    There was a missing <CR> to terminate the search pattern, and the yW should be yw like you said!
    – Antony
    Jun 7, 2016 at 23:19
  • 2
    Yeah, those look like good suggestions to me. You could have two mappings, depending on which file you wanted to jump to, or you could work that out automatically from the + or - at the start of the line and the filenames in the header.
    – Antony
    Jun 7, 2016 at 23:22

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.