This is a plugin
for lualine.nvim
with additional components.
- ✅ Requirenments
- 📥 Installation
- 🔧 New common component options
- 🎬 Make a demo
- 🧩 Provided components
- 🛠️ Tools
The main
branch is compatible with the last version of the neovim and lualine. It contains
the last fixes and updates. Tagged releases can be more stable. The actual
version requires the neovim is 0.10.0
or upper, but the version 0.3.1
can
work with neovim 0.8.0
.
This is not a plugin for neovim. This is a plugin for plugin for neovim ㋡.
So, it's reasonable to install it as dependency for lualine.nvim
:
{
'nvim-lualine/lualine.nvim',
dependencies = {
{ 'dokwork/lualine-ex' },
{ 'nvim-lua/plenary.nvim' },
{ 'kyazdani42/nvim-web-devicons' },
}
}
use {
'nvim-lualine/lualine.nvim',
requires = {
{ 'dokwork/lualine-ex' },
{ 'nvim-lua/plenary.nvim' },
{ 'kyazdani42/nvim-web-devicons' },
}
}
It may be reasonable to use particular tag to avoid breaking changes.
Every provided component has additional options:
{
-- The function or boolean to check is the component enabled or not:
is_enabled = true
-- The color for the disabled component:
disabled_color = { fg = 'grey' }
-- The color for the icon of the disabled component:
disabled_icon_color = { fg = 'grey' }
-- The different default for the option:
draw_empty = true
}
This plugin introduces a new disabled
state. This state means that a component is not active, but
an icon still should be shown with disabled
color. The difference between cond = false
and the
is_enabled = false
is that in the first case a component will not be rendered at all, but in the
second case only the icon with disabled_color
will be shown.
You may try every component from this repo in the separate nvim instance. To do this run in terminal:
make demo component=<component name>
Where the <component name>
is the same string as should be used in the
lualine configuration. For example: ex.cwd
.
Also, it's possible to pass a custom component options to the demo:
make demo component=<component name> component_opts='<json object>'
The <json object>
should correspond to the lua table with component options.
For example:
make demo component=ex.cwd component_opts='{ "depth": 1 }'

Most of the components use icons from a patched nerd font by default.
vim.o.spell=true
:
vim.o.spell=false
:
This simplest component shows an actual status of the vim.wo.spell
option.
sections = {
lualine_a = {
{
'ex.spellcheck',
-- The color for the disabled component:
disabled_color = { fg = 'grey' }
-- The color for the icon of the disabled component:
disabled_icon_color = { fg = 'grey' }
}
}
}
pwd
= /Users/dokwork/.local/share/nvim/lazy/lualine-ex
:
This component shows the last depth
directories from the working path:
sections = {
lualine_a = {
{
'ex.cwd',
-- The count of directories from the current working path, if > 0 then parts will be taken from
-- the end of the path, or from the start if {depth} < 0:
depth = 2,
-- The prefix which should be used when {depth} great than 0 and less than directories in the
-- path:
prefix = '…'
-- The count of symbols in the `cwd` after which the reduction algorith will be applied:
-- if it > 0 and < 1 then it will be calculated as {max_length} * {vim.o.columns} for
-- {laststatus} == 3; and {max_length} * {vim.api.nvim_win_get_width(0)} for {laststatus} ~= 3;
max_length = 0.2
}
}
}
Reduction algorithm
The absolute value of the {depth} will be decreased until the length of the path becomes less then {max_length}.
This component shows the current cursor position in configurable format. Comparing to the default
location
component, this component can show total number of lines, and may be flexibly configured.
pattern | example |
---|---|
'%2C:%-3L/%T' |
![]() |
'%3L:%-2C' |
![]() |
sections = {
lualine_a = {
{
'ex.location',
-- The pattern to show the cursor position. Here three possible specifiers:
-- 'L' means 'line' - the number of the line where is the cursor now;
-- 'C' means 'column' - the number of the virtual column where is the cursor now;
-- 'T' means 'total' - the total count of lines in the current buffer;
-- Every specifier can be used in similar maner to %d in the {string.format} function.
-- The pattern similar to the default 'location' component is '%3L:%-2C'
pattern = '%2C:%-3L/%T'
}
}
}
This component shows the progress in the file. It has two pre-build modes: 'percent' and 'bar'. The first
one is similar to the default progress
component, but in the second 'bar' mode the progress is
shown as a progress bar.
mode | example |
---|---|
'percent' |
![]() |
'bar' |
![]() |
sections = {
lualine_a = {
{
'ex.progress',
-- How to show the progress. It may be the one of two string constants:
-- 'percent' or 'bar'. In the 'percent' mode the progress is shown as percent of the file.
-- In the 'bar' mode it's shown as the vertical bar. Also, it can be a table with symbols
-- which will be taken to show according to the progress, or a function, which receive three
-- arguments: the component itself, the cursor line and total lines count in the file.
mode = 'percent',
-- This string will be shown when the cursor is on the first line of the file. Set `false`
-- to turn this logic off.
top = 'Top',
-- This string will be shown when the cursor is on the last line of the file. Set `false`
-- to turn this logic off.
bottom = 'Bot'
}
}
}
This component shows a filename
: a file name and a path to the current file relative to the
current working directory. The filename
has a prefix, which shows a file's place in the file
system relative to the cwd
:
File path relative to cwd |
Options | Component example |
---|---|---|
inside cwd |
![]() |
|
outside cwd |
external_prefix = "/..." |
![]() |
outside cwd , but inside $HOME |
![]() |
Some path may be very long and takes significant part in the statusline. It's possible to specify the {max_length} of the filename. To achieve that the follow algorithm is used:
- every part of the path is shortened till the {shorten.length} except parts from the {shorten.exclude} list;
- then the {shorten.length} will be repeatedly decreased until 1 or until the {max_length} will be achieved;
- if it's not enough then the {exclude} setting will be ignored and all parts will be shortened;
- if the result is still longer than {max_length} than only the file name will be used with the prefix {filename_only_prefix}.
Example of the shortened filename with follow options { shorten: { length = 3, exclude = { 1 } } }
:
The {max_length} may be a number, or a function which receives the current component value and returns a number:
- Every value less than 0 means that the filename never should be shortened;
- Zero means that filename should be always shortened;
- A value more or equal to 1 represents a length, after which the filename should be shortened;
- A value between 0 and 1 represents a fraction of the current window width if the {laststatus} == 2, or a fraction of the terminal width.
Default configuration:
{
-- The prefix which is used when the current file is outside cwd
external_prefix = nil,
-- The prefix which is used when the length of the filename after shortening
-- is longer than {max_length}
filename_only_prefix = '…/',
-- The max length of the component value. It may be a number or a function.
-- If it's function, then it will be invoked with actual value, and should
-- return a number:
-- < 0 - never shorten;
-- 0 - always shorten;
-- > 0 and < 1 - shorten when longer than {max_length} * {vim.o.columns}
-- for {laststatus} == 3;
-- and shorten when longer than
-- {max_length} * {vim.api.nvim_win_get_width(0)} overwise;
-- >= 1 - shorten when longer then N symbols;
max_length = 0.3,
-- The configuration of the shorten algorithm.
shorten = {
-- The count of letters, which will be taken from every part of the path
length = 5,
-- The list of indexes of filename parts, which should not be shortened
-- at all (the file name { -1 } is always excluded)
exclude = nil
},
}
ex.relative_filename
component doesn't provide options to show file states,
because it is easily possible to do with standard approach:
-- readonly mode indicator example:
{
'%{""}',
draw_empty = true,
icon = { '' },
cond = function()
return not vim.bo.modifiable
end,
}
No git worktree | Worktree is committed | Worktree is changed |
---|---|---|
![]() |
![]() |
![]() |
This component shows a name of a git branch for a current working directory. The color of this component depends on the state of the git worktree. The component can show different states of the git worktree:
changed
means that at least one uncommitted change exists;committed
means that everything is committed, and no one tracked file is changed;disabled
means that thecwd
is not under git control.
Default configuration:
sections = {
lualine_a = {
{
'ex.git.branch',
icon = ' ',
-- The `git status` command is used to check the status of the worktree.
-- By default, it's run in background for performance purpose, but it could lead to
-- the wrong 'unknow' status at the first time. The `sync = true` can prevent it,
-- but it degrades startup time:
sync = false,
-- The colors for possible states:
colors = {
changed = { fg = 'orange' },
committed = { fg = 'green' },
},
-- The color for the disabled component:
disabled_color = { fg = 'grey' },
-- The color for the icon of the disabled component:
disabled_icon_color = { fg = 'grey' },
-- It can be a function which receive an actual component value, and should return a number;
-- or it can be a number:
-- * any number >= 1 is max count of symbols in the branch name
-- * a number between 0 and 1 means fraction of the {vim.o.columns}
-- for {laststatus} == 3, and fraction of the {vim.api.nvim_win_get_width(0)}
-- in other cases.
-- When this option is defined, a component value will be cropped if it's longer then
-- a value of this property.
max_length = nil,
-- Follow options actual only if {max_length} is defined:
crop = {
-- The string which will be used instead of cropped part.
stub = '…',
-- The side from which a value should be cropped. It may be 'left' or 'right'.
-- If not specified, result depends on the component section:
-- 'right' for a|b|c
-- 'left' for x|y|z
side = nil
}
-- The {ex.crop} function is default {fmt} implementation.
fmt = ex.crop
}
}
}
No one lsp client:
lua_ls
is active:
This component shows a name and appropriate icon of the first active lsp client for the current buffer.
An icon and a color are taken from the icons
table or nvim-web-devicons
plugin (if it's installed).
If no one icon was found for the lsp client neither in icons
, nor in nvim-web-devicons
, the unknown
icon
will be used. For the case, when no one server is run, the component is in disabled state and has
the lsp_is_off
icon.
An icon should be either a string or a table with following format: the [1]
element must be a string with
icon's symbol; the optional element color
should be one of: a name of a color, or a color in #RGB format,
or a table with fg
color.
NOTE: the icon's property color
with the type of string for any icon from the icons
has
different meaning comparing to usual lualine
colors. It should be a name of a color not a
highlight group.
sections = {
lualine_a = {
{
'ex.lsp.single',
icons = {
-- Default icon for any unknow server:
unknown = '?',
-- Default icon for a case, when no one server is run:
lsp_is_off = '',
-- Example of the icon for a client, which doesn't have an icon in `nvim-web-devicons`:
['null-ls'] = { 'N', color = 'magenta' }
}
-- If true then the name of the client will be ommited, and only an icon used:
icons_only = false,
-- The color for the disabled component:
disabled_color = { fg = 'grey' }
-- The color for the icon of the disabled component:
disabled_icon_color = { fg = 'grey' }
}
}
}
No one lsp client | Only lua_ls is run and active |
Both lua_ls and vimls are run, but only vimls is active |
---|---|---|
![]() |
![]() |
![]() |
This component provides information about status of all run LSP servers. Every server has its own
color and icon, which can be taken from the option icons
or plugin nvim-web-devicons
(if it's
installed).
When some of already run servers is not active for the current buffer, it is in disabled state.
The component in disabled state has a color specified in the option disabled_color
.
If no one lsp client is run, the component shows only lsp_is_off
icon.
The ex.lsp.all
component has the same options as the ex.lsp.single component,
with few additional:
sections = {
lualine_a = {
{
'ex.lsp.all',
-- Extends options from the `ex.lsp.single`
-- If true then only clients attached to the current buffer will be shown:
only_attached = false,
-- If true then every closed client will be echoed:
notify_enabled = true
-- The name of highlight group which should be used in echo:
notify_hl = 'Comment'
}
}
}
You may double click by this component to stop all not used lsp clients.
Also, you can use the function to close not used clients outside the component
(see Tools > stop_unused_clients), or change the on_click
handler:
-- close on Ctrl+single click
on_click = function(clicks, button, modified)
if modified == 'c' and clicks == 1 then
require('lualine.ex.lsp').stop_unused_clients()
end
end
This component shows names of the
null-ls sources according to the specified
query
.
By default, it shows names of all sources actual to the current buffer. All
duplicated names are merged.
sections = {
lualine_a = {
{
'ex.lsp.none_ls',
-- The table or function that returns the table with the source query.
-- By default it shows only actual sorces. To show all registered sources
-- you can use just empty table:
-- query = {}
query = function()
return { filetype = vim.bo.filetype }
end,
-- The string separator between names
source_names_separator = ',',
-- The color for the disabled component:
disabled_color = { fg = 'grey' }
-- The color for the icon of the disabled component:
disabled_icon_color = { fg = 'grey' }
}
}
}
No one source:
The
jq
and the spell
sources are active for the current buffer:
🛠️ Tools
This plugin provide additional tools to help you create your own components. Read more details here: Tools.md.