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.

  • 2
    :set diffopt+=iwhite, or have I misunderstood? – Antony Jun 7 '16 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 '16 at 18:21
  • Related post: Search within syntax group? – Peter Rincker Jun 8 '16 at 16:17
  • That post links to the Q I posted. :P – Tumbler41 Jun 8 '16 at 16:52
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.

  • Man, vim is huge; didn't even know diff_hlID existed. Thanks! – Antony Jun 8 '16 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 '16 at 17:18
  • @Tumbler41 I think this you are correct. – Christian Brabandt Jun 8 '16 at 20:18
  • @ChristianBrabandt Mind editing for future readers? :) – Tumbler41 Jun 8 '16 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
  • 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 '16 at 22:55
  • Oops, typo there, sorry. Edited. – Antony Jun 7 '16 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 '16 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 '16 at 23:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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