Closed toupeira closed 5 months ago
This should be possible with the existing render function. If you could share your current configuration, I can try to assist with this.
Thanks! Here's my current setup: https://github.com/toupeira/dotfiles/blob/main/vim/plugins/incline.lua
And a screenshot for reference:
I settled on filename + symbol breadcrumbs for now, and I'll probably keep the diagnostics in the statusline to avoid making the incline too distracting.
The filename is only shown if there's more than one window, and the symbols are only shown for the current buffer. So with only 2 sections it's not really a problem, I just conditionally include the separator before the symbols by repeating the check for number of windows:
return (props.windows > 1 and separator or '') .. symbols
It only becomes tricky if I wanted to add another section, and have to check in each section whether other sections are shown.
BTW I'm also abusing Aerial's Lualine component to generate the content for the symbols, was surprised that this worked! :grinning:
Here's what I would do. I changed some of the following code:
local function get_filename(props)
if props.windows <= 1 then
return nil
end
local path = vim.api.nvim_buf_get_name(props.buf)
local filename = vim.fn.fnamemodify(path, ':t')
if filename == '' then
filename = '[No Name]'
end
return {
' ' .. filename,
gui = 'bold',
guifg = props.focused and 'white' or comment,
}
end
local aerial
local function get_symbols(props)
if not props.focused then
return nil
end
if not aerial then
aerial = require 'lualine.components.aerial' {
self = { section = 'x' },
icons_enabled = true,
sep = separator,
}
end
local symbols = vim.api.nvim_eval_statusline(aerial:get_status(), { winid = props.win }).str
if symbols == '' then
return nil
end
return symbols
end
opts.render = function(props)
props.windows = get_window_count()
local sections = {
get_filename(props),
get_symbols(props),
}
local result = {}
for _, section in pairs(sections) do
if section and section ~= '' then
if #result > 0 then
table.insert(result, separator)
end
table.insert(result, section)
end
end
return result
end
Now, you can add additional sections to the sections
table in opts.render()
. Then, the loop that builds the result
table will insert separators between sections, skipping empty ones. With this approach, you can still set highlight groups.
P.s seeing your use of vim.api.nvim_eval_statusline
gave me an idea: I created a helper function in incline.helpers
that will evaluate a statusline string and convert it to an incline render result, including support for highlights (see 49cd56c1fd5166bae7f2af63c7eeb3489fe484af). Here's a version of your get_symbols()
function that uses it:
local helpers = require 'incline.helpers'
local aerial
local function get_symbols(props)
if not props.focused then
return nil
end
if not aerial then
aerial = require 'lualine.components.aerial' {
self = { section = 'x' },
icons_enabled = true,
sep = separator,
sep_highlight = 'InclineNormal',
}
end
local aerial_statusline = vim.api.nvim_win_call(props.win, function()
return aerial:get_status { winid = props.win }
end)
return helpers.eval_statusline(aerial_statusline, { winid = props.win })
end
It looks like this, now supporting highlights:
You could also set a highlight group common to all of the separators if you want:
--- unchanged code omitted ---
local sep = { ' î‚» ', group = 'NonText' }
local helpers = require 'incline.helpers'
local aerial
local function get_symbols(props)
if not props.focused then
return nil
end
if not aerial then
aerial = require 'lualine.components.aerial' {
self = { section = 'x' },
icons_enabled = true,
sep = sep[1],
sep_highlight = sep.group,
}
end
local aerial_statusline = vim.api.nvim_win_call(props.win, function()
return aerial:get_status { winid = props.win }
end)
return helpers.eval_statusline(aerial_statusline, { winid = props.win })
end
require('incline').setup {
render = function(props)
props.windows = get_window_count()
local sections = {
get_filename(props),
get_symbols(props),
}
local result = {}
for _, section in pairs(sections) do
if section and section ~= '' and not (type(section) == 'table' and #section == 0) then
if #result > 0 then
table.insert(result, sep)
end
table.insert(result, section)
end
end
return result
end,
window = {
margin = { horizontal = 0, vertical = 0 },
},
}
Which looks like this:
Putting it all together:
return {
'b0o/incline.nvim',
event = 'VeryLazy',
opts = {
window = {
margin = { horizontal = 0, vertical = 0 },
},
},
config = function(_, opts)
local helpers = require 'incline.helpers'
local sep = { ' î‚» ', group = 'NonText' }
local comment = require('util').get_color 'Comment'
local function get_window_count()
local windows = vim.api.nvim_tabpage_list_wins(0)
return #vim.tbl_filter(function(win)
return vim.api.nvim_win_get_config(win).relative == ''
end, windows)
end
local function get_filename(props)
local path = vim.api.nvim_buf_get_name(props.buf)
local filename = vim.fn.fnamemodify(path, ':t')
if filename == '' then
filename = '[No Name]'
end
return {
' ' .. filename,
gui = 'bold',
guifg = props.focused and 'white' or comment,
}
end
local aerial
local function get_symbols(props)
if not props.focused then
return nil
end
if not aerial then
aerial = require 'lualine.components.aerial' {
self = { section = 'x' },
icons_enabled = true,
sep = sep[1],
sep_highlight = sep.group,
}
end
local aerial_statusline = vim.api.nvim_win_call(props.win, function()
return aerial:get_status { winid = props.win }
end)
return helpers.eval_statusline(aerial_statusline, { winid = props.win })
end
opts.render = function(props)
local window_count = get_window_count()
local sections = {
window_count > 1 and get_filename(props) or nil,
get_symbols(props),
}
local result = {}
for _, section in pairs(sections) do
if section and section ~= '' and not (type(section) == 'table' and #section == 0) then
if #result > 0 then
table.insert(result, sep)
end
table.insert(result, section)
end
end
return result
end
require('incline').setup(opts)
end,
}
Hopefully this gives you some ideas around what's possible.
@b0o thank you very much, that all works great! :bow: Adapted in https://github.com/toupeira/dotfiles/blob/39464e381811f7c4386ea409f218167da71c5a53/vim/plugins/incline.lua.
Using nvim_win_call
to run Aerial also fixes the problem I had where unfocused windows would all show the symbol for the current window's cursor, rather than their own. This was the reason I was only showing symbols in the current window :grinning: But now I've tweaked it to always show symbols, and hide the filename instead if there isn't more than one listed buffer.
I'll go ahead and close this issue!
I'd like to render several sections which are all optional (diagnostics, Aerial breadcrumbs, filename only if more than one window is open), and add separator characters between them.
It doesn't seem like there's a way to do this with the plugin, would you consider adding it as an option? It could just be a single string that gets inserted between non-empty sections.
I could do this formatting myself inside
render()
and return the final string, but then I lose the ability to also set highlight groups. Unless I'm missing something?