User-friendly framework for building your dream tabline in a few lines of code.
Do you know the lua basics and nothing about tablines? Or maybe are you just lazy and don't want to write all the necessary code before fun part? Do you prefer vim tabs or buffer-lines? Or maybe you hate both and just wanted an extra status line? You know what? This plugin is just for you.
local render = function(f)
f.add ' '
f.make_tabs(function(info)
f.add(' ' .. info.index .. ' ')
f.add(info.filename or '[no name]')
f.add(info.modified and '+')
f.add ' '
end)
end
With packer.nvim:
use { "rafcamlet/tabline-framework.nvim", requires = "kyazdani42/nvim-web-devicons" }
require('tabline_framework').setup {
-- Render function is resposible for generating content of tabline
-- This is the place where you do your magic!
render = function(f)
f.add 'This is my tabline!'
end,
-- Default color of tabline items: tabs/bufs
-- if not set TF uses TabLine highlight group colors
hl = { fg = "#abb2bf" bg ="#31353f" }
-- Default color of selected item
-- if not set TF uses TabLineSel highlight group colors
hl_sel = { fg = "#282c34" bg ="#abb2bf" gui = "bold,underline" }
-- Default color of everything except items
-- if not set TF uses TabLineFill highlight group colors
hl_fill = { fg = "#282c34" bg ="#abb2bf" }
}
The render function is a heart of TablineFramework. The whole tabline is defined inside it. It takes a single argument, which contains a table of functions required to manipulating the final result. Let's look at a simple example:
local render = function(f)
f.add { ' ', fg = "#bb0000" }
f.add ' '
end
require('tabline_framework').setup { render = render }
add
function can take a string or a table as its argument. The first item in table is a content which will be added to tabline. Using the fg
, bg
keys, you can specify its highlighting.
Okay, so we have a fancy bug icon, but that isn't too useful. Let's add tabs to it!
local render = function(f)
f.add { ' ', fg = "#bb0000" }
f.make_tabs(function(info)
f.add(' ' .. info.index .. ' ')
f.add(info.filename or '[no name]')
f.add ' '
end)
end
The make_tabs
function takes callback which will be called for each existing tab. As argument it provides table with tab-related information, which you can use in item content. In the example above, we used index number and the filename of focused buffer.
Don't you like tabs? Just replace make_tabs
with make_bufs
. Simple as that.
Do you want something more fancy?
local render = function(f)
f.add { ' ', fg = "#bb0000" }
f.make_tabs(function(info)
f.add( ' ' .. info.index .. ' ')
if info.filename then
-- let's add + sign if the buffer is modified
f.add(info.modified and '+')
f.add(info.filename)
else
-- Why waste space for [no name] ?
-- Let's use [-] if the buffer has no name
-- or [+] if it is also modified
f.add(info.modified and '[+]' or '[-]')
end
f.add ' '
end)
end
Icons? People love icons!
local render = function(f)
f.add { ' ', fg = "#bb0000" }
f.make_tabs(function(info)
-- With the help of kyazdani42/nvim-web-devicons we can fetch color
-- associated with the filetype
local icon_color = f.icon_color(info.filename)
-- If this is the current tab then highlight it
if info.current then
-- We can use set_fg to change default fg color
-- so you won't need to specify it every time
f.set_fg(icon_color)
end
f.add( ' ' .. info.index .. ' ')
if info.filename then
f.add(info.modified and '+')
f.add(info.filename)
-- The icon function returns a filetype icon based on the filename
f.add(' ' .. f.icon(info.filename))
else
f.add(info.modified and '[+]' or '[-]')
end
f.add ' '
end)
end
The right side looks a bit blank. Maybe lsp diagnostic indicators?
local render = function(f)
f.add { ' ', fg = "#bb0000" }
f.make_tabs(function(info)
-- ...
end)
-- Let's add a spacer wich will justify the rest of the tabline to the right
f.add_spacer()
-- get some info from lsp
local errors = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.ERROR })
local warnings = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.WARN })
-- and display it
f.add { ' ' .. errors, fg = "#e86671" }
f.add { ' ' .. warnings, fg = "#e5c07b"}
f.add ' '
end
simple
-- Try it:
require('tabline_framework').setup {
render = require('tabline_framework.examples.simple'),
}
local render = function(f)
f.add ' '
f.make_tabs(function(info)
f.add(' ' .. info.index .. ' ')
f.add(info.filename or '[no name]')
f.add(info.modified and '+')
f.add ' '
end)
end
diagonal_tiles
-- Try it:
require('tabline_framework').setup {
render = require('tabline_framework.examples.diagonal_tiles'),
hl = { fg = '#abb2bf', bg = '#181A1F' },
hl_sel = { fg = '#abb2bf', bg = '#282c34'},
hl_fill = { fg = '#ffffff', bg = '#000000'},
}
local colors = {
black = '#000000',
white = '#ffffff',
bg = '#181A1F',
bg_sel = '#282c34',
fg = '#696969'
}
local render = function(f)
f.add { ' ' }
f.make_tabs(function(info)
f.add { ' ', fg = colors.black }
f.set_fg(not info.current and colors.fg or nil)
f.add( info.index .. ' ')
if info.filename then
f.add(info.modified and '+')
f.add(info.filename)
f.add {
' ' .. f.icon(info.filename),
fg = info.current and f.icon_color(info.filename) or nil
}
else
f.add(info.modified and '[+]' or '[-]')
end
f.add {
' ',
fg = info.current and colors.bg_sel or colors.bg,
bg = colors.black
}
end)
f.add_spacer()
local errors = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.ERROR })
local warnings = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.WARN })
f.add { ' ' .. errors, fg = "#e86671" }
f.add { ' ' .. warnings, fg = "#e5c07b"}
f.add ' '
end
fancy_indexes
-- Try it:
require('tabline_framework').setup {
render = require('tabline_framework.examples.fancy_indexes'),
hl = { fg = '#abb2bf', bg = '#181A1F' },
hl_sel = { fg = '#abb2bf', bg = '#282c34'},
hl_fill = { fg = '#ffffff', bg = '#000000'},
}
local inactive = {
black = '#000000',
white = '#ffffff',
fg = '#696969',
bg_1 = '#181A1F',
bg_2 = '#202728',
index = '#61afef',
}
local active = vim.tbl_extend('force', inactive, {
fg = '#abb2bf',
bg_2 = '#282c34',
index = '#d19a66',
})
local render = function(f)
f.add ' '
f.make_tabs(function(info)
local colors = info.current and active or inactive
f.add {
' ' .. info.index .. ' ',
fg = colors.index,
bg = colors.bg_1
}
f.set_colors { fg = colors.fg, bg = colors.bg_2 }
f.add ' '
if info.filename then
f.add(info.modified and '+')
f.add(info.filename)
f.add {
' ' .. f.icon(info.filename),
fg = info.current and f.icon_color(info.filename) or nil
}
else
f.add(info.modified and '[+]' or '[-]')
end
f.add ' '
f.add { ' ', bg = colors.black }
end)
f.add_spacer()
local errors = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.ERROR })
local warnings = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.WARN })
f.add { ' ' .. errors, fg = "#e86671" }
f.add { ' ' .. warnings, fg = "#e5c07b"}
f.add ' '
end
tabs_and_buffers
WARNING: The current implementation of the buff grouping mechanism is not good enough for real usage and is for presentation purposes only.
-- Try it:
require('tabline_framework').setup {
render = require('tabline_framework.examples.tabs_and_buffers'),
}
local toys = require 'tabline_framework.toys'
toys.setup_tab_buffers()
local render = function(f)
f.add ' '
f.make_bufs(function(info)
f.add(' ' .. info.buf .. ' ')
f.add(info.filename or '[no name]')
f.add(info.modified and '+')
f.add ' '
end, toys.get_tab_buffers(0))
f.add_spacer()
f.make_tabs(function(info)
f.add(' ' .. info.index .. ' ')
end)
end
f.add 'string'
f.add { 'string', fg = '#ffffff', bg = '#000000' }
Adds string
to the tabline and optionally sets its highlighting.
Sets the default foreground color. Useful for changing highlight of many elements. Calling make_tabs
or make_bufs
resets the default colors, same as each tab/bufs item iteration.
Same as set_fg
, but background.
Same as set_fg
, but for gui options.
Sets default colors
Add separation point between alignment sections. Add one to split line into left and right, use two to add centre.
Returns the icon associated with filetype based on the passed filename.
Returns the color associated with filetype based on the passed filename.
f.make_tabs(callback)
f.make_tabs(callback, tablist)
It iterates over all tabs and passes to its callback table with tab related info. Optionally takes a second argument with a list of tab IDs, allowing you to specify custom ordering or filtering.
info.index
- tab indexinfo.tab
- tab idinfo.win
- id of the focused window inside the tabinfo.buf
- id of the buffer displayed in the focused window inside the tabinfo.buf_name
- buffer nameinfo.filename
- filename extracted from buffer name or nil whenbuf_name
is emptyinfo.modified
- boolean: indicates if the buffer has been modifiedinfo.current
- boolean: indicates if the buffer is focusedinfo.before_current
- boolean: indicates if the next buffer is the focused one. Might be useful for conditionally adding item separators.info.after_current
- boolean: indicates if the previous buffer was the focused one.info.first
- boolean: indicates if tab is first in listinfo.last
- boolean: indicates if tab is last in list
f.make_bufs(callback)
f.make_bufs(callback, buflist)
Like make_tabs
but iterates over listed buffers (check the :h buflisted
). The info table has no win
and tab
keys, because buffers can be associated with multiple (or none) windows/tabs.
f.close_tab_btn 'string'
f.close_tab_btn { 'string', fg = '#ffffff', bg = '#000000', gui = 'bold,underline' }
Adds a native close button to the tab. Calling this function outside of make_tabs
gives a warning and does nothing.
Do you have questions? An idea for missing functionalities? Found a bug? Don't be afraid to open a new issue.