How to get handle for current buffer in statusline subexpression

We can specify expressions inside the statusline/tabline syntax using %!..., does anyone know how to get the buffer number inside a function provided to that? Standard means of using bufnr() returns the buffer the cursor is on. Here is a minimal example:

vim.o.statusline = '%!bufnr()'

Then open up two separate buffers in splits and jump between them, the statusline will not show the buffer number tied to the statusline for a specific window, rather all the statuslines will show the same buffer number (whichever your cursor is in).

How about

vim.o.statusline = "%n"

I’m looking to get the buffer number inside a function provided to 'statusline' via the expression syntax (%!...), not just have the buffer number render. The example I provided was just a minimal example.

You are returning a string from your function you can just put %n in that string where you want buf_num to apear.

I’m not looking to just have the buffer number render, I’m looking to get literal access to the buffer number in the callback provided to 'statusline'. I know how %n works, it doesn’t solve my issue.

The closest I’ve found is to use %{...} instead of %!... which has the desired effect, however, it doesn’t evaluate standard statusline/tabline items (like %n, %f, %b, %#hlgroup` etc.), instead it renders everything literally.

You have access to win_id through g:statusline_winid in a function called by statusline.You can translate it to buf_no with winbufnr() I guess .

local buf_no = vim.fn.winbufnr(vim.g.statusline_winid)

Nice, that works thanks! I see it in the helpdocs now, missed it before.

Maybe you could use %{%bufnr()%} instead?