----@type LazyPluginSpec
+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<string, string>
+ 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 {
- -- disabled plugins {{{
- { "folke/which-key.nvim",
- enabled = false,
- },
- -- }}}
{ 'echasnovski/mini.clue',
-- NOTE: this caused some issue with unterminated mappings, i.e. <L>gc when there
-- is also <L>gcc. It would simply terminate early and not allow for next mapping.
},
},
},
- {
- "nvim-notify",
- },
- {
- "bufferline.nvim",
+ { "akinsho/bufferline.nvim",
+ event = "VeryLazy",
+ keys = {
+ { "<leader>bp", "<Cmd>BufferLineTogglePin<CR>", desc = "Toggle Pin" },
+ { "<leader>bP", "<Cmd>BufferLineGroupClose ungrouped<CR>", desc = "Delete Non-Pinned Buffers" },
+ { "<leader>br", "<Cmd>BufferLineCloseRight<CR>", desc = "Delete Buffers to the Right" },
+ { "<leader>bl", "<Cmd>BufferLineCloseLeft<CR>", desc = "Delete Buffers to the Left" },
+ { "<S-h>", "<cmd>BufferLineCyclePrev<cr>", desc = "Prev Buffer" },
+ { "<S-l>", "<cmd>BufferLineCycleNext<cr>", desc = "Next Buffer" },
+ { "[b", "<cmd>BufferLineCyclePrev<cr>", desc = "Prev Buffer" },
+ { "]b", "<cmd>BufferLineCycleNext<cr>", desc = "Next Buffer" },
+ { "[B", "<cmd>BufferLineMovePrev<cr>", desc = "Move buffer prev" },
+ { "]B", "<cmd>BufferLineMoveNext<cr>", 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,
- },
- },
- },
- {
- "stevearc/dressing.nvim",
- lazy = true,
- opts = {
- input = {
- start_in_insert = false,
- insert_only = false,
- },
- },
- },
- {
- "noice.nvim",
- enabled = false,
- ---@type NoiceConfig
- opts = {
- presets = {
- command_palette = false, -- don't position the cmdline and popupmenu together
- lsp_doc_border = true,
- long_message_to_split = true,
- },
- cmdline = {
- view = "cmdline",
- },
- routes = {
- { -- send file written messages to mini
- filter = {
- event = "msg_show",
- kind = "",
- find = "%[w%]",
+ 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",
},
- opts = { skip = true },
},
+ ---@param opts bufferline.IconFetcherOpts
+ get_element_icon = function(opts)
+ return rmz.ui.icons.ft[opts.filetype]
+ end,
},
},
- config = function(_, opts)
- -- ensure [w] is written to msg_show so we can match it
- vim.opt.shortmess:append("w")
- vim.opt.shortmess:remove("W")
-
- require("noice").setup(opts)
- end,
},
- {
- "lualine.nvim",
- --TODO: Things that were in vim but are missing
+ { "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?
-- - 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
- },
- {
- "indent-blankline.nvim",
- },
- {
- "mini.indentscope",
- opts = {
- draw = {
- animation = require("mini.indentscope").gen_animation.linear({ duration = 10 }),
- },
- },
- },
- {
- "nvimdev/dashboard-nvim",
- -- TODO: create cool dashboard header
- -- generate logo from text here:
- -- https://patorjk.com/software/taag/#p=testall&v=0&f=Computer&t=NEOVIM
- -- Can also use use `chafa` and aplha.term to generate text from cli, see
- -- https://github.com/goolord/alpha-nvim/discussions/16#discussioncomment-4915947
- -- https://github.com/goolord/alpha-nvim/discussions/16#discussioncomment-5065731
- -- To add orgmode agenda button in alpha
- -- dashboard.button("a", " " .. " View Agenda", ":lua require('orgmode').action('agenda.agenda')<CR>"),
+ 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()
- local logo = [[
- ██╗ █████╗ ███████╗██╗ ██╗██╗ ██╗██╗███╗ ███╗ Z
- ██║ ██╔══██╗╚══███╔╝╚██╗ ██╔╝██║ ██║██║████╗ ████║ Z
- ██║ ███████║ ███╔╝ ╚████╔╝ ██║ ██║██║██╔████╔██║ z
- ██║ ██╔══██║ ███╔╝ ╚██╔╝ ╚██╗ ██╔╝██║██║╚██╔╝██║ z
- ███████╗██║ ██║███████╗ ██║ ╚████╔╝ ██║██║ ╚═╝ ██║
- ╚══════╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═══╝ ╚═╝╚═╝ ╚═╝
- ]]
+ -- PERF: we don't need this lualine require madness 🤷
+ local lualine_require = require("lualine_require")
+ lualine_require.require = require
+
+ local icons = rmz.ui.icons
- logo = string.rep("\n", 8) .. logo .. "\n\n"
+ vim.o.laststatus = vim.g.lualine_laststatus
local opts = {
- theme = "doom",
- hide = {
- -- this is taken care of by lualine
- -- enabling this messes up the actual laststatus setting after loading a file
- statusline = false,
+ 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,
+ },
},
- config = {
- header = vim.split(logo, "\n"),
- -- stylua: ignore
- center = {
- { action = [[lua require('orgmode').action('agenda.agenda')]], desc = " View Agenda", icon = " ", key = "a" },
- { action = "Telescope find_files", desc = " Find file", icon = " ", key = "f" },
- { action = "ene | startinsert", desc = " New file", icon = " ", key = "n" },
- { action = "Telescope oldfiles", desc = " Recent files", icon = " ", key = "r" },
- { action = [[lua require("lazyvim.util").telescope.config_files()()]], desc = " Config", icon = " ", key = "c" },
- { action = 'lua require("persistence").load()', desc = " Restore Session", icon = " ", key = "s" },
- { action = "LazyExtras", desc = " Lazy Extras", icon = " ", key = "x" },
- { action = "Lazy", desc = " Lazy", icon = " ", key = "l" },
+ inactive_sections = {
+ lualine_c = {
+ { "filetype", icon_only = true, separator = "", padding = { left = 1, right = 0 } },
+ { M.pretty_path() },
},
- footer = function()
- local stats = require("lazy").stats()
- local ms = (math.floor(stats.startuptime * 100 + 0.5) / 100)
- return { "⚡ Neovim loaded " .. stats.loaded .. "/" .. stats.count .. " plugins in " .. ms .. "ms" }
- end,
},
+ extensions = { "neo-tree", "lazy", "fzf" },
}
- for _, button in ipairs(opts.config.center) do
- button.desc = button.desc .. string.rep(" ", 43 - #button.desc)
- button.key_format = " %s"
- end
-
- -- close Lazy and re-open when the dashboard is ready
- if vim.o.filetype == "lazy" then
- vim.cmd.close()
- vim.api.nvim_create_autocmd("User", {
- pattern = "DashboardLoaded",
- callback = function()
- require("lazy").show()
- end,
- })
- end
+ 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
+ end,
},
{
- "SmiteshP/nvim-navic",
+ "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,
},
- {
- "nvim-web-devicons",
+ { "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,
+ },
+ },
},
- {
- "nui.nvim",
+ { "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 = "LazyFile",
+ 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,
},
}