1

I am making changes to an existing C code. If I just want to check my changes, I can easily use vimdiff for that, with old & modified files.

What I want is to limit some syntax highlighting to just the diff part.

Particularly I need to highlight TABS, but only those TABS contained within DiffAdd & DiffChange sections/regions.

What I tried:

syntax region TESTRGN start="TESTRGN_START" end="TESTRGN_END"
highlight TESTRGN ctermbg=lightgreen guibg=lightgreen

syntax match LeadingTabsInRegion display contained containedin=TESTRGN /^\( *\t\+\)\+/
highlight LeadingTabsInRegion ctermbg=darkred guibg=darkred

Above snippet highlights the leading TABS within TESTRGN & tabs in remaining file remain un-highlighted.

However, if I change TESTRGN to DiffAdd in the syntax match line, it does not work as I expected.

My understanding is that DiffAdd is not a region defined using syntax region ... & hence containedin=DiffAdd does not work.

So is there any method/work-around for doing what I am trying to do?

anishsane
  • 20,270
  • 5
  • 40
  • 73

2 Answers2

0

First, what's so bad about having the highlighting everywhere? The diff highlighting stands out well and therefore provides visible scope; couldn't you just ignore the highlighting elsewhere?

In Vim, syntax groups are defined and then linked to colors and attributes defined in highlight groups. The diff stuff uses the second part of that mechanism, but not the syntax part. Therefore, you unfortunately cannot refer to the diff regions within :syntax commands.

There's only a very ugly workaround for this: You have to determine the line numbers that have diff highlighting (via repeatedly stepping through the changes with the ]c motion, and/or using synID() to check for diff highlighting). With those line numbers, you can then define :syntax match commands with the special \%l atom that only matches certain lines. Of course, any addition / deletion of lines would invalidate your definitions, which would need to be frequently re-synchronized (triggered by :autocmd). That's a lot of effort vs. just ignoring the highlighting elsewhere.

Ingo Karkat
  • 167,457
  • 16
  • 250
  • 324
  • 'what's so bad about having the highlighting everywhere': Adding new tabs in code is considered as a no-no at many places. Hence adding a disruptive syntax highlighting for such cases - darkred!. For existing tabs, it's actually don't care case. But it's still very much disruptive to ignore. So I thought there could be a better way... – anishsane Feb 05 '15 at 10:18
  • How does `Diff*` highlights work, if I add a new line above/below such a region? Their line numbers get automatically shifted. So is it line number based, or some rule based? – anishsane Feb 05 '15 at 10:20
  • Vim has the diffing functionality built in; it's not syntax-based, but triggered internally. – Ingo Karkat Feb 06 '15 at 21:02
0

Though you need to reset whenever the line was changed, this is just a tip for one of line number based ideas, you can get a list of all diff highlighted lines with:

let dl = filter(range(1, line('$')),
        \'index([hlID("DiffChange"), hlID("DiffText"), hlID("DiffAdd")],
            \diff_hlID(v:val, 1)) != -1')

And using this, it might be possible to set your TESTRGN with:

exec "syntax match TESTRGN /\\(" . join(map(dl, '"\\%" . v:val . "l"'), "\\|") . "\\).*/"
Rick Howe
  • 429
  • 3
  • 6