🪴 a tiny, customizable statusline for neovim
at main 168 lines 3.4 kB view raw
1---@module 'lylla.config' 2 3---@class lylla.item 4---@field fn fun(): any 5---@field opts? { events?: string[] } 6 7---@alias lylla.item.tuple {[1]: string, [2]?: string} 8 9---@class lylla.config 10---@field refresh_rate integer 11---@field hls table<'normal'|'visual'|'command'|'insert'|'replace'|'operator', vim.api.keyset.highlight> 12---@field modules (lylla.item|lylla.item.tuple|string)[] 13---@field winbar any[] 14---@field tabline (fun(): (lylla.item|lylla.item.tuple|string)[])|vim.NIL 15 16local M, H = {}, {} 17 18---@type lylla.config 19---@eval return MiniDoc.afterlines_to_code(MiniDoc.current.eval_section) 20---@text # Default ~ 21M.default = { 22 refresh_rate = 300, 23 hls = {}, 24 modules = { 25 "%<%f %h%w%m%r", 26 "%=", 27 { 28 fn = function() 29 if vim.o.showcmdloc == "statusline" then 30 return "%-10.S" 31 end 32 return "" 33 end, 34 }, 35 { " " }, 36 { 37 fn = function() 38 if not vim.b.keymap_name then 39 return "" 40 end 41 return "<" .. vim.b.keymap_name .. ">" 42 end, 43 }, 44 { " " }, 45 { 46 fn = function() 47 if vim.bo.busy > 0 then 48 return "" 49 end 50 return "" 51 end, 52 }, 53 { " " }, 54 { 55 fn = function() 56 if not package.loaded["vim.diagnostic"] then 57 return "" 58 end 59 return vim.diagnostic.status() 60 end, 61 opts = { 62 events = { "DiagnosticChanged" }, 63 }, 64 }, 65 { " " }, 66 { 67 fn = function() 68 if not vim.o.ruler then 69 return "" 70 end 71 if vim.o.rulerformat == "" then 72 return "%-14.(%l,%c%V%) %P" 73 end 74 return vim.o.rulerformat 75 end, 76 }, 77 }, 78 winbar = {}, 79 tabline = vim.NIL, 80} 81 82---@type lylla.config 83---@diagnostic disable-next-line: missing-fields 84M.config = {} 85 86---@return lylla.config 87function M.get() 88 return H.merge(M.default, M.config) 89end 90 91---@param cfg lylla.config 92---@return lylla.config 93function M.override(cfg) 94 return H.merge(M.default, cfg) 95end 96 97---@param cfg lylla.config 98function M.set(cfg) 99 M.config = cfg 100end 101 102-- helpers ==================================================================== 103 104---@param tdefault lylla.config 105---@param toverride lylla.config 106---@return lylla.config 107function H.merge(tdefault, toverride) 108 return H.tmerge(tdefault, toverride) 109end 110 111---@private 112---@generic T: table|any[] 113---@param tdefault T 114---@param toverride T 115---@return T 116H.tmerge = function(tdefault, toverride) 117 if toverride == nil then 118 return tdefault 119 end 120 121 -- do not merge lists 122 if H.islist(tdefault) then 123 return toverride 124 end 125 if vim.tbl_isempty(tdefault) then 126 return toverride 127 end 128 129 return vim.iter(pairs(tdefault)):fold({}, function(tnew, k, v) 130 if toverride[k] == nil then 131 tnew[k] = v 132 return tnew 133 end 134 if type(v) ~= type(toverride[k]) then 135 tnew[k] = toverride[k] 136 return tnew 137 end 138 if type(v) == "table" then 139 tnew[k] = H.tmerge(v, toverride[k]) 140 return tnew 141 end 142 143 tnew[k] = toverride[k] 144 return tnew 145 end) 146end 147 148---@param t table 149---@return boolean 150H.islist = function(t) 151 if type(t) ~= "table" then 152 return false 153 end 154 155 for k, _ in ipairs(t) do 156 return type(k) == "number" 157 end 158 159 -- non-numeric keys 160 for _, _ in pairs(t) do 161 return false 162 end 163 164 -- empty table 165 return true 166end 167 168return M, H