5

I wrote a function which returns a string:

function! StatusBricks()
    let l:stat = Brick(statusbricks#ReportLinecount('raw'), {
        \ 'brick_color': 'LineNr',
        \ 'delimiter_position': 'right',
        \ 'delimiter_right': '❯'
        \ })
    return l:stat
endfunction

The result has the following format, generated by Brick():

%#HighlightGroup#SomeData

When I use the function as an expression inside the statusline I expect the highlight group to get expanded in order to colorize the appropriate statusline section:

set statusline =%{StatusBricks()}

But what I get is a statusline literally showing %#HighlightGroup#ExpandedData rather than ExpandedData:

vim statusline highlight group expansion

What am I doing wrong?

Saucier
  • 4,200
  • 1
  • 25
  • 46

2 Answers2

0

The result of %{ isn't interpreted further, however the result of %! is. Use

set statusline=%!StatusBricks()

%! doesn't appear to have a tag in the helpfile, but it's mentioned near the beginning of :help 'statusline'.

Following your comment: if you want different colours in the statusline depending on the state of each particular window, then you can highlight an empty string if you don't want a particular highlight to appear. E.g.

set stl=%#error#%r%#search#

Only read-only windows (e.g. open a help buffer) will have the read-only flag displayed in red. Admittedly this can get complicated depending on your highlighting requirements.

1983
  • 5,882
  • 2
  • 27
  • 39
  • Help isn't quite clear about further interpretion of `%{}`. Maybe I missed something. However `%!` has a sideeffect: From `help`: "Note that the "%!" expression is evaluated in the context of the current window and buffer, while %{} items are evaluated in the context of the window that the statusline belongs to." As a consequence `%!` is not really useful unfortunately. – Saucier Aug 04 '15 at 10:00
  • See the edit, if that's what you mean. Maybe you could include more detail and code in your question so we know what you're trying to achieve. – 1983 Aug 04 '15 at 10:37
  • When using `%!`, you can use `winbufnr(g:statusline_winid)` in your function to identify the buffer whose statusline you are drawing. – pdr Nov 13 '20 at 00:55
0

tl;dr - use {% %}

I realise this is an old question, but I found an answer that future readers might use.

Rather than

set statusline =%{StatusBricks()}

you need

set statusline =%{%StatusBricks()%}

From :help 'statusline':

    {% -  This is almost same as { except the result of the expression is
          re-evaluated as a statusline format string.  Thus if the
          return value of expr contains % items they will get expanded.
          The expression can contain the } character, the end of
          expression is denoted by %}.
          The For example:
            func! Stl_filename() abort
                return "%t"
            endfunc

            `stl=%{Stl_filename()}`   results in `"%t"`
            `stl=%{%Stl_filename()%}` results in `"Name of current file"`
Parker Tailor
  • 1,290
  • 13
  • 12