This plugin has been archived. It originally was made as a proof of concept of a 'statusline'
with bubbles as components. It was my first plugin so the implementation was very inefficient and it was created before some of the fixes made to %{
, so it's not a modern implementation anymore.
I will probably come to create another statusline plugin in the future, as it was fun to create this one, for at least my personal use.
Hello! Bubbly is a plugin created by me with the intention of creating a good looking and efficient status line. Bubbly is modular and easily extensible — more about this later in the documentation for developers.
As this plugin tries to be truly modular, you can enable and disable its modules — or bubbles, as I like to call them — with a simple configuration.
This plugin has support for these bubbles, feel free to open an issue or a pull request if you have an idea for a new bubble.
- Mode bubble (e.g. Insert mode).
- Current file bubble.
- Git branch bubble.
- Signify changes bubble.
- Gitsigns changes bubble.
- Coc.nvim diagnostics bubble.
- Lsp-status diagnostics and messages bubble.
- Neovim built-in LSP current function and diagnostics bubble.
- Filetype bubble.
- Progress bubble.
- Total buffer number bubble.
- BUBBLY.NVIM
- Table of Contents
- Screenshots
- Requirements
- Installation
- Configuration
- For Developers
Click to open
Screenshot using the Windows Terminal and WSL 2
Note: the bar in the upper part is my custom tmux bar, you can see it in my dotfiles.
These are the requirements to use this plugin:
- Neovim nightly — this is because this plugin uses the newest Lua API from this Neovim version.
- True color support — this may change in the future, but currently you need to have true color in your neovim configuration enabled (e.g.
set termguicolors
).
You can install this plugin with any package manager you want, for example I use packer.nvim
.
File name: init.lua
vim.cmd [[packadd]]
return require('packer').startup(function()
use {'wbthomason/packer.nvim', opt = true}
use {'datwaft/bubbly.nvim', config = function()
-- Here you can add the configuration for the plugin
vim.g.bubbly_palette = {
background = "#34343c",
foreground = "#c5cdd9",
black = "#3e4249",
red = "#ec7279",
green = "#a0c980",
yellow = "#deb974",
blue = "#6cb6eb",
purple = "#d38aea",
cyan = "#5dbbc1",
white = "#c5cdd9",
lightgrey = "#57595e",
darkgrey = "#404247",
}
vim.g.bubbly_statusline = {
'mode',
'truncate',
'path',
'branch',
'signify',
'gitsigns',
'coc',
'divisor',
'filetype',
'progress',
}
end}
end)
Bubbly is also a highly configurable plugin, so you can configure almost anything. If you have an idea about something you would want to configure feel free to open an issue.
Bubbly is configured using a dictionary in a global vim variable and is configured to use the default key in the dictionary as a fallback in case a key doesn't exist. If you set the variable without some key that exists by default it will use the value defined in the default configuration.
This variable is used to configure which modules/bubbles are used in the statusline, and their order. Its a list of strings or lists of tables (that should follow the same structure as the components), like the following:
{ 'component1', 'divisor', 'component2', {{ data = 'string', color = 'red', style = 'bold' }}, 'component 4' }
This list can also contain strings like the following, that work like a reserved keyword, and have special functionality:
divisor
ordivision
: this divides the right part of the statusline from the left part, every component after this keyword goes to the right.truncate
ortrunc
: this marks where, if the size of the window is insufficient to show the whole statusline, the statusline is truncated (everything to the left will be conserved).
Every string that is not a keyword should be the name of a module inside lua/bubbly/components
, and if an autocommand in a file with the same name exists, it will be loaded.
mode
path
branch
signify
gitsigns
coc
builtinlsp.diagnostic_count
builtinlsp.current_function
filetype
progress
total_buffer_number
lsp_status.diagnostics
lsp_status.messages
vim.g.bubbly_statusline = {
'mode',
'truncate',
'path',
'divisor',
'filetype',
'progress',
}
This variable is used to activate or deactivate Bubbly tabline.
vim.g.bubbly_tabline = 1
This variable is used to define the palette available to every component and their respective colors. You can define more colors than the default and use them in your components or in the configuration variable without any worry.
Accepted values are cterm-colors
naming such as LightGrey
or DarkMagenta
, hexadecimal values such as #123abc
and highlight groups such as Normal background
or LineNr foreground
.
vim.g.bubbly_palette = {
background = "Black",
foreground = "White",
black = "Black",
red = "Red",
green = "Green",
yellow = "Yellow",
blue = "Blue",
purple = "Magenta",
cyan = "Cyan",
white = "White",
lightgrey = "LightGrey",
darkgrey = "Grey",
}
This variable is used to define a blacklist for in which filetypes do you want to disable some component.
vim.g.bubbly_filter = {
default = {},
}
vim.g.bubbly_filter = {
branch = {
'fern',
},
total_buffer_number = {
'fern',
},
path = {
'fern',
},
filetype = {
'fern',
},
}
This variable is used to define special characters used in the bubbles.
vim.g.bubbly_characters = {
-- Bubble delimiters
left = '',
right = '',
-- Close character for the tabline
close = 'x',
-- Bubble separators
bubble_separator = ' ',
}
This variable is used to define the symbols used in some bubbles. Every string follows the format from the C library for formatting strings.
vim.g.bubbly_symbols = {
default = 'PANIC!',
path = {
readonly = 'RO',
unmodifiable = '',
modified = '+',
},
signify = {
added = '+%s', -- requires 1 '%s'
modified = '~%s', -- requires 1 '%s'
removed = '-%s', -- requires 1 '%s'
},
gitsigns = {
added = '+%s', -- requires 1 '%s'
modified = '~%s', -- requires 1 '%s'
removed = '-%s', -- requires 1 '%s'
},
coc = {
error = 'E%s', -- requires 1 '%s'
warning = 'W%s', -- requires 1 '%s'
},
builtinlsp = {
diagnostic_count = {
error = 'E%s', -- requires 1 '%s'
warning = 'W%s', --requires 1 '%s'
},
},
branch = ' %s', -- requires 1 '%s'
total_buffer_number = ' %s', --requires 1 '%d'
lsp_status = {
diagnostics = {
error = 'E%d',
warning = 'W%d',
hint = 'H%d',
info = 'I%d',
},
},
}
This variable defines the test used in some bubbles, if it's empty the bubble disappears.
vim.g.bubbly_tags = {
default = 'HELP ME PLEASE!',
mode = {
normal = 'NORMAL',
insert = 'INSERT',
visual = 'VISUAL',
visualblock = 'VISUAL-B',
command = 'COMMAND',
terminal = 'TERMINAL',
replace = 'REPLACE',
default = 'UNKOWN',
},
paste = 'PASTE',
filetype = {
noft = 'no ft',
},
}
You can also map filetypes to custom names e.g.
vim.g.bubbly_tags = {
default = 'HELP ME PLEASE!',
mode = {
normal = 'NORMAL',
insert = 'INSERT',
visual = 'VISUAL',
visualblock = 'VISUAL-B',
command = 'COMMAND',
terminal = 'TERMINAL',
replace = 'REPLACE',
default = 'UNKOWN',
},
paste = 'PASTE',
filetype = {
noft = '<none>',
conf = ' config',
config = ' config',
css = ' css',
diff = '繁 diff',
dockerfile = ' docker',
email = ' mail',
gitconfig = ' git config',
html = ' html',
javascript = ' javascript',
javascriptreact = ' javascript',
json = ' json',
less = ' less',
lua = ' lua',
mail = ' mail',
make = ' make',
markdown = ' markdown',
php = ' php',
plain = ' text',
plaintext = ' text',
python = ' python',
sass = ' sass',
scss = ' scss',
text = ' text',
typescript = ' typescript',
typescriptreact = ' typescript',
vim = ' vim',
xml = '謹 xml',
},
}
This variable defines which colors is used by which bubble. Every color can be a string with the name of the color or a table with foreground
and background
keys, which define which color is used for foreground and background.
vim.g.bubbly_colors = {
default = 'red',
mode = {
normal = 'green', -- uses by default 'background' as the foreground color.
insert = 'blue',
visual = 'red',
visualblock = 'red',
command = 'red',
terminal = 'blue',
replace = 'yellow',
default = 'white'
},
path = {
readonly = { background = 'lightgrey', foreground = 'foreground' },
unmodifiable = { background = 'darkgrey', foreground = 'foreground' },
path = 'white',
modified = { background = 'lightgrey', foreground = 'foreground' },
},
branch = 'purple',
signify = {
added = 'green',
modified = 'blue',
removed = 'red',
},
gitsigns = {
added = 'green',
modified = 'blue',
removed = 'red',
},
paste = 'red',
coc = {
error = 'red',
warning = 'yellow',
status = { background = 'lightgrey', foreground = 'foreground' },
},
builtinlsp = {
diagnostic_count = {
error = 'red',
warning = 'yellow',
},
current_function = 'purple',
},
filetype = 'blue',
progress = {
rowandcol = { background = 'lightgrey', foreground = 'foreground' },
percentage = { background = 'darkgrey', foreground = 'foreground' },
},
tabline = {
active = 'blue',
inactive = 'white',
close = 'darkgrey',
},
total_buffer_number = 'cyan',
lsp_status = {
messages = 'white',
diagnostics = {
error = 'red',
warning = 'yellow',
hint = 'white',
info = 'blue',
},
},
}
This variable defines the color used by bubbles when the statusline is inactive. It follows the same structure for colors as g:bubbly_colors
(e.g. it can be 'red'
or { foreground = 'red', background = 'blue' }
).
vim.g.bubbly_inactive_color = { background = 'lightgrey', foreground = 'foreground' }
This variable defines which style is used by which bubble. Styles can be ''
, 'bold'
and 'italic'
.
vim.g.bubbly_styles = {
default = 'bold',
mode = 'bold',
path = {
readonly = 'bold',
unmodifiable = '',
path = '',
modified = '',
},
branch = 'bold',
signify = {
added = 'bold',
modified = 'bold',
removed = 'bold',
},
gitsigns = {
added = 'bold',
modified = 'bold',
removed = 'bold',
},
paste = 'bold',
coc = {
error = 'bold',
warning = 'bold',
status = ''
},
builtinlsp = {
diagnostic_count = {
error = '',
warning = ''
},
current_function = ''
},
filetype = '',
progress = {
rowandcol = '',
percentage = '',
},
tabline = {
active = 'bold',
inactive = '',
},
total_buffer_number = '',
lsp_status = {
messages = '',
diagnostics = {
error = '',
warning = '',
hint = '',
info = '',
},
},
}
This variable defines the style for the bubbles in an inactive statusline.
-- Can be '' or 'bold' or 'italic'.
vim.g.bubbly_inactive_style = ''
This variable defines the minimum width of some bubbles.
If the value is 0 it doesn't have a minimum width.
vim.g.bubbly_width = {
default = 0,
progress = {
rowandcol = 8,
},
}
This variable defines some timing configuration related to some bubbles.
vim.g.bubbly_timing = {
default = 0,
lsp_status = {
messages = {
update_delay = 500, -- ms
},
},
}
Bubbly is a fully modular plugin, so you can add new modules using the folders lua/bubbly/components
and lua/bubbly/autocommands
. Every Lua file in these folders is loaded if the option g:bubbly_statusline
has the module name in its list.
For example, if in these folders there is a file named thingy.lua
and g:bubbly_statusline
contains the string "thingy"
, the file lua/bubbly/components/thingy.lua
will be loaded as a bubble and the file lua/bubbly/autocommands/thingy.lua
(if it exists) will have its return value used as autocommands. Additionally, I haven't tested it yet, but you technically should be able to have your own lua/bubbly/components
and lua/bubbly/autcommands
in your neovim configuration folder and those components should work with this plugin.
Note: If the component is inside another folder (e.g. lua/bubbly/components/folder/thingy.lua
) you should use it inside g:bubbly_statusline
with the same syntax of a Lua module (e.g. folder.thingy
).
Components are bubbles inside the statusline that have some functionality. They can have two states, active and inactive; in their active state they should use the color the user defined for them in the configuration, and in their inactive state they should use the inactive color that the user defined.
The components go inside the lua/bubbly/components
folder. They should be a Lua file that returns a function. This function should follow the following structure:
function(inactive)
return {
-- This is a list of tables
-- Every table follows the following structure:
{
-- This is what the component shows in the statusline
data = 'string',
-- This is what color the component uses when it is active. It should be the name of a color.
color = 'string' or { foreground = 'string', background = 'string' },
-- This is the style the component uses (optional).
style = '' or 'bold' or 'italic',
-- This is a string to place before the bubble (optional) (usually not used).
pre = 'string',
-- This is a string to place after the bubble (optional) (usually not used).
post = 'string',
-- Overwrite the left character
left = 'string',
-- Overwrite the right character
right = 'string',
},
}
end
Usually every part of the bubble gets its data from the g:bubbly_something
variables, to be fully configurable.
You can use components like path
as a reference to create your own.
These are used to automate some part of a bubble. For example they are used to automate the branch of the branch
bubble so that every time a different file is opened the bubble changes to the branch of the file.
These go inside the lua/bubbly/autocommands
folder and should be a Lua file that returns a list of tables with the following structure:
return {
-- Every table inside the list should follow the following structure:
{
-- These are the events that activate the autocommand.
events = { 'Event1', 'Event2' },
-- This is the variable that contains the result of the autocommand.
variable = {
-- This is the type of the variable, it can be either 'buffer', 'window' or 'global'.
type = 'buffer' or 'window' or 'global',
-- This is the name the global function will have and also the name of the variable that contains the result.
name = 'string',
},
-- This is the command that is executed by the autocommand, its return value will be saved into the variable.
command = function() end,
},
}
You can use components' autocommands like branch
as a reference to create your own.