馃 a tiny, customizable statusline for neovim
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 5daeae021b1beb4e7244102a66a8b0fcb5254ce8 234 lines 6.4 kB view raw
1local utils = {} 2 3function utils.get_client() 4 local buf_ft = vim.api.nvim_get_option_value("filetype", { buf = 0 }) 5 local result = vim.iter(vim.lsp.get_clients({ bufnr = 0 })):find(function( 6 client --[[@as vim.lsp.Client]] 7 ) 8 return vim.iter(ipairs(client.config.filetypes)):any(function(_, ft) 9 return ft == buf_ft 10 end) 11 end) 12 if result then 13 return result.config.name 14 end 15end 16 17--- flatten list so all children have level of depth 18---@param lst table 19---@param maxdepth integer 20function utils.flatten(lst, maxdepth) 21 vim.validate("lst", lst, "table") 22 vim.validate("maxdepth", maxdepth, "number") 23 24 ---@param _t any[] 25 ---@return integer 26 local function _depth(_t) 27 return vim.iter(ipairs(_t)):fold(1, function(maxd, _, v) 28 if type(v) == "table" and vim.islist(v) then 29 local d = 1 + _depth(v) 30 if d > maxd then 31 return d 32 end 33 end 34 return maxd 35 end) 36 end 37 38 local result = {} 39 ---@param _t any[] 40 local function _flatten(_t) 41 local n = #_t 42 for i = 1, n do 43 local v = _t[i] 44 if type(v) ~= "table" or (not vim.islist(v)) or _depth(v) <= maxdepth then 45 table.insert(result, v) 46 else 47 _flatten(v) 48 end 49 end 50 end 51 _flatten(lst) 52 return result 53end 54 55local sfmt = "%s%%*%s" 56local sfmt_inherit = "%s%s" 57-- str, hl_name, text 58local hlfmt = "%s%%#%s#%s" 59local hlfmt_inherit = "%s%%$%s$%s" 60 61---@param str string 62---@param text string 63---@param inherit boolean 64---@param hl? string 65---@return string 66local function strfmt(str, text, inherit, hl) 67 if hl then 68 return string.format(inherit and hlfmt_inherit or hlfmt, str, hl, text) 69 end 70 return string.format(inherit and sfmt_inherit or sfmt, str, text) 71end 72 73function utils.fold(lst) 74 vim.validate("lst", lst, "table") 75 76 lst = utils.flatten(lst, 1) 77 ---@type string|false 78 local section = false 79 return vim.iter(ipairs(lst)):fold("", function(str, _, module) 80 local inherit = not not section 81 if type(module) == "string" and #module > 0 then 82 return strfmt(str, module, inherit) 83 end 84 if type(module) ~= "table" then 85 return str 86 end 87 if module.section ~= nil and (type(module.section) == "string" or module.section == false) then 88 section = module.section 89 if section then 90 return string.format("%s%%#%s#", str, module.section) 91 end 92 return str 93 end 94 local text = module[1] 95 if text == nil or type(text) ~= "string" or #text == 0 then 96 return str 97 end 98 local hl = module[2] 99 if not hl then 100 return strfmt(str, text, inherit) 101 end 102 if type(hl) == "string" and #hl > 0 then 103 return strfmt(str, text, inherit, hl) 104 elseif type(hl) == "table" and (hl.fg or hl.bg or hl.link) then 105 inherit = inherit or hl.inherit 106 hl.inherit = nil 107 local hl_name = hl.link 108 if not hl_name then 109 hl_name = utils.create_hl(hl) 110 end 111 return strfmt(str, text, inherit, hl_name) 112 elseif type(hl) == "table" and hl.inherit then 113 return strfmt(str, text, true) 114 end 115 116 return strfmt(str, text, inherit) 117 end) 118end 119 120---@param hl_name string 121---@return vim.api.keyset.highlight 122function utils.reverse_hl(hl_name) 123 local hl = vim.api.nvim_get_hl(0, { name = hl_name }) 124 if vim.tbl_isempty(hl) or (not hl.fg and not hl.bg and not hl.link) then 125 return {} 126 end 127 if hl.link then 128 return utils.reverse_hl(hl.link) 129 end 130 local rev = vim.deepcopy(hl) 131 rev.fg = hl.bg 132 rev.bg = hl.fg 133 ---@diagnostic disable-next-line: return-type-mismatch 134 return rev 135end 136 137---@param hl vim.api.keyset.highlight 138function utils.create_hl(hl) 139 local hl_name = string.format("@lylla.%s", vim.fn.sha256(vim.inspect(hl))) 140 vim.schedule(function() 141 vim.api.nvim_set_hl(0, hl_name, hl) 142 end) 143 return hl_name 144end 145 146function utils.getfilename() 147 local _, default_file_hl = require("mini.icons").get("default", "file") 148 149 local name = vim.fn.expand("%:t") 150 151 local file_icon_raw, file_icon_hl 152 153 if vim.bo.buftype ~= "" then 154 local filetype = vim.bo.filetype 155 file_icon_raw, file_icon_hl = require("mini.icons").get("filetype", filetype) 156 else 157 file_icon_raw, file_icon_hl = require("mini.icons").get("file", name) 158 end 159 160 return { { name, default_file_hl }, { " " }, { file_icon_raw, file_icon_hl } } 161end 162 163function utils.getfilepath() 164 local path = vim.fn.expand("%:p:~:.") 165 166 local file_path_list = {} 167 local _ = string.gsub(path, "[^/]+", function(w) 168 table.insert(file_path_list, w) 169 end) 170 171 local filepath = vim.iter(ipairs(file_path_list)):fold("", function(acc, i, fragment) 172 if i == #file_path_list then 173 return acc 174 end 175 acc = acc .. fragment .. "/" 176 return acc 177 end) 178 179 return { filepath, "Directory" } 180end 181 182function utils.get_searchcount() 183 local result = vim.fn.searchcount({ recompute = 1 }) 184 if vim.v.hlsearch ~= 1 then 185 return "" 186 end 187 if vim.tbl_isempty(result) then 188 return "" 189 end 190 local term = vim.fn.getreg("/") 191 local display 192 if result.incomplete == 1 then 193 -- timed out 194 display = "[?/??]" 195 elseif result.incomplete == 2 then 196 -- max count exceeded 197 if result.total > result.maxcount and result.current > result.maxcount then 198 display = string.format("[>%d/>%d]", result.current, result.total) 199 elseif result.total > result.maxcount then 200 display = string.format("[%d/>%d]", result.current, result.total) 201 end 202 end 203 display = display or string.format("[%d/%d]", result.current, result.total) 204 205 return { { string.format("/%s", term), "IncSearch" }, { " " }, { display, "MsgSeparator" } } 206end 207 208---@param mode string 209---@return string 210function utils.get_modehl_name(mode) 211 return "@lylla." .. mode 212end 213 214---@return string 215function utils.get_modehl() 216 local mode = vim.api.nvim_get_mode().mode 217 local hl_name = utils.get_modehl_name("normal") 218 219 if string.match(mode, "^[vVs]") then 220 hl_name = utils.get_modehl_name("visual") 221 elseif string.match(mode, "^c") then 222 hl_name = utils.get_modehl_name("command") 223 elseif string.match(mode, "^[it]") then 224 hl_name = utils.get_modehl_name("insert") 225 elseif string.match(mode, "^[rR]") then 226 hl_name = utils.get_modehl_name("replace") 227 elseif string.match(mode, "^%ao") then 228 hl_name = utils.get_modehl_name("operator") 229 end 230 231 return hl_name, utils.create_hl(utils.reverse_hl(hl_name)) 232end 233 234return utils