🪴 a tiny, customizable statusline for neovim

doc: add README

robin fc672e4c d7b4560d

+263
+263
README.md
··· 1 + # lylla.nvim 2 + 3 + a minimal statusline plugin for neovim with extensive configuration; simple by default, flexible if needed. 4 + 5 + ## features 6 + 7 + - minimal default look, based on neovim default statusline implementation 8 + - flexible configuration; define your own components 9 + - lightweight design; no required dependencies 10 + 11 + ## goals 12 + 13 + lylla is designed to be: 14 + 15 + - minimal in features (no clutter) 16 + - maximal in configuration 17 + - stable and predictable; i wanted to prevent any hidden logic that i got 18 + annoyed by in other statusline plugins 19 + 20 + ## installation 21 + 22 + ###### `vim.pack` 23 + 24 + ```lua 25 + vim.pack.add({ src = "comfysage/lylla.nvim" }) 26 + ``` 27 + 28 + ###### `lazy.nvim` 29 + 30 + ```lua 31 + { 32 + "comfysage/lylla.nvim", lazy = false, 33 + } 34 + ``` 35 + 36 + ### dependencies 37 + 38 + some of the utilities included in lylla use 39 + [mini.nvim](https://github.com/mini-nvim/mini.nvim) but these are not required 40 + in the default implementation. 41 + 42 + ## configuration 43 + 44 + the default configuration is as follows: 45 + 46 + ```lua 47 + require("lylla").setup({ 48 + refresh_rate = 300, 49 + events = { 50 + "WinEnter", 51 + "BufEnter", 52 + "BufWritePost", 53 + "SessionLoadPost", 54 + "FileChangedShellPost", 55 + "VimResized", 56 + "Filetype", 57 + "CursorMoved", 58 + "CursorMovedI", 59 + "ModeChanged", 60 + "CmdlineEnter", 61 + }, 62 + hls = {}, 63 + modules = { 64 + "%<%f %h%w%m%r", 65 + "%=", 66 + { 67 + fn = function() 68 + if vim.o.showcmdloc == "statusline" then 69 + return "%-10.S" 70 + end 71 + return "" 72 + end, 73 + }, 74 + { " " }, 75 + { 76 + fn = function() 77 + if not vim.b.keymap_name then 78 + return "" 79 + end 80 + return "<" .. vim.b.keymap_name .. ">" 81 + end, 82 + }, 83 + { " " }, 84 + { 85 + fn = function() 86 + if vim.bo.busy > 0 then 87 + return "◐ " 88 + end 89 + return "" 90 + end, 91 + }, 92 + { " " }, 93 + { 94 + fn = function() 95 + if not package.loaded["vim.diagnostic"] then 96 + return "" 97 + end 98 + return vim.diagnostic.status() 99 + end, 100 + opts = { 101 + events = { "DiagnosticChanged" }, 102 + }, 103 + }, 104 + { " " }, 105 + { 106 + fn = function() 107 + if not vim.o.ruler then 108 + return "" 109 + end 110 + if vim.o.rulerformat == "" then 111 + return "%-14.(%l,%c%V%) %P" 112 + end 113 + return vim.o.rulerformat 114 + end, 115 + }, 116 + }, 117 + winbar = {}, 118 + }) 119 + ``` 120 + 121 + ### example configuration 122 + 123 + #### use `mini.icons` for colors 124 + 125 + some nice highlights that i personally use: 126 + 127 + ```lua 128 + hls = { 129 + normal = { link = "MiniIconsAzure" }, 130 + visual = { link = "MiniIconsPurple" }, 131 + command = { link = "MiniIconsOrange" }, 132 + insert = { link = "MiniIconsGrey" }, 133 + }, 134 + ``` 135 + 136 + ### example components 137 + 138 + you can define custom components by passing lua functions: 139 + 140 + ```lua 141 + local lylla = require("lylla") 142 + 143 + lylla.setup({ 144 + modules = { 145 + lylla.component(function() 146 + return "hi " .. vim.env.USER 147 + end, { events = { "VimEnter" } }), 148 + }, 149 + }) 150 + ``` 151 + 152 + components return strings to be shown in the statusline and can register 153 + autocmds to refresh them. 154 + 155 + components can also return a tuple combining text with a highlight group: 156 + 157 + ```lua 158 + { 159 + { 160 + { "meow", "ModeMsg" }, 161 + { " | ", "WinSeparator" }, 162 + }, 163 + { fn = function() return { vim.bo.filetype, "MsgArea" } end }, 164 + } 165 + ``` 166 + 167 + these tables can be nested to any amount; they all get folded down on refresh. 168 + 169 + ### change refresh rate and events 170 + 171 + ```lua 172 + require("lylla").setup { 173 + refresh_rate = 100, -- update faster 174 + events = { "WinEnter", "BufEnter", "CursorMoved" }, -- only update on these 175 + } 176 + ``` 177 + 178 + (events control when the statusline is redrawn) 179 + 180 + ### add a custom module 181 + 182 + modules are just tables that return strings. 183 + this example shows your current working directory: 184 + 185 + ```lua 186 + local lylla = require("lylla") 187 + 188 + lylla.setup { 189 + modules = { 190 + "%<%f %h%w%m%r", -- filename etc 191 + "%=", -- spacer 192 + { 193 + fn = function() 194 + return vim.fn.fnamemodify(vim.fn.getcwd(), ":t") 195 + end, opts = { 196 + events = { "DirChanged" }, 197 + }, 198 + }, 199 + }, 200 + } 201 + ``` 202 + 203 + ### conditional modules 204 + 205 + modules can react to options, buffers, or plugins. 206 + example: only show diagnostics if `vim.diagnostic` is loaded: 207 + 208 + ```lua 209 + { 210 + lylla.component(function() 211 + if not package.loaded["vim.diagnostic"] then 212 + return "" 213 + end 214 + return vim.diagnostic.status() 215 + end, { events = { "DiagnosticChanged" } }), 216 + } 217 + ``` 218 + 219 + ### lsp information 220 + 221 + lylla utils has a builtin helper for getting the current lsp client. 222 + 223 + ```lua 224 + local utils = require("lylla.utils") 225 + 226 + { 227 + lylla.component(function() 228 + local client = utils.get_client() 229 + return client and { 230 + { { "lsp :: " }, { client } }, 231 + } 232 + end, { events = { "FileType" } }), 233 + } 234 + ``` 235 + 236 + ### winbar 237 + 238 + the winbar can be configured in the same way as the statusline: 239 + 240 + ```lua 241 + winbar = { 242 + lylla.component(function() 243 + return { 244 + utils.getfilepath(), 245 + utils.getfilename(), 246 + { " " }, 247 + "%h%w%m%r", 248 + } 249 + end, { 250 + events = { 251 + "WinEnter", 252 + "BufEnter", 253 + "BufWritePost", 254 + "FileChangedShellPost", 255 + "Filetype", 256 + }, 257 + }), 258 + { " " }, 259 + lylla.component(function() 260 + return utils.get_searchcount() 261 + end), 262 + }, 263 + ```