local M = {} local modes = { n = { "NORMAL", "StatuslineModeNormal" }, i = { "INSERT", "StatuslineModeInsert" }, v = { "VISUAL", "StatuslineModeVisual" }, V = { "V-LINE", "StatuslineModeVisual" }, [""] = { "V-BLOCK", "StatuslineModeVisual" }, R = { "REPLACE", "StatuslineModeReplace" }, c = { "COMMAND", "StatuslineModeCommand" }, } local function mode() local m = vim.fn.mode() local entry = modes[m] or { m, "StatusLine" } return string.format("%%#%s# %s %%#StatusLine#", entry[2], entry[1]) end ---------------------------------------------------------------------- -- Git branch (buffer-lokal, gecached, kein redraw-spam) ---------------------------------------------------------------------- local function update_git_branch(bufnr) bufnr = bufnr or 0 -- nur in echten Dateien if vim.bo[bufnr].buftype ~= "" then vim.b[bufnr].git_branch = "" return end -- kein Git → nichts tun if vim.fn.executable("git") ~= 1 then vim.b[bufnr].git_branch = "" return end local branch = vim.fn.systemlist("git rev-parse --abbrev-ref HEAD 2>/dev/null")[1] if branch and branch ~= "" then vim.b[bufnr].git_branch = "  " .. branch .. " " else vim.b[bufnr].git_branch = "" end end ---------------------------------------------------------------------- -- Autocmd: Git nur bei Bedarf aktualisieren ---------------------------------------------------------------------- vim.api.nvim_create_autocmd({ "BufEnter", "FocusGained" }, { callback = function(args) update_git_branch(args.buf) end, }) ---------------------------------------------------------------------- -- Statusline-Sektionen (reine Darstellung, keine IO) ---------------------------------------------------------------------- -- Git-Branch (buffer-lokal, gecached, kein redraw-spam) local function git() return vim.b.git_branch or "" end -- Git-Diff (buffer-lokal, kein redraw-spam) local function git_diff() local gsd = vim.b.gitsigns_status_dict if not gsd then return "" end local parts = {} if gsd.added and gsd.added > 0 then table.insert(parts, "+" .. gsd.added) end if gsd.changed and gsd.changed > 0 then table.insert(parts, "~" .. gsd.changed) end if gsd.removed and gsd.removed > 0 then table.insert(parts, "-" .. gsd.removed) end if #parts > 0 then return " " .. table.concat(parts, " ") .. " " end return "" end ---------------------------------------------------------------------- -- Dateiname mit Modifikationsstatus ---------------------------------------------------------------------- local function filename() local name = vim.fn.expand("%:.") if name == "" then name = "[No Name]" end if vim.bo.modified then name = name .. " [+]" end return " " .. name .. " " end ------------------------------------------------------------------------ -- Treesitter-Aktivität (buffer-lokal, kein redraw-spam) ------------------------------------------------------------------------ local function treesitter() local ok = vim.treesitter.highlighter.active[vim.api.nvim_get_current_buf()] if ok then return " 🌳 " end return "" end ------------------------------------------------------------------------ -- Diagnostik-Counts (buffer-lokal, kein redraw-spam) ------------------------------------------------------------------------ local function diagnostics() local counts = { error = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.ERROR }), warn = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.WARN }), info = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.INFO }), hint = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.HINT }), } local parts = {} if counts.error > 0 then table.insert(parts, "  " .. counts.error) end if counts.warn > 0 then table.insert(parts, "  " .. counts.warn) end if counts.info > 0 then table.insert(parts, "  " .. counts.info) end if counts.hint > 0 then table.insert(parts, "  " .. counts.hint) end if #parts > 0 then return " " .. table.concat(parts, " ") .. " " end return "" end ------------------------------------------------------------------------ -- Filetype & Encoding (buffer-lokal, kein redraw-spam) ------------------------------------------------------------------------ local function fileinfo() local ft = vim.bo.filetype ~= "" and vim.bo.filetype or "none" local enc = vim.bo.fileencoding ~= "" and vim.bo.fileencoding or vim.o.encoding return string.format(" %s %s ", ft, enc) end ------------------------------------------------------------------------ -- Cursor-Position (kein redraw-spam) ------------------------------------------------------------------------ local function position() return string.format(" %d:%d ", vim.fn.line("."), vim.fn.col(".")) end ------------------------------------------------------------------------- -- Copilot-Status (buffer-lokal, kein redraw-spam) ------------------------------------------------------------------------- local function copilot() if vim.fn.exists("*copilot#Enabled") == 0 then return "" end if vim.fn["copilot#Enabled"]() == 0 then return "  OFF " end if vim.b.copilot_suggestion and vim.b.copilot_suggestion.is_visible then return "  SUG " end if vim.b.copilot_suggestion_auto_trigger == false then return "  MAN " end return "  ON " end ---------------------------------------------------------------------- -- Öffentliche Statusline-Funktion ---------------------------------------------------------------------- function M.statusline() return table.concat({ -- LEFT: Mode & Context mode(), "%#PmenuSel#", git(), git_diff(), "%#StatusLine#", filename(), "%=", -- RIGHT: Feedback & Meta copilot(), diagnostics(), treesitter(), fileinfo(), " %p%% ", position(), }) end return M