rebelot/heirline.nvim

I cannot figure out how to make my diagnostics flexible

Closed this issue · 5 comments

Here’s the component

local Diagnostics = {

    condition = conditions.has_diagnostics,

    static = {
        -- error_icon = vim.fn.sign_getdefined("DiagnosticSignError")[1].text,
        -- warn_icon = vim.fn.sign_getdefined("DiagnosticSignWarn")[1].text,
        -- info_icon = vim.fn.sign_getdefined("DiagnosticSignInfo")[1].text,
        -- hint_icon = vim.fn.sign_getdefined("DiagnosticSignHint")[1].text,
        error_icon = "✘ ",
        warn_icon = "▲ ",
        info_icon = " ",
        hint_icon = "⚑ ",
    },

    init = function(self)
        self.errors = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.ERROR })
        self.warnings = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.WARN })
        self.hints = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.HINT })
        self.info = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.INFO })
    end,

    update = { "DiagnosticChanged", "BufEnter" },

    -- {
    --     provider = "![",
    -- },
    flexible = 20,
    {
        {
            provider = function(self)
                -- 0 is just another output, we can decide to print it or not!
                return self.errors > 0 and (self.error_icon .. self.errors .. " ")
            end,
            hl = { fg = "diag_error" },
        },
        {
            provider = function(self)
                return self.warnings > 0 and (self.warn_icon .. self.warnings .. " ")
            end,
            hl = { fg = "diag_warn" },
        },
        {
            provider = function(self)
                return self.info > 0 and (self.info_icon .. self.info .. " ")
            end,
            hl = { fg = "diag_info" },
        },
        {
            provider = function(self)
                return self.hints > 0 and (self.hint_icon .. self.hints)
            end,
            hl = { fg = "diag_hint" },
        },
    },
    {
        {
            provider = function(self)
                -- 0 is just another output, we can decide to print it or not!
                return self.errors > 0 and (self.error_icon .. self.errors .. " ")
            end,
            hl = { fg = "diag_error" },
        },
        {
            provider = function(self)
                return self.warnings > 0 and (self.warn_icon .. self.warnings .. " ")
            end,
            hl = { fg = "diag_warn" },
        },
        {
            provider = function(self)
                return self.info > 0 and (self.info_icon .. self.info .. " ")
            end,
            hl = { fg = "diag_info" },
        },
    },
    {
        {
            provider = function(self)
                -- 0 is just another output, we can decide to print it or not!
                return self.errors > 0 and (self.error_icon .. self.errors .. " ")
            end,
            hl = { fg = "diag_error" },
        },
        {
            provider = function(self)
                return self.warnings > 0 and (self.warn_icon .. self.warnings .. " ")
            end,
            hl = { fg = "diag_warn" },
        },
    },
    {
        {
            provider = function(self)
                -- 0 is just another output, we can decide to print it or not!
                return self.errors > 0 and (self.error_icon .. self.errors .. " ")
            end,
            hl = { fg = "diag_error" },
        },

    }
    -- {
    --     provider = "]",
    -- },
}

The behavior I observe is that this does not become flexible at all and is always shown.

Try removing the update field

Great, it works! I also reckon that the experience will not be noticeably degraded by not having these update events trigger the re-render. Maybe they won't be fully up to date at all times, but once the cursor moves it will update.

You can put the update field inside the flexible children. If the parent (the flexible component) is behind an update autocmd it won't trigger the routine that handles the resize

Perfect, thank you for that clarification! So I take it then that we actually want to specify the update fields where applicable as they serve to reduce unnecessary re-renders of components rather than adding more?

Exactly. Statusline is always re evaluated a bunch of times, update field is mostly there for performance to allow components to be re evaluated only on certain conditions. However, it might be useful also for triggering a redraw on certain events where the statusline is not redrawn, such as entering operator pending mode, or start recording a macro. There's a few examples in the cookbook about that, where you can add redrawstatus within the callback