8

I can read a value from an option like:

let b = &background

Is there a way to read a value from a highlight group? Something like this pseudo-code:

let b = &StatusLine['ctermbg']

Ultimately, what I want to do is define a new highlight group in terms of other highlight group colors (not a link, but picking specific values from more than one highlight group, namely StatusLine and StatusLineNC in my case)

1

2 Answers 2

8

As far as I know, there's not a simple way to do this. Here's a function that should be able to return the value given the highlight group and term. If there is no such term, an empty string will be returned instead.

function! ReturnHighlightTerm(group, term)
   " Store output of group to variable
   let output = execute('hi ' . a:group)

   " Find the term we're looking for
   return matchstr(output, a:term.'=\zs\S*')
endfunction

Given this function you should be able to do

let b = ReturnHighlightTerm('StatusLine', 'ctermbg')

to get what you want.

See :help execute(), :help :highlight, and :help matchstr() for more info on how this works.

7
  • 1
    Using the execute() function is better than :redir, e.g. let l:output = execute('hi ' . a:group). See here for a very similar example with :syntax list. Aside from being more readable, I've found that redir has some serious issues in some cases. I forgot what it was exactly since it was a while ago, but I believe it had to do with nesting two redirs in some complicated ways with plugins/autocommands which causes the wrong output to end up in the wrong variable (!!!!) Suffice to say, I haven't used redir since. May 3, 2017 at 23:23
  • Ah, cool! I didn't know about execute(). Thanks!
    – Tumbler41
    May 4, 2017 at 4:12
  • @Carpetsmoker I believe that problem is not solved by using execute(). I think execute() suffers from the same problem. May 4, 2017 at 12:54
  • Ow, I didn't know that @ChristianBrabandt :-( I haven't had any problems since I replaced redir with execute(), though; but perhaps that's just coincidence. May 4, 2017 at 12:59
  • @Carpetsmoker @ChristianBrabandt at least the execute() solution is simpler and reads better, so I'd stick with it...
    – ericbn
    May 4, 2017 at 13:43
5

I ended up writing a generic function that turns a highlight group into a dictionary of {key}={arg} pairs. Leaving it here for future reference:

function! GetHighlight(group)
  let output = execute('hi ' . a:group)
  let list = split(output, '\s\+')
  let dict = {}
  for item in list
    if match(item, '=') > 0
      let splited = split(item, '=')
      let dict[splited[0]] = splited[1]
    endif
  endfor
  return dict
endfunction

Your Answer

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

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