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