return { "rebelot/heirline.nvim", lazy = false, event = "UiEnter", opts = function() local utils = require("heirline.utils") local conditions = require("heirline.conditions") --[=[ Helpers ]=]-- function inverseColors(highlight) if highlight == nil then return nil end if type(highlight) == "string" then highlight = utils.get_highlight(highlight) end highlight.cterm = { reverse = true } return highlight end local delimiters = { FilledCircle = { "", "" }, Circle = { "", "" }, } local StatusLineColor = utils.get_highlight("StatusLine") function surround(delimiters, component, additional_update) return { init = function(self) local highlight if component.hl ~= nil and type(component.hl) == "function" then if component.init ~= nil then component:init() end highlight = component:hl() else highlight = component.hl end self.inverse = inverseColors(highlight) self.inverse.ctermfg = StatusLineColor.ctermfg -- Actually sets bg, but both are reversed end, { condition = function() return conditions.is_active() end, provider = delimiters[1], hl = function(self) return self.inverse end, }, component, { condition = function() return conditions.is_active() end, provider = delimiters[2], hl = function(self) return self.inverse end, }, update = { "BufEnter", "BufLeave", additional_update }, } end function set_hl(name, val) vim.api.nvim_set_hl(0, name, val) return val end --[=[ Common elements ]=]-- local FileStat = { { condition = function() return vim.bo.readonly end, provider = "", }, { condition = function() return vim.bo.modified or not vim.bo.modifiable end, provider = function(self) local prepend = vim.bo.readonly and " " or "" if vim.bo.modified then return prepend.."" end if not vim.bo.modifiable then return prepend.."" end end, }, } local FileType = { static = { get_icon = require("nvim-web-devicons").get_icon_by_filetype, }, provider = function(self) local icon = self.get_icon(vim.bo.filetype) if icon ~= nil then icon = icon.." " else icon = "" end return icon..vim.bo.filetype end, update = "FileType", } local Filename = { provider = "%f", } local Space = { provider = " ", } --[=[ Statusline ]=]-- set_hl("ModeNormal", { ctermfg = 236, ctermbg = 117 }) set_hl("ModeInsert", { ctermfg = 236, ctermbg = 119 }) set_hl("ModeReplace", { ctermfg = 236, ctermbg = 203 }) set_hl("ModeVisual", { ctermfg = 236, ctermbg = 216 }) local Mode = surround(delimiters.FilledCircle, { init = function(self) self.modestr = vim.fn.mode(1) if self.modestr == "\22" then self.modestr = "V^" elseif self.modestr == "\22s" then self.modestr = "V^s" end end, provider = function(self) if not conditions.is_active() then return " " end return self.modestr end, hl = function(self) if not conditions.is_active() then return "StatusLineNC" end local modeletter = self.modestr:sub(1,1):lower() if modeletter == "i" then return "ModeInsert" elseif modeletter == "r" then return "ModeReplace" elseif modeletter == "v" then return "ModeVisual" end return "ModeNormal" end, }, "ModeChanged") vim.cmd.highlight({ "RowAndColumn", "ctermfg=238", "ctermbg=244" }) local LineAndColumn = surround(delimiters.FilledCircle, { provider = function(self) if not conditions.is_active() then local row,col = unpack(vim.api.nvim_win_get_cursor(0)) return string.rep(" ", 1 + tostring(row):len() + tostring(col):len()) end return "%l:%c" end, hl = function(self) if not conditions.is_active() then return "StatusLineNC" end return "RowAndColumn" end, }) local LeftShrink = { provider = "%<", } local LeftSep = { provider = " "..delimiters.Circle[2].." " } local RightSep = { provider = " "..delimiters.Circle[1].." " } local ExpandMiddle = { provider = "%=", } local CursorChar = { provider = "%b", } local StatusLine = { Mode, LeftShrink, Space, Filename, LeftSep, FileStat, ExpandMiddle, CursorChar, RightSep, FileType, Space, LineAndColumn } --[=[ Tabline ]=]-- local hl_TabLine = set_hl("TabLine", { ctermfg = 252, ctermbg = 242 }) local hl_TabLineSel = set_hl("TabLineSel", { ctermfg = 252, ctermbg = 235 }) local hl_TabLineFill = set_hl("TabLineFill", { ctermfg = 248, ctermbg = 238 }) set_hl("TabLineRFR", { ctermfg = hl_TabLine.ctermbg, ctermbg = hl_TabLineFill.ctermbg }) -- nonactive Right Full, Rightmost set_hl("TabLineSelRF", { ctermfg = hl_TabLineSel.ctermbg, ctermbg = hl_TabLine.ctermbg }) -- active Right Full set_hl("TabLineSelRFR", { ctermfg = hl_TabLineSel.ctermbg, ctermbg = hl_TabLineFill.ctermbg }) -- active Right Full, Rightmost set_hl("TabLineSelLF", { ctermfg = hl_TabLine.ctermbg, ctermbg = hl_TabLineSel.ctermbg }) -- active Left Full (left one's Right Full) local TabPage = { init = function(self) self.pages = vim.api.nvim_list_tabpages() end, { static = { get_icon = require("nvim-web-devicons").get_icon, ft_icon = require("nvim-web-devicons").get_icon_by_filetype, none_icon = "", }, init = function(self) self.bufnr = vim.api.nvim_win_get_buf(vim.api.nvim_tabpage_get_win(self.tabpage)) end, provider = function(self) --[==[ Filename ]==]-- local filename = vim.fn.fnamemodify(vim.api.nvim_buf_get_name(self.bufnr), ":t") if #filename == 0 then filename = "[No Name]" end local max_name_len = vim.o.columns / (5 + #self.pages) filename = (self.get_icon(filename, vim.fn.fnamemodify(filename, ":e")) or self.ft_icon(vim.bo[self.bufnr].filetype) or self.none_icon) .. " " .. string.sub(filename, 1, max_name_len) --[==[ Readonly ]==]-- local readonly = vim.bo[self.bufnr].readonly and " " or "" --[==[ Modification ]==]-- local mod = vim.bo[self.bufnr].modified and " " or (vim.bo[self.bufnr].modifiable and "" or " ") --[==[ Tab ]==]-- return "%" .. self.tabnr .. "T" .. " " .. filename .. readonly .. mod .. " " end, hl = function(self) if not self.is_active then return "TabLine" else return "TabLineSel" end end, }, { init = function(self) local activenr = vim.api.nvim_tabpage_get_number(vim.api.nvim_get_current_tabpage()) self.dist = self.tabnr - activenr self.last = self.tabnr == #self.pages end, provider = function(self) return (self.last or self.dist == -1 or self.dist == 0) and delimiters.FilledCircle[2] or delimiters.Circle[2] end, hl = function(self) if not self.is_active then return self.last and "TabLineRFR" or (self.dist == -1 and "TabLineSelLF" or "TabLine") else return self.last and "TabLineSelRFR" or "TabLineSelRF" end end, }, { provider = "%T" } } local TabPages = { -- only show this component if there's 2 or more tabpages condition = function() return #vim.api.nvim_list_tabpages() >= 2 end, utils.make_tablist(TabPage), } local TabLine = { TabPages, } --[=[ Setup ]=]-- return { statusline = StatusLine, tabline = TabLine, } end, }