diff --git a/nvim/.config/nvim/lazy-lock.json b/nvim/.config/nvim/lazy-lock.json index f8bd112..b3153a0 100644 --- a/nvim/.config/nvim/lazy-lock.json +++ b/nvim/.config/nvim/lazy-lock.json @@ -30,6 +30,7 @@ "gitsigns.nvim": { "branch": "main", "commit": "0b04035bb7b3c83e999b9676e2fb46fd0aa9f910" }, "glance.nvim": { "branch": "master", "commit": "51059bcf21016387b6233c89eed220cf47fca752" }, "grug-far.nvim": { "branch": "main", "commit": "536b23dcf3165a622654544e5f9f395584e73b57" }, + "heirline.nvim": { "branch": "master", "commit": "0d797435e54645a5f98bad7ad6046aac1ef95c1e" }, "image.nvim": { "branch": "master", "commit": "da64ce69598875c9af028afe129f916b02ccc42e" }, "img-clip.nvim": { "branch": "main", "commit": "fc30500c35663aa1762697f5aba31d43b86028f0" }, "jupytext.nvim": { "branch": "main", "commit": "c8baf3ad344c59b3abd461ecc17fc16ec44d0f7b" }, @@ -37,7 +38,6 @@ "lazydev.nvim": { "branch": "main", "commit": "491452cf1ca6f029e90ad0d0368848fac717c6d2" }, "lsp-setup.nvim": { "branch": "main", "commit": "6e4e977512ce426d8b52c27f3b6e6aefc73e1452" }, "ltex_extra.nvim": { "branch": "dev", "commit": "57192d7ae5ba8cef3c10e90f2cd62d4a7cdaab69" }, - "lualine.nvim": { "branch": "master", "commit": "b431d228b7bbcdaea818bdc3e25b8cdbe861f056" }, "luarocks.nvim": { "branch": "main", "commit": "1db9093915eb16ba2473cfb8d343ace5ee04130a" }, "luvit-meta": { "branch": "main", "commit": "ce76f6f6cdc9201523a5875a4471dcfe0186eb60" }, "markmap.nvim": { "branch": "main", "commit": "5fb6755cf5434511cc23a4936c9eb76b9142fba5" }, diff --git a/nvim/.config/nvim/lua/custom/components.lua b/nvim/.config/nvim/lua/custom/components.lua new file mode 100644 index 0000000..a7fbe90 --- /dev/null +++ b/nvim/.config/nvim/lua/custom/components.lua @@ -0,0 +1,310 @@ +local M = {} + +local conditions = require("heirline.conditions") +local utils = require("heirline.utils") +M.Align = { provider = "%=" } +M.Space = { provider = " " } +M.Separator = { + static = { + component = { left = "  ", right = "  " }, + section = { + left = "█ ", + right = "█", + }, + }, +} +M.ViMode = { + init = function(self) + self.mode = vim.fn.mode(1) + end, + static = { + mode_names = { + n = "N", + no = "N?", + nov = "N?", + noV = "N?", + ["no\22"] = "N?", + niI = "Ni", + niR = "Nr", + niV = "Nv", + nt = "Nt", + v = "V", + vs = "Vs", + V = "_V", + Vs = "Vs", + ["\22"] = "^V", + ["\22s"] = "^V", + s = "S", + S = "S_", + ["\19"] = "^S", + i = "I", + ic = "Ic", + ix = "Ix", + R = "R", + Rc = "Rc", + Rx = "Rx", + Rv = "Rv", + Rvc = "Rv", + Rvx = "Rv", + c = "C", + cv = "Ex", + r = "...", + rm = "M", + ["r?"] = "?", + ["!"] = "!", + t = "T", + }, + mode_colors = { + n = "white", + i = "green", + v = "cyan", + V = "cyan", + ["\22"] = "cyan", + c = "orange", + s = "purple", + S = "purple", + ["\19"] = "purple", + R = "orange", + r = "orange", + ["!"] = "red", + t = "red", + }, + }, + provider = function(self) + return "%3(" .. self.mode_names[self.mode] .. "%) " + end, + hl = function(self) + local general_mode = self.mode:sub(1, 1) + self.bg = self.mode_colors[general_mode] + return { bg = self.bg, fg = utils.get_highlight("StatusLine").bg, bold = true } + end, + update = { + "ModeChanged", + pattern = "*:*", + callback = vim.schedule_wrap(function() + vim.cmd("redrawstatus") + end), + }, +} +local FileIcon = { + init = function(self) + local filename = self.filename + local ext = vim.fn.fnamemodify(filename, ":e") + self.icon, self.icon_color = require("nvim-web-devicons").get_icon_color(filename, ext, { default = true }) + end, + provider = function(self) + if self.icon then + return " " .. self.icon .. " " + end + return "" + end, + hl = function(self) + return { fg = self.icon_color } + end, +} +local FileName = { + provider = function(self) + local filename = vim.fn.fnamemodify(self.filename, ":.") + if filename == "" then + return " [Unnamed] " + end + if not conditions.width_percent_below(#filename, 0.25) then + filename = vim.fn.pathshorten(filename) + end + return " " .. filename .. " " + end, + hl = { fg = "bright_fg" }, + update = { "BufRead", "BufNewFile", "BufEnter", "FileReadPost", "FileWritePre" }, +} +local FileFlags = { + { + condition = function() + return vim.bo.modified + end, + provider = "[+]", + hl = { fg = "green" }, + }, + { + condition = function() + return not vim.bo.modifiable or vim.bo.readonly + end, + provider = "", + hl = { fg = "orange" }, + }, +} +M.FileNameBlock = { + init = function(self) + self.filename = vim.api.nvim_buf_get_name(0) + end, + FileIcon, + M.Space, + FileName, + -- M.Space, + FileFlags, +} + +local FileType = { + provider = function() + return string.upper(vim.bo.filetype) + end, + hl = { fg = utils.get_highlight("Type").fg, bold = true }, +} +local FileEncoding = { + provider = function() + local enc = (vim.bo.fenc ~= "" and vim.bo.fenc) or vim.o.enc -- :h 'enc' + return enc ~= "utf-8" and enc:upper() + end, +} +local FileFormat = { + provider = function() + local fmt = vim.bo.fileformat + return fmt ~= "unix" and fmt:upper() + end, +} +M.FileAttributesBlock = { + FileFormat, + M.Space, + FileEncoding, + M.Space, + FileType, +} + +M.Ruler = { + -- %l = current line number + -- %L = number of lines in the buffer + -- %c = column number + -- %P = percentage through file of displayed window + -- TODO: check how many lines file has in total and + -- set amount of 'whitespace' here accordingly + provider = "%l:%2c", +} +M.ScrollBar = { + static = { + sbar = { "▔", "🮂", "🮃", "▀", "🮄", "🮅", "🮆", "█" }, + -- sbar = { '▁', '▂', '▃', '▄', '▅', '▆', '▇', '█' } + -- sbar = { '🭶', '🭷', '🭸', '🭹', '🭺', '🭻' } + }, + provider = function(self) + local curr_line = vim.api.nvim_win_get_cursor(0)[1] + local lines = vim.api.nvim_buf_line_count(0) + local i = math.floor((curr_line - 1) / lines * #self.sbar) + 1 + return string.rep(self.sbar[i], 2) + end, + hl = { fg = "blue", bg = "bright_bg" }, +} +M.FilePositionBlock = { + M.ScrollBar, + M.Space, + M.Ruler, + update = "CursorMoved", +} + +M.LSPActive = { + condition = conditions.lsp_attached, + update = { "LspAttach", "LspDetach" }, + provider = "  ", + hl = { fg = "green", bold = true }, +} + +M.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, + }, + init = function(self) + self.error_icon = vim.fn.sign_getdefined("DiagnosticSignError")[1].text + self.warn_icon = vim.fn.sign_getdefined("DiagnosticSignWarn")[1].text + self.info_icon = vim.fn.sign_getdefined("DiagnosticSignInfo")[1].text + self.hint_icon = vim.fn.sign_getdefined("DiagnosticSignHint")[1].text + 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 = "![", + }, + { + 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 = "]", + }, +} + +M.Git = { + condition = require("core.util").is_available("gitsigns") and conditions.is_git_repo, + init = function(self) + self.status_dict = vim.b.gitsigns_status_dict + self.has_changes = self.status_dict.added ~= 0 or self.status_dict.removed ~= 0 or self.status_dict.changed ~= 0 + end, + hl = { fg = "orange" }, + { -- git branch name + provider = function(self) + return " " .. self.status_dict.head + end, + hl = { bold = true }, + }, + -- You could handle delimiters, icons and counts similar to Diagnostics + { + condition = function(self) + return self.has_changes + end, + provider = "(", + }, + { + provider = function(self) + local count = self.status_dict.added or 0 + return count > 0 and ("+" .. count) + end, + hl = { fg = "green" }, + }, + { + provider = function(self) + local count = self.status_dict.removed or 0 + return count > 0 and ("-" .. count) + end, + hl = { fg = "red" }, + }, + { + provider = function(self) + local count = self.status_dict.changed or 0 + return count > 0 and ("~" .. count) + end, + hl = { fg = "orange" }, + }, + { + condition = function(self) + return self.has_changes + end, + provider = ")", + }, +} +return M diff --git a/nvim/.config/nvim/lua/plugins/statusline.lua b/nvim/.config/nvim/lua/plugins/statusline.lua index 468067b..e6f2c49 100644 --- a/nvim/.config/nvim/lua/plugins/statusline.lua +++ b/nvim/.config/nvim/lua/plugins/statusline.lua @@ -87,4 +87,70 @@ return { end, event = { "VeryLazy" }, }, + { + "rebelot/heirline.nvim", + dependencies = { { "nvim-tree/nvim-web-devicons", optional = true } }, + cond = false, + lazy = false, + config = function() + local cond = require("heirline.conditions") + local utils = require("heirline.utils") + local c = require("custom.components") + + local function setup_colors() + return { + bright_bg = utils.get_highlight("Folded").bg, + bright_fg = utils.get_highlight("Folded").fg, + red = utils.get_highlight("DiagnosticError").fg, + dark_red = utils.get_highlight("DiffDelete").bg, + green = utils.get_highlight("String").fg, + blue = utils.get_highlight("Function").fg, + gray = utils.get_highlight("NonText").fg, + orange = utils.get_highlight("Constant").fg, + purple = utils.get_highlight("Statement").fg, + cyan = utils.get_highlight("Special").fg, + diag_warn = utils.get_highlight("DiagnosticWarn").fg, + diag_error = utils.get_highlight("DiagnosticError").fg, + diag_hint = utils.get_highlight("DiagnosticHint").fg, + diag_info = utils.get_highlight("DiagnosticInfo").fg, + git_del = utils.get_highlight("diffDeleted").fg, + git_add = utils.get_highlight("diffAdded").fg, + git_change = utils.get_highlight("diffChanged").fg, + } + end + vim.api.nvim_create_augroup("Heirline", { clear = true }) + vim.api.nvim_create_autocmd("ColorScheme", { + callback = function() + utils.on_colorscheme(setup_colors) + end, + group = "Heirline", + }) + + require("heirline").setup({ + opts = { + colors = setup_colors(), + }, + statusline = { + hl = { + fg = utils.get_highlight("StatusLineNC").fg, + bg = utils.get_highlight("StatusLineNC").bg, + }, + -- TODO: load dynamically: color and surrounding sep shapes + -- utils.surround({ "", c.Separator.static.section.left }, "white", c.ViMode), + + { + c.ViMode, + -- c.Git, + -- c.Diagnostics, + c.FileNameBlock, + c.Align, + c.LSPActive, + c.FileAttributesBlock, + c.Space, + c.FilePositionBlock, + }, + }, + }) + end, + }, }