🪴 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 },
121```
122
123### example components
124
125you can define custom components by passing lua functions:
126
127```lua
128local lylla = require("lylla")
129
130lylla.setup({
131 modules = {
132 lylla.component(function()
133 return "hi " .. vim.env.USER
134 end, { events = { "VimEnter" } }),
135 },
136})
137```
138
139components return strings to be shown in the statusline and can register
140autocmds to refresh them.
141
142components can also return a tuple combining text with a highlight group:
143
144```lua
145{
146 {
147 { "meow", "ModeMsg" },
148 { " | ", "WinSeparator" },
149 },
150 { fn = function() return { vim.bo.filetype, "MsgArea" } end },
151}
152```
153
154these tables can be nested to any amount; they all get folded down on refresh.
155
156### change refresh rate and events
157
158```lua
159require("lylla").setup {
160 refresh_rate = 100, -- update faster
161 events = { "WinEnter", "BufEnter", "CursorMoved" }, -- only update on these
162}
163```
164
165(events control when the statusline is redrawn)
166
167### add a custom module
168
169modules are just tables that return strings.
170this example shows your current working directory:
171
172```lua
173local lylla = require("lylla")
174
175lylla.setup {
176 modules = {
177 "%<%f %h%w%m%r", -- filename etc
178 "%=", -- spacer
179 {
180 fn = function()
181 return vim.fn.fnamemodify(vim.fn.getcwd(), ":t")
182 end, opts = {
183 events = { "DirChanged" },
184 },
185 },
186 },
187}
188```
189
190### conditional modules
191
192modules can react to options, buffers, or plugins.
193example: only show diagnostics if `vim.diagnostic` is loaded:
194
195```lua
196{
197 lylla.component(function()
198 if not package.loaded["vim.diagnostic"] then
199 return ""
200 end
201 return vim.diagnostic.status()
202 end, { events = { "DiagnosticChanged" } }),
203}
204```
205
206### lsp information
207
208lylla utils has a builtin helper for getting the current lsp client.
209
210```lua
211local utils = require("lylla.utils")
212
213{
214 lylla.component(function()
215 local client = utils.get_client()
216 return client and {
217 { { "lsp :: " }, { client } },
218 }
219 end, { events = { "FileType" } }),
220}
221```
222
223### winbar
224
225the winbar can be configured in the same way as the statusline:
226
227```lua
228winbar = {
229 lylla.component(function()
230 return {
231 utils.getfilepath(),
232 utils.getfilename(),
233 { " " },
234 "%h%w%m%r",
235 }
236 end, {
237 events = {
238 "WinEnter",
239 "BufEnter",
240 "BufWritePost",
241 "FileChangedShellPost",
242 "Filetype",
243 },
244 }),
245 { " " },
246 lylla.component(function()
247 return utils.get_searchcount()
248 end),
249},
250```