0

To set custom statusline text based on whether the window is active/inactive I followed the method here, which works by wrapping and expanding a function in the statusline format string that checks if a window ID matches the window ID that called the wrapper function.

Now I'm trying to set a custom highlight group for certain text that should only show up in the active window.

What I've tried:

hi StatusLineActiveHighlight ctermfg=white ctermbg=028 cterm=bold
hi StatusLineInactiveHighlight ctermfg=white ctermbg=130 cterm=bold

set laststatus=2 " always show statusline
set statusline= " clear

function ShowIfActive(wid)
    if a:wid == win_getid()
        return "%#StatusLineActiveHighlight#Active"
    else
        return "%#StatusLineInactiveHighlight#Inactive"
    endif
endfun

function ShowIfActiveWrapper() abort
    let l:wid = win_getid()
    return "%{ShowIfActive(".l:wid.")}"
endfun

set statusline+=%!ShowIfActiveWrapper().'\ %f\ Line\ %l/%L'

The issue is that %#StatusLine[Active/Inactive]Highlight# isn't being expanded - it's showing as the literal string. I tried following :h statusline and tested with {% instead of %{ to no avail.

I know that vim-airline can do what I want, but I'm looking to make my statusline as DIY as I can and learn some more Vimscript in the process.

1 Answer 1

1

There are several issues with your code.

First, :help :set doesn't support concatenation with .. Therefore, the correct way to set the option is:

set statusline+=%!ShowIfActiveWrapper()

as per :help 'statusline', with the \ %f\ Line\ %l/%L format string part of the return value of ShowIfActiveWrapper().

Second, in a status line format string, %{<expr>} is used to insert the return value of <expr> without further evaluation. This is generally used to show arbitrary info for which there is no existing "item", such as time of day or curent Git branch or whatever. Since what you want to insert contains an actual "item" that requires further evaluation, %#StatusLineActiveHighlight#, you must use the form %{%<expr>%}, again as per :help 'statusline':

function ShowIfActiveWrapper() abort
    let l:wid = win_getid()
    return "%{%ShowIfActive(".l:wid.")%}" .. "\ %f\ Line\ %l/%L"
endfun

tada

NOTE: :help hl-statusline and :help hl-statuslinenc already exist so your StatusLineActiveHighlight and StatusLineInactiveHighlight are probably not necessary.

1
  • Works great, appreciate the detailed answer
    – user54579
    Commented Dec 2, 2024 at 9:25

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.