-- ===================================================== -- Native Statusline Implementation -- Replacement for lualine.nvim -- ===================================================== local M = {} -- Import colors from our native colorscheme local function get_colors() local ok, colorscheme = pcall(require, "config.native-colorscheme") if ok then return colorscheme.colors end -- Fallback colors return { base03 = "#16161e", fg = "#c0caf5", blue100 = "#9bb3f7", green100 = "#b3d882", yellow100 = "#e7c664", orange100 = "#ffad7a", red100 = "#ff7a93", cyan100 = "#7dd3c0", magenta100 = "#d2a8ff", base4 = "#c0caf5", green300 = "#9ece6a", yellow300 = "#e0af68", red300 = "#f7768e", blue300 = "#7aa2f7", cyan300 = "#73daca", orange300 = "#ff9e64", } end local colors = get_colors() -- Helper function to create highlight groups local function create_highlight(name, fg, bg, style) local hl = { fg = fg, bg = bg } if style then if style:find("bold") then hl.bold = true end if style:find("italic") then hl.italic = true end end vim.api.nvim_set_hl(0, name, hl) return "%#" .. name .. "#" end -- Define statusline highlight groups local function setup_highlights() create_highlight("StatuslineModeNormal", colors.blue100, colors.base03, "bold") create_highlight("StatuslineModeInsert", colors.green100, colors.base03, "bold") create_highlight("StatuslineModeVisual", colors.magenta100, colors.base03, "bold") create_highlight("StatuslineModeReplace", colors.red100, colors.base03, "bold") create_highlight("StatuslineModeCommand", colors.yellow100, colors.base03, "bold") create_highlight("StatuslineModeTerminal", colors.orange100, colors.base03, "bold") create_highlight("StatuslineBranch", colors.orange100, colors.base03, "bold") create_highlight("StatuslineFilename", colors.yellow100, colors.base03, "bold") create_highlight("StatuslineLSP", colors.base4, colors.base03, "bold") create_highlight("StatuslineFiletype", colors.magenta100, colors.base03, "bold") create_highlight("StatuslineProgress", colors.cyan100, colors.base03, "bold") create_highlight("StatuslineGitAdd", colors.green300, colors.base03, "bold") create_highlight("StatuslineGitChange", colors.yellow300, colors.base03, "bold") create_highlight("StatuslineGitDelete", colors.red300, colors.base03, "bold") create_highlight("StatuslineDiagError", colors.red300, colors.base03, "bold") create_highlight("StatuslineDiagWarn", colors.yellow300, colors.base03, "bold") create_highlight("StatuslineDiagInfo", colors.blue300, colors.base03, "bold") create_highlight("StatuslineDiagHint", colors.cyan300, colors.base03, "bold") create_highlight("StatuslineSeparator", colors.base03, colors.base03, "") end -- Get current mode local function get_mode() local mode_map = { n = { "NORMAL", "StatuslineModeNormal", " " }, i = { "INSERT", "StatuslineModeInsert", " " }, v = { "VISUAL", "StatuslineModeVisual", "󰈈 " }, V = { "V-LINE", "StatuslineModeVisual", " " }, [""] = { "V-BLOCK", "StatuslineModeVisual", "󰩭 " }, c = { "COMMAND", "StatuslineModeCommand", " " }, R = { "REPLACE", "StatuslineModeReplace", "󰛔 " }, t = { "TERMINAL", "StatuslineModeTerminal", " " }, } local current_mode = vim.fn.mode() local mode_info = mode_map[current_mode] or { "UNKNOWN", "StatuslineModeNormal", " " } return "%#" .. mode_info[2] .. "#" .. mode_info[3] .. mode_info[1] .. " " end -- Get git branch local function get_git_branch() local handle = io.popen("git branch --show-current 2>/dev/null") if not handle then return "" end local branch = handle:read("*l") handle:close() if not branch or branch == "" then return "" end return "%#StatuslineBranch# " .. branch .. " " end -- Get git diff stats local function get_git_diff() -- Check if we're in a git repository local handle = io.popen("git rev-parse --is-inside-work-tree 2>/dev/null") if not handle then return "" end local is_git = handle:read("*l") handle:close() if is_git ~= "true" then return "" end -- Get staged changes local staged_handle = io.popen("git diff --cached --numstat 2>/dev/null | wc -l") local added = staged_handle and staged_handle:read("*l") or "0" if staged_handle then staged_handle:close() end -- Get unstaged changes local unstaged_handle = io.popen("git diff --numstat 2>/dev/null | wc -l") local modified = unstaged_handle and unstaged_handle:read("*l") or "0" if unstaged_handle then unstaged_handle:close() end local result = "" if tonumber(added) and tonumber(added) > 0 then result = result .. "%#StatuslineGitAdd# +" .. added .. " " end if tonumber(modified) and tonumber(modified) > 0 then result = result .. "%#StatuslineGitChange# ~" .. modified .. " " end return result end -- Get filename with path local function get_filename() local filename = vim.fn.expand("%:t") if filename == "" then filename = "[No Name]" end return "%#StatuslineFilename# " .. filename .. " " end -- Get LSP clients local function get_lsp_clients() local clients = vim.lsp.get_clients({ bufnr = 0 }) if #clients == 0 then return "%#StatuslineLSP#No LSP " end local client_names = {} for _, client in ipairs(clients) do table.insert(client_names, client.name) end return "%#StatuslineLSP#" .. table.concat(client_names, ",") .. " " end -- Get diagnostics local function get_diagnostics() local diagnostics = vim.diagnostic.get(0) local counts = { error = 0, warn = 0, info = 0, hint = 0 } for _, diagnostic in ipairs(diagnostics) do if diagnostic.severity == vim.diagnostic.severity.ERROR then counts.error = counts.error + 1 elseif diagnostic.severity == vim.diagnostic.severity.WARN then counts.warn = counts.warn + 1 elseif diagnostic.severity == vim.diagnostic.severity.INFO then counts.info = counts.info + 1 elseif diagnostic.severity == vim.diagnostic.severity.HINT then counts.hint = counts.hint + 1 end end local result = "" if counts.error > 0 then result = result .. "%#StatuslineDiagError# " .. counts.error .. " " end if counts.warn > 0 then result = result .. "%#StatuslineDiagWarn# " .. counts.warn .. " " end if counts.info > 0 then result = result .. "%#StatuslineDiagInfo# " .. counts.info .. " " end if counts.hint > 0 then result = result .. "%#StatuslineDiagHint#󰠠 " .. counts.hint .. " " end return result end -- Get filetype local function get_filetype() local filetype = vim.bo.filetype if filetype == "" then return "" end return "%#StatuslineFiletype#" .. filetype .. " " end -- Get progress (line/total) local function get_progress() local current = vim.fn.line(".") local total = vim.fn.line("$") local percentage = math.floor((current / total) * 100) return "%#StatuslineProgress#" .. percentage .. "%% " end -- Get separator local function separator() return "%#StatuslineSeparator# " end -- Build the statusline function M.build_statusline() local left = get_mode() .. separator() .. get_git_branch() .. separator() .. get_git_diff() .. separator() .. get_filename() local right = get_diagnostics() .. separator() .. get_lsp_clients() .. separator() .. get_filetype() .. separator() .. get_progress() return left .. "%=" .. right end -- Setup function function M.setup() setup_highlights() -- Set up autocommands to refresh statusline vim.api.nvim_create_augroup("NativeStatusline", { clear = true }) -- Update statusline on various events vim.api.nvim_create_autocmd({ "VimEnter", "WinEnter", "BufEnter", "ModeChanged", "DiagnosticChanged" }, { group = "NativeStatusline", callback = function() vim.opt.statusline = M.build_statusline() end, }) -- Set initial statusline vim.opt.statusline = M.build_statusline() -- Always show statusline vim.opt.laststatus = 2 end return M