🪴 a tiny, customizable statusline for neovim
3
fork

Configure Feed

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

feat: winbar support

robin df9af247 fa624f55

+170 -6
+38 -5
lua/lylla/config.lua
··· 6 6 ---@field prefix string 7 7 ---@field hls table<'normal'|'visual'|'command'|'insert', vim.api.keyset.highlight> 8 8 ---@field modules any[] 9 + ---@field winbar any[] 9 10 10 11 local utils = require("lylla.utils") 11 12 ··· 43 44 hls = {}, 44 45 modules = { 45 46 component(function() 46 - local prefix = require('lylla.config').get().prefix 47 + local prefix = require("lylla.config").get().prefix 47 48 local modehl = utils.get_modehl() 48 49 return { 49 50 { prefix, modehl }, ··· 90 91 { "%l:%c" }, 91 92 { " " }, 92 93 }, 94 + winbar = { 95 + component(function() 96 + local prefix = require("lylla.config").get().prefix 97 + local modehl = utils.get_modehl() 98 + return { 99 + { prefix, modehl }, 100 + } 101 + end, { 102 + events = { "ModeChanged", "CmdlineEnter" }, 103 + }), 104 + { " " }, 105 + component(function() 106 + return { 107 + utils.getfilepath(), 108 + utils.getfilename(), 109 + { " " }, 110 + } 111 + end, { 112 + events = { 113 + "WinEnter", 114 + "BufEnter", 115 + "BufWritePost", 116 + "FileChangedShellPost", 117 + "Filetype", 118 + }, 119 + }), 120 + { " " }, 121 + component(function() 122 + return { utils.get_searchcount() } 123 + end), 124 + }, 93 125 } 94 126 95 127 ---@type lylla.config ··· 118 150 tnew[k] = v 119 151 return tnew 120 152 end 121 - if type(v) == 'table' then 153 + if type(v) == "table" then 122 154 tnew[k] = tmerge(v, toverride[k]) 123 155 return tnew 124 156 end ··· 132 164 ---@param toverride lylla.config 133 165 ---@return lylla.config 134 166 function M.merge(tdefault, toverride) 135 - if vim.fn.has('nvim-0.11.0') == 1 then 136 - toverride = vim.tbl_deep_extend('keep', toverride, { editor = { float = { solid_border = vim.o.winborder == 'solid' } } }) 167 + if vim.fn.has("nvim-0.11.0") == 1 then 168 + toverride = 169 + vim.tbl_deep_extend("keep", toverride, { editor = { float = { solid_border = vim.o.winborder == "solid" } } }) 137 170 end 138 171 return tmerge(tdefault, toverride) 139 172 end ··· 146 179 ---@param cfg lylla.config 147 180 ---@return lylla.config 148 181 function M.override(cfg) 149 - return M.merge( M.default, cfg) 182 + return M.merge(M.default, cfg) 150 183 end 151 184 152 185 ---@param cfg lylla.config
+7 -1
lua/lylla/init.lua
··· 35 35 36 36 function M.init() 37 37 vim.api.nvim_create_autocmd("WinNew", { 38 - group = vim.api.nvim_create_augroup("lylla:statusline:new", { clear = true }), 38 + group = vim.api.nvim_create_augroup("lylla:win:new", { clear = true }), 39 39 callback = function() 40 40 local win = vim.api.nvim_get_current_win() 41 41 require("lylla.statusline"):new(win):init() 42 + require("lylla.winbar"):new(win):init() 42 43 end, 43 44 }) 44 45 local win = vim.api.nvim_get_current_win() 45 46 require("lylla.statusline"):new(win):init() 47 + require("lylla.winbar"):new(win):init() 46 48 47 49 vim.api.nvim_create_autocmd("WinClosed", { 48 50 group = vim.api.nvim_create_augroup("lylla:close", { clear = true }), ··· 50 52 local stl = require("lylla.statusline").wins[ev.match] 51 53 if stl then 52 54 stl:close() 55 + end 56 + local wbar = require("lylla.winbar").wins[ev.match] 57 + if wbar then 58 + wbar:close() 53 59 end 54 60 end, 55 61 })
+125
lua/lylla/winbar.lua
··· 1 + local utils = require("lylla.utils") 2 + 3 + ---@type lylla.proto 4 + ---@diagnostic disable-next-line: missing-fields 5 + local winbar = {} 6 + 7 + winbar.wins = {} 8 + 9 + ---@class lylla.proto 10 + ---@field new fun(self, win): lylla.proto 11 + function winbar:new(win) 12 + if winbar.wins[win] then 13 + winbar.wins[win]:close() 14 + end 15 + local stl = setmetatable({ 16 + win = win, 17 + modules = vim.deepcopy(require("lylla.config").get().winbar, true), 18 + }, { __index = winbar }) 19 + winbar.wins[win] = stl 20 + return stl 21 + end 22 + 23 + ---@class lylla.proto 24 + ---@field init fun(self) 25 + function winbar:init() 26 + local err, err_kind 27 + ---@diagnostic disable-next-line: assign-type-mismatch 28 + self.timer, err, err_kind = vim.uv.new_timer() 29 + if not self.timer or err then 30 + vim.api.nvim_echo({ { err_kind }, { "\n\t" }, { err } }, true, { err = true }) 31 + return 32 + end 33 + 34 + local refresh = require("lylla.config").get().refresh_rate 35 + self.timer:start(0, refresh, function() 36 + self:refresh() 37 + end) 38 + 39 + self.refreshau = vim.api.nvim_create_autocmd(require("lylla.config").get().events, { 40 + group = vim.api.nvim_create_augroup("lylla:refresh", { clear = false }), 41 + callback = function(ev) 42 + self:refresh(ev) 43 + end, 44 + }) 45 + end 46 + 47 + ---@class lylla.proto 48 + ---@field close fun(self) 49 + function winbar:close() 50 + self.timer:stop() 51 + self.timer:close() 52 + vim.api.nvim_del_autocmd(self.refreshau) 53 + winbar.wins[self.win] = nil 54 + end 55 + 56 + ---@class lylla.proto 57 + ---@field refresh fun(self, ev?: vim.api.keyset.create_autocmd.callback_args) 58 + function winbar:refresh(ev) 59 + vim.schedule(function() 60 + if not vim.api.nvim_win_is_valid(self.win) then 61 + return 62 + end 63 + 64 + local buf = vim.api.nvim_win_get_buf(self.win) 65 + if vim.bo[buf].buftype ~= "" then 66 + return 67 + end 68 + 69 + local ok, result = pcall(vim.api.nvim_win_call, self.win, function() 70 + return self:get(ev) 71 + end) 72 + if not ok then 73 + return 74 + end 75 + 76 + vim.wo[self.win].winbar = result 77 + end) 78 + end 79 + 80 + ---@class lylla.proto 81 + ---@field fold fun(self, ev?: vim.api.keyset.create_autocmd.callback_args): string 82 + function winbar:fold(ev) 83 + local modules = vim 84 + .iter(ipairs(self.modules)) 85 + :map(function(i, module) 86 + if type(module) == "table" and module._type == "component" then 87 + if module.opts and module.opts.events then 88 + -- refresh from timer 89 + if not ev and module.prev then 90 + return module.prev 91 + end 92 + -- refresh from non-match event 93 + if ev and not vim.tbl_contains(module.opts.events, ev.event) and module.prev then 94 + return module.prev 95 + end 96 + end 97 + module.prev = module.fn() 98 + return module.prev 99 + end 100 + if type(module) == "function" then 101 + module = module() 102 + end 103 + return module 104 + end) 105 + :totable() 106 + modules = utils.flatten(modules, 1) 107 + return vim.iter(modules):fold("", function(str, module) 108 + if type(module) ~= "table" or #module == 0 then 109 + return str 110 + end 111 + local text = module[1] 112 + if #module > 1 then 113 + return str .. "%#" .. module[2] .. "#" .. text .. "%*" 114 + end 115 + return str .. "%*" .. text 116 + end) 117 + end 118 + 119 + ---@class lylla.proto 120 + ---@field get fun(self, ev?: vim.api.keyset.create_autocmd.callback_args) 121 + function winbar:get(ev) 122 + return self:fold(ev) 123 + end 124 + 125 + return winbar