local M = {} ---@param component any -- actually a lualine.component ---@param text string ---@param hl_group? string ---@return string function M.format(component, text, hl_group) text = text:gsub("%%", "%%%%") if not hl_group or hl_group == "" then return text end --- hl_cache is added here, not modified ---@type table component.hl_cache = component.hl_cache or {} local lualine_hl_group = component.hl_cache[hl_group] if not lualine_hl_group then local utils = require("lualine.utils.utils") ---@type string[] local gui = vim.tbl_filter(function(x) return x end, { utils.extract_highlight_colors(hl_group, "bold") and "bold", utils.extract_highlight_colors(hl_group, "italic") and "italic", }) lualine_hl_group = component:create_hl({ fg = utils.extract_highlight_colors(hl_group, "fg"), gui = #gui > 0 and table.concat(gui, ",") or nil, }, "LV_" .. hl_group) --[[@as string]] component.hl_cache[hl_group] = lualine_hl_group end return component:format_hl(lualine_hl_group) .. text .. component:get_default_hl() end function M.pretty_path() return function(self) local opts = { directory_hl = "", filename_hl = "Bold", length = 3, modified_hl = "MatchParen", -- hl group when file is modified modified_sign = "", readonly_icon = " 󰌾 ", } local path = vim.fn.expand("%:p") --[[@as string]] if path == "" then return "" end path = require("lazy.core.util").norm(path) local cwd = vim.uv.cwd() if path:find(cwd, 1, true) == 1 then path = path:sub(#cwd + 2) end local sep = package.config:sub(1, 1) local parts = vim.split(path, "[\\/]") if opts.length == 0 then parts = parts elseif #parts > opts.length then parts = { parts[1], "…", unpack(parts, #parts - opts.length + 2, #parts) } end if vim.bo.modified then parts[#parts] = parts[#parts] .. opts.modified_sign parts[#parts] = M.format(self, parts[#parts], opts.modified_hl) else parts[#parts] = M.format(self, parts[#parts], opts.filename_hl) end local dir = "" if #parts > 1 then dir = table.concat({ unpack(parts, 1, #parts - 1) }, sep) dir = M.format(self, dir .. sep, opts.directory_hl) end local readonly = "" if vim.bo.readonly then readonly = M.format(self, opts.readonly_icon, opts.modified_hl) end return dir .. parts[#parts] .. readonly end end ---@type LazySpec return { { 'echasnovski/mini.clue', -- NOTE: this caused some issue with unterminated mappings, i.e. gc when there -- is also gcc. It would simply terminate early and not allow for next mapping. version = '*', lazy = true, -- NOTE: load this explicitely when needed, it blocks querying for key definitons via :Verbose map opts = { triggers = { { mode = 'n', keys = '' }, { mode = 'x', keys = '' }, -- `g` key { mode = 'n', keys = 'g' }, { mode = 'x', keys = 'g' }, -- Marks { mode = 'n', keys = "'" }, { mode = 'n', keys = '`' }, { mode = 'x', keys = "'" }, { mode = 'x', keys = '`' }, -- Window commands { mode = 'n', keys = '' }, -- `z` key { mode = 'n', keys = 'z' }, { mode = 'x', keys = 'z' }, }, clues = { { mode = 'n', keys = 'b', desc = '+Buffers' }, { mode = 'n', keys = 'c', desc = '+LSP' }, }, }, }, { "akinsho/bufferline.nvim", event = "VeryLazy", keys = { { "bp", "BufferLineTogglePin", desc = "Toggle Pin" }, { "bP", "BufferLineGroupClose ungrouped", desc = "Delete Non-Pinned Buffers" }, { "br", "BufferLineCloseRight", desc = "Delete Buffers to the Right" }, { "bl", "BufferLineCloseLeft", desc = "Delete Buffers to the Left" }, { "", "BufferLineCyclePrev", desc = "Prev Buffer" }, { "", "BufferLineCycleNext", desc = "Next Buffer" }, { "[b", "BufferLineCyclePrev", desc = "Prev Buffer" }, { "]b", "BufferLineCycleNext", desc = "Next Buffer" }, { "[B", "BufferLineMovePrev", desc = "Move buffer prev" }, { "]B", "BufferLineMoveNext", desc = "Move buffer next" }, }, ---@type BufferlineConfig opts = { options = { close_command = function(n) Snacks.bufdelete(n) end, right_mouse_command = function(n) Snacks.bufdelete(n) end, diagnostics = "nvim_lsp", always_show_bufferline = false, diagnostics_indicator = function(_, _, diag) local icons = rmz.ui.icons.diagnostics local ret = (diag.error and icons.Error .. diag.error .. " " or "") .. (diag.warning and icons.Warn .. diag.warning or "") return vim.trim(ret) end, offsets = { { filetype = "man", text = "Man page", highlight = "Directory", text_align = "left", }, }, ---@param opts bufferline.IconFetcherOpts get_element_icon = function(opts) return rmz.ui.icons.ft[opts.filetype] end, }, }, }, { "nvim-lualine/lualine.nvim", -- TODO: Things that were in vim but are missing -- - git line add/mod/del ar next to branch name rather on right -- - one status line per splits -- - maybe a single one is OK too? -- - I think I want a line stating wihch file is in the split though -- - unix/dos eof markers -- - really I only want to know if it's not unix -- - filetype in text form. It's quite important to glance this quickly event = "VeryLazy", init = function() vim.g.lualine_laststatus = vim.o.laststatus if vim.fn.argc(-1) > 0 then -- set an empty statusline till lualine loads vim.o.statusline = " " else -- hide the statusline on the starter page vim.o.laststatus = 0 end end, opts = function() -- PERF: we don't need this lualine require madness 🤷 local lualine_require = require("lualine_require") lualine_require.require = require local icons = rmz.ui.icons vim.o.laststatus = vim.g.lualine_laststatus local opts = { options = { theme = "auto", globalstatus = vim.o.laststatus == 3, disabled_filetypes = { statusline = { "dashboard", "alpha", "ministarter", "snacks_dashboard" } }, }, sections = { lualine_a = { "mode" }, lualine_b = { "branch" }, lualine_c = { { "diagnostics", symbols = { error = icons.diagnostics.Error, warn = icons.diagnostics.Warn, info = icons.diagnostics.Info, hint = icons.diagnostics.Hint, }, }, { "filetype", icon_only = true, separator = "", padding = { left = 1, right = 0 } }, { M.pretty_path() }, }, lualine_x = { Snacks.profiler.status(), -- stylua: ignore { function() return " " .. require("dap").status() end, cond = function() return package.loaded["dap"] and require("dap").status() ~= "" end, color = function() return { fg = Snacks.util.color("Debug") } end, }, -- stylua: ignore { require("lazy.status").updates, cond = require("lazy.status").has_updates, color = function() return { fg = Snacks.util.color("Special") } end, }, { "diff", symbols = { added = icons.git.added, modified = icons.git.modified, removed = icons.git.removed, }, source = function() local gitsigns = vim.b.gitsigns_status_dict if gitsigns then return { added = gitsigns.added, modified = gitsigns.changed, removed = gitsigns.removed, } end end, }, }, lualine_y = { { "progress", separator = " ", padding = { left = 1, right = 0 } }, { "location", padding = { left = 0, right = 1 } }, }, lualine_z = { function() return " " .. os.date("%R") end, }, }, inactive_sections = { lualine_c = { { "filetype", icon_only = true, separator = "", padding = { left = 1, right = 0 } }, { M.pretty_path() }, }, }, extensions = { "neo-tree", "lazy", "fzf" }, } local trouble = require("trouble") local symbols = trouble.statusline({ mode = "symbols", groups = {}, title = false, filter = { range = true }, format = "{kind_icon}{symbol.name:Normal}", hl_group = "lualine_c_normal", }) table.insert(opts.sections.lualine_c, { symbols and symbols.get, cond = function() return vim.b.trouble_lualine ~= false and symbols.has() end, }) return opts end, }, { "echasnovski/mini.icons", lazy = true, opts = { file = { [".keep"] = { glyph = "󰊢", hl = "MiniIconsGrey" }, ["devcontainer.json"] = { glyph = "", hl = "MiniIconsAzure" }, }, filetype = { dotenv = { glyph = "", hl = "MiniIconsYellow" }, }, }, init = function() -- TODO: try without this -- see :h MiniIcons.mock_nvim_web_devicons() package.preload["nvim-web-devicons"] = function() require("mini.icons").mock_nvim_web_devicons() return package.loaded["nvim-web-devicons"] end end, }, { "MunifTanjim/nui.nvim", lazy = true }, { "stevearc/dressing.nvim", enabled = false, -- replaced by snacks.input lazy = true, opts = { input = { start_in_insert = false, insert_only = false, }, }, }, { "indent-blankline.nvim", enabled = false, -- replaced by snacks.indent }, { "echasnovski/mini.indentscope", enabled = false, -- replaced by snacks.indent version = false, -- wait till new 0.7.0 release to put it back on semver event = { "BufReadPost", "BufNewFile", "BufWritePre" }, opts = function (_, opts) return { draw = { animation = require("mini.indentscope").gen_animation.linear({ duration = 10 }) } } end, }, { "SmiteshP/nvim-navic", lazy = true, init = function() vim.g.navic_silence = true rmz.lsp.on_attach(function(client, buffer) if client.supports_method("textDocument/documentSymbol") then require("nvim-navic").attach(client, buffer) end end) end, opts = function() return { separator = " ", highlight = true, depth_limit = 5, icons = rmz.ui.icons.kinds, lazy_update_context = true, } end, }, { "nvim-lualine/lualine.nvim", optional = true, opts = function(_, opts) if not vim.g.trouble_lualine then table.insert(opts.sections.lualine_c, { "navic", color_correction = "dynamic" }) end end, }, }